Rename SessionType to Mode. takePicture fails when Mode == VIDEO

v2
Mattia Iavarone 7 years ago
parent 348cda70ad
commit 7884f486e5
  1. 5
      MIGRATION.md
  2. 14
      README.md
  3. 6
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraOptions1Test.java
  4. 4
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewCallbacksTest.java
  5. 14
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java
  6. 36
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/IntegrationTest.java
  7. 4
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/MockCameraController.java
  8. 161
      cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java
  9. 2
      cameraview/src/main/java/com/otaliastudios/cameraview/Camera2.java
  10. 10
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java
  11. 15
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraOptions.java
  12. 55
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
  13. 54
      cameraview/src/main/options/com/otaliastudios/cameraview/Mode.java
  14. 56
      cameraview/src/main/options/com/otaliastudios/cameraview/SessionType.java
  15. 2
      cameraview/src/main/res/values/attrs.xml
  16. 4
      demo/src/main/java/com/otaliastudios/cameraview/demo/CameraActivity.java
  17. 11
      demo/src/main/java/com/otaliastudios/cameraview/demo/Control.java
  18. 2
      demo/src/main/res/layout/activity_camera.xml

@ -17,3 +17,8 @@
- onPictureTaken(): now passing a PictureResult. Use PictureResult.getJpeg() to access the jpeg stream.
- CameraUtils.BitmapCallback: has been moved in a separate BitmapCallback class.
- isCapturingVideo(): renamed to isTakingVideo().
- SessionType: renamed to Mode. This means that setSessionType() and cameraSessionType are renamed to
setMode() and cameraMode.
- CameraOptions.isVideoSnapshotSupported(): removed, this would be ambiguous now. While in video
mode, you can only use takePictureSnapshot(), not takePicture().
- takePicture(): will now throw an exception if called when Mode == Mode.VIDEO. You can only take snapshots.

@ -410,8 +410,8 @@ Most camera parameters can be controlled through XML attributes or linked method
app:cameraFacing="back"
app:cameraFlash="off"
app:cameraGrid="off"
app:cameraSessionType="picture"
app:cameraVideoQuality="max480p"
app:cameraMode="picture"
app:cameraVideoCodec="deviceDefault"
app:cameraWhiteBalance="auto"
app:cameraHdr="off"
@ -423,7 +423,7 @@ Most camera parameters can be controlled through XML attributes or linked method
|XML Attribute|Method|Values|Default Value|
|-------------|------|------|-------------|
|[`cameraSessionType`](#camerasessiontype)|`setSessionType()`|`picture` `video`|`picture`|
|[`cameraMode`](#cameramode)|`setMode()`|`picture` `video`|`picture`|
|[`cameraFacing`](#camerafacing)|`setFacing()`|`back` `front`|`back`|
|[`cameraFlash`](#cameraflash)|`setFlash()`|`off` `on` `auto` `torch`|`off`|
|[`cameraGrid`](#cameragrid)|`setGrid()`|`off` `draw3x3` `draw4x4` `drawPhi`|`off`|
@ -436,21 +436,21 @@ Most camera parameters can be controlled through XML attributes or linked method
|[`cameraVideoMaxSize`](#cameravideomaxsize)|`setVideoMaxSize()`|number|`0`|
|[`cameraVideoMaxDuration`](#cameravideomaxduration)|`setVideoMaxDuration()`|number|`0`|
#### cameraSessionType
#### cameraMode
What to capture - either picture or video. This has a couple of consequences:
- Sizing: picture and preview size are chosen among the available picture or video sizes,
depending on the flag. The picture size is chosen according to the given [size selector](#picture-size).
When `video`, in addition, we try to match the `videoQuality` aspect ratio.
- Picture capturing: while recording a video, image capturing might work, but it is not guaranteed
(it's device dependent)
- Capturing: while in picture mode, `takeVideo` will throw an exception.
- Capturing: while in video mode, `takePicture` will throw an exception, but picture snapshots are supported.
- Permission behavior: when requesting a `video` session, the record audio permission will be requested.
If this is needed, the audio permission should be added to your manifest or the app will crash.
```java
cameraView.setSessionType(SessionType.PICTURE);
cameraView.setSessionType(SessionType.VIDEO);
cameraView.setMode(Mode.PICTURE);
cameraView.setMode(Mode.VIDEO);
```
#### cameraFacing

@ -35,7 +35,6 @@ public class CameraOptions1Test extends BaseTest {
assertTrue(o.getSupportedHdr().isEmpty());
assertFalse(o.isAutoFocusSupported());
assertFalse(o.isExposureCorrectionSupported());
assertFalse(o.isVideoSnapshotSupported());
assertFalse(o.isZoomSupported());
assertEquals(o.getExposureCorrectionMaxValue(), 0f, 0);
assertEquals(o.getExposureCorrectionMinValue(), 0f, 0);
@ -135,11 +134,11 @@ public class CameraOptions1Test extends BaseTest {
Collection<Grid> grids = o.getSupportedControls(Grid.class);
Collection<VideoQuality> video = o.getSupportedControls(VideoQuality.class);
Collection<SessionType> sessions = o.getSupportedControls(SessionType.class);
Collection<Mode> sessions = o.getSupportedControls(Mode.class);
Collection<Audio> audio = o.getSupportedControls(Audio.class);
assertEquals(grids.size(), Grid.values().length);
assertEquals(video.size(), VideoQuality.values().length);
assertEquals(sessions.size(), SessionType.values().length);
assertEquals(sessions.size(), Mode.values().length);
assertEquals(audio.size(), Audio.values().length);
}
@ -223,7 +222,6 @@ public class CameraOptions1Test extends BaseTest {
when(params.isZoomSupported()).thenReturn(true);
when(params.getSupportedFocusModes()).thenReturn(Arrays.asList(Camera.Parameters.FOCUS_MODE_AUTO));
CameraOptions o = new CameraOptions(params, false);
assertTrue(o.isVideoSnapshotSupported());
assertTrue(o.isZoomSupported());
assertTrue(o.isAutoFocusSupported());
}

@ -2,8 +2,6 @@ package com.otaliastudios.cameraview;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.PointF;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
@ -63,7 +61,7 @@ public class CameraViewCallbacksTest extends BaseTest {
}
@Override
protected boolean checkPermissions(SessionType sessionType, Audio audio) {
protected boolean checkPermissions(Mode mode, Audio audio) {
return true;
}
};

@ -50,7 +50,7 @@ public class CameraViewTest extends BaseTest {
}
@Override
protected boolean checkPermissions(SessionType sessionType, Audio audio) {
protected boolean checkPermissions(Mode mode, Audio audio) {
return hasPermissions;
}
};
@ -85,7 +85,7 @@ public class CameraViewTest extends BaseTest {
assertEquals(cameraView.getFacing(), Facing.DEFAULT);
assertEquals(cameraView.getGrid(), Grid.DEFAULT);
assertEquals(cameraView.getWhiteBalance(), WhiteBalance.DEFAULT);
assertEquals(cameraView.getSessionType(), SessionType.DEFAULT);
assertEquals(cameraView.getMode(), Mode.DEFAULT);
assertEquals(cameraView.getHdr(), Hdr.DEFAULT);
assertEquals(cameraView.getAudio(), Audio.DEFAULT);
assertEquals(cameraView.getVideoQuality(), VideoQuality.DEFAULT);
@ -503,11 +503,11 @@ public class CameraViewTest extends BaseTest {
}
@Test
public void testSessionType() {
cameraView.set(SessionType.VIDEO);
assertEquals(cameraView.getSessionType(), SessionType.VIDEO);
cameraView.set(SessionType.PICTURE);
assertEquals(cameraView.getSessionType(), SessionType.PICTURE);
public void testMode() {
cameraView.set(Mode.VIDEO);
assertEquals(cameraView.getMode(), Mode.VIDEO);
cameraView.set(Mode.PICTURE);
assertEquals(cameraView.getMode(), Mode.PICTURE);
}
@Test

@ -37,7 +37,7 @@ import static org.mockito.Mockito.mock;
*/
@RunWith(AndroidJUnit4.class)
@MediumTest
@Ignore
// @Ignore
public class IntegrationTest extends BaseTest {
@Rule
@ -231,8 +231,8 @@ public class IntegrationTest extends BaseTest {
}
@Test
public void testSetSessionType() throws Exception {
camera.setSessionType(SessionType.PICTURE);
public void testSetMode() throws Exception {
camera.setMode(Mode.PICTURE);
waitForOpen(true);
// set session type should call stop and start again.
@ -240,11 +240,11 @@ public class IntegrationTest extends BaseTest {
doCountDown(latch).when(listener).onCameraOpened(any(CameraOptions.class));
doCountDown(latch).when(listener).onCameraClosed();
camera.setSessionType(SessionType.VIDEO);
camera.setMode(Mode.VIDEO);
boolean did = latch.await(2, TimeUnit.SECONDS);
assertTrue("Handles setSessionType while active", did);
assertEquals(camera.getSessionType(), SessionType.VIDEO);
assertTrue("Handles setMode while active", did);
assertEquals(camera.getMode(), Mode.VIDEO);
}
//endregion
@ -391,7 +391,7 @@ public class IntegrationTest extends BaseTest {
public void testSetVideoQuality_whileRecording() throws Throwable {
// Can't run on Travis, MediaRecorder not supported.
// Error while starting MediaRecorder. java.lang.RuntimeException: start failed.
camera.setSessionType(SessionType.VIDEO);
camera.setMode(Mode.VIDEO);
waitForVideoQuality(VideoQuality.HIGHEST);
waitForOpen(true);
waitForVideoStart();
@ -400,8 +400,8 @@ public class IntegrationTest extends BaseTest {
}
@Test
public void testSetVideoQuality_whileInPictureSessionType() {
camera.setSessionType(SessionType.PICTURE);
public void testSetVideoQuality_whileInPictureMode() {
camera.setMode(Mode.PICTURE);
waitForVideoQuality(VideoQuality.HIGHEST);
waitForOpen(true);
waitForVideoQuality(VideoQuality.LOWEST);
@ -435,7 +435,7 @@ public class IntegrationTest extends BaseTest {
// Fails on Travis. Some emulators can't deal with MediaRecorder
// Error while starting MediaRecorder. java.lang.RuntimeException: start failed.
// as documented. This works locally though.
camera.setSessionType(SessionType.PICTURE);
camera.setMode(Mode.PICTURE);
waitForOpen(true);
waitForVideoStart();
waitForUiException();
@ -446,7 +446,7 @@ public class IntegrationTest extends BaseTest {
// Fails on Travis. Some emulators can't deal with MediaRecorder,
// Error while starting MediaRecorder. java.lang.RuntimeException: start failed.
// as documented. This works locally though.
camera.setSessionType(SessionType.VIDEO);
camera.setMode(Mode.VIDEO);
waitForOpen(true);
camera.takeVideo(null, 4000);
waitForVideoEnd(true);
@ -454,7 +454,7 @@ public class IntegrationTest extends BaseTest {
@Test
public void testEndVideo_withoutStarting() {
camera.setSessionType(SessionType.VIDEO);
camera.setMode(Mode.VIDEO);
waitForOpen(true);
camera.stopVideo();
waitForVideoEnd(false);
@ -462,7 +462,7 @@ public class IntegrationTest extends BaseTest {
@Test
public void testEndVideo_withMaxSize() {
camera.setSessionType(SessionType.VIDEO);
camera.setMode(Mode.VIDEO);
camera.setVideoMaxSize(500*1000); // 0.5 mb
waitForOpen(true);
waitForVideoStart();
@ -471,7 +471,7 @@ public class IntegrationTest extends BaseTest {
@Test
public void testEndVideo_withMaxDuration() {
camera.setSessionType(SessionType.VIDEO);
camera.setMode(Mode.VIDEO);
camera.setVideoMaxDuration(4000);
waitForOpen(true);
waitForVideoStart();
@ -540,6 +540,14 @@ public class IntegrationTest extends BaseTest {
assertFalse(result.isSnapshot());
}
@Test(expected = RuntimeException.class)
public void testCapturePicture_whileInVideoMode() throws Throwable {
camera.setMode(Mode.VIDEO);
waitForOpen(true);
camera.takePicture();
waitForUiException();
}
@Test
public void testCaptureSnapshot_beforeStarted() {
camera.takePictureSnapshot();

@ -72,8 +72,8 @@ public class MockCameraController extends CameraController {
}
@Override
void setSessionType(SessionType sessionType) {
mSessionType = sessionType;
void setMode(Mode mode) {
mMode = mode;
}
@Override

@ -187,7 +187,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
mergeWhiteBalance(params, WhiteBalance.DEFAULT);
mergeHdr(params, Hdr.DEFAULT);
mergePlaySound(mPlaySounds);
params.setRecordingHint(mSessionType == SessionType.VIDEO);
params.setRecordingHint(mMode == Mode.VIDEO);
mCamera.setParameters(params);
// Try starting preview.
@ -284,9 +284,9 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
}
@Override
void setSessionType(SessionType sessionType) {
if (sessionType != mSessionType) {
mSessionType = sessionType;
void setMode(Mode mode) {
if (mode != mMode) {
mMode = mode;
schedule(null, true, new Runnable() {
@Override
public void run() {
@ -441,7 +441,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
private void applyDefaultFocus(Camera.Parameters params) {
List<String> modes = params.getSupportedFocusModes();
if (mSessionType == SessionType.VIDEO &&
if (mMode == Mode.VIDEO &&
modes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
return;
@ -478,7 +478,7 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
throw new IllegalStateException("Can't change video quality while recording a video.");
}
if (mSessionType == SessionType.VIDEO) {
if (mMode == Mode.VIDEO) {
// Change capture size to a size that fits the video aspect ratio.
Size oldSize = mPictureSize;
mPictureSize = computePictureSize();
@ -503,11 +503,14 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
schedule(null, true, new Runnable() {
@Override
public void run() {
if (mMode == Mode.VIDEO) {
throw new IllegalStateException("Can't take hq pictures while in VIDEO mode");
}
LOG.v("takePicture: performing.", mIsCapturingImage);
if (mIsCapturingImage) return;
if (mIsTakingVideo && !mCameraOptions.isVideoSnapshotSupported()) return;
mIsCapturingImage = true;
final int sensorToOutput = offset(REF_SENSOR, REF_OUTPUT);
final Size outputSize = getPictureSize(REF_OUTPUT);
Camera.Parameters params = mCamera.getParameters();
@ -556,15 +559,15 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
schedule(null, true, new Runnable() {
@Override
public void run() {
LOG.v("takePictureSnapshot: performing.", mIsCapturingImage);
if (mIsCapturingImage) return;
// This won't work while capturing a video.
// Switch to takePicture.
// TODO v2: what to do here?
if (mIsTakingVideo) {
takePicture();
// TODO v2: what to do here?
// This won't work while capturing a video.
// But we want it to work.
return;
}
LOG.v("takePictureSnapshot: performing.", mIsCapturingImage);
if (mIsCapturingImage) return;
mIsCapturingImage = true;
mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
@Override
@ -654,74 +657,74 @@ class Camera1 extends CameraController implements Camera.PreviewCallback, Camera
schedule(mStartVideoTask, true, new Runnable() {
@Override
public void run() {
if (mMode == Mode.PICTURE) {
throw new IllegalStateException("Can't record video while in PICTURE mode");
}
if (mIsTakingVideo) return;
if (mSessionType == SessionType.VIDEO) {
mIsTakingVideo = true;
// Create the video result
CamcorderProfile profile = getCamcorderProfile();
Size videoSize = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
mVideoResult = new VideoResult();
mVideoResult.file = videoFile;
mVideoResult.isSnapshot = false;
mVideoResult.codec = mVideoCodec;
mVideoResult.location = mLocation;
mVideoResult.rotation = offset(REF_SENSOR, REF_OUTPUT);
mVideoResult.size = flip(REF_SENSOR, REF_OUTPUT) ? videoSize.flip() : videoSize;
// Initialize the media recorder
mCamera.unlock();
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
if (mAudio == Audio.ON) {
// Must be called before setOutputFormat.
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
}
mMediaRecorder.setOutputFormat(profile.fileFormat);
mMediaRecorder.setVideoFrameRate(profile.videoFrameRate);
mMediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
mMediaRecorder.setVideoEncoder(mMapper.map(mVideoCodec));
mMediaRecorder.setVideoEncodingBitRate(profile.videoBitRate);
if (mAudio == Audio.ON) {
mMediaRecorder.setAudioChannels(profile.audioChannels);
mMediaRecorder.setAudioSamplingRate(profile.audioSampleRate);
mMediaRecorder.setAudioEncoder(profile.audioCodec);
mMediaRecorder.setAudioEncodingBitRate(profile.audioBitRate);
}
if (mLocation != null) {
mMediaRecorder.setLocation(
(float) mLocation.getLatitude(),
(float) mLocation.getLongitude());
}
mMediaRecorder.setOutputFile(mVideoResult.getFile().getAbsolutePath());
mMediaRecorder.setOrientationHint(mVideoResult.getRotation());
mMediaRecorder.setMaxFileSize(mVideoMaxSize);
mMediaRecorder.setMaxDuration(mVideoMaxDuration);
mMediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
@Override
public void onInfo(MediaRecorder mediaRecorder, int what, int extra) {
switch (what) {
case MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED:
case MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED:
stopVideoImmediately();
break;
}
mIsTakingVideo = true;
// Create the video result
CamcorderProfile profile = getCamcorderProfile();
Size videoSize = new Size(profile.videoFrameWidth, profile.videoFrameHeight);
mVideoResult = new VideoResult();
mVideoResult.file = videoFile;
mVideoResult.isSnapshot = false;
mVideoResult.codec = mVideoCodec;
mVideoResult.location = mLocation;
mVideoResult.rotation = offset(REF_SENSOR, REF_OUTPUT);
mVideoResult.size = flip(REF_SENSOR, REF_OUTPUT) ? videoSize.flip() : videoSize;
// Initialize the media recorder
mCamera.unlock();
mMediaRecorder = new MediaRecorder();
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
if (mAudio == Audio.ON) {
// Must be called before setOutputFormat.
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
}
mMediaRecorder.setOutputFormat(profile.fileFormat);
mMediaRecorder.setVideoFrameRate(profile.videoFrameRate);
mMediaRecorder.setVideoSize(profile.videoFrameWidth, profile.videoFrameHeight);
mMediaRecorder.setVideoEncoder(mMapper.map(mVideoCodec));
mMediaRecorder.setVideoEncodingBitRate(profile.videoBitRate);
if (mAudio == Audio.ON) {
mMediaRecorder.setAudioChannels(profile.audioChannels);
mMediaRecorder.setAudioSamplingRate(profile.audioSampleRate);
mMediaRecorder.setAudioEncoder(profile.audioCodec);
mMediaRecorder.setAudioEncodingBitRate(profile.audioBitRate);
}
if (mLocation != null) {
mMediaRecorder.setLocation(
(float) mLocation.getLatitude(),
(float) mLocation.getLongitude());
}
mMediaRecorder.setOutputFile(mVideoResult.getFile().getAbsolutePath());
mMediaRecorder.setOrientationHint(mVideoResult.getRotation());
mMediaRecorder.setMaxFileSize(mVideoMaxSize);
mMediaRecorder.setMaxDuration(mVideoMaxDuration);
mMediaRecorder.setOnInfoListener(new MediaRecorder.OnInfoListener() {
@Override
public void onInfo(MediaRecorder mediaRecorder, int what, int extra) {
switch (what) {
case MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED:
case MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED:
stopVideoImmediately();
break;
}
});
// Not needed. mMediaRecorder.setPreviewDisplay(mPreview.getSurface());
try {
mMediaRecorder.prepare();
mMediaRecorder.start();
} catch (Exception e) {
LOG.e("Error while starting MediaRecorder. Swallowing.", e);
mVideoResult = null;
mCamera.lock();
stopVideoImmediately();
}
} else {
throw new IllegalStateException("Can't record video while session type is picture");
});
// Not needed. mMediaRecorder.setPreviewDisplay(mPreview.getSurface());
try {
mMediaRecorder.prepare();
mMediaRecorder.start();
} catch (Exception e) {
LOG.e("Error while starting MediaRecorder. Swallowing.", e);
mVideoResult = null;
mCamera.lock();
stopVideoImmediately();
}
}
});

@ -36,7 +36,7 @@ class Camera2 extends CameraController {
}
@Override
void setSessionType(SessionType sessionType) {
void setMode(Mode mode) {
}

@ -44,7 +44,7 @@ abstract class CameraController implements
protected WhiteBalance mWhiteBalance;
protected VideoQuality mVideoQuality;
protected VideoCodec mVideoCodec;
protected SessionType mSessionType;
protected Mode mMode;
protected Hdr mHdr;
protected Location mLocation;
protected Audio mAudio;
@ -299,7 +299,7 @@ abstract class CameraController implements
//region Abstract setters and APIs
// Should restart the session if active.
abstract void setSessionType(SessionType sessionType);
abstract void setMode(Mode mode);
// Should restart the session if active.
abstract void setFacing(Facing facing);
@ -377,8 +377,8 @@ abstract class CameraController implements
return mVideoMaxDuration;
}
final SessionType getSessionType() {
return mSessionType;
final Mode getMode() {
return mMode;
}
final Hdr getHdr() {
@ -479,7 +479,7 @@ abstract class CameraController implements
boolean flip = flip(REF_SENSOR, REF_VIEW);
SizeSelector selector;
if (mSessionType == SessionType.PICTURE) {
if (mMode == Mode.PICTURE) {
selector = SizeSelectors.or(mPictureSizeSelector, SizeSelectors.biggest());
} else {
// The Camcorder internally checks for cameraParameters.getSupportedVideoSizes() etc.

@ -148,8 +148,8 @@ public class CameraOptions {
return (Collection<T>) Arrays.asList(Grid.values());
} else if (controlClass.equals(Hdr.class)) {
return (Collection<T>) getSupportedHdr();
} else if (controlClass.equals(SessionType.class)) {
return (Collection<T>) Arrays.asList(SessionType.values());
} else if (controlClass.equals(Mode.class)) {
return (Collection<T>) Arrays.asList(Mode.values());
} else if (controlClass.equals(VideoQuality.class)) {
return (Collection<T>) Arrays.asList(VideoQuality.values());
} else if (controlClass.equals(WhiteBalance.class)) {
@ -255,17 +255,6 @@ public class CameraOptions {
}
/**
* Whether video snapshots are supported. If this is false, taking pictures
* while recording a video will have no effect.
*
* @return whether video snapshot is supported.
*/
public boolean isVideoSnapshotSupported() {
return videoSnapshotSupported;
}
/**
* Whether auto focus is supported. This means you can map gestures to
* {@link GestureAction#FOCUS} or {@link GestureAction#FOCUS_WITH_MARKER}

@ -101,7 +101,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
Grid grid = Grid.fromValue(a.getInteger(R.styleable.CameraView_cameraGrid, Grid.DEFAULT.value()));
WhiteBalance whiteBalance = WhiteBalance.fromValue(a.getInteger(R.styleable.CameraView_cameraWhiteBalance, WhiteBalance.DEFAULT.value()));
VideoQuality videoQuality = VideoQuality.fromValue(a.getInteger(R.styleable.CameraView_cameraVideoQuality, VideoQuality.DEFAULT.value()));
SessionType sessionType = SessionType.fromValue(a.getInteger(R.styleable.CameraView_cameraSessionType, SessionType.DEFAULT.value()));
Mode mode = Mode.fromValue(a.getInteger(R.styleable.CameraView_cameraMode, Mode.DEFAULT.value()));
Hdr hdr = Hdr.fromValue(a.getInteger(R.styleable.CameraView_cameraHdr, Hdr.DEFAULT.value()));
Audio audio = Audio.fromValue(a.getInteger(R.styleable.CameraView_cameraAudio, Audio.DEFAULT.value()));
VideoCodec codec = VideoCodec.fromValue(a.getInteger(R.styleable.CameraView_cameraVideoCodec, VideoCodec.DEFAULT.value()));
@ -169,7 +169,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
// Apply camera controller params
setFacing(facing);
setFlash(flash);
setSessionType(sessionType);
setMode(mode);
setVideoQuality(videoQuality);
setWhiteBalance(whiteBalance);
setGrid(grid);
@ -551,7 +551,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
public void start() {
if (!isEnabled()) return;
if (checkPermissions(getSessionType(), getAudio())) {
if (checkPermissions(getMode(), getAudio())) {
// Update display orientation for current CameraController
mOrientationHelper.enable(getContext());
mCameraController.setDisplayOffset(mOrientationHelper.getDisplayOffset());
@ -563,19 +563,19 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
/**
* Checks that we have appropriate permissions for this session type.
* Throws if session = audio and manifest did not add the microphone permissions.
* @param sessionType the sessionType to be checked
* @param mode the sessionType to be checked
* @param audio the audio setting to be checked
* @return true if we can go on, false otherwise.
*/
@SuppressLint("NewApi")
protected boolean checkPermissions(SessionType sessionType, Audio audio) {
checkPermissionsManifestOrThrow(sessionType, audio);
protected boolean checkPermissions(Mode mode, Audio audio) {
checkPermissionsManifestOrThrow(mode, audio);
// Manifest is OK at this point. Let's check runtime permissions.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) return true;
Context c = getContext();
boolean needsCamera = true;
boolean needsAudio = sessionType == SessionType.VIDEO && audio == Audio.ON;
boolean needsAudio = mode == Mode.VIDEO && audio == Audio.ON;
needsCamera = needsCamera && c.checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED;
needsAudio = needsAudio && c.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED;
@ -593,8 +593,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
* If the developer did not add this to its manifest, throw and fire warnings.
* (Hoping this is not caught elsewhere... we should test).
*/
private void checkPermissionsManifestOrThrow(SessionType sessionType, Audio audio) {
if (sessionType == SessionType.VIDEO && audio == Audio.ON) {
private void checkPermissionsManifestOrThrow(Mode mode, Audio audio) {
if (mode == Mode.VIDEO && audio == Audio.ON) {
try {
PackageManager manager = getContext().getPackageManager();
PackageInfo info = manager.getPackageInfo(getContext().getPackageName(), PackageManager.GET_PERMISSIONS);
@ -656,8 +656,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
setGrid((Grid) control);
} else if (control instanceof Hdr) {
setHdr((Hdr) control);
} else if (control instanceof SessionType) {
setSessionType((SessionType) control);
} else if (control instanceof Mode) {
setMode((Mode) control);
} else if (control instanceof VideoQuality) {
setVideoQuality((VideoQuality) control);
} else if (control instanceof WhiteBalance) {
@ -932,7 +932,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
// Check did took place, or will happen on start().
mCameraController.setAudio(audio);
} else if (checkPermissions(getSessionType(), audio)) {
} else if (checkPermissions(getMode(), audio)) {
// Camera is running. Pass.
mCameraController.setAudio(audio);
@ -971,24 +971,21 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
/**
* Set the current session type to either picture or video.
* When sessionType is video,
* - {@link #takeVideo(File)} will not throw any exception
* - {@link #takePicture()} might fallback to {@link #takePictureSnapshot()} or might not work
*
* @see SessionType#PICTURE
* @see SessionType#VIDEO
* @see Mode#PICTURE
* @see Mode#VIDEO
*
* @param sessionType desired session type.
* @param mode desired session type.
*/
public void setSessionType(SessionType sessionType) {
public void setMode(Mode mode) {
if (sessionType == getSessionType() || isStopped()) {
if (mode == getMode() || isStopped()) {
// Check did took place, or will happen on start().
mCameraController.setSessionType(sessionType);
mCameraController.setMode(mode);
} else if (checkPermissions(sessionType, getAudio())) {
// Camera is running. CameraImpl setSessionType will do the trick.
mCameraController.setSessionType(sessionType);
} else if (checkPermissions(mode, getAudio())) {
// Camera is running. CameraImpl setMode will do the trick.
mCameraController.setMode(mode);
} else {
// This means that the audio permission is being asked.
@ -1001,11 +998,11 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
/**
* Gets the current session type.
* @return the current session type
* Gets the current mode.
* @return the current mode
*/
public SessionType getSessionType() {
return mCameraController.getSessionType();
public Mode getMode() {
return mCameraController.getMode();
}
@ -1123,7 +1120,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
* This will trigger {@link CameraListener#onPictureTaken(PictureResult)} if a listener
* was registered.
*
* Note that if sessionType is {@link SessionType#VIDEO}, this
* Note that if sessionType is {@link Mode#VIDEO}, this
* might fall back to {@link #takePictureSnapshot()} (that is, we might capture a preview frame).
*
* @see #takePictureSnapshot()

@ -0,0 +1,54 @@
package com.otaliastudios.cameraview;
import java.io.File;
/**
* Type of the session to be opened or to move to.
* Session modes have influence over the capture and preview size, ability to shoot pictures,
* focus modes, runtime permissions needed.
*
* @see CameraView#setMode(Mode)
*/
public enum Mode implements Control {
/**
* Session used to capture pictures.
*
* - {@link CameraView#takeVideo(File)} will throw an exception
* - Only the camera permission is requested
* - Capture size is chosen according to the current picture size selector
*/
PICTURE(0),
/**
* Session used to capture videos.
*
* - {@link CameraView#takePicture()} will throw an exception
* - Camera and audio record permissions are requested
* - Capture size is chosen according to the current video size selector
*/
VIDEO(1);
static final Mode DEFAULT = PICTURE;
private int value;
Mode(int value) {
this.value = value;
}
int value() {
return value;
}
static Mode fromValue(int value) {
Mode[] list = Mode.values();
for (Mode action : list) {
if (action.value() == value) {
return action;
}
}
return null;
}
}

@ -1,56 +0,0 @@
package com.otaliastudios.cameraview;
/**
* Type of the session to be opened or to move to.
* Session types have influence over the capture and preview size, ability to shoot pictures,
* focus modes, runtime permissions needed.
*
* @see CameraView#setSessionType(SessionType)
*/
public enum SessionType implements Control {
/**
* Session optimized to capture pictures.
*
* - Trying to take videos in this session will throw an exception
* - Only the camera permission is requested
* - Capture size is chosen according to the current picture size selector
*/
PICTURE(0),
/**
* Session optimized to capture videos.
*
* - Trying to take pictures in this session will work, though with lower quality
* - Trying to take pictures while recording a video will work if supported
* - Camera and audio record permissions are requested
* - Capture size is chosen trying to respect the {@link VideoQuality} aspect ratio
*
* @see CameraOptions#isVideoSnapshotSupported()
*/
VIDEO(1);
static final SessionType DEFAULT = PICTURE;
private int value;
SessionType(int value) {
this.value = value;
}
int value() {
return value;
}
static SessionType fromValue(int value) {
SessionType[] list = SessionType.values();
for (SessionType action : list) {
if (action.value() == value) {
return action;
}
}
return null;
}
}

@ -84,7 +84,7 @@
<enum name="drawPhi" value="3" />
</attr>
<attr name="cameraSessionType" format="enum">
<attr name="cameraMode" format="enum">
<enum name="picture" value="0" />
<enum name="video" value="1" />
</attr>

@ -18,7 +18,7 @@ import com.otaliastudios.cameraview.CameraLogger;
import com.otaliastudios.cameraview.CameraOptions;
import com.otaliastudios.cameraview.CameraView;
import com.otaliastudios.cameraview.PictureResult;
import com.otaliastudios.cameraview.SessionType;
import com.otaliastudios.cameraview.Mode;
import com.otaliastudios.cameraview.VideoResult;
import java.io.File;
@ -163,7 +163,7 @@ public class CameraActivity extends AppCompatActivity implements View.OnClickLis
}
private void captureVideo() {
if (camera.getSessionType() != SessionType.VIDEO) {
if (camera.getMode() != Mode.VIDEO) {
message("Can't record video while session type is 'picture'.", false);
return;
}

@ -11,12 +11,11 @@ import com.otaliastudios.cameraview.Gesture;
import com.otaliastudios.cameraview.GestureAction;
import com.otaliastudios.cameraview.Grid;
import com.otaliastudios.cameraview.Hdr;
import com.otaliastudios.cameraview.SessionType;
import com.otaliastudios.cameraview.Mode;
import com.otaliastudios.cameraview.VideoQuality;
import com.otaliastudios.cameraview.WhiteBalance;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@ -27,7 +26,7 @@ public enum Control {
WIDTH("Width", false),
HEIGHT("Height", true),
SESSION("Session type", false),
MODE("Mode", false),
FLASH("Flash", false),
WHITE_BALANCE("White balance", false),
GRID("Grid", true),
@ -72,7 +71,7 @@ public enum Control {
list.add(i);
}
return list;
case SESSION: return options.getSupportedControls(SessionType.class);
case MODE: return options.getSupportedControls(Mode.class);
case FLASH: return options.getSupportedControls(Flash.class);
case WHITE_BALANCE: return options.getSupportedControls(WhiteBalance.class);
case HDR: return options.getSupportedControls(Hdr.class);
@ -108,7 +107,7 @@ public enum Control {
switch (this) {
case WIDTH: return view.getLayoutParams().width;
case HEIGHT: return view.getLayoutParams().height;
case SESSION: return view.getSessionType();
case MODE: return view.getMode();
case FLASH: return view.getFlash();
case WHITE_BALANCE: return view.getWhiteBalance();
case GRID: return view.getGrid();
@ -134,7 +133,7 @@ public enum Control {
camera.getLayoutParams().height = (int) value;
camera.setLayoutParams(camera.getLayoutParams());
break;
case SESSION:
case MODE:
case FLASH:
case WHITE_BALANCE:
case GRID:

@ -25,7 +25,7 @@
app:cameraGesturePinch="zoom"
app:cameraGestureScrollHorizontal="exposureCorrection"
app:cameraGestureScrollVertical="none"
app:cameraSessionType="picture" />
app:cameraMode="picture" />
<ImageButton

Loading…
Cancel
Save