Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Camera2 focus state stuck

I need to use Camera2 API on my application. (Api21+) I found the next sample: https://github.com/googlesamples/android-Camera2Basic

I downloaded it and started on my phone. When I pressed the "Picture" Button, it's call the takePhoto method.

private void takePicture() {
    lockFocus();
}

It is a State machine. Sometimes this machine stuck on STATE_WAITING_LOCK. My device is waiting for Focus, but nothing happens! (Yes, my device is support auto focus)

case 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 = STATE_PICTURE_TAKEN;
                captureStillPicture();
            } else {
                runPrecaptureSequence();
            }
        }
        break;
    }

What is the good solution for this problem? And this program sometimes crashed here:

private void unlockFocus() {
    try {
        // Reset the auto-focus trigger
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
                CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
        setAutoFlash(mPreviewRequestBuilder);
/*HERE*/ mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
                mBackgroundHandler);
        // After this, the camera will go back to the normal state of preview.
        mState = STATE_PREVIEW;
        mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback,
                mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

Why can't focus my device?

like image 642
ketom Avatar asked Jun 13 '17 16:06

ketom


2 Answers

It seems that your program stucks sometimes in CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED where according to documentation "The AF algorithm has been unable to focus. The lens is not moving." link

Try to cancel the AF_TRIGGER and start it again. Something like this:

 if (afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
          getRidOfNotFocusedLock();
}

And:

private void getRidOfNotFocusedLock(){
        try {
            mPreviewRequestBuilder.set(
                    CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
            mCaptureSession.capture(
                    captureRequestBuilder.build(), captureSessionCaptureCallback, backgroundHandler);
            mPreviewRequestBuilder.set(
                    CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }
like image 78
Lautern Avatar answered Oct 14 '22 10:10

Lautern


When I found Lautern's answer, I had to adjust it a little, as it wasn't working for me.
As the program stucks sometimes in CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED, you can try to restart the AF_TRIGGER:

if (afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) {
    restartFocus();
}

private void restartFocus(){
        try {
            mPreviewRequestBuilder.set(
                CaptureRequest.CONTROL_AF_TRIGGER,
                CaptureRequest.CONTROL_AF_TRIGGER_CANCEL);
            mCaptureSession.capture(
                captureRequestBuilder.build(),
                captureSessionCaptureCallback,
                mBackgroundHandler);
            lockFocus();

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

private void lockFocus() {
    try {
        mPreviewRequestBuilder.set(
            CaptureRequest.CONTROL_AF_TRIGGER,
            CaptureRequest.CONTROL_AF_TRIGGER_START);
        mState = STATE_WAIT_LOCK;
        mCaptureSession.capture(
                mPreviewRequestBuilder.build(),
                mPreviewCaptureCallback,
                mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

As some time has passed, since I implemented this, I'm not entirely sure why I had to restart the capture session. But without it, it doesn't work for me.

like image 37
EarlGrey Avatar answered Oct 14 '22 09:10

EarlGrey