Extend auto focus functionality to more cameras

pull/574/head
Mattia Iavarone 6 years ago
parent 37226cb45e
commit 894ec4f4b1
  1. 27
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraOptions.java
  2. 46
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java
  3. 5
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/metering/AutoExposure.java
  4. 1
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/metering/AutoFocus.java
  5. 3
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/metering/AutoWhiteBalance.java
  6. 2
      cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java

@ -196,22 +196,24 @@ public class CameraOptions {
if (value != null) supportedHdr.add(value); if (value != null) supportedHdr.add(value);
} }
//zoom // Zoom
Float maxZoom = cameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM); Float maxZoom = cameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
if(maxZoom != null) { if(maxZoom != null) {
zoomSupported = maxZoom > 1; zoomSupported = maxZoom > 1;
} }
// autofocus // AutoFocus
int[] afModes = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES); // This now means 3A metering with respect to a specific region of the screen.
autoFocusSupported = false; // Some controls (AF, AE) have special triggers that might or might not be supported.
//noinspection ConstantConditions // But they can also be on some continuous search mode so that the trigger is not needed.
for (int afMode : afModes) { // What really matters in my opinion is the availability of regions.
if (afMode == CameraCharacteristics.CONTROL_AF_MODE_AUTO) { Integer afRegions = cameraCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
autoFocusSupported = true; Integer aeRegions = cameraCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AE);
} Integer awbRegions = cameraCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AWB);
} autoFocusSupported = (afRegions != null && afRegions > 0)
|| (aeRegions != null && aeRegions > 0)
|| (awbRegions != null && awbRegions > 0);
// Exposure correction // Exposure correction
Range<Integer> exposureRange = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE); Range<Integer> exposureRange = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE);
@ -430,8 +432,9 @@ public class CameraOptions {
/** /**
* Whether auto focus is supported. This means you can map gestures to * Whether auto focus (metering with respect to a specific region of the screen) is
* {@link GestureAction#AUTO_FOCUS} and focus will be changed on tap. * supported. If it is, you can map gestures to {@link GestureAction#AUTO_FOCUS}
* and metering will change on tap.
* *
* @return whether auto focus is supported. * @return whether auto focus is supported.
*/ */

@ -811,6 +811,29 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
} }
} }
private void applyFocusForMetering(@NonNull CaptureRequest.Builder builder) {
// All focus modes support the AF trigger, except OFF and EDOF.
// However, unlike the preview, we'd prefer AUTO to any CONTINUOUS value.
int[] modesArray = readCharacteristic(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES, new int[]{});
List<Integer> modes = new ArrayList<>();
for (int mode : modesArray) { modes.add(mode); }
if (modes.contains(CaptureRequest.CONTROL_AF_MODE_AUTO)) {
builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO);
return;
}
if (getMode() == Mode.VIDEO &&
modes.contains(CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO)) {
builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO);
return;
}
if (modes.contains(CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE)) {
builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
//noinspection UnnecessaryReturnStatement
return;
}
}
@Override @Override
public void setFlash(@NonNull Flash flash) { public void setFlash(@NonNull Flash flash) {
final Flash old = mFlash; final Flash old = mFlash;
@ -1135,23 +1158,22 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
// Even without this it would need the bind state at least, since we need the preview size. // Even without this it would need the bind state at least, since we need the preview size.
if (getPreviewState() < STATE_STARTED) return; if (getPreviewState() < STATE_STARTED) return;
// The camera options API still has the auto focus API but it really
// refers to 3A metering.
if (!mCameraOptions.isAutoFocusSupported()) return;
// Reset the old meter if present. // Reset the old meter if present.
if (mMeter != null) { if (mMeter != null) {
mMeter.resetMetering(); mMeter.resetMetering();
} }
// The meter will check the current state to see if AF/AE/AWB should be run. // The meter will check the current configuration to see if AF/AE/AWB should run.
// - AE should be on CONTROL_AE_MODE_ON* (depends on setFlash()) // - AE should be on CONTROL_AE_MODE_ON* (this depends on setFlash())
// - AWB should be on CONTROL_AWB_MODE_AUTO (depends on setWhiteBalance()) // - AWB should be on CONTROL_AWB_MODE_AUTO (this depends on setWhiteBalance())
// - AF should be on CONTROL_AF_MODE_AUTO (or others) // - 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 is under our control because the library has no focus API.
// just been asked to fo auto focus. So let's do this - go to auto and remove any // So let's set a good af mode here. This operation is reverted during onMeteringReset().
// CONTINUOUS value that might not be what we want here. applyFocusForMetering(mRepeatingRequestBuilder);
// Note that this operation is reverted during onMeteringReset().
if (!mCameraOptions.isAutoFocusSupported()) return;
mRepeatingRequestBuilder.set(
CaptureRequest.CONTROL_AF_MODE,
CaptureRequest.CONTROL_AF_MODE_AUTO);
// Create the meter and start. // Create the meter and start.
mMeter = new Meter(Camera2Engine.this, mMeter = new Meter(Camera2Engine.this,

@ -66,6 +66,11 @@ public class AutoExposure extends MeteringParameter {
if (!isStarted) { if (!isStarted) {
if (aeState == CaptureRequest.CONTROL_AE_STATE_PRECAPTURE) { if (aeState == CaptureRequest.CONTROL_AE_STATE_PRECAPTURE) {
isStarted = true; isStarted = true;
} else if (aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED
|| aeState == CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED) {
// PRECAPTURE is a transient state, so also check for the final states.
isMetered = true;
isSuccessful = true;
} }
} else { } else {
if (aeState == CaptureRequest.CONTROL_AE_STATE_CONVERGED if (aeState == CaptureRequest.CONTROL_AE_STATE_CONVERGED

@ -27,6 +27,7 @@ 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);
// Exclude OFF and EDOF as per docs.
isSupported = afMode != null && isSupported = afMode != null &&
(afMode == CameraCharacteristics.CONTROL_AF_MODE_AUTO (afMode == CameraCharacteristics.CONTROL_AF_MODE_AUTO
|| afMode == CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_PICTURE || afMode == CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_PICTURE

@ -38,7 +38,8 @@ public class AutoWhiteBalance extends MeteringParameter {
} }
// Even if auto is not supported, change the regions anyway. // Even if auto is not supported, change the regions anyway.
int maxRegions = readCharacteristic(characteristics, CameraCharacteristics.CONTROL_MAX_REGIONS_AWB, 0); int maxRegions = readCharacteristic(characteristics,
CameraCharacteristics.CONTROL_MAX_REGIONS_AWB, 0);
if (maxRegions > 0) { if (maxRegions > 0) {
int max = Math.min(maxRegions, areas.size()); int max = Math.min(maxRegions, areas.size());
builder.set(CaptureRequest.CONTROL_AWB_REGIONS, builder.set(CaptureRequest.CONTROL_AWB_REGIONS,

@ -81,7 +81,7 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader
private boolean supportsAutoFocus() { private boolean supportsAutoFocus() {
//noinspection ConstantConditions //noinspection ConstantConditions
int afMode = mBuilder.get(CaptureRequest.CONTROL_AF_MODE); int afMode = mBuilder.get(CaptureRequest.CONTROL_AF_MODE);
// Exclude OFF and EDOF as per their docs. // Exclude OFF and EDOF as per docs.
return afMode == CameraCharacteristics.CONTROL_AF_MODE_AUTO return afMode == CameraCharacteristics.CONTROL_AF_MODE_AUTO
|| afMode == CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_PICTURE || afMode == CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_PICTURE
|| afMode == CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_VIDEO || afMode == CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_VIDEO

Loading…
Cancel
Save