From b5921ec6bf376fa6df3a69b1e09ef545abbf7d7e Mon Sep 17 00:00:00 2001 From: jeffreyfjohnson Date: Sat, 11 Jul 2020 13:56:32 -0600 Subject: [PATCH 1/2] Restart Camera1 Frame Processing After Taking a Picture - Fixes Issue 824 (#877) * resetup frame manager after taking full picture for Camera1 Engine * Wrap frame processing restart in conditional * Add unit test --- .../engine/CameraIntegrationTest.java | 14 ++++++++++ .../picture/Full1PictureRecorder.java | 28 ++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java index e10f608e..779e23e8 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/CameraIntegrationTest.java @@ -1080,6 +1080,20 @@ public abstract class CameraIntegrationTest extends assert15Frames(processor); } + @Test + @Retry(emulatorOnly = true) + @SdkExclude(maxSdkVersion = 22, emulatorOnly = true) + public void testFrameProcessing_afterPicture() throws Exception { + FrameProcessor processor = mock(FrameProcessor.class); + camera.addFrameProcessor(processor); + openSync(true); + + camera.takePicture(); + waitForPictureResult(true); + + assert15Frames(processor); + } + @Test @Retry(emulatorOnly = true) @SdkExclude(maxSdkVersion = 22, emulatorOnly = true) diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full1PictureRecorder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full1PictureRecorder.java index 1260015a..c5a17077 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full1PictureRecorder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/Full1PictureRecorder.java @@ -2,12 +2,15 @@ package com.otaliastudios.cameraview.picture; import android.hardware.Camera; +import androidx.annotation.NonNull; +import androidx.exifinterface.media.ExifInterface; + import com.otaliastudios.cameraview.PictureResult; import com.otaliastudios.cameraview.engine.Camera1Engine; +import com.otaliastudios.cameraview.engine.offset.Reference; +import com.otaliastudios.cameraview.engine.orchestrator.CameraState; import com.otaliastudios.cameraview.internal.ExifHelper; - -import androidx.annotation.NonNull; -import androidx.exifinterface.media.ExifInterface; +import com.otaliastudios.cameraview.size.Size; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -40,6 +43,7 @@ public class Full1PictureRecorder extends FullPictureRecorder { // Stopping the preview callback is important on older APIs / emulators, // or takePicture can hang and leave the camera in a bad state. mCamera.setPreviewCallbackWithBuffer(null); + mEngine.getFrameManager().release(); mCamera.takePicture( new Camera.ShutterCallback() { @Override @@ -67,7 +71,23 @@ public class Full1PictureRecorder extends FullPictureRecorder { mResult.data = data; mResult.rotation = exifRotation; LOG.i("take(): starting preview again. ", Thread.currentThread()); - camera.setPreviewCallbackWithBuffer(mEngine); + + if (mEngine.getState().isAtLeast(CameraState.PREVIEW)) { + camera.setPreviewCallbackWithBuffer(mEngine); + Size previewStreamSize = mEngine.getPreviewStreamSize(Reference.SENSOR); + if (previewStreamSize == null) { + throw new IllegalStateException("Preview stream size " + + "should never be null here."); + } + // Need to re-setup the frame manager, otherwise no frames are processed + // after takePicture() is called + mEngine.getFrameManager().setUp( + mEngine.getFrameProcessingFormat(), + previewStreamSize, + mEngine.getAngles() + ); + } + camera.startPreview(); // This is needed, read somewhere in the docs. dispatchResult(); } From 8455c23fb19cd99a99780fcc670a85dc4a4a54aa Mon Sep 17 00:00:00 2001 From: Alexander Date: Sat, 11 Jul 2020 23:02:00 +0300 Subject: [PATCH 2/2] Wrapped some crashes which connect with empty camera params (#851) Co-authored-by: Mattia Iavarone --- .../cameraview/engine/Camera1Engine.java | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) 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 bd5da1e0..7cb41d1a 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java @@ -100,7 +100,13 @@ public class Camera1Engine extends CameraBaseEngine implements @NonNull @Override protected List getPreviewStreamAvailableSizes() { - List sizes = mCamera.getParameters().getSupportedPreviewSizes(); + List sizes; + try { + sizes = mCamera.getParameters().getSupportedPreviewSizes(); + } catch (Exception e) { + LOG.e("getPreviewStreamAvailableSizes:", "Failed to compute preview size. Camera params is empty"); + throw new CameraException(e, CameraException.REASON_FAILED_TO_START_PREVIEW); + } List result = new ArrayList<>(sizes.size()); for (Camera.Size size : sizes) { Size add = new Size(size.width, size.height); @@ -163,11 +169,16 @@ public class Camera1Engine extends CameraBaseEngine implements // Set parameters that might have been set before the camera was opened. LOG.i("onStartEngine:", "Applying default parameters."); - Camera.Parameters params = mCamera.getParameters(); - mCameraOptions = new Camera1Options(params, mCameraId, - getAngles().flip(Reference.SENSOR, Reference.VIEW)); - applyAllParameters(params); - mCamera.setParameters(params); + try { + Camera.Parameters params = mCamera.getParameters(); + mCameraOptions = new Camera1Options(params, mCameraId, + getAngles().flip(Reference.SENSOR, Reference.VIEW)); + applyAllParameters(params); + mCamera.setParameters(params); + } catch (Exception e) { + LOG.e("onStartEngine:", "Failed to connect. Problem with camera params"); + throw new CameraException(e, CameraException.REASON_FAILED_TO_CONNECT); + } mCamera.setDisplayOrientation(getAngles().offset(Reference.SENSOR, Reference.VIEW, Axis.ABSOLUTE)); // <- not allowed during preview LOG.i("onStartEngine:", "Ended");