allow disabling overlay in pictures or videos

pull/421/head
Giacomo Randazzo 7 years ago
parent 86a7a0f1f3
commit c3371022e7
  1. 11
      cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java
  2. 8
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java
  3. 23
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraOptions.java
  4. 31
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
  5. 5
      cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotPictureRecorder.java
  6. 9
      cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotVideoRecorder.java
  7. 55
      cameraview/src/main/options/com/otaliastudios/cameraview/DisableOverlayFor.java
  8. 8
      cameraview/src/main/res/values/attrs.xml
  9. 7
      demo/src/main/res/layout/activity_camera.xml

@ -477,6 +477,15 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
return false; 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. // Choose the best default focus, based on session type.
private void applyDefaultFocus(@NonNull Camera.Parameters params) { private void applyDefaultFocus(@NonNull Camera.Parameters params) {
@ -744,7 +753,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
// Reset facing and start. // Reset facing and start.
mFacing = realFacing; mFacing = realFacing;
GlCameraPreview cameraPreview = (GlCameraPreview) mPreview; GlCameraPreview cameraPreview = (GlCameraPreview) mPreview;
mVideoRecorder = new SnapshotVideoRecorder(videoResult, Camera1.this, cameraPreview); mVideoRecorder = new SnapshotVideoRecorder(videoResult, Camera1.this, cameraPreview, mDisableOverlayFor != DisableOverlayFor.VIDEO);
mVideoRecorder.start(); mVideoRecorder.start();
} }
}); });

@ -48,6 +48,7 @@ abstract class CameraController implements
protected float mZoomValue; protected float mZoomValue;
protected float mExposureCorrectionValue; protected float mExposureCorrectionValue;
protected boolean mPlaySounds; protected boolean mPlaySounds;
protected DisableOverlayFor mDisableOverlayFor;
@Nullable private SizeSelector mPreviewSizeSelector; @Nullable private SizeSelector mPreviewSizeSelector;
private SizeSelector mPictureSizeSelector; private SizeSelector mPictureSizeSelector;
@ -356,6 +357,8 @@ abstract class CameraController implements
abstract void setPlaySounds(boolean playSounds); abstract void setPlaySounds(boolean playSounds);
abstract void setDisableOverlayFor(@NonNull DisableOverlayFor disableOverlayFor);
//endregion //endregion
//region final getters //region final getters
@ -451,6 +454,11 @@ abstract class CameraController implements
return mPictureRecorder != null; return mPictureRecorder != null;
} }
@NonNull
final DisableOverlayFor getDisableOverlayFor() {
return mDisableOverlayFor;
}
//endregion //endregion
//region Orientation utils //region Orientation utils

@ -26,6 +26,7 @@ public class CameraOptions {
private Set<Size> supportedVideoSizes = new HashSet<>(5); private Set<Size> supportedVideoSizes = new HashSet<>(5);
private Set<AspectRatio> supportedPictureAspectRatio = new HashSet<>(4); private Set<AspectRatio> supportedPictureAspectRatio = new HashSet<>(4);
private Set<AspectRatio> supportedVideoAspectRatio = new HashSet<>(3); private Set<AspectRatio> supportedVideoAspectRatio = new HashSet<>(3);
private Set<DisableOverlayFor> supportedDisableOverlayFor = new HashSet<>(3);
private boolean zoomSupported; private boolean zoomSupported;
private boolean exposureCorrectionSupported; private boolean exposureCorrectionSupported;
@ -104,6 +105,12 @@ public class CameraOptions {
supportedVideoAspectRatio.add(AspectRatio.of(width, height)); 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<T>) Arrays.asList(VideoCodec.values()); return (Collection<T>) Arrays.asList(VideoCodec.values());
} else if (controlClass.equals(WhiteBalance.class)) { } else if (controlClass.equals(WhiteBalance.class)) {
return (Collection<T>) getSupportedWhiteBalance(); return (Collection<T>) getSupportedWhiteBalance();
} else if (controlClass.equals(DisableOverlayFor.class)) {
return (Collection<T>) getSupportedDisableOverlayFor();
} }
// Unrecognized control. // Unrecognized control.
return Collections.emptyList(); return Collections.emptyList();
@ -341,4 +350,18 @@ public class CameraOptions {
public float getExposureCorrectionMaxValue() { public float getExposureCorrectionMaxValue() {
return exposureCorrectionMaxValue; 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<DisableOverlayFor> getSupportedDisableOverlayFor() {
return Collections.unmodifiableSet(supportedDisableOverlayFor);
}
} }

@ -24,7 +24,6 @@ import androidx.annotation.ColorInt;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.Surface; import android.view.Surface;
import android.view.View; 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 videoMaxDuration = a.getInteger(R.styleable.CameraView_cameraVideoMaxDuration, 0);
int videoBitRate = a.getInteger(R.styleable.CameraView_cameraVideoBitRate, 0); int videoBitRate = a.getInteger(R.styleable.CameraView_cameraVideoBitRate, 0);
int audioBitRate = a.getInteger(R.styleable.CameraView_cameraAudioBitRate, 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 // Picture size selector
List<SizeSelector> pictureConstraints = new ArrayList<>(3); List<SizeSelector> pictureConstraints = new ArrayList<>(3);
@ -227,6 +227,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
setVideoMaxSize(videoMaxSize); setVideoMaxSize(videoMaxSize);
setVideoMaxDuration(videoMaxDuration); setVideoMaxDuration(videoMaxDuration);
setVideoBitRate(videoBitRate); setVideoBitRate(videoBitRate);
setDisableOverlayFor(disableOverlayFor);
// Apply gestures // Apply gestures
mapGesture(Gesture.TAP, tapGesture); mapGesture(Gesture.TAP, tapGesture);
@ -782,6 +783,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
setVideoCodec((VideoCodec) control); setVideoCodec((VideoCodec) control);
} else if (control instanceof Preview) { } else if (control instanceof Preview) {
setPreview((Preview) control); 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(); 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 //endregion
//region Callbacks and dispatching //region Callbacks and dispatching
@ -1915,7 +1942,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
private void readStyleParameters(Context context, AttributeSet attributeSet) { private void readStyleParameters(Context context, AttributeSet attributeSet) {
TypedArray a = context.obtainStyledAttributes(attributeSet, R.styleable.CameraView_Layout); TypedArray a = context.obtainStyledAttributes(attributeSet, R.styleable.CameraView_Layout);
try { try {
this.isOverlay = a.getBoolean(R.styleable.CameraView_Layout_layout_overlay, false); this.isOverlay = a.getBoolean(R.styleable.CameraView_Layout_layout_isOverlay, false);
} finally { } finally {
a.recycle(); a.recycle();
} }

@ -31,6 +31,8 @@ class SnapshotPictureRecorder extends PictureRecorder {
private Size mSensorPreviewSize; private Size mSensorPreviewSize;
private int mFormat; private int mFormat;
private boolean mWithOverlay;
SnapshotPictureRecorder(@NonNull PictureResult stub, @NonNull Camera1 controller, SnapshotPictureRecorder(@NonNull PictureResult stub, @NonNull Camera1 controller,
@NonNull Camera camera, @NonNull AspectRatio outputRatio) { @NonNull Camera camera, @NonNull AspectRatio outputRatio) {
super(stub, controller); super(stub, controller);
@ -40,6 +42,7 @@ class SnapshotPictureRecorder extends PictureRecorder {
mOutputRatio = outputRatio; mOutputRatio = outputRatio;
mFormat = mController.mPreviewFormat; mFormat = mController.mPreviewFormat;
mSensorPreviewSize = mController.mPreviewSize; mSensorPreviewSize = mController.mPreviewSize;
mWithOverlay = mController.mDisableOverlayFor != DisableOverlayFor.PICTURE;
} }
@Override @Override
@ -65,7 +68,7 @@ class SnapshotPictureRecorder extends PictureRecorder {
@RendererThread @RendererThread
public void onRendererTextureCreated(int... textureIds) { public void onRendererTextureCreated(int... textureIds) {
mTextureId = textureIds[0]; mTextureId = textureIds[0];
if (textureIds.length > 1) { if (textureIds.length > 1 && mWithOverlay) {
mOverlayTextureId = textureIds[1]; mOverlayTextureId = textureIds[1];
} }
mSurfaceTexture = new SurfaceTexture(mTextureId, true); mSurfaceTexture = new SurfaceTexture(mTextureId, true);

@ -33,10 +33,13 @@ class SnapshotVideoRecorder extends VideoRecorder implements GlCameraPreview.Ren
private int mTextureId = 0; private int mTextureId = 0;
private int mOverlayTextureId = 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); super(stub, listener);
mPreview = preview; mPreview = preview;
mPreview.addRendererFrameCallback(this); mPreview.addRendererFrameCallback(this);
mWithOverlay = withOverlay;
} }
@Override @Override
@ -83,7 +86,7 @@ class SnapshotVideoRecorder extends VideoRecorder implements GlCameraPreview.Ren
mResult.videoFrameRate, mResult.videoFrameRate,
mResult.rotation, mResult.rotation,
type, mTextureId, type, mTextureId,
mOverlayTextureId, mWithOverlay ? mOverlayTextureId : 0,
scaleX, scaleY, scaleX, scaleY,
mPreview.mInputFlipped, mPreview.mInputFlipped,
EGL14.eglGetCurrentContext() 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.transform = new float[16]; // TODO would be cool to avoid this at every frame. But it's not easy.
frame.overlayTransform = new float[16]; frame.overlayTransform = new float[16];
surfaceTexture.getTransformMatrix(frame.transform); surfaceTexture.getTransformMatrix(frame.transform);
if (overlaySurfaceTexture != null) { if (mWithOverlay && overlaySurfaceTexture != null) {
overlaySurfaceTexture.getTransformMatrix(frame.overlayTransform); overlaySurfaceTexture.getTransformMatrix(frame.overlayTransform);
} }
mEncoderEngine.notify(TextureMediaEncoder.FRAME_EVENT, frame); mEncoderEngine.notify(TextureMediaEncoder.FRAME_EVENT, frame);

@ -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;
}
}

@ -121,11 +121,17 @@
<attr name="cameraExperimental" format="boolean" /> <attr name="cameraExperimental" format="boolean" />
<attr name="cameraDisableOverlayFor" format="enum">
<enum name="none" value="0" />
<enum name="picture" value="1" />
<enum name="video" value="2" />
</attr>
</declare-styleable> </declare-styleable>
<declare-styleable name="CameraView_Layout"> <declare-styleable name="CameraView_Layout">
<attr name="layout_overlay" format="boolean"/> <attr name="layout_isOverlay" format="boolean"/>
</declare-styleable> </declare-styleable>
</resources> </resources>

@ -26,15 +26,16 @@
app:cameraGesturePinch="zoom" app:cameraGesturePinch="zoom"
app:cameraGestureScrollHorizontal="exposureCorrection" app:cameraGestureScrollHorizontal="exposureCorrection"
app:cameraGestureScrollVertical="none" app:cameraGestureScrollVertical="none"
app:cameraMode="picture"> app:cameraMode="picture"
app:cameraDisableOverlayFor="none">
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Ciao" android:text="Ciao ciao"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:layout_gravity="bottom|end" android:layout_gravity="bottom|end"
app:layout_overlay="true" app:layout_isOverlay="true"
/> />
</com.otaliastudios.cameraview.CameraView> </com.otaliastudios.cameraview.CameraView>

Loading…
Cancel
Save