From 407b2d4e6474941e2dc3c2418987a9b9644d257a Mon Sep 17 00:00:00 2001 From: Mattia Iavarone Date: Tue, 2 Apr 2019 15:32:24 -0300 Subject: [PATCH] Fix processor bug --- .../com/otaliastudios/cameraview/Frame.java | 21 ++++- .../cameraview/FrameManager.java | 8 +- .../cameraview/demo/CameraActivity.java | 77 ++++++++++--------- 3 files changed, 67 insertions(+), 39 deletions(-) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/Frame.java b/cameraview/src/main/java/com/otaliastudios/cameraview/Frame.java index 3b584839..44a83928 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/Frame.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/Frame.java @@ -20,6 +20,18 @@ public class Frame { mManager = manager; } + boolean isAlive() { + return mData != null; + } + + private void ensureAlive() { + if (!isAlive()) { + throw new RuntimeException("You should not access a released frame. " + + "If this frame was passed to a FrameProcessor, you can only use its contents synchronously," + + "for the duration of the process() method."); + } + } + void set(@NonNull byte[] data, long time, int rotation, @NonNull Size size, int format) { this.mData = data; this.mTime = time; @@ -44,6 +56,7 @@ public class Frame { @SuppressWarnings("WeakerAccess") @NonNull public Frame freeze() { + ensureAlive(); byte[] data = new byte[mData.length]; System.arraycopy(mData, 0, data, 0, mData.length); Frame other = new Frame(mManager); @@ -56,11 +69,12 @@ public class Frame { * that are not useful anymore. */ public void release() { + if (!isAlive()) return; + if (mManager != null) { // If needed, the manager will call releaseManager on us. mManager.onFrameReleased(this); } - mData = null; mRotation = 0; mTime = -1; @@ -79,6 +93,7 @@ public class Frame { */ @NonNull public byte[] getData() { + ensureAlive(); return mData; } @@ -89,6 +104,7 @@ public class Frame { * @return time data */ public long getTime() { + ensureAlive(); return mTime; } @@ -100,6 +116,7 @@ public class Frame { * @return clock-wise rotation */ public int getRotation() { + ensureAlive(); return mRotation; } @@ -110,6 +127,7 @@ public class Frame { */ @NonNull public Size getSize() { + ensureAlive(); return mSize; } @@ -122,6 +140,7 @@ public class Frame { * @see android.graphics.ImageFormat */ public int getFormat() { + ensureAlive(); return mFormat; } } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/FrameManager.java b/cameraview/src/main/java/com/otaliastudios/cameraview/FrameManager.java index e05f607f..f08eaf1c 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/FrameManager.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/FrameManager.java @@ -52,15 +52,17 @@ class FrameManager { byte[] buffer = frame.getData(); boolean willRecycle = mQueue.offer(frame); if (!willRecycle) { + // If frame queue is full, let's drop everything. frame.releaseManager(); - } - if (buffer != null && mCallback != null) { + } else { + // If frame will be recycled, let's recycle the buffer as well. int currSize = buffer.length; int reqSize = mBufferSize; - if (currSize == reqSize) { + if (currSize == reqSize && mCallback != null) { mCallback.onBufferAvailable(buffer); } } + } /** diff --git a/demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java b/demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java index 0b0d348a..ea80ab64 100644 --- a/demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java +++ b/demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java @@ -7,6 +7,8 @@ import android.os.Bundle; import androidx.annotation.NonNull; import com.google.android.material.bottomsheet.BottomSheetBehavior; import androidx.appcompat.app.AppCompatActivity; + +import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; @@ -17,6 +19,8 @@ import com.otaliastudios.cameraview.CameraListener; import com.otaliastudios.cameraview.CameraLogger; import com.otaliastudios.cameraview.CameraOptions; import com.otaliastudios.cameraview.CameraView; +import com.otaliastudios.cameraview.Frame; +import com.otaliastudios.cameraview.FrameProcessor; import com.otaliastudios.cameraview.PictureResult; import com.otaliastudios.cameraview.Mode; import com.otaliastudios.cameraview.VideoResult; @@ -40,14 +44,7 @@ public class CameraActivity extends AppCompatActivity implements View.OnClickLis camera = findViewById(R.id.camera); camera.setLifecycleOwner(this); - camera.addCameraListener(new CameraListener() { - public void onCameraOpened(@NonNull CameraOptions options) { onOpened(options); } - public void onPictureTaken(@NonNull PictureResult result) { onPicture(result); } - public void onVideoTaken(@NonNull VideoResult result) { onVideo(result); } - public void onCameraError(@NonNull CameraException exception) { - onError(exception); - } - }); + camera.addCameraListener(new Listener()); findViewById(R.id.edit).setOnClickListener(this); findViewById(R.id.capturePicture).setOnClickListener(this); @@ -80,38 +77,48 @@ public class CameraActivity extends AppCompatActivity implements View.OnClickLis Toast.makeText(this, content, length).show(); } - private void onOpened(CameraOptions options) { - ViewGroup group = (ViewGroup) controlPanel.getChildAt(0); - for (int i = 0; i < group.getChildCount(); i++) { - ControlView view = (ControlView) group.getChildAt(i); - view.onCameraOpened(camera, options); - } - } + private class Listener extends CameraListener { - private void onError(@NonNull CameraException exception) { - message("Got CameraException #" + exception.getReason(), true); - } + @Override + public void onCameraOpened(@NonNull CameraOptions options) { + ViewGroup group = (ViewGroup) controlPanel.getChildAt(0); + for (int i = 0; i < group.getChildCount(); i++) { + ControlView view = (ControlView) group.getChildAt(i); + view.onCameraOpened(camera, options); + } + } - private void onPicture(PictureResult result) { - if (camera.isTakingVideo()) { - message("Captured while taking video. Size=" + result.getSize(), false); - return; + @Override + public void onCameraError(@NonNull CameraException exception) { + super.onCameraError(exception); + message("Got CameraException #" + exception.getReason(), true); } - // This can happen if picture was taken with a gesture. - long callbackTime = System.currentTimeMillis(); - if (mCaptureTime == 0) mCaptureTime = callbackTime - 300; - PicturePreviewActivity.setPictureResult(result); - Intent intent = new Intent(CameraActivity.this, PicturePreviewActivity.class); - intent.putExtra("delay", callbackTime - mCaptureTime); - startActivity(intent); - mCaptureTime = 0; - } + @Override + public void onPictureTaken(@NonNull PictureResult result) { + super.onPictureTaken(result); + if (camera.isTakingVideo()) { + message("Captured while taking video. Size=" + result.getSize(), false); + return; + } + + // This can happen if picture was taken with a gesture. + long callbackTime = System.currentTimeMillis(); + if (mCaptureTime == 0) mCaptureTime = callbackTime - 300; + PicturePreviewActivity.setPictureResult(result); + Intent intent = new Intent(CameraActivity.this, PicturePreviewActivity.class); + intent.putExtra("delay", callbackTime - mCaptureTime); + startActivity(intent); + mCaptureTime = 0; + } - private void onVideo(VideoResult video) { - VideoPreviewActivity.setVideoResult(video); - Intent intent = new Intent(CameraActivity.this, VideoPreviewActivity.class); - startActivity(intent); + @Override + public void onVideoTaken(@NonNull VideoResult result) { + super.onVideoTaken(result); + VideoPreviewActivity.setVideoResult(result); + Intent intent = new Intent(CameraActivity.this, VideoPreviewActivity.class); + startActivity(intent); + } } @Override