From f34e52b175c483d8fa20547eadf8a2f89bacb795 Mon Sep 17 00:00:00 2001 From: Mattia Iavarone Date: Wed, 23 Oct 2019 21:04:25 +0200 Subject: [PATCH] Complete Camera1 integration --- .../cameraview/CameraOptions1Test.java | 14 +++++ .../cameraview/engine/Camera1Engine.java | 52 +++++++++++++++++-- .../cameraview/engine/Camera2Engine.java | 6 ++- 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraOptions1Test.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraOptions1Test.java index 25f218ab..5aaae714 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraOptions1Test.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraOptions1Test.java @@ -22,6 +22,7 @@ import androidx.test.filters.SmallTest; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -345,4 +346,17 @@ public class CameraOptions1Test extends BaseTest { assertEquals(o.getExposureCorrectionMaxValue(), 10f * 0.5f, 0f); } + @Test + public void testPreviewFrameRate() { + Camera.Parameters params = mock(Camera.Parameters.class); + List result = Arrays.asList( + new int[]{20000, 30000}, + new int[]{30000, 60000}, + new int[]{60000, 120000} + ); + when(params.getSupportedPreviewFpsRange()).thenReturn(result); + CameraOptions o = new CameraOptions(params, 0, false); + assertEquals(20F, o.getPreviewFrameRateMinValue(), 0.001F); + assertEquals(120F, o.getPreviewFrameRateMaxValue(), 0.001F); + } } 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 f32232e2..5a65ce71 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera1Engine.java @@ -12,8 +12,8 @@ import android.os.Build; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import androidx.annotation.WorkerThread; +import android.util.Range; import android.view.SurfaceHolder; import com.google.android.gms.tasks.Task; @@ -423,6 +423,7 @@ public class Camera1Engine extends CameraEngine implements applyZoom(params, 0F); applyExposureCorrection(params, 0F); applyPlaySounds(mPlaySounds); + applyPreviewFrameRate(params, 0F); } private void applyDefaultFocus(@NonNull Camera.Parameters params) { @@ -666,8 +667,53 @@ public class Camera1Engine extends CameraEngine implements return false; } - @Override public void setPreviewFrameRate(float previewFrameRate) { - // This method does nothing + @Override + public void setPreviewFrameRate(float previewFrameRate) { + final float old = previewFrameRate; + mPreviewFrameRate = previewFrameRate; + mHandler.run(new Runnable() { + @Override + public void run() { + if (getEngineState() == STATE_STARTED) { + Camera.Parameters params = mCamera.getParameters(); + if (applyPreviewFrameRate(params, old)) mCamera.setParameters(params); + } + mPreviewFrameRateOp.end(null); + } + }); + } + + private boolean applyPreviewFrameRate(@NonNull Camera.Parameters params, + float oldPreviewFrameRate) { + List fpsRanges = params.getSupportedPreviewFpsRange(); + if (mPreviewFrameRate == 0F) { + // 0F is a special value. Fallback to a reasonable default. + for (int[] fpsRange : fpsRanges) { + float lower = (float) fpsRange[0] / 1000F; + float upper = (float) fpsRange[1] / 1000F; + if ((lower <= 30F && 30F <= upper) || (lower <= 24F && 24F <= upper)) { + params.setPreviewFpsRange(fpsRange[0], fpsRange[1]); + return true; + } + } + } else { + // If out of boundaries, adjust it. + mPreviewFrameRate = Math.min(mPreviewFrameRate, + mCameraOptions.getPreviewFrameRateMaxValue()); + mPreviewFrameRate = Math.max(mPreviewFrameRate, + mCameraOptions.getPreviewFrameRateMinValue()); + for (int[] fpsRange : fpsRanges) { + float lower = (float) fpsRange[0] / 1000F; + float upper = (float) fpsRange[1] / 1000F; + float rate = Math.round(mPreviewFrameRate); + if (lower <= rate && rate <= upper) { + params.setPreviewFpsRange(fpsRange[0], fpsRange[1]); + return true; + } + } + } + mPreviewFrameRate = oldPreviewFrameRate; + return false; } //endregion 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 8a6b6851..4b712af0 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/Camera2Engine.java @@ -1289,8 +1289,10 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv } } else { // If out of boundaries, adjust it. - mPreviewFrameRate = Math.min(mPreviewFrameRate, mCameraOptions.getPreviewFrameRateMaxValue()); - mPreviewFrameRate = Math.max(mPreviewFrameRate, mCameraOptions.getPreviewFrameRateMinValue()); + mPreviewFrameRate = Math.min(mPreviewFrameRate, + mCameraOptions.getPreviewFrameRateMaxValue()); + mPreviewFrameRate = Math.max(mPreviewFrameRate, + mCameraOptions.getPreviewFrameRateMinValue()); for (Range fpsRange : fpsRanges) { if (fpsRange.contains(Math.round(mPreviewFrameRate))) { builder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);