Improve Camera2 pictures speed and quality

pull/574/head
Mattia Iavarone 6 years ago
parent 953b23f813
commit 37226cb45e
  1. 7
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java
  2. 6
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/metering/AutoFocus.java
  3. 44
      cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.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. // 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()) // - AE should be on CONTROL_AE_MODE_ON* (depends on setFlash())
// - AWB should be on CONTROL_AWB_MODE_AUTO (depends on setWhiteBalance()) // - 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 // 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 // just been asked to fo auto focus. So let's do this - go to auto and remove any
// during onMeteringReset(). // CONTINUOUS value that might not be what we want here.
// Note that this operation is reverted during onMeteringReset().
if (!mCameraOptions.isAutoFocusSupported()) return; if (!mCameraOptions.isAutoFocusSupported()) return;
mRepeatingRequestBuilder.set( mRepeatingRequestBuilder.set(
CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE,

@ -27,7 +27,11 @@ public class AutoFocus extends MeteringParameter {
isMetered = false; isMetered = false;
Integer afMode = builder.get(CaptureRequest.CONTROL_AF_MODE); 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) { if (isSupported) {
builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START); builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
} }

@ -35,11 +35,12 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader
private static final CameraLogger LOG = CameraLogger.create(TAG); private static final CameraLogger LOG = CameraLogger.create(TAG);
private static final int STATE_IDLE = 0; private static final int STATE_IDLE = 0;
private static final int STATE_WAITING_AUTOFOCUS = 1; private static final int STATE_WAITING_FIRST_FRAME = 1;
private static final int STATE_WAITING_PRECAPTURE_START = 2; private static final int STATE_WAITING_AUTOFOCUS = 2;
private static final int STATE_WAITING_PRECAPTURE_END = 3; private static final int STATE_WAITING_PRECAPTURE_START = 3;
private static final int STATE_WAITING_CAPTURE = 4; private static final int STATE_WAITING_PRECAPTURE_END = 4;
private static final int STATE_WAITING_IMAGE = 5; 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; private static final int REQUEST_TAG = CameraDevice.TEMPLATE_STILL_CAPTURE;
@ -74,7 +75,7 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader
@Override @Override
public void take() { public void take() {
runAutoFocus(); mState = STATE_WAITING_FIRST_FRAME;
} }
private boolean supportsAutoFocus() { private boolean supportsAutoFocus() {
@ -87,8 +88,12 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader
|| afMode == CameraCharacteristics.CONTROL_AF_MODE_MACRO; || afMode == CameraCharacteristics.CONTROL_AF_MODE_MACRO;
} }
private void runAutoFocus() { private void runAutoFocus(@NonNull CaptureResult lastResult) {
if (supportsAutoFocus()) { 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 { try {
mState = STATE_WAITING_AUTOFOCUS; mState = STATE_WAITING_AUTOFOCUS;
mBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START); mBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
@ -99,8 +104,8 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader
dispatchResult(); dispatchResult();
} }
} else { } else {
LOG.w("Device does not support focus lock. Running precapture."); LOG.w("Device does not support auto focus. Running precapture.");
runPrecapture(null); runPrecapture(lastResult);
} }
} }
@ -118,12 +123,12 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader
|| aeMode == 5 /* CameraCharacteristics.CONTROL_AE_MODE_ON_EXTERNAL_FLASH, API 28 */; || aeMode == 5 /* CameraCharacteristics.CONTROL_AE_MODE_ON_EXTERNAL_FLASH, API 28 */;
} }
private void runPrecapture(@Nullable CaptureResult lastResult) { private void runPrecapture(@NonNull CaptureResult lastResult) {
//noinspection ConstantConditions Integer aeState = lastResult.get(CaptureResult.CONTROL_AE_STATE);
boolean shouldSkipPrecapture = lastResult != null boolean shouldSkip = aeState != null && aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED;
&& lastResult.get(CaptureResult.CONTROL_AE_STATE) != null boolean supports = supportsPrecapture();
&& lastResult.get(CaptureResult.CONTROL_AE_STATE) == CaptureResult.CONTROL_AE_STATE_CONVERGED; LOG.i("runPrecapture:", "supports:", supports, "shouldSkip:", shouldSkip, "aeState:", aeState);
if (supportsPrecapture() && !shouldSkipPrecapture) { if (supports && !shouldSkip) {
try { try {
mState = STATE_WAITING_PRECAPTURE_START; mState = STATE_WAITING_PRECAPTURE_START;
mBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, mBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
@ -170,7 +175,8 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader
} }
public void onCaptureProgressed(@NonNull CaptureResult result) { 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) { public void onCaptureCompleted(@NonNull CaptureResult result) {
@ -180,6 +186,10 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader
private void process(@NonNull CaptureResult result) { private void process(@NonNull CaptureResult result) {
switch (mState) { switch (mState) {
case STATE_IDLE: break; case STATE_IDLE: break;
case STATE_WAITING_FIRST_FRAME: {
runAutoFocus(result);
break;
}
case STATE_WAITING_AUTOFOCUS: { case STATE_WAITING_AUTOFOCUS: {
Integer afState = result.get(CaptureResult.CONTROL_AF_STATE); Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
if (afState == null if (afState == null

Loading…
Cancel
Save