Lock AE and AWB. Account for captureBuilder changes

pull/580/head
Mattia Iavarone 6 years ago
parent a40c91bff9
commit 883a74d1ed
  1. 37
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java
  2. 36
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/Meter.java
  3. 9
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/metering/AutoExposure.java
  4. 9
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/metering/AutoFocus.java
  5. 11
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/metering/AutoWhiteBalance.java
  6. 6
      cameraview/src/main/java/com/otaliastudios/cameraview/engine/metering/MeteringParameter.java
  7. 3
      cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full2PictureRecorder.java
  8. 46
      cameraview/src/main/java/com/otaliastudios/cameraview/picture/Snapshot2PictureRecorder.java
  9. 15
      demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java
  10. 3
      demo/src/main/res/layout/activity_camera.xml

@ -167,9 +167,10 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
@SuppressWarnings("UnusedReturnValue") @SuppressWarnings("UnusedReturnValue")
@NonNull @NonNull
private CaptureRequest.Builder createRepeatingRequestBuilder(int template) throws CameraAccessException { private CaptureRequest.Builder createRepeatingRequestBuilder(int template) throws CameraAccessException {
CaptureRequest.Builder oldBuilder = mRepeatingRequestBuilder;
mRepeatingRequestBuilder = mCamera.createCaptureRequest(template); mRepeatingRequestBuilder = mCamera.createCaptureRequest(template);
mRepeatingRequestBuilder.setTag(template); mRepeatingRequestBuilder.setTag(template);
applyAllParameters(mRepeatingRequestBuilder); applyAllParameters(mRepeatingRequestBuilder, oldBuilder);
return mRepeatingRequestBuilder; return mRepeatingRequestBuilder;
} }
@ -653,7 +654,7 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
LOG.i("onTakePicture:", "doMetering is false. Performing."); LOG.i("onTakePicture:", "doMetering is false. Performing.");
try { try {
CaptureRequest.Builder builder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); CaptureRequest.Builder builder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
applyAllParameters(builder); applyAllParameters(builder, mRepeatingRequestBuilder);
mPictureRecorder = new Full2PictureRecorder(stub, this, mPictureRecorder = new Full2PictureRecorder(stub, this,
mSession, mSession,
mRepeatingRequestCallback, mRepeatingRequestCallback,
@ -797,7 +798,9 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
//region Parameters //region Parameters
private void applyAllParameters(@NonNull CaptureRequest.Builder builder) { private void applyAllParameters(@NonNull CaptureRequest.Builder builder,
@Nullable CaptureRequest.Builder oldBuilder) {
LOG.i("applyAllParameters:", "called for tag", builder.build().getTag());
builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO); builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
applyDefaultFocus(builder); applyDefaultFocus(builder);
applyFlash(builder, Flash.OFF); applyFlash(builder, Flash.OFF);
@ -806,6 +809,18 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
applyHdr(builder, Hdr.OFF); applyHdr(builder, Hdr.OFF);
applyZoom(builder, 0F); applyZoom(builder, 0F);
applyExposureCorrection(builder, 0F); applyExposureCorrection(builder, 0F);
if (oldBuilder != null) {
// We might be in a metering operation, or the old builder might have some special
// metering parameters. Copy these special keys over to the new builder.
// These are the keys changed by MeteringParameters, or by us in applyFocusForMetering.
builder.set(CaptureRequest.CONTROL_AF_REGIONS, oldBuilder.get(CaptureRequest.CONTROL_AF_REGIONS));
builder.set(CaptureRequest.CONTROL_AE_REGIONS, oldBuilder.get(CaptureRequest.CONTROL_AE_REGIONS));
builder.set(CaptureRequest.CONTROL_AWB_REGIONS, oldBuilder.get(CaptureRequest.CONTROL_AWB_REGIONS));
builder.set(CaptureRequest.CONTROL_AE_LOCK, oldBuilder.get(CaptureRequest.CONTROL_AE_LOCK));
builder.set(CaptureRequest.CONTROL_AWB_LOCK, oldBuilder.get(CaptureRequest.CONTROL_AWB_LOCK));
builder.set(CaptureRequest.CONTROL_AF_MODE, oldBuilder.get(CaptureRequest.CONTROL_AF_MODE));
}
} }
private void applyDefaultFocus(@NonNull CaptureRequest.Builder builder) { private void applyDefaultFocus(@NonNull CaptureRequest.Builder builder) {
@ -1184,6 +1199,7 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
// Reset the old meter if present. // Reset the old meter if present.
if (mMeter != null) { if (mMeter != null) {
mMeter.resetMetering(); mMeter.resetMetering();
mMeter = null;
} }
// The meter will check the current configuration to see if AF/AE/AWB should run. // The meter will check the current configuration to see if AF/AE/AWB should run.
@ -1197,7 +1213,6 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
// Create the meter and start. // Create the meter and start.
mMeteringGesture = gesture; mMeteringGesture = gesture;
mMeter = new Meter(Camera2Engine.this, mMeter = new Meter(Camera2Engine.this,
mRepeatingRequestBuilder,
mCameraCharacteristics, mCameraCharacteristics,
Camera2Engine.this); Camera2Engine.this);
mMeter.startMetering(mLastRepeatingResult, point); mMeter.startMetering(mLastRepeatingResult, point);
@ -1214,10 +1229,10 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
@Override @Override
public void onMeteringStarted(@Nullable PointF point) { public void onMeteringStarted(@Nullable PointF point) {
LOG.w("onMeteringStarted - point:", point, "gesture:", mMeteringGesture); LOG.w("onMeteringStarted - point:", point, "gesture:", mMeteringGesture);
applyRepeatingRequestBuilder();
if (point != null) { if (point != null) {
mCallback.dispatchOnFocusStart(mMeteringGesture, point); mCallback.dispatchOnFocusStart(mMeteringGesture, point);
} }
applyRepeatingRequestBuilder();
} }
/** /**
@ -1229,6 +1244,7 @@ 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);
applyRepeatingRequestBuilder();
if (point != null) { if (point != null) {
mCallback.dispatchOnFocusEnd(mMeteringGesture, success, point); mCallback.dispatchOnFocusEnd(mMeteringGesture, success, point);
} else { } else {
@ -1257,5 +1273,16 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv
} }
} }
/**
* Called by {@link Meter} to get the current capture request
* builder so it can apply changes on it.
* @return our builder
*/
@NonNull
@Override
public CaptureRequest.Builder getMeteringBuilder() {
return mRepeatingRequestBuilder;
}
//endregion //endregion
} }

@ -70,6 +70,16 @@ public class Meter {
* *
*/ */
void onMeteringReset(@Nullable PointF point); void onMeteringReset(@Nullable PointF point);
/**
* Returns the currently used builder. This can change while a metering
* operation happens, so the meter will never cache this value.
* It is the engine responsibility to copy over values to the new builder
* when it changes.
* @return a builder
*/
@NonNull
CaptureRequest.Builder getMeteringBuilder();
} }
private static final String TAG = Meter.class.getSimpleName(); private static final String TAG = Meter.class.getSimpleName();
@ -77,7 +87,6 @@ public class Meter {
private static final int FORCED_END_DELAY = 2500; private static final int FORCED_END_DELAY = 2500;
private final CameraEngine mEngine; private final CameraEngine mEngine;
private final CaptureRequest.Builder mBuilder;
private final CameraCharacteristics mCharacteristics; private final CameraCharacteristics mCharacteristics;
private final Callback mCallback; private final Callback mCallback;
private PointF mPoint; private PointF mPoint;
@ -91,17 +100,14 @@ public class Meter {
/** /**
* Creates a new meter. * Creates a new meter.
* @param engine the engine * @param engine the engine
* @param builder a capture builder
* @param characteristics the camera characteristics * @param characteristics the camera characteristics
* @param callback the callback * @param callback the callback
*/ */
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public Meter(@NonNull CameraEngine engine, public Meter(@NonNull CameraEngine engine,
@NonNull CaptureRequest.Builder builder,
@NonNull CameraCharacteristics characteristics, @NonNull CameraCharacteristics characteristics,
@NonNull Callback callback) { @NonNull Callback callback) {
mEngine = engine; mEngine = engine;
mBuilder = builder;
mCharacteristics = characteristics; mCharacteristics = characteristics;
mCallback = callback; mCallback = callback;
} }
@ -158,9 +164,9 @@ public class Meter {
// 7. And finally dispatch everything // 7. And finally dispatch everything
boolean skipIfPossible = mPoint == null; boolean skipIfPossible = mPoint == null;
mAutoFocus.startMetering(mCharacteristics, mBuilder, areas, lastResult, skipIfPossible); mAutoFocus.startMetering(mCharacteristics, mCallback.getMeteringBuilder(), areas, lastResult, skipIfPossible);
mAutoWhiteBalance.startMetering(mCharacteristics, mBuilder, areas, lastResult, skipIfPossible); mAutoWhiteBalance.startMetering(mCharacteristics, mCallback.getMeteringBuilder(), areas, lastResult, skipIfPossible);
mAutoExposure.startMetering(mCharacteristics, mBuilder, areas, lastResult, skipIfPossible); mAutoExposure.startMetering(mCharacteristics, mCallback.getMeteringBuilder(), areas, lastResult, skipIfPossible);
// Dispatch to callback // Dispatch to callback
mCallback.onMeteringStarted(mPoint); mCallback.onMeteringStarted(mPoint);
@ -239,7 +245,7 @@ public class Meter {
// The input point and size refer to the stream rect. // The input point and size refer to the stream rect.
// The stream rect is part of the 'crop region', as described below. // The stream rect is part of the 'crop region', as described below.
// https://source.android.com/devices/camera/camera3_crop_reprocess.html // https://source.android.com/devices/camera/camera3_crop_reprocess.html
Rect cropRect = mBuilder.get(CaptureRequest.SCALER_CROP_REGION); Rect cropRect = mCallback.getMeteringBuilder().get(CaptureRequest.SCALER_CROP_REGION);
// For now, we don't care about x and y position. Rect should be non-null, but let's be safe. // For now, we don't care about x and y position. Rect should be non-null, but let's be safe.
int cropRectWidth = cropRect == null ? referenceSize.getWidth() : cropRect.width(); int cropRectWidth = cropRect == null ? referenceSize.getWidth() : cropRect.width();
int cropRectHeight = cropRect == null ? referenceSize.getHeight() : cropRect.height(); int cropRectHeight = cropRect == null ? referenceSize.getHeight() : cropRect.height();
@ -254,7 +260,7 @@ public class Meter {
private Size applyActiveArrayCoordinates(@NonNull Size referenceSize, @NonNull PointF referencePoint) { private Size applyActiveArrayCoordinates(@NonNull Size referenceSize, @NonNull PointF referencePoint) {
// The input point and size refer to the scaler crop region. // The input point and size refer to the scaler crop region.
// We can query for the crop region position inside the active array, so this is easy. // We can query for the crop region position inside the active array, so this is easy.
Rect cropRect = mBuilder.get(CaptureRequest.SCALER_CROP_REGION); Rect cropRect = mCallback.getMeteringBuilder().get(CaptureRequest.SCALER_CROP_REGION);
referencePoint.x += cropRect == null ? 0 : cropRect.left; referencePoint.x += cropRect == null ? 0 : cropRect.left;
referencePoint.y += cropRect == null ? 0 : cropRect.top; referencePoint.y += cropRect == null ? 0 : cropRect.top;
// Finally, get the active rect width and height from characteristics. // Finally, get the active rect width and height from characteristics.
@ -320,9 +326,9 @@ public class Meter {
if (!mIsMetering) return; // We're not interested in results anymore if (!mIsMetering) return; // We're not interested in results anymore
if (!(result instanceof TotalCaptureResult)) return; // Let's ignore these, contents are missing/wrong if (!(result instanceof TotalCaptureResult)) return; // Let's ignore these, contents are missing/wrong
if (!mAutoFocus.isMetered()) mAutoFocus.onCapture(result); if (!mAutoFocus.isMetered()) mAutoFocus.onCapture(mCallback.getMeteringBuilder(), result);
if (!mAutoExposure.isMetered()) mAutoExposure.onCapture(result); if (!mAutoExposure.isMetered()) mAutoExposure.onCapture(mCallback.getMeteringBuilder(), result);
if (!mAutoWhiteBalance.isMetered()) mAutoWhiteBalance.onCapture(result); if (!mAutoWhiteBalance.isMetered()) mAutoWhiteBalance.onCapture(mCallback.getMeteringBuilder(), result);
if (mAutoFocus.isMetered() && mAutoExposure.isMetered() && mAutoWhiteBalance.isMetered()) { if (mAutoFocus.isMetered() && mAutoExposure.isMetered() && mAutoWhiteBalance.isMetered()) {
LOG.i("onCapture:", "all MeteringParameters have converged. Dispatching onMeteringEnd"); LOG.i("onCapture:", "all MeteringParameters have converged. Dispatching onMeteringEnd");
boolean success = mAutoFocus.isSuccessful() boolean success = mAutoFocus.isSuccessful()
@ -359,9 +365,9 @@ public class Meter {
if (wholeRect == null) wholeRect = new Rect(); if (wholeRect == null) wholeRect = new Rect();
whole = new MeteringRectangle(wholeRect, MeteringRectangle.METERING_WEIGHT_DONT_CARE); whole = new MeteringRectangle(wholeRect, MeteringRectangle.METERING_WEIGHT_DONT_CARE);
} }
mAutoFocus.resetMetering(mCharacteristics, mBuilder, whole); mAutoFocus.resetMetering(mCharacteristics, mCallback.getMeteringBuilder(), whole);
mAutoWhiteBalance.resetMetering(mCharacteristics, mBuilder, whole); mAutoWhiteBalance.resetMetering(mCharacteristics, mCallback.getMeteringBuilder(), whole);
mAutoExposure.resetMetering(mCharacteristics, mBuilder, whole); mAutoExposure.resetMetering(mCharacteristics, mCallback.getMeteringBuilder(), whole);
mCallback.onMeteringReset(mPoint); mCallback.onMeteringReset(mPoint);
} }

@ -57,6 +57,9 @@ public class AutoExposure extends MeteringParameter {
isStarted = false; isStarted = false;
if (supportsProcessing) { if (supportsProcessing) {
// Remove any lock. This would make processing be stuck into the process method.
builder.set(CaptureRequest.CONTROL_AE_LOCK, false);
// Launch the precapture trigger.
builder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, builder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START); CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
} }
@ -96,6 +99,11 @@ public class AutoExposure extends MeteringParameter {
} }
} }
@Override
protected void onMetered(@NonNull CaptureRequest.Builder builder) {
builder.set(CaptureRequest.CONTROL_AE_LOCK, true);
}
@Override @Override
protected void onResetMetering(@NonNull CameraCharacteristics characteristics, protected void onResetMetering(@NonNull CameraCharacteristics characteristics,
@NonNull CaptureRequest.Builder builder, @NonNull CaptureRequest.Builder builder,
@ -107,6 +115,7 @@ public class AutoExposure extends MeteringParameter {
builder.set(CaptureRequest.CONTROL_AE_REGIONS, new MeteringRectangle[]{area}); builder.set(CaptureRequest.CONTROL_AE_REGIONS, new MeteringRectangle[]{area});
} }
if (supportsProcessing) { if (supportsProcessing) {
builder.set(CaptureRequest.CONTROL_AE_LOCK, false);
// Cleanup any precapture sequence. // Cleanup any precapture sequence.
if (Build.VERSION.SDK_INT >= 23) { if (Build.VERSION.SDK_INT >= 23) {
builder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, builder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,

@ -37,7 +37,9 @@ public class AutoFocus extends MeteringParameter {
@Override @Override
protected boolean checkShouldSkip(@NonNull CaptureResult lastResult) { protected boolean checkShouldSkip(@NonNull CaptureResult lastResult) {
Integer afState = lastResult.get(CaptureResult.CONTROL_AF_STATE); Integer afState = lastResult.get(CaptureResult.CONTROL_AF_STATE);
boolean result = afState != null && afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED; boolean result = afState != null &&
(afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED ||
afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED);
LOG.i("checkShouldSkip:", result); LOG.i("checkShouldSkip:", result);
return result; return result;
} }
@ -83,6 +85,11 @@ public class AutoFocus extends MeteringParameter {
} }
} }
@Override
protected void onMetered(@NonNull CaptureRequest.Builder builder) {
// Do nothing.
}
@Override @Override
protected void onResetMetering(@NonNull CameraCharacteristics characteristics, protected void onResetMetering(@NonNull CameraCharacteristics characteristics,
@NonNull CaptureRequest.Builder builder, @NonNull CaptureRequest.Builder builder,

@ -46,8 +46,7 @@ public class AutoWhiteBalance extends MeteringParameter {
@NonNull List<MeteringRectangle> areas, @NonNull List<MeteringRectangle> areas,
boolean supportsProcessing) { boolean supportsProcessing) {
if (supportsProcessing) { if (supportsProcessing) {
// Remove any lock. We're not setting any, but just in case. // Remove any lock. This would make processing be stuck into the process method.
// This would make processing be stuck into the process method.
builder.set(CaptureRequest.CONTROL_AWB_LOCK, false); builder.set(CaptureRequest.CONTROL_AWB_LOCK, false);
} }
@ -80,11 +79,19 @@ public class AutoWhiteBalance extends MeteringParameter {
} }
} }
@Override
protected void onMetered(@NonNull CaptureRequest.Builder builder) {
builder.set(CaptureRequest.CONTROL_AWB_LOCK, true);
}
@Override @Override
protected void onResetMetering(@NonNull CameraCharacteristics characteristics, protected void onResetMetering(@NonNull CameraCharacteristics characteristics,
@NonNull CaptureRequest.Builder builder, @NonNull CaptureRequest.Builder builder,
@Nullable MeteringRectangle area, @Nullable MeteringRectangle area,
boolean supportsProcessing) { boolean supportsProcessing) {
if (supportsProcessing) {
builder.set(CaptureRequest.CONTROL_AWB_LOCK, false);
}
int maxRegions = readCharacteristic(characteristics, int maxRegions = readCharacteristic(characteristics,
CameraCharacteristics.CONTROL_MAX_REGIONS_AWB, 0); CameraCharacteristics.CONTROL_MAX_REGIONS_AWB, 0);
if (area != null && maxRegions > 0) { if (area != null && maxRegions > 0) {

@ -67,13 +67,17 @@ public abstract class MeteringParameter {
@NonNull List<MeteringRectangle> areas, @NonNull List<MeteringRectangle> areas,
boolean supportsProcessing); boolean supportsProcessing);
public final void onCapture(@NonNull CaptureResult result) { public final void onCapture(@NonNull CaptureRequest.Builder builder,
@NonNull CaptureResult result) {
if (isMetered()) return; if (isMetered()) return;
processCapture(result); processCapture(result);
if (isMetered()) onMetered(builder);
} }
protected abstract void processCapture(@NonNull CaptureResult result); protected abstract void processCapture(@NonNull CaptureResult result);
protected abstract void onMetered(@NonNull CaptureRequest.Builder builder);
public final void resetMetering(@NonNull CameraCharacteristics characteristics, public final void resetMetering(@NonNull CameraCharacteristics characteristics,
@NonNull CaptureRequest.Builder builder, @NonNull CaptureRequest.Builder builder,
@Nullable MeteringRectangle area) { @Nullable MeteringRectangle area) {

@ -68,6 +68,7 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader
mState = STATE_WAITING_CAPTURE; mState = STATE_WAITING_CAPTURE;
mPictureBuilder.addTarget(mPictureReader.getSurface()); mPictureBuilder.addTarget(mPictureReader.getSurface());
mPictureBuilder.set(CaptureRequest.JPEG_ORIENTATION, mResult.rotation); mPictureBuilder.set(CaptureRequest.JPEG_ORIENTATION, mResult.rotation);
mPictureBuilder.setTag(CameraDevice.TEMPLATE_STILL_CAPTURE);
if (mStopPreviewBeforeCapture) { if (mStopPreviewBeforeCapture) {
// These two are present in official samples and are probably meant to speed things up? // These two are present in official samples and are probably meant to speed things up?
// But from my tests, they actually make everything slower. So this is disabled by default // But from my tests, they actually make everything slower. So this is disabled by default
@ -87,7 +88,7 @@ public class Full2PictureRecorder extends PictureRecorder implements ImageReader
public void onCaptureStarted(@NonNull CaptureRequest request) { public void onCaptureStarted(@NonNull CaptureRequest request) {
if (mState == STATE_WAITING_CAPTURE) { if (mState == STATE_WAITING_CAPTURE) {
if (request.getTag() == mPictureBuilder.build().getTag()) { if (request.getTag() == (Integer) CameraDevice.TEMPLATE_STILL_CAPTURE) {
dispatchOnShutter(false); dispatchOnShutter(false);
} }
} }

@ -24,7 +24,7 @@ import com.otaliastudios.cameraview.preview.RendererFrameCallback;
import com.otaliastudios.cameraview.size.AspectRatio; import com.otaliastudios.cameraview.size.AspectRatio;
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
public class Snapshot2PictureRecorder extends SnapshotGlPictureRecorder implements RendererFrameCallback { public class Snapshot2PictureRecorder extends SnapshotGlPictureRecorder {
private final static String TAG = Snapshot2PictureRecorder.class.getSimpleName(); private final static String TAG = Snapshot2PictureRecorder.class.getSimpleName();
private final static CameraLogger LOG = CameraLogger.create(TAG); private final static CameraLogger LOG = CameraLogger.create(TAG);
@ -64,6 +64,27 @@ public class Snapshot2PictureRecorder extends SnapshotGlPictureRecorder implemen
mBuilder = builder; mBuilder = builder;
} }
private final RendererFrameCallback mRendererCallback = new RendererFrameCallback() {
@Override
public void onRendererTextureCreated(int textureId) {
Snapshot2PictureRecorder.super.onRendererTextureCreated(textureId);
}
@Override
public void onRendererFilterChanged(@NonNull Filter filter) {
Snapshot2PictureRecorder.super.onRendererFilterChanged(filter);
}
@Override
public void onRendererFrame(@NonNull SurfaceTexture surfaceTexture, float scaleX, float scaleY) {
mLastFrameSurfaceTexture = surfaceTexture;
mLastFrameScaleX = scaleX;
mLastFrameScaleY = scaleY;
mLastFrameScaleEGLContext = EGL14.eglGetCurrentContext();
maybeTakeFrame();
}
};
@Override @Override
public void take() { public void take() {
if (!mEngine.getPictureSnapshotMetering()) { if (!mEngine.getPictureSnapshotMetering()) {
@ -72,7 +93,7 @@ public class Snapshot2PictureRecorder extends SnapshotGlPictureRecorder implemen
} }
LOG.i("take:", "Engine does metering, adding our CONTROL_CAPTURE_INTENT."); LOG.i("take:", "Engine does metering, adding our CONTROL_CAPTURE_INTENT.");
mPreview.addRendererFrameCallback(this); mPreview.addRendererFrameCallback(mRendererCallback);
mState = STATE_WAITING_CAPTURE; mState = STATE_WAITING_CAPTURE;
try { try {
mOldCaptureIntent = mBuilder.get(CaptureRequest.CONTROL_CAPTURE_INTENT); mOldCaptureIntent = mBuilder.get(CaptureRequest.CONTROL_CAPTURE_INTENT);
@ -86,25 +107,6 @@ public class Snapshot2PictureRecorder extends SnapshotGlPictureRecorder implemen
} }
} }
@Override
public void onRendererTextureCreated(int textureId) {
super.onRendererTextureCreated(textureId);
}
@Override
public void onRendererFilterChanged(@NonNull Filter filter) {
super.onRendererFilterChanged(filter);
}
@Override
public void onRendererFrame(@NonNull SurfaceTexture surfaceTexture, float scaleX, float scaleY) {
mLastFrameSurfaceTexture = surfaceTexture;
mLastFrameScaleX = scaleX;
mLastFrameScaleY = scaleY;
mLastFrameScaleEGLContext = EGL14.eglGetCurrentContext();
maybeTakeFrame();
}
public void onCaptureCompleted(@NonNull TotalCaptureResult result) { public void onCaptureCompleted(@NonNull TotalCaptureResult result) {
LOG.i("onCaptureCompleted:", LOG.i("onCaptureCompleted:",
"aeState:", result.get(CaptureResult.CONTROL_AE_STATE), "aeState:", result.get(CaptureResult.CONTROL_AE_STATE),
@ -158,7 +160,7 @@ public class Snapshot2PictureRecorder extends SnapshotGlPictureRecorder implemen
mSession.setRepeatingRequest(mBuilder.build(), mCallback, null); mSession.setRepeatingRequest(mBuilder.build(), mCallback, null);
} catch (CameraAccessException ignore) {} } catch (CameraAccessException ignore) {}
} }
mPreview.removeRendererFrameCallback(this); mPreview.removeRendererFrameCallback(mRendererCallback);
mState = STATE_IDLE; mState = STATE_IDLE;
super.dispatchResult(); super.dispatchResult();
} }

@ -7,11 +7,14 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.ImageFormat; import android.graphics.ImageFormat;
import android.graphics.PointF;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.YuvImage; import android.graphics.YuvImage;
import android.os.Bundle; import android.os.Bundle;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.android.material.bottomsheet.BottomSheetBehavior; import com.google.android.material.bottomsheet.BottomSheetBehavior;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import android.view.View; import android.view.View;
@ -237,6 +240,18 @@ public class CameraActivity extends AppCompatActivity implements View.OnClickLis
message("Video taken. Processing...", false); message("Video taken. Processing...", false);
LOG.w("onVideoRecordingEnd!"); LOG.w("onVideoRecordingEnd!");
} }
@Override
public void onExposureCorrectionChanged(float newValue, @NonNull float[] bounds, @Nullable PointF[] fingers) {
super.onExposureCorrectionChanged(newValue, bounds, fingers);
message("Exposure correction:" + newValue, false);
}
@Override
public void onZoomChanged(float newValue, @NonNull float[] bounds, @Nullable PointF[] fingers) {
super.onZoomChanged(newValue, bounds, fingers);
message("Zoom:" + newValue, false);
}
} }
@Override @Override

@ -20,7 +20,7 @@
app:cameraPreview="glSurface" app:cameraPreview="glSurface"
app:cameraPlaySounds="true" app:cameraPlaySounds="true"
app:cameraGrid="off" app:cameraGrid="off"
app:cameraFlash="on" app:cameraFlash="auto"
app:cameraAudio="on" app:cameraAudio="on"
app:cameraFacing="back" app:cameraFacing="back"
app:cameraGestureTap="autoFocus" app:cameraGestureTap="autoFocus"
@ -29,7 +29,6 @@
app:cameraGestureScrollHorizontal="filterControl1" app:cameraGestureScrollHorizontal="filterControl1"
app:cameraGestureScrollVertical="exposureCorrection" app:cameraGestureScrollVertical="exposureCorrection"
app:cameraMode="picture" app:cameraMode="picture"
app:cameraPictureSnapshotMetering="true"
app:cameraAutoFocusMarker="@string/cameraview_default_autofocus_marker"> app:cameraAutoFocusMarker="@string/cameraview_default_autofocus_marker">
<!-- Watermark --> <!-- Watermark -->

Loading…
Cancel
Save