diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java index 1bc19bed..ce08f799 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java @@ -184,6 +184,7 @@ public class CameraViewTest extends BaseTest { assertEquals(cameraView.getUseDeviceOrientation(), CameraView.DEFAULT_USE_DEVICE_ORIENTATION); assertEquals(cameraView.getPictureMetering(), CameraView.DEFAULT_PICTURE_METERING); assertEquals(cameraView.getPictureSnapshotMetering(), CameraView.DEFAULT_PICTURE_SNAPSHOT_METERING); + assertEquals(cameraView.getFrameProcessingPoolSize(), CameraView.DEFAULT_FRAME_PROCESSING_POOL_SIZE); assertEquals(cameraView.getGestureAction(Gesture.TAP), gestures.getTapAction()); assertEquals(cameraView.getGestureAction(Gesture.LONG_TAP), gestures.getLongTapAction()); assertEquals(cameraView.getGestureAction(Gesture.PINCH), gestures.getPinchAction()); @@ -831,6 +832,14 @@ public class CameraViewTest extends BaseTest { assertEquals(ImageFormat.YUV_422_888, cameraView.getFrameProcessingFormat()); } + @Test + public void testFrameProcessingPoolSize() { + cameraView.setFrameProcessingPoolSize(4); + assertEquals(4, cameraView.getFrameProcessingPoolSize()); + cameraView.setFrameProcessingPoolSize(6); + assertEquals(6, cameraView.getFrameProcessingPoolSize()); + } + //endregion //region Lists of listeners and processors diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/MockCameraEngine.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/MockCameraEngine.java index aa556810..5b3486c4 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/MockCameraEngine.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/engine/MockCameraEngine.java @@ -195,8 +195,8 @@ public class MockCameraEngine extends CameraBaseEngine { @NonNull @Override - protected FrameManager instantiateFrameManager() { - return new ByteBufferFrameManager(2, null); + protected FrameManager instantiateFrameManager(int poolSize) { + return new ByteBufferFrameManager(poolSize, null); } @Override diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index 636bc98a..8dcb2ded 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -111,6 +111,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { final static boolean DEFAULT_USE_DEVICE_ORIENTATION = true; final static boolean DEFAULT_PICTURE_METERING = true; final static boolean DEFAULT_PICTURE_SNAPSHOT_METERING = false; + final static int DEFAULT_FRAME_PROCESSING_POOL_SIZE = 2; // Self managed parameters private boolean mPlaySounds; @@ -206,6 +207,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver { int frameMaxWidth = a.getInteger(R.styleable.CameraView_cameraFrameProcessingMaxWidth, 0); int frameMaxHeight = a.getInteger(R.styleable.CameraView_cameraFrameProcessingMaxHeight, 0); int frameFormat = a.getInteger(R.styleable.CameraView_cameraFrameProcessingFormat, 0); + int framePoolSize = a.getInteger(R.styleable.CameraView_cameraFrameProcessingPoolSize, + DEFAULT_FRAME_PROCESSING_POOL_SIZE); // Size selectors and gestures SizeSelectorParser sizeSelectors = new SizeSelectorParser(a); @@ -267,6 +270,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { setFrameProcessingMaxWidth(frameMaxWidth); setFrameProcessingMaxHeight(frameMaxHeight); setFrameProcessingFormat(frameFormat); + setFrameProcessingPoolSize(framePoolSize); mCameraEngine.setHasFrameProcessors(!mFrameProcessors.isEmpty()); // Apply gestures @@ -982,6 +986,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { setFrameProcessingMaxWidth(oldEngine.getFrameProcessingMaxWidth()); setFrameProcessingMaxHeight(oldEngine.getFrameProcessingMaxHeight()); setFrameProcessingFormat(0 /* this is very engine specific, so do not pass */); + setFrameProcessingPoolSize(oldEngine.getFrameProcessingPoolSize()); } /** @@ -2370,6 +2375,26 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getFrameProcessingFormat(); } + /** + * Sets the frame processing pool size. This is (roughly) the max number of + * {@link Frame} instances that can exist at a given moment in the frame pipeline, + * excluding frozen frames. + * + * @param poolSize pool size + */ + public void setFrameProcessingPoolSize(int poolSize) { + mCameraEngine.setFrameProcessingPoolSize(poolSize); + } + + /** + * Returns the current frame processing pool size. + * @see #setFrameProcessingPoolSize(int) + * @return pool size + */ + public int getFrameProcessingPoolSize() { + return mCameraEngine.getFrameProcessingPoolSize(); + } + //endregion //region Overlays 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 cc668bce..e96867d6 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java @@ -757,8 +757,8 @@ public class Camera1Engine extends CameraBaseEngine implements @NonNull @Override - protected FrameManager instantiateFrameManager() { - return new ByteBufferFrameManager(2, this); + protected FrameManager instantiateFrameManager(int poolSize) { + return new ByteBufferFrameManager(poolSize, this); } @NonNull 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 644bf4be..5fe71e99 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java @@ -61,7 +61,6 @@ import com.otaliastudios.cameraview.frame.FrameManager; import com.otaliastudios.cameraview.frame.ImageFrameManager; import com.otaliastudios.cameraview.gesture.Gesture; import com.otaliastudios.cameraview.internal.utils.CropHelper; -import com.otaliastudios.cameraview.internal.utils.WorkerHandler; import com.otaliastudios.cameraview.picture.Full2PictureRecorder; import com.otaliastudios.cameraview.picture.Snapshot2PictureRecorder; import com.otaliastudios.cameraview.preview.GlCameraPreview; @@ -81,7 +80,6 @@ public class Camera2Engine extends CameraBaseEngine implements ImageReader.OnImageAvailableListener, ActionHolder { - private static final int FRAME_PROCESSING_POOL_SIZE = 2; private static final int FRAME_PROCESSING_FORMAT = ImageFormat.YUV_420_888; @VisibleForTesting static final long METER_TIMEOUT = 2500; @@ -97,8 +95,6 @@ public class Camera2Engine extends CameraBaseEngine implements // Frame processing private ImageReader mFrameProcessingReader; // need this or the reader surface is collected private Surface mFrameProcessingSurface; - private final WorkerHandler mFrameProcessingHandler = WorkerHandler.get("FrameProcessing"); - private final Object mFrameProcessingImageLock = new Object(); // Preview private Surface mPreviewStreamSurface; @@ -549,7 +545,7 @@ public class Camera2Engine extends CameraBaseEngine implements mFrameProcessingFormat, getFrameProcessingPoolSize()); mFrameProcessingReader.setOnImageAvailableListener(this, - mFrameProcessingHandler.getHandler()); + null); mFrameProcessingSurface = mFrameProcessingReader.getSurface(); outputSurfaces.add(mFrameProcessingSurface); } else { @@ -1402,17 +1398,13 @@ public class Camera2Engine extends CameraBaseEngine implements //region Frame Processing - protected int getFrameProcessingPoolSize() { - return FRAME_PROCESSING_POOL_SIZE; - } - @NonNull @Override - protected FrameManager instantiateFrameManager() { - return new ImageFrameManager(getFrameProcessingPoolSize()); + protected FrameManager instantiateFrameManager(int poolSize) { + return new ImageFrameManager(poolSize); } - // Frame processing thread + @EngineThread @Override public void onImageAvailable(ImageReader reader) { LOG.v("onImageAvailable", "trying to acquire Image."); 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 e2cd5ae9..486fd51a 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraBaseEngine.java @@ -67,8 +67,8 @@ public abstract class CameraBaseEngine extends CameraEngine { @SuppressWarnings("WeakerAccess") protected boolean mPictureSnapshotMetering; @SuppressWarnings("WeakerAccess") protected float mPreviewFrameRate; - private final FrameManager mFrameManager; - private final Angles mAngles; + private FrameManager mFrameManager; + private final Angles mAngles = new Angles(); @Nullable private SizeSelector mPreviewStreamSizeSelector; private SizeSelector mPictureSizeSelector; private SizeSelector mVideoSizeSelector; @@ -84,6 +84,7 @@ public abstract class CameraBaseEngine extends CameraEngine { private int mSnapshotMaxHeight; // in REF_VIEW like SizeSelectors private int mFrameProcessingMaxWidth; // in REF_VIEW like SizeSelectors private int mFrameProcessingMaxHeight; // in REF_VIEW like SizeSelectors + private int mFrameProcessingPoolSize; private Overlay mOverlay; // Ops used for testing. @@ -107,17 +108,16 @@ public abstract class CameraBaseEngine extends CameraEngine { @SuppressWarnings("WeakerAccess") protected CameraBaseEngine(@NonNull Callback callback) { super(callback); - mFrameManager = instantiateFrameManager(); - mAngles = new Angles(); } /** * Called at construction time to get a frame manager that can later be * accessed through {@link #getFrameManager()}. + * @param poolSize pool size * @return a frame manager */ @NonNull - protected abstract FrameManager instantiateFrameManager(); + protected abstract FrameManager instantiateFrameManager(int poolSize); @NonNull @Override @@ -128,6 +128,9 @@ public abstract class CameraBaseEngine extends CameraEngine { @NonNull @Override public FrameManager getFrameManager() { + if (mFrameManager == null) { + mFrameManager = instantiateFrameManager(mFrameProcessingPoolSize); + } return mFrameManager; } @@ -290,6 +293,16 @@ public abstract class CameraBaseEngine extends CameraEngine { return mFrameProcessingFormat; } + @Override + public final void setFrameProcessingPoolSize(int poolSize) { + mFrameProcessingPoolSize = poolSize; + } + + @Override + public final int getFrameProcessingPoolSize() { + return mFrameProcessingPoolSize; + } + @Override public final void setAutoFocusResetDelay(long delayMillis) { mAutoFocusResetDelayMillis = delayMillis; 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 837c7331..7fd3a062 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java @@ -650,6 +650,9 @@ public abstract class CameraEngine implements public abstract void setFrameProcessingFormat(int format); public abstract int getFrameProcessingFormat(); + public abstract void setFrameProcessingPoolSize(int poolSize); + public abstract int getFrameProcessingPoolSize(); + public abstract void setAutoFocusResetDelay(long delayMillis); public abstract long getAutoFocusResetDelay(); diff --git a/cameraview/src/main/res/values/attrs.xml b/cameraview/src/main/res/values/attrs.xml index ba905f08..84b60152 100644 --- a/cameraview/src/main/res/values/attrs.xml +++ b/cameraview/src/main/res/values/attrs.xml @@ -28,6 +28,7 @@ +