From c3371022e73dc71be3c9a8ef3ee24f46d4fc8ca6 Mon Sep 17 00:00:00 2001 From: Giacomo Randazzo Date: Sun, 20 Jan 2019 17:09:41 +0100 Subject: [PATCH] allow disabling overlay in pictures or videos --- .../com/otaliastudios/cameraview/Camera1.java | 11 +++- .../cameraview/CameraController.java | 8 +++ .../cameraview/CameraOptions.java | 23 ++++++++ .../otaliastudios/cameraview/CameraView.java | 31 ++++++++++- .../cameraview/SnapshotPictureRecorder.java | 5 +- .../cameraview/SnapshotVideoRecorder.java | 9 ++- .../cameraview/DisableOverlayFor.java | 55 +++++++++++++++++++ cameraview/src/main/res/values/attrs.xml | 8 ++- demo/src/main/res/layout/activity_camera.xml | 7 ++- 9 files changed, 146 insertions(+), 11 deletions(-) create mode 100644 cameraview/src/main/options/com/otaliastudios/cameraview/DisableOverlayFor.java diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java index 3e34236b..bf0e5617 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java @@ -477,6 +477,15 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera return false; } + @Override + void setDisableOverlayFor(@NonNull DisableOverlayFor disableOverlayFor) { + if (mDisableOverlayFor != disableOverlayFor) { + LOG.w("DisableOverlayFor setting was changed while recording. " + + "Changes will take place starting from next video/picture."); + mDisableOverlayFor = disableOverlayFor; + } + } + // Choose the best default focus, based on session type. private void applyDefaultFocus(@NonNull Camera.Parameters params) { @@ -744,7 +753,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera // Reset facing and start. mFacing = realFacing; GlCameraPreview cameraPreview = (GlCameraPreview) mPreview; - mVideoRecorder = new SnapshotVideoRecorder(videoResult, Camera1.this, cameraPreview); + mVideoRecorder = new SnapshotVideoRecorder(videoResult, Camera1.this, cameraPreview, mDisableOverlayFor != DisableOverlayFor.VIDEO); mVideoRecorder.start(); } }); diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java index f283e5af..07e6bb72 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java @@ -48,6 +48,7 @@ abstract class CameraController implements protected float mZoomValue; protected float mExposureCorrectionValue; protected boolean mPlaySounds; + protected DisableOverlayFor mDisableOverlayFor; @Nullable private SizeSelector mPreviewSizeSelector; private SizeSelector mPictureSizeSelector; @@ -356,6 +357,8 @@ abstract class CameraController implements abstract void setPlaySounds(boolean playSounds); + abstract void setDisableOverlayFor(@NonNull DisableOverlayFor disableOverlayFor); + //endregion //region final getters @@ -451,6 +454,11 @@ abstract class CameraController implements return mPictureRecorder != null; } + @NonNull + final DisableOverlayFor getDisableOverlayFor() { + return mDisableOverlayFor; + } + //endregion //region Orientation utils diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraOptions.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraOptions.java index 8042c505..1fabc8dc 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraOptions.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraOptions.java @@ -26,6 +26,7 @@ public class CameraOptions { private Set supportedVideoSizes = new HashSet<>(5); private Set supportedPictureAspectRatio = new HashSet<>(4); private Set supportedVideoAspectRatio = new HashSet<>(3); + private Set supportedDisableOverlayFor = new HashSet<>(3); private boolean zoomSupported; private boolean exposureCorrectionSupported; @@ -104,6 +105,12 @@ public class CameraOptions { supportedVideoAspectRatio.add(AspectRatio.of(width, height)); } } + + + // Disable overlay for + supportedDisableOverlayFor.add(DisableOverlayFor.NONE); + supportedDisableOverlayFor.add(DisableOverlayFor.PICTURE); + supportedDisableOverlayFor.add(DisableOverlayFor.VIDEO); } @@ -166,6 +173,8 @@ public class CameraOptions { return (Collection) Arrays.asList(VideoCodec.values()); } else if (controlClass.equals(WhiteBalance.class)) { return (Collection) getSupportedWhiteBalance(); + } else if (controlClass.equals(DisableOverlayFor.class)) { + return (Collection) getSupportedDisableOverlayFor(); } // Unrecognized control. return Collections.emptyList(); @@ -341,4 +350,18 @@ public class CameraOptions { public float getExposureCorrectionMaxValue() { return exposureCorrectionMaxValue; } + + /** + * Set of supported mode values for which the overlay can be disabled. + * + * @see DisableOverlayFor#NONE + * @see DisableOverlayFor#PICTURE + * @see DisableOverlayFor#VIDEO + * @return a collection of supported values. + */ + @SuppressWarnings("WeakerAccess") + @NonNull + public Collection getSupportedDisableOverlayFor() { + return Collections.unmodifiableSet(supportedDisableOverlayFor); + } } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index e576cf4e..6a660594 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -24,7 +24,6 @@ import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import android.util.AttributeSet; -import android.util.Log; import android.view.MotionEvent; import android.view.Surface; import android.view.View; @@ -121,6 +120,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { int videoMaxDuration = a.getInteger(R.styleable.CameraView_cameraVideoMaxDuration, 0); int videoBitRate = a.getInteger(R.styleable.CameraView_cameraVideoBitRate, 0); int audioBitRate = a.getInteger(R.styleable.CameraView_cameraAudioBitRate, 0); + DisableOverlayFor disableOverlayFor = DisableOverlayFor.fromValue(a.getInteger(R.styleable.CameraView_cameraDisableOverlayFor, DisableOverlayFor.DEFAULT.value())); // Picture size selector List pictureConstraints = new ArrayList<>(3); @@ -227,6 +227,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { setVideoMaxSize(videoMaxSize); setVideoMaxDuration(videoMaxDuration); setVideoBitRate(videoBitRate); + setDisableOverlayFor(disableOverlayFor); // Apply gestures mapGesture(Gesture.TAP, tapGesture); @@ -782,6 +783,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver { setVideoCodec((VideoCodec) control); } else if (control instanceof Preview) { setPreview((Preview) control); + } else if (control instanceof DisableOverlayFor) { + setDisableOverlayFor((DisableOverlayFor) control); } } @@ -1678,6 +1681,30 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraController.isTakingPicture(); } + + /** + * Sets the mode where the overlay is disabled. + * + * @see DisableOverlayFor#NONE + * @see DisableOverlayFor#PICTURE + * @see DisableOverlayFor#VIDEO + + * @param mode desired mode. + */ + public void setDisableOverlayFor(@NonNull DisableOverlayFor mode) { + mCameraController.setDisableOverlayFor(mode); + } + + + /** + * Gets the current mode where the overlay is disabled. + * @return a mode + */ + @NonNull + public DisableOverlayFor getDisableOverlayFor() { + return mCameraController.getDisableOverlayFor(); + } + //endregion //region Callbacks and dispatching @@ -1915,7 +1942,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { private void readStyleParameters(Context context, AttributeSet attributeSet) { TypedArray a = context.obtainStyledAttributes(attributeSet, R.styleable.CameraView_Layout); try { - this.isOverlay = a.getBoolean(R.styleable.CameraView_Layout_layout_overlay, false); + this.isOverlay = a.getBoolean(R.styleable.CameraView_Layout_layout_isOverlay, false); } finally { a.recycle(); } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotPictureRecorder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotPictureRecorder.java index 22990200..55ae9a41 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotPictureRecorder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotPictureRecorder.java @@ -31,6 +31,8 @@ class SnapshotPictureRecorder extends PictureRecorder { private Size mSensorPreviewSize; private int mFormat; + private boolean mWithOverlay; + SnapshotPictureRecorder(@NonNull PictureResult stub, @NonNull Camera1 controller, @NonNull Camera camera, @NonNull AspectRatio outputRatio) { super(stub, controller); @@ -40,6 +42,7 @@ class SnapshotPictureRecorder extends PictureRecorder { mOutputRatio = outputRatio; mFormat = mController.mPreviewFormat; mSensorPreviewSize = mController.mPreviewSize; + mWithOverlay = mController.mDisableOverlayFor != DisableOverlayFor.PICTURE; } @Override @@ -65,7 +68,7 @@ class SnapshotPictureRecorder extends PictureRecorder { @RendererThread public void onRendererTextureCreated(int... textureIds) { mTextureId = textureIds[0]; - if (textureIds.length > 1) { + if (textureIds.length > 1 && mWithOverlay) { mOverlayTextureId = textureIds[1]; } mSurfaceTexture = new SurfaceTexture(mTextureId, true); diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotVideoRecorder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotVideoRecorder.java index 9cf92952..11e1d1c4 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotVideoRecorder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotVideoRecorder.java @@ -33,10 +33,13 @@ class SnapshotVideoRecorder extends VideoRecorder implements GlCameraPreview.Ren private int mTextureId = 0; private int mOverlayTextureId = 0; - SnapshotVideoRecorder(@NonNull VideoResult stub, @Nullable VideoResultListener listener, @NonNull GlCameraPreview preview) { + private boolean mWithOverlay; + + SnapshotVideoRecorder(@NonNull VideoResult stub, @Nullable VideoResultListener listener, @NonNull GlCameraPreview preview, boolean withOverlay) { super(stub, listener); mPreview = preview; mPreview.addRendererFrameCallback(this); + mWithOverlay = withOverlay; } @Override @@ -83,7 +86,7 @@ class SnapshotVideoRecorder extends VideoRecorder implements GlCameraPreview.Ren mResult.videoFrameRate, mResult.rotation, type, mTextureId, - mOverlayTextureId, + mWithOverlay ? mOverlayTextureId : 0, scaleX, scaleY, mPreview.mInputFlipped, EGL14.eglGetCurrentContext() @@ -106,7 +109,7 @@ class SnapshotVideoRecorder extends VideoRecorder implements GlCameraPreview.Ren frame.transform = new float[16]; // TODO would be cool to avoid this at every frame. But it's not easy. frame.overlayTransform = new float[16]; surfaceTexture.getTransformMatrix(frame.transform); - if (overlaySurfaceTexture != null) { + if (mWithOverlay && overlaySurfaceTexture != null) { overlaySurfaceTexture.getTransformMatrix(frame.overlayTransform); } mEncoderEngine.notify(TextureMediaEncoder.FRAME_EVENT, frame); diff --git a/cameraview/src/main/options/com/otaliastudios/cameraview/DisableOverlayFor.java b/cameraview/src/main/options/com/otaliastudios/cameraview/DisableOverlayFor.java new file mode 100644 index 00000000..85116214 --- /dev/null +++ b/cameraview/src/main/options/com/otaliastudios/cameraview/DisableOverlayFor.java @@ -0,0 +1,55 @@ +package com.otaliastudios.cameraview; + + +import androidx.annotation.Nullable; + +/** + * DisableOverlayFor value allow the user to prevent the overlay from being recorded. + * + * @see CameraView#setDisableOverlayFor(DisableOverlayFor) + */ +public enum DisableOverlayFor implements Control { + + /** + * Record the overlay both in picture and video snapshots. + */ + NONE(0), + + /** + * The picture snapshots will not contain the overlay. + * + * @see CameraOptions#getSupportedDisableOverlayFor() + */ + PICTURE(1), + + + /** + * The picture snapshots will not contain the overlay. + * + * @see CameraOptions#getSupportedDisableOverlayFor() + */ + VIDEO(2); + + static final DisableOverlayFor DEFAULT = NONE; + + private int value; + + DisableOverlayFor(int value) { + this.value = value; + } + + int value() { + return value; + } + + @Nullable + static DisableOverlayFor fromValue(int value) { + DisableOverlayFor[] list = DisableOverlayFor.values(); + for (DisableOverlayFor action : list) { + if (action.value() == value) { + return action; + } + } + return null; + } +} diff --git a/cameraview/src/main/res/values/attrs.xml b/cameraview/src/main/res/values/attrs.xml index cb629d59..73f97bbc 100644 --- a/cameraview/src/main/res/values/attrs.xml +++ b/cameraview/src/main/res/values/attrs.xml @@ -121,11 +121,17 @@ + + + + + + - + \ No newline at end of file diff --git a/demo/src/main/res/layout/activity_camera.xml b/demo/src/main/res/layout/activity_camera.xml index f93f4939..082afb06 100644 --- a/demo/src/main/res/layout/activity_camera.xml +++ b/demo/src/main/res/layout/activity_camera.xml @@ -26,15 +26,16 @@ app:cameraGesturePinch="zoom" app:cameraGestureScrollHorizontal="exposureCorrection" app:cameraGestureScrollVertical="none" - app:cameraMode="picture"> + app:cameraMode="picture" + app:cameraDisableOverlayFor="none">