12

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?

user4232
  • 592
  • 1
  • 12
  • 37
user2128112
  • 299
  • 4
  • 13
  • Is it possible that after you take a photo, camera goes back to a precapture state in order to prepare for next photo? – Jani Oct 13 '15 at 12:46
  • Shouldn't be the case. Documentation says it should lock on the CONVERGED or FLASH_REQUIRED state. Then stays locked until a picture is taken or the application submits a request with android.control.aeLock == true, followed by a request with android.control.aeLock == false https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#CONTROL_AE_PRECAPTURE_TRIGGER – user2128112 Oct 13 '15 at 13:13
  • i am getting `CONTROL_AE_STATE` always null. Any idea why? i am using the same sample. And tried on multiple devices. – iMDroid Aug 31 '17 at 10:32

2 Answers2

1

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.

virusman
  • 76
  • 1
  • 4
0

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?

hrk_er
  • 73
  • 10