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);
}
//zoom
// Zoom
Float maxZoom = cameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM);
if(maxZoom != null) {
zoomSupported = maxZoom > 1;
}
// autofocus
int[] afModes = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
autoFocusSupported = false;
//noinspection ConstantConditions
for (int afMode : afModes) {
if (afMode == CameraCharacteristics.CONTROL_AF_MODE_AUTO) {
autoFocusSupported = true;
}
}
// AutoFocus
// This now means 3A metering with respect to a specific region of the screen.
// Some controls (AF, AE) have special triggers that might or might not be supported.
// But they can also be on some continuous search mode so that the trigger is not needed.
// What really matters in my opinion is the availability of regions.
Integer afRegions = cameraCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF);
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
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
* {@link GestureAction#AUTO_FOCUS} and focus will be changed on tap.
* Whether auto focus (metering with respect to a specific region of the screen) is
* 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.
*/

@ -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
public void setFlash(@NonNull Flash flash) {
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.
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.
if (mMeter != null) {
mMeter.resetMetering();
}
// 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 (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 - 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,
CaptureRequest.CONTROL_AF_MODE_AUTO);
// The meter will check the current configuration to see if AF/AE/AWB should run.
// - AE should be on CONTROL_AE_MODE_ON* (this depends on setFlash())
// - AWB should be on CONTROL_AWB_MODE_AUTO (this depends on setWhiteBalance())
// - AF should be on CONTROL_AF_MODE_AUTO or others
// The last one is under our control because the library has no focus API.
// So let's set a good af mode here. This operation is reverted during onMeteringReset().
applyFocusForMetering(mRepeatingRequestBuilder);
// Create the meter and start.
mMeter = new Meter(Camera2Engine.this,

@ -66,6 +66,11 @@ public class AutoExposure extends MeteringParameter {
if (!isStarted) {
if (aeState == CaptureRequest.CONTROL_AE_STATE_PRECAPTURE) {
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 {
if (aeState == CaptureRequest.CONTROL_AE_STATE_CONVERGED

@ -27,6 +27,7 @@ public class AutoFocus extends MeteringParameter {
isMetered = false;
Integer afMode = builder.get(CaptureRequest.CONTROL_AF_MODE);
// Exclude OFF and EDOF as per docs.
isSupported = afMode != null &&
(afMode == CameraCharacteristics.CONTROL_AF_MODE_AUTO
|| 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.
int maxRegions = readCharacteristic(characteristics, CameraCharacteristics.CONTROL_MAX_REGIONS_AWB, 0);
int maxRegions = readCharacteristic(characteristics,
CameraCharacteristics.CONTROL_MAX_REGIONS_AWB, 0);
if (maxRegions > 0) {
int max = Math.min(maxRegions, areas.size());
builder.set(CaptureRequest.CONTROL_AWB_REGIONS,

@ -81,7 +81,7 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader
private boolean supportsAutoFocus() {
//noinspection ConstantConditions
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
|| afMode == CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_PICTURE
|| afMode == CameraCharacteristics.CONTROL_AF_MODE_CONTINUOUS_VIDEO

Loading…
Cancel
Save