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.
// - 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,

@ -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);
}

@ -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

Loading…
Cancel
Save