Implement Locker in Camera2Engine

pull/580/head
Mattia Iavarone 6 years ago
parent ef879c2bbb
commit d1acae558e
  1. 69
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java
  2. 25
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/Locker.java

@ -67,7 +67,9 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAvailableListener, Meter.Callback { public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAvailableListener,
Meter.Callback,
Locker.Callback {
private static final String TAG = Camera2Engine.class.getSimpleName(); private static final String TAG = Camera2Engine.class.getSimpleName();
private static final CameraLogger LOG = CameraLogger.create(TAG); private static final CameraLogger LOG = CameraLogger.create(TAG);
@ -689,6 +691,18 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
// See comments in Full2PictureRecorder. // See comments in Full2PictureRecorder.
applyRepeatingRequestBuilder(); applyRepeatingRequestBuilder();
} }
boolean unlock = (fullPicture && getPictureMetering()) ||
(!fullPicture && getPictureSnapshotMetering());
if (unlock) {
if (mLocker != null) {
mLocker.unlock();
mLocker = null;
}
if (mMeter != null) {
mMeter.resetMetering();
mMeter = null;
}
}
} }
//endregion //endregion
@ -1268,18 +1282,8 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
@Override @Override
public void onMeteringEnd(@Nullable PointF point, boolean success) { public void onMeteringEnd(@Nullable PointF point, boolean success) {
LOG.w("onMeteringEnd - point:", point, "gesture:", mMeteringGesture, "success:", success); LOG.w("onMeteringEnd - point:", point, "gesture:", mMeteringGesture, "success:", success);
if (point != null) { mLocker = new Locker(mCameraCharacteristics, this);
mCallback.dispatchOnFocusEnd(mMeteringGesture, success, point); mLocker.lock(mLastRepeatingResult, point);
} else {
LOG.w("onMeteringEnd - restoring the picture capturing. isSnapshot:", mDelayedPictureStub.isSnapshot);
if (mDelayedPictureStub.isSnapshot) {
onTakePictureSnapshot(mDelayedPictureStub, mDelayedPictureRatio, false);
} else {
onTakePicture(mDelayedPictureStub, false);
}
mDelayedPictureStub = null;
mDelayedPictureRatio = null;
}
} }
/** /**
@ -1296,11 +1300,28 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
} }
} }
/** @Override
* Called by {@link Meter} to get the current capture request public void onLocked(@Nullable PointF point, boolean success) {
* builder so it can apply changes on it. LOG.w("onLocked - point:", point, "gesture:", mMeteringGesture, "success:", success);
* @return our builder if (point != null) {
*/ mCallback.dispatchOnFocusEnd(mMeteringGesture, success, point);
} else {
LOG.w("onLocked - restoring the picture capturing. isSnapshot:", mDelayedPictureStub.isSnapshot);
if (mDelayedPictureStub.isSnapshot) {
onTakePictureSnapshot(mDelayedPictureStub, mDelayedPictureRatio, false);
} else {
onTakePicture(mDelayedPictureStub, false);
}
mDelayedPictureStub = null;
mDelayedPictureRatio = null;
}
}
@Override
public void onUnlocked(@Nullable PointF point) {
// Nothing to do.
}
@NonNull @NonNull
@Override @Override
public CaptureRequest.Builder getMeteringBuilder() { public CaptureRequest.Builder getMeteringBuilder() {
@ -1313,5 +1334,17 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
applyRepeatingRequestBuilder(); applyRepeatingRequestBuilder();
} }
@NonNull
@Override
public CaptureRequest.Builder getLockingBuilder() {
return mRepeatingRequestBuilder;
}
@Override
public void onLockingChange() {
LOG.i("onLockingChange:", "applying the builder.");
applyRepeatingRequestBuilder();
}
//endregion //endregion
} }

@ -1,5 +1,6 @@
package com.otaliastudios.cameraview.engine; package com.otaliastudios.cameraview.engine;
import android.graphics.PointF;
import android.hardware.camera2.CameraCharacteristics; import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest; import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult; import android.hardware.camera2.CaptureResult;
@ -7,6 +8,7 @@ import android.hardware.camera2.TotalCaptureResult;
import android.os.Build; import android.os.Build;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import com.otaliastudios.cameraview.CameraLogger; import com.otaliastudios.cameraview.CameraLogger;
@ -19,7 +21,7 @@ import com.otaliastudios.cameraview.engine.locking.Parameter;
* Helps Camera2-based engines to perform 3A locking and unlocking. * Helps Camera2-based engines to perform 3A locking and unlocking.
* Users are required to: * Users are required to:
* *
* - Call {@link #lock(CaptureResult)} to start * - Call {@link #lock(CaptureResult, PointF)} to start
* - Call {@link #onCapture(CaptureResult)} when they have partial or total results, as long as the * - Call {@link #onCapture(CaptureResult)} when they have partial or total results, as long as the
* locker is still in a locking operation, which can be checked through {@link #isLocking()} ()} * locker is still in a locking operation, which can be checked through {@link #isLocking()} ()}
* - Call {@link #unlock()} to reset the locked parameters if needed. * - Call {@link #unlock()} to reset the locked parameters if needed.
@ -35,16 +37,18 @@ public class Locker {
/** /**
* Notifies that locking has ended. No action is required for implementors. * Notifies that locking has ended. No action is required for implementors.
* From now on, {@link #isLocking()} will return false. * From now on, {@link #isLocking()} will return false.
* @param point a point
* @param success success * @param success success
*/ */
void onLocked(boolean success); void onLocked(@Nullable PointF point, boolean success);
/** /**
* Notifies that locking has been undone. From now on, this locker instance * Notifies that locking has been undone. From now on, this locker instance
* is done, although in theory it could be reused by calling * is done, although in theory it could be reused by calling
* {@link #lock(CaptureResult)} again. * {@link #lock(CaptureResult, PointF)} again.
* @param point point
*/ */
void onUnlocked(); void onUnlocked(@Nullable PointF point);
/** /**
* Returns the currently used builder. This can change while a locking * Returns the currently used builder. This can change while a locking
@ -64,6 +68,7 @@ public class Locker {
private final CameraCharacteristics mCharacteristics; private final CameraCharacteristics mCharacteristics;
private final Callback mCallback; private final Callback mCallback;
private PointF mPoint;
private boolean mIsLocking; private boolean mIsLocking;
private Parameter mAutoFocus; private Parameter mAutoFocus;
private Parameter mAutoWhiteBalance; private Parameter mAutoWhiteBalance;
@ -88,10 +93,12 @@ public class Locker {
/** /**
* Locks 3A values. * Locks 3A values.
* @param lastResult the last result * @param lastResult the last result
* @param point a point
*/ */
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public void lock(@NonNull CaptureResult lastResult) { public void lock(@NonNull CaptureResult lastResult, @Nullable PointF point) {
mIsLocking = true; mIsLocking = true;
mPoint = point;
mLockingStartTime = System.currentTimeMillis(); mLockingStartTime = System.currentTimeMillis();
mAutoFocus.lock(mCharacteristics, mCallback.getLockingBuilder(), lastResult); mAutoFocus.lock(mCharacteristics, mCallback.getLockingBuilder(), lastResult);
mAutoWhiteBalance.lock(mCharacteristics, mCallback.getLockingBuilder(), lastResult); mAutoWhiteBalance.lock(mCharacteristics, mCallback.getLockingBuilder(), lastResult);
@ -100,7 +107,7 @@ public class Locker {
/** /**
* True if we're locking. False if we're not, for example * True if we're locking. False if we're not, for example
* if {@link #lock(CaptureResult)} was never called. * if {@link #lock(CaptureResult, PointF)} was never called.
* @return true if locking * @return true if locking
*/ */
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@ -134,13 +141,13 @@ public class Locker {
} }
private void dispatchEnd(boolean success) { private void dispatchEnd(boolean success) {
mCallback.onLocked(success); mCallback.onLocked(mPoint, success);
mIsLocking = false; mIsLocking = false;
} }
/** /**
* Should be called to unlock. * Should be called to unlock.
* Note that {@link Callback#onUnlocked()} will be called immediately, * Note that {@link Callback#onUnlocked(PointF)} will be called immediately,
* we're not waiting for the results. * we're not waiting for the results.
*/ */
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
@ -149,6 +156,6 @@ public class Locker {
mAutoFocus.unlock(mCharacteristics, mCallback.getLockingBuilder()); mAutoFocus.unlock(mCharacteristics, mCallback.getLockingBuilder());
mAutoExposure.unlock(mCharacteristics, mCallback.getLockingBuilder()); mAutoExposure.unlock(mCharacteristics, mCallback.getLockingBuilder());
mAutoWhiteBalance.unlock(mCharacteristics, mCallback.getLockingBuilder()); mAutoWhiteBalance.unlock(mCharacteristics, mCallback.getLockingBuilder());
mCallback.onUnlocked(); mCallback.onUnlocked(mPoint);
} }
} }

Loading…
Cancel
Save