diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java index 8bf95be9..3d7207dd 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java @@ -171,7 +171,10 @@ public class CameraViewTest extends BaseTest { // Self managed GestureParser gestures = new GestureParser(empty); assertEquals(cameraView.getPlaySounds(), CameraView.DEFAULT_PLAY_SOUNDS); + assertEquals(cameraView.getAutoFocusResetDelay(), CameraView.DEFAULT_AUTOFOCUS_RESET_DELAY_MILLIS); 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.getGestureAction(Gesture.TAP), gestures.getTapAction()); assertEquals(cameraView.getGestureAction(Gesture.LONG_TAP), gestures.getLongTapAction()); assertEquals(cameraView.getGestureAction(Gesture.PINCH), gestures.getPinchAction()); @@ -649,6 +652,22 @@ public class CameraViewTest extends BaseTest { assertFalse(cameraView.getUseDeviceOrientation()); } + @Test + public void testSetPictureMetering() { + cameraView.setPictureMetering(true); + assertTrue(cameraView.getPictureMetering()); + cameraView.setPictureMetering(false); + assertFalse(cameraView.getPictureMetering()); + } + + @Test + public void testSetPictureSnapshotMetering() { + cameraView.setPictureSnapshotMetering(true); + assertTrue(cameraView.getPictureSnapshotMetering()); + cameraView.setPictureSnapshotMetering(false); + assertFalse(cameraView.getPictureSnapshotMetering()); + } + @Test public void testSetFlash() { cameraView.set(Flash.TORCH); diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index adbda849..ab69fa1b 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -107,6 +107,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver { final static long DEFAULT_AUTOFOCUS_RESET_DELAY_MILLIS = 3000; final static boolean DEFAULT_PLAY_SOUNDS = true; final static boolean DEFAULT_USE_DEVICE_ORIENTATION = true; + final static boolean DEFAULT_PICTURE_METERING = true; + final static boolean DEFAULT_PICTURE_SNAPSHOT_METERING = false; // Self managed parameters private boolean mPlaySounds; @@ -182,6 +184,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver { int videoBitRate = a.getInteger(R.styleable.CameraView_cameraVideoBitRate, 0); int audioBitRate = a.getInteger(R.styleable.CameraView_cameraAudioBitRate, 0); long autoFocusResetDelay = (long) a.getInteger(R.styleable.CameraView_cameraAutoFocusResetDelay, (int) DEFAULT_AUTOFOCUS_RESET_DELAY_MILLIS); + boolean pictureMetering = a.getBoolean(R.styleable.CameraView_cameraPictureMetering, DEFAULT_PICTURE_METERING); + boolean pictureSnapshotMetering = a.getBoolean(R.styleable.CameraView_cameraPictureSnapshotMetering, DEFAULT_PICTURE_SNAPSHOT_METERING); // Size selectors and gestures SizeSelectorParser sizeSelectors = new SizeSelectorParser(a); @@ -228,6 +232,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver { setAudio(controls.getAudio()); setAudioBitRate(audioBitRate); setPictureSize(sizeSelectors.getPictureSizeSelector()); + setPictureMetering(pictureMetering); + setPictureSnapshotMetering(pictureSnapshotMetering); setVideoSize(sizeSelectors.getVideoSizeSelector()); setVideoCodec(controls.getVideoCodec()); setVideoMaxSize(videoMaxSize); @@ -280,7 +286,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - /** * Instantiates the camera engine. * @@ -547,7 +552,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return false; } - /** * Clears any action mapped to the given gesture. * @param gesture which gesture to clear @@ -556,7 +560,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mapGesture(gesture, GestureAction.NONE); } - /** * Returns the action currently mapped to the given gesture. * @@ -569,13 +572,11 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mGestureMap.get(gesture); } - @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return true; // Steal our own events. } - @SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) { @@ -598,7 +599,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return true; } - // Some gesture layout detected a gesture. It's not known at this moment: // (1) if it was mapped to some action (we check here) // (2) if it's supported by the camera (CameraEngine checks) @@ -691,7 +691,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mLifecycle.addObserver(this); } - /** * Starts the camera preview, if not started already. * This should be called onResume(), or when you are ready with permissions. @@ -708,7 +707,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - /** * Checks that we have appropriate permissions. * This means checking that we have audio permissions if audio = Audio.ON. @@ -736,7 +734,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return true; } - /** * If audio is on we will ask for RECORD_AUDIO permission. * If the developer did not add this to its manifest, throw and fire warnings. @@ -760,7 +757,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - /** * Stops the current preview, if any was started. * This should be called onPause(). @@ -772,7 +768,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { if (mCameraPreview != null) mCameraPreview.onPause(); } - /** * Destroys this instance, releasing immediately * the camera resource. @@ -865,7 +860,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - /** * Controls the preview engine. Should only be called * if this CameraView was never added to any window @@ -959,7 +953,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getCameraOptions(); } - /** * Sets exposure adjustment, in EV stops. A positive value will mean brighter picture. * @@ -985,7 +978,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - /** * Returns the current exposure correction value, typically 0 * at start-up. @@ -995,7 +987,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getExposureCorrectionValue(); } - /** * Sets a zoom value. This is not guaranteed to be supported by the current device, * but you can take a look at {@link CameraOptions#isZoomSupported()}. @@ -1012,7 +1003,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setZoom(zoom, null, false); } - /** * Returns the current zoom value, something between 0 and 1. * @return the current zoom value @@ -1021,7 +1011,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getZoomValue(); } - /** * Controls the grids to be drawn over the current layout. * @@ -1036,7 +1025,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mGridLinesLayout.setGridMode(gridMode); } - /** * Gets the current grid mode. * @return the current grid mode @@ -1046,7 +1034,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mGridLinesLayout.getGridMode(); } - /** * Controls the color of the grid lines that will be drawn * over the current layout. @@ -1077,7 +1064,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setHdr(hdr); } - /** * Gets the current hdr value. * @return the current hdr value @@ -1087,7 +1073,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getHdr(); } - /** * Set location coordinates to be found later in the EXIF header * @@ -1103,7 +1088,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setLocation(location); } - /** * Set location values to be found later in the EXIF header * @@ -1113,7 +1097,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setLocation(location); } - /** * Retrieves the location previously applied with setLocation(). * @@ -1124,7 +1107,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getLocation(); } - /** * Sets desired white balance to current camera session. * @@ -1140,7 +1122,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setWhiteBalance(whiteBalance); } - /** * Returns the current white balance behavior. * @return white balance value. @@ -1150,7 +1131,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getWhiteBalance(); } - /** * Sets which camera sensor should be used. * @@ -1163,7 +1143,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setFacing(facing); } - /** * Gets the facing camera currently being used. * @return a facing value. @@ -1173,7 +1152,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getFacing(); } - /** * Toggles the facing value between {@link Facing#BACK} * and {@link Facing#FRONT}. @@ -1195,7 +1173,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getFacing(); } - /** * Sets the flash mode. * @@ -1210,7 +1187,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setFlash(flash); } - /** * Gets the current flash mode. * @return a flash mode @@ -1220,7 +1196,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getFlash(); } - /** * Controls the audio mode. * @@ -1250,7 +1225,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - /** * Gets the current audio value. * @return the current audio value @@ -1260,7 +1234,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getAudio(); } - /** * Sets an {@link AutoFocusMarker} to be notified of autofocus start, end and fail events * so that it can draw elements on screen. @@ -1272,7 +1245,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mMarkerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, autoFocusMarker); } - /** * Sets the current delay in milliseconds to reset the focus after an autofocus process. * @@ -1284,7 +1256,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setAutoFocusResetDelay(delayMillis); } - /** * Returns the current delay in milliseconds to reset the focus after an autofocus process. * @return the current autofocus reset delay in milliseconds. @@ -1292,7 +1263,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { @SuppressWarnings("unused") public long getAutoFocusResetDelay() { return mCameraEngine.getAutoFocusResetDelay(); } - /** * Starts an autofocus process at the given coordinates, with respect * to the view width and height. @@ -1306,7 +1276,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.startAutoFocus(null, new PointF(x, y)); } - /** * ADVANCED FEATURE - sets a size selector for the preview stream. * The {@link SizeSelector} will be invoked with the list of available sizes, and the first @@ -1328,7 +1297,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setPreviewStreamSizeSelector(selector); } - /** * Set the current session type to either picture or video. * @@ -1341,7 +1309,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setMode(mode); } - /** * Gets the current mode. * @return the current mode @@ -1351,7 +1318,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getMode(); } - /** * Sets a capture size selector for picture mode. * The {@link SizeSelector} will be invoked with the list of available sizes, and the first @@ -1364,6 +1330,61 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setPictureSizeSelector(selector); } + /** + * Whether the engine should perform a metering sequence before taking pictures requested + * with {@link #takePicture()}. A metering sequence includes adjusting focus, exposure + * and white balance to ensure a good quality of the result. + * + * When this parameter is true, the quality of the picture increases, but the latency + * increases as well. Defaults to true. + * + * This is a CAMERA2 only API. On CAMERA1, picture metering is always enabled. + * + * @see #setPictureSnapshotMetering(boolean) + * @param enable true to enable + */ + public void setPictureMetering(boolean enable) { + mCameraEngine.setPictureMetering(enable); + } + + /** + * Whether the engine should perform a metering sequence before taking pictures requested + * with {@link #takePicture()}. See {@link #setPictureMetering(boolean)}. + * + * @see #setPictureMetering(boolean) + * @return true if picture metering is enabled + */ + public boolean getPictureMetering() { + return mCameraEngine.getPictureMetering(); + } + + /** + * Whether the engine should perform a metering sequence before taking pictures requested + * with {@link #takePictureSnapshot()}. A metering sequence includes adjusting focus, + * exposure and white balance to ensure a good quality of the result. + * + * When this parameter is true, the quality of the picture increases, but the latency + * increases as well. To keep snapshots fast, this defaults to false. + * + * This is a CAMERA2 only API. On CAMERA1, picture snapshot metering is always disabled. + * + * @see #setPictureMetering(boolean) + * @param enable true to enable + */ + public void setPictureSnapshotMetering(boolean enable) { + mCameraEngine.setPictureSnapshotMetering(enable); + } + + /** + * Whether the engine should perform a metering sequence before taking pictures requested + * with {@link #takePictureSnapshot()}. See {@link #setPictureSnapshotMetering(boolean)}. + * + * @see #setPictureSnapshotMetering(boolean) + * @return true if picture metering is enabled + */ + public boolean getPictureSnapshotMetering() { + return mCameraEngine.getPictureSnapshotMetering(); + } /** * Sets a capture size selector for video mode. @@ -1425,7 +1446,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mListeners.add(cameraListener); } - /** * Remove a {@link CameraListener} that was previously registered. * @@ -1435,7 +1455,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mListeners.remove(cameraListener); } - /** * Clears the list of {@link CameraListener} that are registered * to camera events. @@ -1444,7 +1463,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mListeners.clear(); } - /** * Adds a {@link FrameProcessor} instance to be notified of * new frames in the preview stream. @@ -1460,7 +1478,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - /** * Remove a {@link FrameProcessor} that was previously registered. * @@ -1475,7 +1492,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - /** * Clears the list of {@link FrameProcessor} that have been registered * to preview frames. @@ -1488,7 +1504,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - /** * Asks the camera to capture an image of the current scene. * This will trigger {@link CameraListener#onPictureTaken(PictureResult)} if a listener @@ -1504,7 +1519,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.takePicture(stub); } - /** * Asks the camera to capture a snapshot of the current preview. * This eventually triggers {@link CameraListener#onPictureTaken(PictureResult)} if a listener @@ -1520,7 +1534,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.takePictureSnapshot(stub); } - /** * Starts recording a video. Video will be written to the given file, * so callers should ensure they have appropriate permissions to write to the file. @@ -1560,7 +1573,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { }); } - /** * Starts recording a video. Video will be written to the given file, * so callers should ensure they have appropriate permissions to write to the file. @@ -1628,10 +1640,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver { takeVideoSnapshot(file); } - // TODO: pauseVideo and resumeVideo? There is mediarecorder.pause(), but API 24... - /** * Stops capturing video or video snapshots being recorded, if there was any. * This will fire {@link CameraListener#onVideoTaken(VideoResult)}. @@ -1699,7 +1709,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - /** * Returns the size used for pictures taken with {@link #takePicture()}, * or null if it hasn't been computed (for example if the surface is not ready), @@ -1714,7 +1723,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getPictureSize(Reference.OUTPUT); } - /** * Returns the size used for videos taken with {@link #takeVideo(File)}, * or null if it hasn't been computed (for example if the surface is not ready), @@ -1729,7 +1737,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getVideoSize(Reference.OUTPUT); } - // If we end up here, we're in M. @TargetApi(Build.VERSION_CODES.M) private void requestPermissions(boolean requestCamera, boolean requestAudio) { @@ -1751,7 +1758,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - @SuppressLint("NewApi") private void playSound(int soundType) { if (mPlaySounds) { @@ -1760,7 +1766,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - /** * Controls whether CameraView should play sound effects on certain * events (picture taken, focus complete). Note that: @@ -1774,7 +1779,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setPlaySounds(playSounds); } - /** * Gets the current sound effect behavior. * @@ -1821,7 +1825,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setVideoCodec(codec); } - /** * Gets the current encoder for video recordings. * @return the current video codec @@ -1831,7 +1834,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getVideoCodec(); } - /** * Sets the maximum size in bytes for recorded video files. * Once this size is reached, the recording will automatically stop. @@ -1843,7 +1845,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setVideoMaxSize(videoMaxSizeInBytes); } - /** * Returns the maximum size in bytes for recorded video files, or 0 * if no size was set. @@ -1855,7 +1856,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getVideoMaxSize(); } - /** * Sets the maximum duration in milliseconds for video recordings. * Once this duration is reached, the recording will automatically stop. @@ -1867,7 +1867,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { mCameraEngine.setVideoMaxDuration(videoMaxDurationMillis); } - /** * Returns the maximum duration in milliseconds for video recordings, or 0 * if no limit was set. @@ -1879,7 +1878,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.getVideoMaxDuration(); } - /** * Returns true if the camera is currently recording a video * @return boolean indicating if the camera is recording a video @@ -1888,7 +1886,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { return mCameraEngine.isTakingVideo(); } - /** * Returns true if the camera is currently capturing a picture * @return boolean indicating if the camera is capturing a picture 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 0cc4fa9a..27acdd47 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java @@ -167,6 +167,8 @@ public abstract class CameraEngine implements @SuppressWarnings("WeakerAccess") protected float mZoomValue; @SuppressWarnings("WeakerAccess") protected float mExposureCorrectionValue; @SuppressWarnings("WeakerAccess") protected boolean mPlaySounds; + @SuppressWarnings("WeakerAccess") protected boolean mPictureMetering; + @SuppressWarnings("WeakerAccess") protected boolean mPictureSnapshotMetering; // Can be private @VisibleForTesting Handler mCrashHandler; @@ -1008,6 +1010,22 @@ public abstract class CameraEngine implements return mAutoFocusResetDelayMillis > 0 && mAutoFocusResetDelayMillis != Long.MAX_VALUE; } + public final void setPictureMetering(boolean enable) { + mPictureMetering = enable; + } + + public final boolean getPictureMetering() { + return mPictureMetering; + } + + public final void setPictureSnapshotMetering(boolean enable) { + mPictureSnapshotMetering = enable; + } + + public final boolean getPictureSnapshotMetering() { + return mPictureSnapshotMetering; + } + //endregion //region Abstract setters and APIs diff --git a/cameraview/src/main/res/values/attrs.xml b/cameraview/src/main/res/values/attrs.xml index 59905eb1..f7d0c143 100644 --- a/cameraview/src/main/res/values/attrs.xml +++ b/cameraview/src/main/res/values/attrs.xml @@ -141,6 +141,10 @@ + + + +