From 1bd1816919ead3a721aa51cb3813395503762014 Mon Sep 17 00:00:00 2001 From: chaitanyaraghav Date: Mon, 4 Dec 2017 03:44:00 +0530 Subject: [PATCH] Max video file size (#104) * Added a maximum file size for videos * Revereted changes to the onVideoTaken callback signature * Renamed isRecordingVideo, added xml attribute for video max size and updated the documentation --- README.md | 1 + .../cameraview/CameraViewCallbacksTest.java | 3 -- .../cameraview/IntegrationTest.java | 10 +++++-- .../cameraview/MockCameraController.java | 5 ++++ .../com/otaliastudios/cameraview/Camera1.java | 28 +++++++++++++++++++ .../com/otaliastudios/cameraview/Camera2.java | 16 ++++------- .../cameraview/CameraController.java | 7 +++++ .../otaliastudios/cameraview/CameraView.java | 27 ++++++++++++++++++ cameraview/src/main/res/values/attrs.xml | 2 ++ .../cameraview/demo/CameraActivity.java | 13 ++++----- 10 files changed, 88 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 2b9dcefc..f5428457 100644 --- a/README.md +++ b/README.md @@ -595,6 +595,7 @@ Other APIs not mentioned above are provided, and are well documented and comment |`getPreviewSize()`|Returns the size of the preview surface. If CameraView was not constrained in its layout phase (e.g. it was `wrap_content`), this will return the same aspect ratio of CameraView.| |`getSnapshotSize()`|Returns `getPreviewSize()`, since a snapshot is a preview frame.| |`getPictureSize()`|Returns the size of the output picture. The aspect ratio is consistent with `getPreviewSize()`.| +|`setVideoMaxSize(long)`|Set a max file size (in bytes) for a video recording. There is no file size limit by default unless set by the user.| Take also a look at public methods in `CameraUtils`, `CameraOptions`, `ExtraProperties`. diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewCallbacksTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewCallbacksTest.java index ddf91bf8..5f5054e1 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewCallbacksTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewCallbacksTest.java @@ -19,16 +19,13 @@ import org.mockito.stubbing.Stubber; import static junit.framework.Assert.assertNotNull; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyFloat; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/IntegrationTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/IntegrationTest.java index 60b8fe72..c1c8d6ad 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/IntegrationTest.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/IntegrationTest.java @@ -3,7 +3,6 @@ package com.otaliastudios.cameraview; import android.graphics.Bitmap; import android.graphics.PointF; -import android.media.MediaRecorder; import android.support.test.filters.MediumTest; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; @@ -20,8 +19,13 @@ import java.io.File; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import static org.mockito.Mockito.*; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.mock; /** diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java index cc3026dd..f2347292 100644 --- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java @@ -124,4 +124,9 @@ public class MockCameraController extends CameraController { @Override public void onBufferAvailable(byte[] buffer) { } + + @Override + void setVideoMaxSize(long videoMaxSizeInBytes) { + + } } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java index 2c4e1a17..e1fe1420 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java @@ -676,6 +676,25 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera mMediaRecorder.setOutputFile(mVideoFile.getAbsolutePath()); mMediaRecorder.setOrientationHint(computeSensorToOutputOffset()); + + //If the user sets a max file size, set it to the max file size + if(mVideoMaxSizeInBytes > 0) { + mMediaRecorder.setMaxFileSize(mVideoMaxSizeInBytes); + + //Attach a listener to the media recorder to listen for file size notifications + mMediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() { + @Override + public void onInfo(MediaRecorder mediaRecorder, int i, int i1) { + switch (i){ + case MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED:{ + endVideoImmediately(); + break; + } + } + + } + }); + } // Not needed. mMediaRecorder.setPreviewDisplay(mPreview.getSurface()); } @@ -833,4 +852,13 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera LOG.i("size:", "sizesFromList:", result); return result; } + + @Override + void setVideoMaxSize(long videoMaxSizeInBytes) { + mVideoMaxSizeInBytes = videoMaxSizeInBytes; + } + + // ----------------- + // Additional helper info } + diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera2.java b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera2.java index 48bed418..9c1346d2 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera2.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera2.java @@ -1,23 +1,12 @@ package com.otaliastudios.cameraview; import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.ImageFormat; import android.graphics.PointF; -import android.hardware.camera2.CameraAccessException; -import android.hardware.camera2.CameraCharacteristics; -import android.hardware.camera2.CameraDevice; -import android.hardware.camera2.CameraManager; -import android.hardware.camera2.params.StreamConfigurationMap; import android.location.Location; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.annotation.WorkerThread; import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; @TargetApi(21) class Camera2 extends CameraController { @@ -125,4 +114,9 @@ class Camera2 extends CameraController { public void onBufferAvailable(byte[] buffer) { } + + @Override + void setVideoMaxSize(long videoMaxSizeInBytes) { + + } } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java index a7387fd7..85f2b5b8 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java @@ -66,6 +66,7 @@ abstract class CameraController implements protected boolean mIsCapturingVideo = false; protected int mState = STATE_STOPPED; + protected long mVideoMaxSizeInBytes = 0; // Used for testing. Task mZoomTask = new Task<>(); @@ -317,6 +318,8 @@ abstract class CameraController implements abstract void startAutoFocus(@Nullable Gesture gesture, PointF point); + abstract void setVideoMaxSize(long videoMaxSizeInBytes); + //endregion //region final getters @@ -383,6 +386,10 @@ abstract class CameraController implements return mPreviewSize; } + final boolean isCapturingVideo() { + return mIsCapturingVideo; + } + //endregion //region Orientation utils diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index 2a4bca06..4b0a1dec 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -144,6 +144,10 @@ public class CameraView extends FrameLayout { GestureAction pinchGesture = GestureAction.fromValue(a.getInteger(R.styleable.CameraView_cameraGesturePinch, GestureAction.DEFAULT_PINCH.value())); GestureAction scrollHorizontalGesture = GestureAction.fromValue(a.getInteger(R.styleable.CameraView_cameraGestureScrollHorizontal, GestureAction.DEFAULT_SCROLL_HORIZONTAL.value())); GestureAction scrollVerticalGesture = GestureAction.fromValue(a.getInteger(R.styleable.CameraView_cameraGestureScrollVertical, GestureAction.DEFAULT_SCROLL_VERTICAL.value())); + + //Get max size + float cameraVideoMaxSize = a.getFloat(R.styleable.CameraView_cameraVideoMaxSize, -1); + a.recycle(); // Components @@ -186,6 +190,11 @@ public class CameraView extends FrameLayout { mapGesture(Gesture.SCROLL_HORIZONTAL, scrollHorizontalGesture); mapGesture(Gesture.SCROLL_VERTICAL, scrollVerticalGesture); + //Set camera video maxSize + if(cameraVideoMaxSize > 0) { + setVideoMaxSize((long)cameraVideoMaxSize); + } + if (!isInEditMode()) { mOrientationHelper = new OrientationHelper(context, mCameraCallbacks); } @@ -1364,6 +1373,24 @@ public class CameraView extends FrameLayout { return mPlaySounds; } + /** + * Set a max file size (in bytes) for a video recording. There is no file size limit by default + * unless set by the user. + * + * @param videoMaxSizeInBytes The maximum size of videos in bytes + */ + public void setVideoMaxSize(long videoMaxSizeInBytes){ + mCameraController.setVideoMaxSize(videoMaxSizeInBytes); + } + + /** + * Returns true if the camera is currently recording a video + * @return boolean indicating if the camera is recording a video + */ + public boolean isCapturingVideo(){ + return mCameraController.isCapturingVideo(); + } + //endregion //region Callbacks and dispatching diff --git a/cameraview/src/main/res/values/attrs.xml b/cameraview/src/main/res/values/attrs.xml index 07471631..d52abdd1 100644 --- a/cameraview/src/main/res/values/attrs.xml +++ b/cameraview/src/main/res/values/attrs.xml @@ -110,6 +110,8 @@ + +