Home » Android » android – Camera2 API onCaptureComplete() is called but camera state is still CONTROL_AE_STATE_PRECAPTURE

android – Camera2 API onCaptureComplete() is called but camera state is still CONTROL_AE_STATE_PRECAPTURE

Posted by: admin May 14, 2020 Leave a comment

Questions:

I’m trying to create an app that takes some photos from a service using the camera2 API.

I can get the app to take pictures fine from a fragment based on the Camera2Basic sample.

But when I try move to a service the image doesn’t finish capturing properly. It never progresses past the autoexposure precapture state.

I narrowed it down to being some problem with not having a preview. I’ve put together a test fragment by taking the Camera2Basic code and removing the preview, which results in the same issue.

I put together a test fragment that has the issue, based on the Camera2Basic sample where i’ve basically just removed code for the preview. Fragment code uploaded here http://pastebin.ca/3182401.

I’m getting the onCaptureCompleted() callback but when i check the camera autoexposure state here, it’s still in the CONTROL_AE_STATE_PRECAPTURE state.

It doesn’t make sense to me that the capture would be completed if one of the camera states is still in precapture.

Anyone know what might be happening here?

How to&Answers:

It’s not mentioned in the docs, but onCaptureCompleted is actually called when the request has been sent, not when precapture or autofocus sequence has finished. Camera2Basic relies on preview running constantly, because preview acts as a constant monitor for the camera’s state. Without it, you won’t know when the precapture sequence actually finishes.

Answer:

I think there is a flaw in your logic where you set your mState as pre capture state

private void process(CaptureResult result) {
        switch (mState) {
            case STATE_PREVIEW: {
                // We have nothing to do when the camera preview is working normally.
                break;
            }
            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;
            }
            case 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 = STATE_WAITING_NON_PRECAPTURE;
                }
                break;
            }
            case 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 = STATE_PICTURE_TAKEN;
                    captureStillPicture();
                }
                break;
            }
        }
    }

Would case STATE_WAITING_PRECAPTURE even be entered at all?