6

I work with camera 2 API.

I use standard google sample for camera.

Issue is code allow to user take a picture even if image is not in a focus...

private final CameraCaptureSession.CaptureCallback mCaptureCallback
        = new CameraCaptureSession.CaptureCallback() {

    @Override
    public void onCaptureProgressed(@NonNull CameraCaptureSession session,
                                    @NonNull CaptureRequest request,
                                    @NonNull CaptureResult partialResult) {
    }

    @Override
    public void onCaptureCompleted(@NonNull CameraCaptureSession session,
                                   @NonNull CaptureRequest request,
                                   @NonNull TotalCaptureResult result) {
        process(result);
    }

    private void process(CaptureResult result) {
        switch (mState) {
            case CameraHelper.STATE_PREVIEW: {
                // We have nothing to do when the camera preview is working normally.

                break;
            }
            case CameraHelper.STATE_WAITING_LOCK: {
                Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
                if (afState == null) {
                    captureStillPicture();
                } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
                        CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {

                    // CONTROL_AE_STATE can be null on some devices
                    Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                    if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                        mState = CameraHelper.STATE_PICTURE_TAKEN;
                        captureStillPicture();
                    } else {
                        runPrecaptureSequence();
                    }
                }
                break;
            }
            case CameraHelper.STATE_WAITING_PRECAPTURE: {
                // CONTROL_AE_STATE can be null on some devices
                Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                if (aeState == null ||
                        aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
                        aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
                    mState = CameraHelper.STATE_WAITING_NON_PRECAPTURE;
                }
                break;
            }
            case CameraHelper.STATE_WAITING_NON_PRECAPTURE: {
                // CONTROL_AE_STATE can be null on some devices
                Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
                    mState = CameraHelper.STATE_PICTURE_TAKEN;
                    captureStillPicture();
                }
                break;
            }
        }
    }
};

It is standard callback

How I can implement smth like in a regular camera, when user click take picture button, the first camera take a focus and only after that take a picture...

But in my case even if picture not in a focus anyway it is allow to take a picture...

What am I doing wrong?

EDIT

private void captureStillPicture() {
    try {
        if (null == cameraDevice) {
            return;
        }
        // This is the CaptureRequest.Builder that we use to take a picture.
        final CaptureRequest.Builder captureBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
        captureBuilder.addTarget(imageReader.getSurface());

        captureBuilder.set(CaptureRequest.JPEG_QUALITY, (byte) 100);

        // Use the same AE and AF modes as the preview.
        captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
        setAutoFlash(captureBuilder);

        // Orientation
        int rotation = getWindowManager().getDefaultDisplay().getRotation();
        captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, CameraHelper.ORIENTATIONS.get(rotation));

        // Этот метод показывает, что будет происходить после того как снимок будет сделан
        final CameraCaptureSession.CaptureCallback CaptureCallback = new CameraCaptureSession.CaptureCallback() {

            @Override
            public void onCaptureCompleted(@NonNull CameraCaptureSession session,
                                           @NonNull CaptureRequest request,
                                           @NonNull TotalCaptureResult result) {
                Logger.logGeneral("LENS_FOCAL_LENGTH : " + request.get(CaptureRequest.LENS_FOCAL_LENGTH));
                unlockFocus();
            }
        };

        captureSession.stopRepeating();
        captureSession.capture(captureBuilder.build(), CaptureCallback, null);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

EDIT2

Maybe I don't have to allow user take a picture if focus doesn't set up? It means I should track focus condition every moment and eventually when user click take picture button I should check focus condition and if it is in focus - take picture, if not - show Toast - set up focus

I have found snip of code according to this question

private CameraCaptureSession.CaptureCallback mCaptureCallback
    = new CameraCaptureSession.CaptureCallback() {

private void process(CaptureResult result) {
    switch (mState) {
        case STATE_PREVIEW: {

            int afState = result.get(CaptureResult.CONTROL_AF_STATE);
            if (CaptureResult.CONTROL_AF_TRIGGER_START == afState) {
                if (areWeFocused) {
                    //Run specific task here
                }
            }
            if (CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED == afState) {
                areWeFocused = true;
            } else {
                areWeFocused = false;
            }

            break;
        }
    }
}

@Override
public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request,
                                CaptureResult partialResult) {
    process(partialResult);
}

@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
                               TotalCaptureResult result) {
    process(result);
}
};

And I faced with such case result.get(CaptureResult.CONTROL_AF_STATE); always return 0 ... 0 it is CaptureResult.CONTROL_AF_STATE_INACTIVE . I faced it testing on Samsung S5... But the same code always return 1 or 2 on Meizu MX5... What is the difference?

What am I doing wrong?

How can I take a picture only when camera in focus?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Sirop4ik
  • 4,543
  • 2
  • 54
  • 121
  • looks like you need to look at CaptureRequest and CONTROL_CAPTURE_INTENT, all the code you attached is for the result and not the request. – L7ColWinters Oct 21 '16 at 21:25
  • @L7ColWinters you mean i should set this param in request? – Sirop4ik Oct 22 '16 at 07:31
  • @L7ColWinters i added capture requst, but i can't guess how to add it in request... it have to be smth like this `captureBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, 100);` ? – Sirop4ik Oct 22 '16 at 10:27
  • Check http://stackoverflow.com/a/33181620/192373 - this explains how camera2 API implements manual focus. If you set auto-focus, then the picture should be expected focused already. – Alex Cohn Oct 22 '16 at 14:36
  • Re: EDIT2. This is just another case of crooked camera2 implementation on S5. Don't use camera2 unless the device supports it better than the deprecated Camera API – Alex Cohn Oct 24 '16 at 02:07
  • @AlexCohn but how i can know that moment when device will support it in appropriate way? – Sirop4ik Oct 24 '16 at 08:42
  • @AlexCohn Anyway you understand my purpose, would you suggest me how to accomplish? – Sirop4ik Oct 24 '16 at 08:45
  • Check [ndroid.info.supportedHardwareLevel](https://source.android.com/devices/camera/versioning.html). In the meanwhile, I suggest to rewrite your code using the deprecated old API, the new camera2 API is worth working with only when you need something that the old API does not support (e.g. high-framerate full-res, raw frame capture, etc.) – Alex Cohn Oct 24 '16 at 09:43
  • @AlexCohn I cannot help agreeing with you, but project has already builded and it used camera2API... It is going to be very expensive to chenge it now( – Sirop4ik Oct 24 '16 at 13:01
  • Samsung is not in the best financial situation these days, so unfortunately your chances to get compensation for your efforts from them are very low. – Alex Cohn Oct 24 '16 at 17:29

0 Answers0