From 37226cb45eb606c20eb2689af907d8e4344d631e Mon Sep 17 00:00:00 2001 From: Mattia Iavarone Date: Thu, 29 Aug 2019 21:53:11 +0200 Subject: [PATCH] Improve Camera2 pictures speed and quality --- .../cameraview/engine/Camera2Engine.java | 7 +-- .../cameraview/engine/metering/AutoFocus.java | 6 ++- .../picture/Full2PictureRecorder.java | 44 ++++++++++++------- 3 files changed, 36 insertions(+), 21 deletions(-) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java index b9048f8e..364cbd51 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java @@ -1143,10 +1143,11 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv // The meter will check the current state to see if AF/AE/AWB should be run. // - AE should be on CONTROL_AE_MODE_ON* (depends on setFlash()) // - AWB should be on CONTROL_AWB_MODE_AUTO (depends on setWhiteBalance()) - // - AF should be on CONTROL_AF_MODE_AUTO + // - AF should be on CONTROL_AF_MODE_AUTO (or others) // The last one depends on us because the library has no focus API and we have - // just been asked to fo auto focus. So let's do this. This operation is reverted - // during onMeteringReset(). + // just been asked to fo auto focus. So let's do this - go to auto and remove any + // CONTINUOUS value that might not be what we want here. + // Note that this operation is reverted during onMeteringReset(). if (!mCameraOptions.isAutoFocusSupported()) return; mRepeatingRequestBuilder.set( CaptureRequest.CONTROL_AF_MODE, diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/metering/AutoFocus.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/metering/AutoFocus.java index 7a552a74..5b172be2 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/metering/AutoFocus.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/metering/AutoFocus.java @@ -27,7 +27,11 @@ public class AutoFocus extends MeteringParameter { isMetered = false; Integer afMode = builder.get(CaptureRequest.CONTROL_AF_MODE); - isSupported = afMode != null && afMode == CaptureRequest.CONTROL_AF_MODE_AUTO; + isSupported = afMode != null && + (afMode == CameraCharacteristics.CONTROL_AF_MODE_AUTO + || afMode == CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_PICTURE + || afMode == CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_VIDEO + || afMode == CameraCharacteristics.CONTROL_AF_MODE_MACRO); if (isSupported) { builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START); } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java index f9a5b873..80fe7eca 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java @@ -35,11 +35,12 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader private static final CameraLogger LOG = CameraLogger.create(TAG); private static final int STATE_IDLE = 0; - private static final int STATE_WAITING_AUTOFOCUS = 1; - private static final int STATE_WAITING_PRECAPTURE_START = 2; - private static final int STATE_WAITING_PRECAPTURE_END = 3; - private static final int STATE_WAITING_CAPTURE = 4; - private static final int STATE_WAITING_IMAGE = 5; + private static final int STATE_WAITING_FIRST_FRAME = 1; + private static final int STATE_WAITING_AUTOFOCUS = 2; + private static final int STATE_WAITING_PRECAPTURE_START = 3; + private static final int STATE_WAITING_PRECAPTURE_END = 4; + private static final int STATE_WAITING_CAPTURE = 5; + private static final int STATE_WAITING_IMAGE = 6; private static final int REQUEST_TAG = CameraDevice.TEMPLATE_STILL_CAPTURE; @@ -74,7 +75,7 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader @Override public void take() { - runAutoFocus(); + mState = STATE_WAITING_FIRST_FRAME; } private boolean supportsAutoFocus() { @@ -87,8 +88,12 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader || afMode == CameraCharacteristics.CONTROL_AF_MODE_MACRO; } - private void runAutoFocus() { - if (supportsAutoFocus()) { + private void runAutoFocus(@NonNull CaptureResult lastResult) { + Integer afState = lastResult.get(CaptureResult.CONTROL_AF_STATE); + boolean shouldSkip = afState != null && afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED; + boolean supports = supportsAutoFocus(); + LOG.i("runAutoFocus:", "supports:", supports, "shouldSkip:", shouldSkip, "afState:", afState); + if (supports && !shouldSkip) { try { mState = STATE_WAITING_AUTOFOCUS; mBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START); @@ -99,8 +104,8 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader dispatchResult(); } } else { - LOG.w("Device does not support focus lock. Running precapture."); - runPrecapture(null); + LOG.w("Device does not support auto focus. Running precapture."); + runPrecapture(lastResult); } } @@ -118,12 +123,12 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader || aeMode == 5 /* CameraCharacteristics.CONTROL_AE_MODE_ON_EXTERNAL_FLASH, API 28 */; } - private void runPrecapture(@Nullable CaptureResult lastResult) { - //noinspection ConstantConditions - boolean shouldSkipPrecapture = lastResult != null - && lastResult.get(CaptureResult.CONTROL_AE_STATE) != null - && lastResult.get(CaptureResult.CONTROL_AE_STATE) == CaptureResult.CONTROL_AE_STATE_CONVERGED; - if (supportsPrecapture() && !shouldSkipPrecapture) { + private void runPrecapture(@NonNull CaptureResult lastResult) { + Integer aeState = lastResult.get(CaptureResult.CONTROL_AE_STATE); + boolean shouldSkip = aeState != null && aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED; + boolean supports = supportsPrecapture(); + LOG.i("runPrecapture:", "supports:", supports, "shouldSkip:", shouldSkip, "aeState:", aeState); + if (supports && !shouldSkip) { try { mState = STATE_WAITING_PRECAPTURE_START; mBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, @@ -170,7 +175,8 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader } public void onCaptureProgressed(@NonNull CaptureResult result) { - process(result); + // Let's ignore these. They often do not have good results. + // process(result); } public void onCaptureCompleted(@NonNull CaptureResult result) { @@ -180,6 +186,10 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader private void process(@NonNull CaptureResult result) { switch (mState) { case STATE_IDLE: break; + case STATE_WAITING_FIRST_FRAME: { + runAutoFocus(result); + break; + } case STATE_WAITING_AUTOFOCUS: { Integer afState = result.get(CaptureResult.CONTROL_AF_STATE); if (afState == null