From f70ee53a333960c19b6475359beb55799d0e69ff Mon Sep 17 00:00:00 2001 From: "alexander.melnikov" Date: Thu, 12 Mar 2020 17:41:26 +0300 Subject: [PATCH 1/4] Tried change switch mode without restart for Engine 1. --- .../otaliastudios/cameraview/CameraView.java | 7 +++++- .../cameraview/engine/Camera1Engine.java | 22 +++++++++++++++++++ .../cameraview/engine/Camera2Engine.java | 7 ++++++ .../cameraview/engine/CameraBaseEngine.java | 10 +++++++-- .../cameraview/engine/CameraEngine.java | 2 +- 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index 07c1d6b4f..c018988a1 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -159,6 +159,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { @SuppressWarnings({"FieldCanBeLocal", "unused"}) private boolean mExperimental; private boolean mInEditor; + private boolean mChangeModeWithoutRestart; // Overlays @VisibleForTesting OverlayLayout mOverlayLayout; @@ -869,6 +870,10 @@ public void setExperimental(boolean experimental) { mExperimental = experimental; } + public void setChangeModeWithoutRestart(boolean changeModeWithoutRestart) { + mChangeModeWithoutRestart = changeModeWithoutRestart; + } + /** * Shorthand for the appropriate set* method. * For example, if control is a {@link Grid}, this calls {@link #setGrid(Grid)}. @@ -1420,7 +1425,7 @@ public void setPreviewStreamSize(@NonNull SizeSelector selector) { * @param mode desired session type. */ public void setMode(@NonNull Mode mode) { - mCameraEngine.setMode(mode); + mCameraEngine.setMode(mode, mChangeModeWithoutRestart); } /** diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java index 95549c648..7c6ad4e26 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java @@ -145,6 +145,28 @@ protected boolean collectCameraInfo(@NonNull Facing facing) { return false; } + @EngineThread + @Override + protected void prepareNewMode() { + mCaptureSize = computeCaptureSize(); + Camera.Parameters params = mCamera.getParameters(); + if (getMode() == Mode.PICTURE) { + // setPictureSize is allowed during preview + params.setPictureSize(mCaptureSize.getWidth(), mCaptureSize.getHeight()); + } else { + // mCaptureSize in this case is a video size. The available video sizes are not + // necessarily a subset of the picture sizes, so we can't use the mCaptureSize value: + // it might crash. However, the setPictureSize() passed here is useless : we don't allow + // HQ pictures in video mode. + // While this might be lifted in the future, for now, just use a picture capture size. + Size pictureSize = computeCaptureSize(Mode.PICTURE); + params.setPictureSize(pictureSize.getWidth(), pictureSize.getHeight()); + } + applyDefaultFocus(params); + params.setRecordingHint(getMode() == Mode.VIDEO); + mCamera.setParameters(params); + } + //endregion //region Start diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java index 7e09f5884..a00504f12 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java @@ -389,6 +389,13 @@ protected final boolean collectCameraInfo(@NonNull Facing facing) { return false; } + @EngineThread + @Override + protected void prepareNewMode() { + LOG.w("prepareNewMode:", "can't prepare new mode without restart for Engine2"); + restart(); + } + //endregion //region Start diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java index df95098f3..398de4156 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java @@ -383,19 +383,25 @@ public final Audio getAudio() { * @param mode desired mode. */ @Override - public final void setMode(@NonNull Mode mode) { + public final void setMode(@NonNull Mode mode, final boolean withoutRestart) { if (mode != mMode) { mMode = mode; getOrchestrator().scheduleStateful("mode", CameraState.ENGINE, new Runnable() { @Override public void run() { - restart(); + if (withoutRestart) { + prepareNewMode(); + } else { + restart(); + } } }); } } + protected abstract void prepareNewMode(); + @NonNull @Override public final Mode getMode() { diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java index 2817bbdb4..967ef6cff 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java @@ -664,7 +664,7 @@ public final void onSurfaceDestroyed() { public abstract void setAudio(@NonNull Audio audio); @NonNull public abstract Audio getAudio(); - public abstract void setMode(@NonNull Mode mode); + public abstract void setMode(@NonNull Mode mode, boolean withoutRestart); @NonNull public abstract Mode getMode(); public abstract void setZoom(float zoom, @Nullable PointF[] points, boolean notify); From 17439581a94af6abe6a363b61f0a8f3992418ab1 Mon Sep 17 00:00:00 2001 From: "alexander.melnikov" Date: Mon, 23 Mar 2020 11:40:03 +0300 Subject: [PATCH 2/4] Small refactoring --- .../otaliastudios/cameraview/CameraView.java | 5 ++++ .../cameraview/engine/Camera1Engine.java | 26 ++----------------- .../cameraview/engine/CameraBaseEngine.java | 16 ++++++++++++ 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index c018988a1..4514624be 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -870,6 +870,11 @@ public void setExperimental(boolean experimental) { mExperimental = experimental; } + /** + * Sets the flag if you want disable restart camera on change mode (Photo/Video), + * but only for {@link Engine#CAMERA1} + * @param changeModeWithoutRestart - true if you want disable restart + */ public void setChangeModeWithoutRestart(boolean changeModeWithoutRestart) { mChangeModeWithoutRestart = changeModeWithoutRestart; } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java index 7c6ad4e26..e61ec24b8 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java @@ -150,18 +150,7 @@ protected boolean collectCameraInfo(@NonNull Facing facing) { protected void prepareNewMode() { mCaptureSize = computeCaptureSize(); Camera.Parameters params = mCamera.getParameters(); - if (getMode() == Mode.PICTURE) { - // setPictureSize is allowed during preview - params.setPictureSize(mCaptureSize.getWidth(), mCaptureSize.getHeight()); - } else { - // mCaptureSize in this case is a video size. The available video sizes are not - // necessarily a subset of the picture sizes, so we can't use the mCaptureSize value: - // it might crash. However, the setPictureSize() passed here is useless : we don't allow - // HQ pictures in video mode. - // While this might be lifted in the future, for now, just use a picture capture size. - Size pictureSize = computeCaptureSize(Mode.PICTURE); - params.setPictureSize(pictureSize.getWidth(), pictureSize.getHeight()); - } + setPictureSize(params); applyDefaultFocus(params); params.setRecordingHint(getMode() == Mode.VIDEO); mCamera.setParameters(params); @@ -238,18 +227,7 @@ protected Task onStartPreview() { params.setPreviewFormat(ImageFormat.NV21); // setPreviewSize is not allowed during preview params.setPreviewSize(mPreviewStreamSize.getWidth(), mPreviewStreamSize.getHeight()); - if (getMode() == Mode.PICTURE) { - // setPictureSize is allowed during preview - params.setPictureSize(mCaptureSize.getWidth(), mCaptureSize.getHeight()); - } else { - // mCaptureSize in this case is a video size. The available video sizes are not - // necessarily a subset of the picture sizes, so we can't use the mCaptureSize value: - // it might crash. However, the setPictureSize() passed here is useless : we don't allow - // HQ pictures in video mode. - // While this might be lifted in the future, for now, just use a picture capture size. - Size pictureSize = computeCaptureSize(Mode.PICTURE); - params.setPictureSize(pictureSize.getWidth(), pictureSize.getHeight()); - } + setPictureSize(params); mCamera.setParameters(params); mCamera.setPreviewCallbackWithBuffer(null); // Release anything left diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java index 398de4156..1c1ac52de 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java @@ -2,6 +2,7 @@ import android.graphics.PointF; import android.graphics.RectF; +import android.hardware.Camera; import android.location.Location; import androidx.annotation.CallSuper; @@ -756,6 +757,21 @@ private Size getPreviewSurfaceSize(@NonNull Reference reference) { : preview.getSurfaceSize(); } + void setPictureSize(Camera.Parameters params) { + if (getMode() == Mode.PICTURE) { + // setPictureSize is allowed during preview + params.setPictureSize(mCaptureSize.getWidth(), mCaptureSize.getHeight()); + } else { + // mCaptureSize in this case is a video size. The available video sizes are not + // necessarily a subset of the picture sizes, so we can't use the mCaptureSize value: + // it might crash. However, the setPictureSize() passed here is useless : we don't allow + // HQ pictures in video mode. + // While this might be lifted in the future, for now, just use a picture capture size. + Size pictureSize = computeCaptureSize(Mode.PICTURE); + params.setPictureSize(pictureSize.getWidth(), pictureSize.getHeight()); + } + } + /** * Returns the snapshot size, but not cropped with the view dimensions, which * is what we will do before creating the snapshot. However, cropping is done at various From 3b28133623280c7ac17aa0c15737e669378c85b4 Mon Sep 17 00:00:00 2001 From: "alexander.melnikov" Date: Thu, 26 Mar 2020 11:25:59 +0300 Subject: [PATCH 3/4] Added smarter logic for understand that need restart camera or preview when we switch mode --- .../otaliastudios/cameraview/CameraView.java | 12 +-------- .../cameraview/engine/Camera1Engine.java | 26 +++++++++++++++---- .../cameraview/engine/Camera2Engine.java | 2 +- .../cameraview/engine/CameraBaseEngine.java | 8 ++---- .../cameraview/engine/CameraEngine.java | 2 +- 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index 4514624be..07c1d6b4f 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -159,7 +159,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { @SuppressWarnings({"FieldCanBeLocal", "unused"}) private boolean mExperimental; private boolean mInEditor; - private boolean mChangeModeWithoutRestart; // Overlays @VisibleForTesting OverlayLayout mOverlayLayout; @@ -870,15 +869,6 @@ public void setExperimental(boolean experimental) { mExperimental = experimental; } - /** - * Sets the flag if you want disable restart camera on change mode (Photo/Video), - * but only for {@link Engine#CAMERA1} - * @param changeModeWithoutRestart - true if you want disable restart - */ - public void setChangeModeWithoutRestart(boolean changeModeWithoutRestart) { - mChangeModeWithoutRestart = changeModeWithoutRestart; - } - /** * Shorthand for the appropriate set* method. * For example, if control is a {@link Grid}, this calls {@link #setGrid(Grid)}. @@ -1430,7 +1420,7 @@ public void setPreviewStreamSize(@NonNull SizeSelector selector) { * @param mode desired session type. */ public void setMode(@NonNull Mode mode) { - mCameraEngine.setMode(mode, mChangeModeWithoutRestart); + mCameraEngine.setMode(mode); } /** diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java index e61ec24b8..90684e5a4 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java @@ -148,12 +148,28 @@ protected boolean collectCameraInfo(@NonNull Facing facing) { @EngineThread @Override protected void prepareNewMode() { + if(previewAspectRatioEqualsForModes()) { + Camera.Parameters params = mCamera.getParameters(); + setPictureSize(params); + applyDefaultFocus(params); + params.setRecordingHint(getMode() == Mode.VIDEO); + mCamera.setParameters(params); + } else { + restartBind(); + } + } + + private boolean previewAspectRatioEqualsForModes() { + Size prevModeSize = mCaptureSize; mCaptureSize = computeCaptureSize(); - Camera.Parameters params = mCamera.getParameters(); - setPictureSize(params); - applyDefaultFocus(params); - params.setRecordingHint(getMode() == Mode.VIDEO); - mCamera.setParameters(params); + + boolean flip = getAngles().flip(Reference.SENSOR, Reference.VIEW); + AspectRatio prevModePreviewTargetRatio = AspectRatio.of(prevModeSize.getWidth(), prevModeSize.getHeight()); + AspectRatio targetRatio = AspectRatio.of(mCaptureSize.getWidth(), mCaptureSize.getHeight()); + if (flip) prevModePreviewTargetRatio = prevModePreviewTargetRatio.flip(); + if (flip) targetRatio = targetRatio.flip(); + + return prevModePreviewTargetRatio.equals(targetRatio); } //endregion diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java index a00504f12..5eb7b665b 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java @@ -393,7 +393,7 @@ protected final boolean collectCameraInfo(@NonNull Facing facing) { @Override protected void prepareNewMode() { LOG.w("prepareNewMode:", "can't prepare new mode without restart for Engine2"); - restart(); + restartBind(); } //endregion diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java index 1c1ac52de..2bf55f709 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java @@ -384,18 +384,14 @@ public final Audio getAudio() { * @param mode desired mode. */ @Override - public final void setMode(@NonNull Mode mode, final boolean withoutRestart) { + public final void setMode(@NonNull Mode mode) { if (mode != mMode) { mMode = mode; getOrchestrator().scheduleStateful("mode", CameraState.ENGINE, new Runnable() { @Override public void run() { - if (withoutRestart) { - prepareNewMode(); - } else { - restart(); - } + prepareNewMode(); } }); } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java index 967ef6cff..2817bbdb4 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java @@ -664,7 +664,7 @@ public final void onSurfaceDestroyed() { public abstract void setAudio(@NonNull Audio audio); @NonNull public abstract Audio getAudio(); - public abstract void setMode(@NonNull Mode mode, boolean withoutRestart); + public abstract void setMode(@NonNull Mode mode); @NonNull public abstract Mode getMode(); public abstract void setZoom(float zoom, @Nullable PointF[] points, boolean notify); From ca6c81edaf8e8231cd5e69b0afa48e57bf8033d8 Mon Sep 17 00:00:00 2001 From: "alexander.melnikov" Date: Thu, 26 Mar 2020 11:36:30 +0300 Subject: [PATCH 4/4] Added nullability check --- .../com/otaliastudios/cameraview/engine/Camera1Engine.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java index 90684e5a4..39cbf63ef 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java @@ -160,6 +160,9 @@ protected void prepareNewMode() { } private boolean previewAspectRatioEqualsForModes() { + if (mCaptureSize == null) { + return false; + } Size prevModeSize = mCaptureSize; mCaptureSize = computeCaptureSize();