From 94293978e883d162b385a20761045451b34816a2 Mon Sep 17 00:00:00 2001 From: Mattia Iavarone Date: Thu, 5 Sep 2019 18:08:11 +0200 Subject: [PATCH] Fix VideoRecorder state --- .../cameraview/engine/CameraEngine.java | 5 ++- .../cameraview/video/Full1VideoRecorder.java | 4 +- .../cameraview/video/VideoRecorder.java | 41 ++++++++++++++++--- demo/build.gradle | 4 +- 4 files changed, 43 insertions(+), 11 deletions(-) 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 f27f4731..b726fb2f 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java @@ -1215,10 +1215,13 @@ public abstract class CameraEngine implements }); } + @SuppressWarnings("WeakerAccess") protected void onStopVideo() { if (mVideoRecorder != null) { mVideoRecorder.stop(false); - mVideoRecorder = null; + // Do not null this, so we respond correctly to isTakingVideo(), + // which checks for recorder presence and recorder.isRecording(). + // It will be nulled in onVideoResult. } } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/video/Full1VideoRecorder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/video/Full1VideoRecorder.java index 010ea055..f6588bed 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/video/Full1VideoRecorder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/video/Full1VideoRecorder.java @@ -45,9 +45,9 @@ public class Full1VideoRecorder extends FullVideoRecorder { } @Override - protected void dispatchResult() { + protected void onDispatchResult() { // Restore frame processing. mCamera.setPreviewCallbackWithBuffer(mEngine); - super.dispatchResult(); + super.onDispatchResult(); } } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/video/VideoRecorder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/video/VideoRecorder.java index 394cfbbe..12513740 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/video/VideoRecorder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/video/VideoRecorder.java @@ -1,5 +1,6 @@ package com.otaliastudios.cameraview.video; +import com.otaliastudios.cameraview.CameraLogger; import com.otaliastudios.cameraview.VideoResult; import androidx.annotation.CallSuper; @@ -13,6 +14,9 @@ import androidx.annotation.VisibleForTesting; */ public abstract class VideoRecorder { + private final static String TAG = VideoRecorder.class.getSimpleName(); + private final static CameraLogger LOG = CameraLogger.create(TAG); + /** * Listens for video recorder events. */ @@ -37,11 +41,15 @@ public abstract class VideoRecorder { void onVideoRecordingEnd(); } + private final static int STATE_IDLE = 0; + private final static int STATE_RECORDING = 1; + private final static int STATE_STOPPING = 2; + @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) VideoResult.Stub mResult; private final VideoResultListener mListener; @SuppressWarnings("WeakerAccess") protected Exception mError; - private boolean mIsRecording; + private int mState; /** * Creates a new video recorder. @@ -49,6 +57,7 @@ public abstract class VideoRecorder { */ VideoRecorder(@Nullable VideoResultListener listener) { mListener = listener; + mState = STATE_IDLE; } /** @@ -57,8 +66,13 @@ public abstract class VideoRecorder { * @param stub the video stub */ public final void start(@NonNull VideoResult.Stub stub) { + if (mState != STATE_IDLE) { + LOG.e("start:", "called twice, or while stopping! " + + "Ignoring. state:", mState); + return; + } + mState = STATE_RECORDING; mResult = stub; - mIsRecording = true; onStart(); } @@ -67,6 +81,12 @@ public abstract class VideoRecorder { * @param isCameraShutdown whether this is a full shutdown, camera is being closed */ public final void stop(boolean isCameraShutdown) { + if (mState == STATE_IDLE) { + LOG.e("stop:", "called twice, or called before start! " + + "Ignoring. isCameraShutdown:", isCameraShutdown); + return; + } + mState = STATE_STOPPING; onStop(isCameraShutdown); } @@ -75,7 +95,8 @@ public abstract class VideoRecorder { * @return true if recording */ public boolean isRecording() { - return mIsRecording; + // true if not idle. + return mState != STATE_IDLE; } protected abstract void onStart(); @@ -86,9 +107,10 @@ public abstract class VideoRecorder { * Subclasses can call this to notify that the result was obtained, * either with some error (null result) or with the actual stub, filled. */ - @CallSuper - protected void dispatchResult() { - mIsRecording = false; + protected final void dispatchResult() { + if (!isRecording()) return; + mState = STATE_IDLE; + onDispatchResult(); if (mListener != null) { mListener.onVideoResult(mResult, mError); } @@ -96,6 +118,13 @@ public abstract class VideoRecorder { mError = null; } + /** + * Subclasses can override this to release resources. + */ + protected void onDispatchResult() { + // No-op + } + /** * Subclasses can call this to notify that the video recording has started, * this will be called when camera is prepared and started. diff --git a/demo/build.gradle b/demo/build.gradle index be25003a..bbf6cff8 100644 --- a/demo/build.gradle +++ b/demo/build.gradle @@ -23,6 +23,6 @@ android { dependencies { implementation project(':cameraview') - implementation 'androidx.appcompat:appcompat:1.1.0-alpha02' - implementation 'com.google.android.material:material:1.1.0-alpha03' + implementation 'androidx.appcompat:appcompat:1.1.0-rc01' + implementation 'com.google.android.material:material:1.1.0-alpha09' }