From 632cc0f09a64c0abed5ee6a9ff8a417a569a0e54 Mon Sep 17 00:00:00 2001 From: Mattia Iavarone Date: Sun, 24 Feb 2019 16:35:27 +0100 Subject: [PATCH] Rename setPreviewSize and all internals to setPreviewStreamSize --- .../cameraview/CameraPreviewTest.java | 22 +++---- .../cameraview/CameraViewTest.java | 20 +++--- .../cameraview/MockCameraController.java | 4 +- .../cameraview/TextureCameraPreviewTest.java | 4 +- .../com/otaliastudios/cameraview/Camera1.java | 66 +++++++++++++------ .../cameraview/CameraController.java | 32 ++++----- .../otaliastudios/cameraview/CameraView.java | 16 ++--- .../cameraview/SnapshotPictureRecorder.java | 4 +- .../cameraview/CameraPreview.java | 25 ++++--- .../cameraview/GlCameraPreview.java | 8 +-- .../cameraview/SurfaceCameraPreview.java | 6 +- .../cameraview/TextureCameraPreview.java | 10 +-- docs/_posts/2018-12-20-preview-size.md | 12 ++-- 13 files changed, 132 insertions(+), 97 deletions(-) diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraPreviewTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraPreviewTest.java index 05f5e462..85c2374d 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraPreviewTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraPreviewTest.java @@ -102,17 +102,17 @@ public abstract class CameraPreviewTest extends BaseTest { @Test public void testDesiredSize() { - preview.setInputStreamSize(160, 90, false); - assertEquals(160, preview.getInputStreamSize().getWidth()); - assertEquals(90, preview.getInputStreamSize().getHeight()); + preview.setStreamSize(160, 90, false); + assertEquals(160, preview.getStreamSize().getWidth()); + assertEquals(90, preview.getStreamSize().getHeight()); } @Test public void testSurfaceAvailable() { ensureAvailable(); verify(callback, times(1)).onSurfaceAvailable(); - assertEquals(surfaceSize.getWidth(), preview.getOutputSurfaceSize().getWidth()); - assertEquals(surfaceSize.getHeight(), preview.getOutputSurfaceSize().getHeight()); + assertEquals(surfaceSize.getWidth(), preview.getSurfaceSize().getWidth()); + assertEquals(surfaceSize.getHeight(), preview.getSurfaceSize().getHeight()); } @Test @@ -121,8 +121,8 @@ public abstract class CameraPreviewTest extends BaseTest { ensureDestroyed(); // This might be called twice in Texture because it overrides ensureDestroyed method verify(callback, atLeastOnce()).onSurfaceDestroyed(); - assertEquals(0, preview.getOutputSurfaceSize().getWidth()); - assertEquals(0, preview.getOutputSurfaceSize().getHeight()); + assertEquals(0, preview.getSurfaceSize().getWidth()); + assertEquals(0, preview.getSurfaceSize().getHeight()); } @Test @@ -146,7 +146,7 @@ public abstract class CameraPreviewTest extends BaseTest { // Since desired is 'desired', let's fake a new view size that is consistent with it. // Ensure crop is not happening anymore. preview.mCropTask.listen(); - preview.dispatchOnOutputSurfaceSizeChanged((int) (50f * desired), 50); // Wait... + preview.dispatchOnSurfaceSizeChanged((int) (50f * desired), 50); // Wait... preview.mCropTask.await(); assertEquals(desired, getViewAspectRatioWithScale(), 0.01f); assertFalse(preview.isCropping()); @@ -154,19 +154,19 @@ public abstract class CameraPreviewTest extends BaseTest { private void setDesiredAspectRatio(float desiredAspectRatio) { preview.mCropTask.listen(); - preview.setInputStreamSize((int) (10f * desiredAspectRatio), 10, false); // Wait... + preview.setStreamSize((int) (10f * desiredAspectRatio), 10, false); // Wait... preview.mCropTask.await(); assertEquals(desiredAspectRatio, getViewAspectRatioWithScale(), 0.01f); } private float getViewAspectRatio() { - Size size = preview.getOutputSurfaceSize(); + Size size = preview.getSurfaceSize(); return AspectRatio.of(size.getWidth(), size.getHeight()).toFloat(); } private float getViewAspectRatioWithScale() { - Size size = preview.getOutputSurfaceSize(); + Size size = preview.getSurfaceSize(); int newWidth = (int) (((float) size.getWidth()) * getCropScaleX()); int newHeight = (int) (((float) size.getHeight()) * getCropScaleY()); return AspectRatio.of(newWidth, newHeight).toFloat(); diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java index aed9b4af..d26d666a 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java @@ -288,14 +288,14 @@ public class CameraViewTest extends BaseTest { //region testMeasure - private void mockPreviewSize() { + private void mockPreviewStreamSize() { Size size = new Size(900, 1600); - mockController.setMockPreviewSize(size); + mockController.setMockPreviewStreamSize(size); } @Test public void testMeasure_early() { - mockController.setMockPreviewSize(null); + mockController.setMockPreviewStreamSize(null); cameraView.measure( makeMeasureSpec(500, EXACTLY), makeMeasureSpec(500, EXACTLY)); @@ -305,7 +305,7 @@ public class CameraViewTest extends BaseTest { @Test public void testMeasure_matchParentBoth() { - mockPreviewSize(); + mockPreviewStreamSize(); // Respect parent/layout constraints on both dimensions. cameraView.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); @@ -331,7 +331,7 @@ public class CameraViewTest extends BaseTest { @Test public void testMeasure_wrapContentBoth() { - mockPreviewSize(); + mockPreviewStreamSize(); // Respect parent constraints, but fit aspect ratio. // Fit into a 160x160 parent so we espect final width to be 90. @@ -345,7 +345,7 @@ public class CameraViewTest extends BaseTest { @Test public void testMeasure_wrapContentSingle() { - mockPreviewSize(); + mockPreviewStreamSize(); // Respect MATCH_PARENT on height, change width to fit the aspect ratio. cameraView.setLayoutParams(new ViewGroup.LayoutParams(WRAP_CONTENT, MATCH_PARENT)); @@ -366,7 +366,7 @@ public class CameraViewTest extends BaseTest { @Test public void testMeasure_scrollableContainer() { - mockPreviewSize(); + mockPreviewStreamSize(); // Assume a vertical scroll view. It will pass UNSPECIFIED as height. // We respect MATCH_PARENT on width (160), and enlarge height to match the aspect ratio. @@ -559,10 +559,10 @@ public class CameraViewTest extends BaseTest { } @Test - public void testPreviewSizeSelector() { + public void testPreviewStreamSizeSelector() { SizeSelector source = SizeSelectors.minHeight(50); - cameraView.setPreviewSize(source); - SizeSelector result = mockController.getPreviewSizeSelector(); + cameraView.setPreviewStreamSize(source); + SizeSelector result = mockController.getPreviewStreamSizeSelector(); assertNotNull(result); assertEquals(result, source); } diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java index 7be7053d..1026b215 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java @@ -23,8 +23,8 @@ public class MockCameraController extends CameraController { mCameraOptions = options; } - void setMockPreviewSize(Size size) { - mPreviewSize = size; + void setMockPreviewStreamSize(Size size) { + mPreviewStreamSize = size; } void mockStarted(boolean started) { diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/TextureCameraPreviewTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/TextureCameraPreviewTest.java index 0f604fc7..4e5e3251 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/TextureCameraPreviewTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/TextureCameraPreviewTest.java @@ -23,7 +23,7 @@ public class TextureCameraPreviewTest extends CameraPreviewTest { if (isHardwareAccelerated()) { super.ensureAvailable(); } else { - preview.dispatchOnOutputSurfaceAvailable( + preview.dispatchOnSurfaceAvailable( surfaceSize.getWidth(), surfaceSize.getHeight()); } @@ -34,7 +34,7 @@ public class TextureCameraPreviewTest extends CameraPreviewTest { super.ensureDestroyed(); if (!isHardwareAccelerated()) { // Ensure it is called. - preview.dispatchOnOutputSurfaceDestroyed(); + preview.dispatchOnSurfaceDestroyed(); } } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java index df684901..8e6c62d5 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java @@ -97,12 +97,12 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera if (!mIsBound) return; // Compute a new camera preview size. - Size newSize = computePreviewSize(sizesFromList(mCamera.getParameters().getSupportedPreviewSizes())); - if (newSize.equals(mPreviewSize)) return; + Size newSize = computePreviewStreamSize(sizesFromList(mCamera.getParameters().getSupportedPreviewSizes())); + if (newSize.equals(mPreviewStreamSize)) return; // Apply. LOG.i("onSurfaceChanged:", "Computed a new preview size. Going on."); - mPreviewSize = newSize; + mPreviewStreamSize = newSize; stopPreview(); startPreview("onSurfaceChanged:"); } @@ -135,10 +135,12 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera LOG.i("bindToSurface:", "Started"); Object output = mPreview.getOutput(); try { - if (mPreview.getOutputClass() == SurfaceHolder.class) { + if (output instanceof SurfaceHolder) { mCamera.setPreviewDisplay((SurfaceHolder) output); - } else { + } else if (output instanceof SurfaceTexture) { mCamera.setPreviewTexture((SurfaceTexture) output); + } else { + throw new RuntimeException("Unknown CameraPreview output class."); } } catch (IOException e) { LOG.e("bindToSurface:", "Failed to bind.", e); @@ -146,20 +148,22 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera } mCaptureSize = computeCaptureSize(); - mPreviewSize = computePreviewSize(sizesFromList(mCamera.getParameters().getSupportedPreviewSizes())); + mPreviewStreamSize = computePreviewStreamSize(sizesFromList(mCamera.getParameters().getSupportedPreviewSizes())); mIsBound = true; } @WorkerThread private void unbindFromSurface() { mIsBound = false; - mPreviewSize = null; + mPreviewStreamSize = null; mCaptureSize = null; try { if (mPreview.getOutputClass() == SurfaceHolder.class) { mCamera.setPreviewDisplay(null); - } else { + } else if (mPreview.getOutputClass() == SurfaceTexture.class) { mCamera.setPreviewTexture(null); + } else { + throw new RuntimeException("Unknown CameraPreview output class."); } } catch (IOException e) { LOG.e("unbindFromSurface", "Could not release surface", e); @@ -172,16 +176,16 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera // To be called when the preview size is setup or changed. private void startPreview(String log) { - LOG.i(log, "Dispatching onCameraPreviewSizeChanged."); - mCameraCallbacks.onCameraPreviewSizeChanged(); + LOG.i(log, "Dispatching onCameraPreviewStreamSizeChanged."); + mCameraCallbacks.onCameraPreviewStreamSizeChanged(); - Size previewSize = getPreviewSize(REF_VIEW); + Size previewSize = getPreviewStreamSize(REF_VIEW); boolean wasFlipped = flip(REF_SENSOR, REF_VIEW); - mPreview.setInputStreamSize(previewSize.getWidth(), previewSize.getHeight(), wasFlipped); + mPreview.setStreamSize(previewSize.getWidth(), previewSize.getHeight(), wasFlipped); Camera.Parameters params = mCamera.getParameters(); mPreviewFormat = params.getPreviewFormat(); - params.setPreviewSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); // <- not allowed during preview + params.setPreviewSize(mPreviewStreamSize.getWidth(), mPreviewStreamSize.getHeight()); // <- not allowed during preview if (mMode == Mode.PICTURE) { params.setPictureSize(mCaptureSize.getWidth(), mCaptureSize.getHeight()); // <- allowed } else { @@ -196,7 +200,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera mCamera.setPreviewCallbackWithBuffer(null); // Release anything left mCamera.setPreviewCallbackWithBuffer(this); // Add ourselves - mFrameManager.allocate(ImageFormat.getBitsPerPixel(mPreviewFormat), mPreviewSize); + mFrameManager.allocate(ImageFormat.getBitsPerPixel(mPreviewFormat), mPreviewStreamSize); LOG.i(log, "Starting preview with startPreview()."); try { @@ -289,7 +293,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera } mCameraOptions = null; mCamera = null; - mPreviewSize = null; + mPreviewStreamSize = null; mCaptureSize = null; mIsBound = false; LOG.w("onStop:", "Clean up.", "Returning."); @@ -574,7 +578,22 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera }); } - + /** + * Just a note about the snapshot size - it is the PreviewStreamSize, cropped with the view ratio. + * One might be tempted to say that it is the SurfaceSize (which already matches the view ratio), + * but it's not. + * + * The camera sensor will capture preview frames with PreviewStreamSize and that's it. Then they + * are hardware-scaled by the preview surface, but this does not affect the snapshot, as the + * snapshot recorder simply creates another surface. + * + * Done tests to ensure that this is true, by using + * 1. small SurfaceSize and biggest() PreviewStreamSize: output is not low quality + * 2. big SurfaceSize and smallest() PreviewStreamSize: output is low quality + * In both cases the result.size here was set to the biggest of the two. + * + * @param viewAspectRatio the view aspect ratio + */ @Override void takePictureSnapshot(@NonNull final AspectRatio viewAspectRatio) { LOG.v("takePictureSnapshot: scheduling"); @@ -588,7 +607,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera result.location = mLocation; result.isSnapshot = true; result.facing = mFacing; - result.size = getPreviewSize(REF_OUTPUT); // Not the real size: it will be cropped to match the view ratio + result.size = getPreviewStreamSize(REF_OUTPUT); // Not the real size: it will be cropped to match the view ratio result.rotation = offset(REF_SENSOR, REF_OUTPUT); // Actually it will be rotated and set to 0. AspectRatio outputRatio = flip(REF_OUTPUT, REF_VIEW) ? viewAspectRatio.inverse() : viewAspectRatio; // LOG.e("ROTBUG_pic", "aspectRatio (REF_VIEW):", viewAspectRatio); @@ -611,7 +630,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera Frame frame = mFrameManager.getFrame(data, System.currentTimeMillis(), offset(REF_SENSOR, REF_OUTPUT), - mPreviewSize, + mPreviewStreamSize, mPreviewFormat); mCameraCallbacks.dispatchFrame(frame); } @@ -693,6 +712,15 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera }); } + /** + * Is output size the SurfaceSize or the PreviewStreamSize ? + * I could not find evidence by testing, but I think that comments in {@link #takePictureSnapshot(AspectRatio)} + * would still apply here, despite the capturing mechanism being different. + * So we should use PreviewStreamSize as output size, cropped by the view aspect ratio. + * + * @param file the output file + * @param viewAspectRatio the view aspect ratio + */ @SuppressLint("NewApi") @Override void takeVideoSnapshot(@NonNull final File file, @NonNull final AspectRatio viewAspectRatio) { @@ -755,7 +783,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera // Based on this we will use VO for everything. See if we get issues about distortion // and maybe we can improve. The reason why this happen is beyond my understanding. - Size outputSize = getPreviewSize(REF_OUTPUT); + Size outputSize = getPreviewStreamSize(REF_OUTPUT); AspectRatio outputRatio = flip(REF_OUTPUT, REF_VIEW) ? viewAspectRatio.inverse() : viewAspectRatio; Rect outputCrop = CropHelper.computeCrop(outputSize, outputRatio); outputSize = new Size(outputCrop.width(), outputCrop.height()); diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java index 3c39b10c..752b037c 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java @@ -49,7 +49,7 @@ abstract class CameraController implements protected float mExposureCorrectionValue; protected boolean mPlaySounds; - @Nullable private SizeSelector mPreviewSizeSelector; + @Nullable private SizeSelector mPreviewStreamSizeSelector; private SizeSelector mPictureSizeSelector; private SizeSelector mVideoSizeSelector; @@ -64,7 +64,7 @@ abstract class CameraController implements protected int mVideoBitRate; protected int mAudioBitRate; protected Size mCaptureSize; - protected Size mPreviewSize; + protected Size mPreviewStreamSize; protected int mPreviewFormat; protected int mSensorOffset; @@ -279,8 +279,8 @@ abstract class CameraController implements mDeviceOrientation = deviceOrientation; } - final void setPreviewSizeSelector(@Nullable SizeSelector selector) { - mPreviewSizeSelector = selector; + final void setPreviewStreamSizeSelector(@Nullable SizeSelector selector) { + mPreviewStreamSizeSelector = selector; } final void setPictureSizeSelector(@NonNull SizeSelector selector) { @@ -421,8 +421,8 @@ abstract class CameraController implements } @Nullable - /* for tests */ final SizeSelector getPreviewSizeSelector() { - return mPreviewSizeSelector; + /* for tests */ final SizeSelector getPreviewStreamSizeSelector() { + return mPreviewStreamSizeSelector; } @NonNull @@ -506,15 +506,15 @@ abstract class CameraController implements } @Nullable - final Size getPreviewSize(int reference) { - if (mPreviewSize == null) return null; - return flip(REF_SENSOR, reference) ? mPreviewSize.flip() : mPreviewSize; + final Size getPreviewStreamSize(int reference) { + if (mPreviewStreamSize == null) return null; + return flip(REF_SENSOR, reference) ? mPreviewStreamSize.flip() : mPreviewStreamSize; } @Nullable final Size getSurfaceSize(int reference) { if (mPreview == null) return null; - return flip(REF_VIEW, reference) ? mPreview.getOutputSurfaceSize().flip() : mPreview.getOutputSurfaceSize(); + return flip(REF_VIEW, reference) ? mPreview.getSurfaceSize().flip() : mPreview.getSurfaceSize(); } @@ -559,7 +559,7 @@ abstract class CameraController implements @NonNull @SuppressWarnings("WeakerAccess") - protected final Size computePreviewSize(@NonNull List previewSizes) { + protected final Size computePreviewStreamSize(@NonNull List previewSizes) { // These sizes come in REF_SENSOR. Since there is an external selector involved, // we must convert all of them to REF_VIEW, then flip back when returning. boolean flip = flip(REF_SENSOR, REF_VIEW); @@ -568,12 +568,12 @@ abstract class CameraController implements sizes.add(flip ? size.flip() : size); } - // Create our own default selector, which will be used if the external mPreviewSizeSelector + // Create our own default selector, which will be used if the external mPreviewStreamSizeSelector // is null, or if it fails in finding a size. Size targetMinSize = getSurfaceSize(REF_VIEW); AspectRatio targetRatio = AspectRatio.of(mCaptureSize.getWidth(), mCaptureSize.getHeight()); if (flip) targetRatio = targetRatio.inverse(); - LOG.i("size:", "computePreviewSize:", "targetRatio:", targetRatio, "targetMinSize:", targetMinSize); + LOG.i("size:", "computePreviewStreamSize:", "targetRatio:", targetRatio, "targetMinSize:", targetMinSize); SizeSelector matchRatio = SizeSelectors.and( // Match this aspect ratio and sort by biggest SizeSelectors.aspectRatio(targetRatio, 0), SizeSelectors.biggest()); @@ -591,14 +591,14 @@ abstract class CameraController implements // Apply the external selector with this as a fallback, // and return a size in REF_SENSOR reference. SizeSelector selector; - if (mPreviewSizeSelector != null) { - selector = SizeSelectors.or(mPreviewSizeSelector, matchAll); + if (mPreviewStreamSizeSelector != null) { + selector = SizeSelectors.or(mPreviewStreamSizeSelector, matchAll); } else { selector = matchAll; } Size result = selector.select(sizes).get(0); if (flip) result = result.flip(); - LOG.i("computePreviewSize:", "result:", result, "flip:", flip); + LOG.i("computePreviewStreamSize:", "result:", result, "flip:", flip); return result; } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index 7f2f6213..489a5cfe 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -311,7 +311,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - Size previewSize = mCameraController.getPreviewSize(CameraController.REF_VIEW); + Size previewSize = mCameraController.getPreviewStreamSize(CameraController.REF_VIEW); if (previewSize == null) { LOG.w("onMeasure:", "surface is not ready. Calling default behavior."); super.onMeasure(widthMeasureSpec, heightMeasureSpec); @@ -1073,15 +1073,15 @@ public class CameraView extends FrameLayout implements LifecycleObserver { * upscaling. If all you want is set an aspect ratio, use {@link #setPictureSize(SizeSelector)} * and {@link #setVideoSize(SizeSelector)}. * - * When size changes, the {@link CameraView} is remeasured so any WRAP_CONTENT dimension + * When stream size changes, the {@link CameraView} is remeasured so any WRAP_CONTENT dimension * is recomputed accordingly. * * See the {@link SizeSelectors} class for handy utilities for creating selectors. * * @param selector a size selector */ - public void setPreviewSize(@NonNull SizeSelector selector) { - mCameraController.setPreviewSizeSelector(selector); + public void setPreviewStreamSize(@NonNull SizeSelector selector) { + mCameraController.setPreviewStreamSizeSelector(selector); } @@ -1402,7 +1402,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { // Get the preview size and crop according to the current view size. // It's better to do calculations in the REF_VIEW reference, and then flip if needed. - Size preview = mCameraController.getPreviewSize(CameraController.REF_VIEW); + Size preview = mCameraController.getPreviewStreamSize(CameraController.REF_VIEW); AspectRatio viewRatio = AspectRatio.of(getWidth(), getHeight()); Rect crop = CropHelper.computeCrop(preview, viewRatio); Size cropSize = new Size(crop.width(), crop.height()); @@ -1597,7 +1597,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { interface CameraCallbacks extends OrientationHelper.Callback { void dispatchOnCameraOpened(CameraOptions options); void dispatchOnCameraClosed(); - void onCameraPreviewSizeChanged(); + void onCameraPreviewStreamSizeChanged(); void onShutter(boolean shouldPlaySound); void dispatchOnVideoTaken(VideoResult result); void dispatchOnPictureTaken(PictureResult result); @@ -1642,8 +1642,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } @Override - public void onCameraPreviewSizeChanged() { - mLogger.i("onCameraPreviewSizeChanged"); + public void onCameraPreviewStreamSizeChanged() { + mLogger.i("onCameraPreviewStreamSizeChanged"); // Camera preview size has changed. // Request a layout pass for onMeasure() to do its stuff. // Potentially this will change CameraView size, which changes Surface size, diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotPictureRecorder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotPictureRecorder.java index 11fb97dc..444d5a70 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotPictureRecorder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/SnapshotPictureRecorder.java @@ -37,7 +37,7 @@ class SnapshotPictureRecorder extends PictureRecorder { mCamera = camera; mOutputRatio = outputRatio; mFormat = mController.mPreviewFormat; - mSensorPreviewSize = mController.mPreviewSize; + mSensorPreviewSize = mController.mPreviewStreamSize; } @Override @@ -189,7 +189,7 @@ class SnapshotPictureRecorder extends PictureRecorder { // It seems that the buffers are already cleared here, so we need to allocate again. camera.setPreviewCallbackWithBuffer(null); // Release anything left camera.setPreviewCallbackWithBuffer(mController); // Add ourselves - mController.mFrameManager.allocate(ImageFormat.getBitsPerPixel(mFormat), mController.mPreviewSize); + mController.mFrameManager.allocate(ImageFormat.getBitsPerPixel(mFormat), mController.mPreviewStreamSize); } }); } diff --git a/cameraview/src/main/views/com/otaliastudios/cameraview/CameraPreview.java b/cameraview/src/main/views/com/otaliastudios/cameraview/CameraPreview.java index 43bb0ec2..9469ef61 100644 --- a/cameraview/src/main/views/com/otaliastudios/cameraview/CameraPreview.java +++ b/cameraview/src/main/views/com/otaliastudios/cameraview/CameraPreview.java @@ -6,6 +6,13 @@ import androidx.annotation.Nullable; import android.view.View; import android.view.ViewGroup; +/** + * A CameraPreview takes in input stream from the {@link CameraController}, and streams it + * into an output surface that belongs to the view hierarchy. + * + * @param the type of view which hosts the content surface + * @param the type of output, either {@link android.view.SurfaceHolder} or {@link android.graphics.SurfaceTexture} + */ abstract class CameraPreview { protected final static CameraLogger LOG = CameraLogger.create(CameraPreview.class.getSimpleName()); @@ -60,8 +67,8 @@ abstract class CameraPreview { // As far as I can see, these are the actual preview dimensions, as set in CameraParameters. // This is called by the CameraImpl. // These must be alredy rotated, if needed, to be consistent with surface/view sizes. - void setInputStreamSize(int width, int height, boolean wasFlipped) { - LOG.i("setInputStreamSize:", "desiredW=", width, "desiredH=", height); + void setStreamSize(int width, int height, boolean wasFlipped) { + LOG.i("setStreamSize:", "desiredW=", width, "desiredH=", height); mInputStreamWidth = width; mInputStreamHeight = height; mInputFlipped = wasFlipped; @@ -71,12 +78,12 @@ abstract class CameraPreview { } @NonNull - final Size getInputStreamSize() { + final Size getStreamSize() { return new Size(mInputStreamWidth, mInputStreamHeight); } @NonNull - final Size getOutputSurfaceSize() { + final Size getSurfaceSize() { return new Size(mOutputSurfaceWidth, mOutputSurfaceHeight); } @@ -90,8 +97,8 @@ abstract class CameraPreview { @SuppressWarnings("WeakerAccess") - protected final void dispatchOnOutputSurfaceAvailable(int width, int height) { - LOG.i("dispatchOnOutputSurfaceAvailable:", "w=", width, "h=", height); + protected final void dispatchOnSurfaceAvailable(int width, int height) { + LOG.i("dispatchOnSurfaceAvailable:", "w=", width, "h=", height); mOutputSurfaceWidth = width; mOutputSurfaceHeight = height; if (mOutputSurfaceWidth > 0 && mOutputSurfaceHeight > 0) { @@ -104,8 +111,8 @@ abstract class CameraPreview { // As far as I can see, these are the view/surface dimensions. // This is called by subclasses. @SuppressWarnings("WeakerAccess") - protected final void dispatchOnOutputSurfaceSizeChanged(int width, int height) { - LOG.i("dispatchOnOutputSurfaceSizeChanged:", "w=", width, "h=", height); + protected final void dispatchOnSurfaceSizeChanged(int width, int height) { + LOG.i("dispatchOnSurfaceSizeChanged:", "w=", width, "h=", height); if (width != mOutputSurfaceWidth || height != mOutputSurfaceHeight) { mOutputSurfaceWidth = width; mOutputSurfaceHeight = height; @@ -117,7 +124,7 @@ abstract class CameraPreview { } @SuppressWarnings("WeakerAccess") - protected final void dispatchOnOutputSurfaceDestroyed() { + protected final void dispatchOnSurfaceDestroyed() { mOutputSurfaceWidth = 0; mOutputSurfaceHeight = 0; mSurfaceCallback.onSurfaceDestroyed(); diff --git a/cameraview/src/main/views/com/otaliastudios/cameraview/GlCameraPreview.java b/cameraview/src/main/views/com/otaliastudios/cameraview/GlCameraPreview.java index 44ece2a9..d29463f3 100644 --- a/cameraview/src/main/views/com/otaliastudios/cameraview/GlCameraPreview.java +++ b/cameraview/src/main/views/com/otaliastudios/cameraview/GlCameraPreview.java @@ -85,7 +85,7 @@ class GlCameraPreview extends CameraPreview imple @Override public void surfaceDestroyed(SurfaceHolder holder) { - dispatchOnOutputSurfaceDestroyed(); + dispatchOnSurfaceDestroyed(); mDispatched = false; } }); @@ -159,7 +159,7 @@ class GlCameraPreview extends CameraPreview imple @Override public void onSurfaceChanged(GL10 gl, final int width, final int height) { if (!mDispatched) { - dispatchOnOutputSurfaceAvailable(width, height); + dispatchOnSurfaceAvailable(width, height); mDispatched = true; } else if (mOutputSurfaceWidth == width && mOutputSurfaceHeight == height) { // I was experimenting and this was happening. @@ -168,13 +168,13 @@ class GlCameraPreview extends CameraPreview imple // With other CameraPreview implementation we could just dispatch the 'size changed' event // to the controller and everything would go straight. In case of GL, apparently we have to // force recreate the EGLContext by calling onPause and onResume in the UI thread. - dispatchOnOutputSurfaceDestroyed(); + dispatchOnSurfaceDestroyed(); getView().post(new Runnable() { @Override public void run() { getView().onPause(); getView().onResume(); - dispatchOnOutputSurfaceAvailable(width, height); + dispatchOnSurfaceAvailable(width, height); } }); } diff --git a/cameraview/src/main/views/com/otaliastudios/cameraview/SurfaceCameraPreview.java b/cameraview/src/main/views/com/otaliastudios/cameraview/SurfaceCameraPreview.java index 7defa65b..ac63767d 100644 --- a/cameraview/src/main/views/com/otaliastudios/cameraview/SurfaceCameraPreview.java +++ b/cameraview/src/main/views/com/otaliastudios/cameraview/SurfaceCameraPreview.java @@ -44,17 +44,17 @@ class SurfaceCameraPreview extends CameraPreview { public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { LOG.i("callback:", "surfaceChanged", "w:", width, "h:", height, "dispatched:", mDispatched); if (!mDispatched) { - dispatchOnOutputSurfaceAvailable(width, height); + dispatchOnSurfaceAvailable(width, height); mDispatched = true; } else { - dispatchOnOutputSurfaceSizeChanged(width, height); + dispatchOnSurfaceSizeChanged(width, height); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { LOG.i("callback:", "surfaceDestroyed"); - dispatchOnOutputSurfaceDestroyed(); + dispatchOnSurfaceDestroyed(); mDispatched = false; } }); diff --git a/cameraview/src/main/views/com/otaliastudios/cameraview/TextureCameraPreview.java b/cameraview/src/main/views/com/otaliastudios/cameraview/TextureCameraPreview.java index c5664013..05b641fc 100644 --- a/cameraview/src/main/views/com/otaliastudios/cameraview/TextureCameraPreview.java +++ b/cameraview/src/main/views/com/otaliastudios/cameraview/TextureCameraPreview.java @@ -28,17 +28,17 @@ class TextureCameraPreview extends CameraPreview { @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - dispatchOnOutputSurfaceAvailable(width, height); + dispatchOnSurfaceAvailable(width, height); } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { - dispatchOnOutputSurfaceSizeChanged(width, height); + dispatchOnSurfaceSizeChanged(width, height); } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - dispatchOnOutputSurfaceDestroyed(); + dispatchOnSurfaceDestroyed(); return true; } @@ -70,8 +70,8 @@ class TextureCameraPreview extends CameraPreview { @TargetApi(15) @Override - void setInputStreamSize(int width, int height, boolean wasFlipped) { - super.setInputStreamSize(width, height, wasFlipped); + void setStreamSize(int width, int height, boolean wasFlipped) { + super.setStreamSize(width, height, wasFlipped); if (getView().getSurfaceTexture() != null) { getView().getSurfaceTexture().setDefaultBufferSize(width, height); } diff --git a/docs/_posts/2018-12-20-preview-size.md b/docs/_posts/2018-12-20-preview-size.md index 4573f591..5914b5c6 100644 --- a/docs/_posts/2018-12-20-preview-size.md +++ b/docs/_posts/2018-12-20-preview-size.md @@ -55,13 +55,13 @@ This means that part of the preview might be hidden, and the output might contai that were not visible during the capture, **unless it is taken as a snapshot, since snapshots account for cropping**. -## Advanced feature: Preview Size Selection +## Advanced feature: Preview Stream Size Selection **Only do this if you know what you are doing. This is typically not needed - prefer picture/video size selectors, -as they will drive the preview size selection and, eventually, the view size. If what you want is just +as they will drive the preview stream size selection and, eventually, the view size. If what you want is just choose an aspect ratio, do so with [Capture Size](capture-size.html) selection.** -As said, `WRAP_CONTENT` adapts the view boundaries to the preview size. The preview size must be determined +As said, `WRAP_CONTENT` adapts the view boundaries to the preview stream size. The preview stream size must be determined based on the sizes that the device sensor & hardware actually support. This operation is done automatically by the engine. The default selector will do the following: @@ -70,10 +70,10 @@ by the engine. The default selector will do the following: - Try to match both, or just one, or fallback to the biggest available size There are not so many reason why you would replace this, other than control the frame processor size -or, indirectly, the snapshot size. You can, however, hook into the process using `setPreviewSize(SizeSelector)`: +or, indirectly, the snapshot size. You can, however, hook into the process using `setPreviewStreamSize(SizeSelector)`: ```java -cameraView.setPreviewSize(new SizeSelector() { +cameraView.setPreviewStreamSize(new SizeSelector() { @Override public List select(List source) { // Receives a list of available sizes. @@ -82,7 +82,7 @@ cameraView.setPreviewSize(new SizeSelector() { }); ``` -After the preview size is determined, if it has changed since list time, the `CameraView` will receive +After the preview stream size is determined, if it has changed since list time, the `CameraView` will receive another call to `onMeasure` so the `WRAP_CONTENT` magic can take place. To understand how SizeSelectors work and the available utilities, please read the [Capture Size](capture-size.html) document.