4

I'm having issues with my touch-to-focus implementation using Camera2 APIs. Here's my code:

    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
    if (isMeteringAreaAESupported()) {
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS,
                new MeteringRectangle[]{focusArea});
    }
    if (isMeteringAreaAFSupported()) {
        mPreviewRequestBuilder
                .set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[]{focusArea});
        mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                CaptureRequest.CONTROL_AF_MODE_AUTO);
    }
    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
            CameraMetadata.CONTROL_AF_TRIGGER_START);
    try {
        mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null,
                mBackgroundHandler);
        mManualFocusEngaged = true;
    } catch (CameraAccessException e) {
      // error handling
    }

The problem I'm seeing is weird behaviour with the flash on some devices when the above code is called multiple times within a short period of time (i.e. user touches the screen way too fast before the focus has been set). For example, on S5 it looks like all the requests are queued up and if the user touch quite a few times, they execute one by one for a while. On my Nexus 5, the flash will not blink from request to request, but will be constantly ON until the last request finished executing.

What I'm after is to actually cancel the in-flight request like they do in Google Camera. If you try the same thing with flash ON using Google Camera, they cancel the request immediately when the new touch is registered.

I've tried adding mCaptureSession.abortCaptures(); before the above method but it didn't work the same way and started dropping frames as well. mCaptureSession.stopRepeating(); didn't make any difference at all.

vkislicins
  • 3,331
  • 3
  • 32
  • 62

1 Answers1

3

Apparently I had to do a capture request to cancel the AF.

I've added this after the first line with my CANCEL trigger:

        try {
            mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
                mBackgroundHandler);
            // After this, the camera will go back to the normal state of preview.
            mState = STATE_PREVIEW;
        } catch (CameraAccessException e){
            // log
        }
vkislicins
  • 3,331
  • 3
  • 32
  • 62
  • 4
    Can you share the code for touch to focus using camera2? – Bhoomika Brahmbhatt Mar 21 '16 at 06:36
  • Brilliant! This is what I was looking for – mudin Feb 07 '17 at 10:43
  • 1
    In fact, you should perform all the triggers start and cancel (in AF and precapture triggers) with capture() not with repeatingRequest(), in order to send the request only once, if not, the state machine get stuck in a loop trying to focus in some devices. And after that, call repeatingRequest() with the triggers to IDLE – Yamidragut Feb 10 '17 at 11:52