Skip to content

Instantly share code, notes, and snippets.

@delacrixmorgan
Last active March 31, 2020 21:21
Show Gist options
  • Save delacrixmorgan/41cacede10247f1ddfdde1210b2ad76c to your computer and use it in GitHub Desktop.
Save delacrixmorgan/41cacede10247f1ddfdde1210b2ad76c to your computer and use it in GitHub Desktop.
Camera2 Infinite Loop in `CONTROL_AF_STATE_PASSIVE_FOCUSED`

Camera2 Infinite Loop in CONTROL_AF_STATE_PASSIVE_FOCUSED

There's a few reasons.

a) While you are capturePicture(), the AutoFocus state is stucked at CONTROL_AF_STATE_PASSIVE_FOCUSED and there is no way to shake it off.

Thus, you'll need to manually restart the focus and get a lock on it again.

b) setRepeatingRequest() from captureSession is overwhelming it.

To resolve that, you'll need to add a delay.

Step 1 - Restructure capturePicture(result: CaptureResult)

private fun capturePicture(result: CaptureResult) {
    val afState = result.get(CaptureResult.CONTROL_AF_STATE)
    when (afState) {
        CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED, CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED -> {
            val aeState = result.get(CaptureResult.CONTROL_AE_STATE)
            if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                state = STATE_PICTURE_TAKEN
                captureStillPicture()
            } else {
                runPrecaptureSequence()
            }
        }
        null -> captureStillPicture()
        else -> restartFocus()
    }
}

Step 2 - Add restartFocus()

private fun restartFocus() {
    try {
        previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL)
        captureSession?.capture(previewRequestBuilder.build(), captureCallback, backgroundHandler)
        lockFocus()
    } catch (e: CameraAccessException) {
        Log.e(CameraFragment::class.java.simpleName, e.toString())
    }
}

Step 3 - Add Delay for repeatingRequest inside unlockFocus()

private fun unlockFocus() {
    try {
        // Reset the auto-focus trigger
        previewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL)
        captureSession?.capture(previewRequestBuilder.build(), captureCallback, backgroundHandler)
        // After this, the camera will go back to the normal state of preview.
        state = STATE_PREVIEW
        Handler().postDelayed({
            captureSession?.setRepeatingRequest(previewRequest, captureCallback, backgroundHandler)
        }, 500)
    } catch (e: CameraAccessException) {
        Log.e(CameraFragment::class.java.simpleName, e.toString())
    }
}

Special thanks to these StackOverFlow discussion that enabled me to figure it out.

https://stackoverflow.com/questions/44527420/android-camera2-focus-state-stuck

https://stackoverflow.com/questions/40146485/session-has-been-closed-further-changes-are-illegal

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment