pull/37/head
Mattia Iavarone 8 years ago
parent ef3672e8d6
commit 9065e195fd
  1. 25
      .travis.yml
  2. 48
      cameraview/src/androidTest/java/com/otaliastudios/cameraview/IntegrationTest.java
  3. 57
      cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java
  4. 31
      cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java

@ -39,29 +39,34 @@ install:
- export EMULATOR="system-images;android-$EMULATOR_API;$EMULATOR_TAG;$EMULATOR_ABI" - export EMULATOR="system-images;android-$EMULATOR_API;$EMULATOR_TAG;$EMULATOR_ABI"
- echo yes | sdkmanager "platforms;android-$EMULATOR_API" # Install sdk - echo yes | sdkmanager "platforms;android-$EMULATOR_API" # Install sdk
- echo yes | sdkmanager "$EMULATOR" # Install system image - echo yes | sdkmanager "$EMULATOR" # Install system image
- sdkmanager --list || true # Check everything is updated
# Create adn start emulator # Create adn start emulator
- echo no | avdmanager create avd -n test -k "$EMULATOR" -f # Create emulator - echo no | avdmanager create avd -n test -k "$EMULATOR" -f # Create emulator
- emulator -avd test -no-window -camera-back emulated -camera-front emulated -memory 2048 & # Launch - which emulator # ensure we are using the right emulator (home/emulator/)
- emulator -avd test -no-window -camera-back emulated -camera-front emulated -memory 2048 -writable-system & # Launch
- adb wait-for-device # Wait for adb process - adb wait-for-device # Wait for adb process
- sdkmanager --list || true # Check everything is updated - adb remount # Mount as writable
before_script: before_script:
# Wait for emulator
- android-wait-for-emulator # Wait for emulator ready to interact - android-wait-for-emulator # Wait for emulator ready to interact
- adb shell settings put global window_animation_scale 0 & # Disable animations - adb shell settings put global window_animation_scale 0 & # Disable animations
- adb shell settings put global transition_animation_scale 0 & # Disable animations - adb shell settings put global transition_animation_scale 0 & # Disable animations
- adb shell settings put global animator_duration_scale 0 & # Disable animations - adb shell settings put global animator_duration_scale 0 & # Disable animations
# Unlock and configure logs.
# Would be great to use -v color to adb logcat but looks not supported on travis.
- sleep 20 # Sleep 20 seconds just in case - sleep 20 # Sleep 20 seconds just in case
- adb shell input keyevent 82 & # Dispatch event - adb shell input keyevent 82 & # Dispatch unlock event
- adb logcat -c # Clear logcat until now
- adb logcat Test:V TestRunner:V CameraView:V CameraController:V Camera1:V WorkerHandler:V *:E &
# - export LOGCAT_PID=$! # Save PID of the logcat process. Should kill later with kill $LOGCAT_PID
script: script:
- ./gradlew clean testDebugUnitTest - ./gradlew clean testDebugUnitTest connectedCheck mergedCoverageReport
- adb logcat -c
- adb logcat -v color Test:V TestRunner:V CameraView:V CameraController:V Camera1:V WorkerHandler:V *:S &
- export LOGCAT_PID=$!
- ./gradlew connectedCheck
- kill $LOGCAT_PID
- ./gradlew mergedCoverageReport
after_success: after_success:
- bash <(curl -s https://codecov.io/bash) -s "*/build/reports/mergedCoverageReport/" - bash <(curl -s https://codecov.io/bash) -s "*/build/reports/mergedCoverageReport/"

@ -1,11 +1,13 @@
package com.otaliastudios.cameraview; package com.otaliastudios.cameraview;
import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.PointF; import android.graphics.PointF;
import android.support.test.filters.MediumTest; import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule; import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4; import android.support.test.runner.AndroidJUnit4;
import android.view.ViewGroup;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -103,7 +105,7 @@ public class IntegrationTest extends BaseTest {
final Task<byte[]> pic = new Task<>(); final Task<byte[]> pic = new Task<>();
pic.listen(); pic.listen();
doEndTask(pic, 0).when(listener).onPictureTaken(any(byte[].class)); doEndTask(pic, 0).when(listener).onPictureTaken(any(byte[].class));
byte[] result = pic.await(2000); byte[] result = pic.await(5000);
if (expectSuccess) { if (expectSuccess) {
assertNotNull("Can take picture", result); assertNotNull("Can take picture", result);
} else { } else {
@ -143,7 +145,7 @@ public class IntegrationTest extends BaseTest {
} }
@Test @Test
// TODO: This works great on the device but crashes on the emulator. // This works great on the device but crashes often on the emulator.
// There must be something wrong with the emulated camera... // There must be something wrong with the emulated camera...
// Like stopPreview() and release() are not really sync calls? // Like stopPreview() and release() are not really sync calls?
public void testConcurrentCalls() throws Exception { public void testConcurrentCalls() throws Exception {
@ -160,7 +162,7 @@ public class IntegrationTest extends BaseTest {
assertTrue("Handles concurrent calls to start & stop, " + latch.getCount(), did); assertTrue("Handles concurrent calls to start & stop, " + latch.getCount(), did);
} }
//-@Test @Test
public void testStartInitializesOptions() { public void testStartInitializesOptions() {
assertNull(camera.getCameraOptions()); assertNull(camera.getCameraOptions());
assertNull(camera.getExtraProperties()); assertNull(camera.getExtraProperties());
@ -175,7 +177,7 @@ public class IntegrationTest extends BaseTest {
//region test Facing/SessionType //region test Facing/SessionType
// Test things that should reset the camera. // Test things that should reset the camera.
//-@Test @Test
public void testSetFacing() throws Exception { public void testSetFacing() throws Exception {
camera.start(); camera.start();
CameraOptions o = waitForOpen(true); CameraOptions o = waitForOpen(true);
@ -193,7 +195,7 @@ public class IntegrationTest extends BaseTest {
} }
} }
//-@Test @Test
public void testSetSessionType() throws Exception { public void testSetSessionType() throws Exception {
camera.setSessionType(SessionType.PICTURE); camera.setSessionType(SessionType.PICTURE);
camera.start(); camera.start();
@ -216,7 +218,7 @@ public class IntegrationTest extends BaseTest {
//region test Set Parameters //region test Set Parameters
// When camera is open, parameters will be set only if supported. // When camera is open, parameters will be set only if supported.
//-@Test @Test
public void testSetZoom() { public void testSetZoom() {
camera.start(); camera.start();
CameraOptions options = waitForOpen(true); CameraOptions options = waitForOpen(true);
@ -227,7 +229,7 @@ public class IntegrationTest extends BaseTest {
assertEquals(can ? newValue : oldValue, camera.getZoom(), 0f); assertEquals(can ? newValue : oldValue, camera.getZoom(), 0f);
} }
//-@Test @Test
public void testSetExposureCorrection() { public void testSetExposureCorrection() {
camera.start(); camera.start();
CameraOptions options = waitForOpen(true); CameraOptions options = waitForOpen(true);
@ -238,7 +240,7 @@ public class IntegrationTest extends BaseTest {
assertEquals(can ? newValue : oldValue, camera.getExposureCorrection(), 0f); assertEquals(can ? newValue : oldValue, camera.getExposureCorrection(), 0f);
} }
//-@Test @Test
public void testSetFlash() { public void testSetFlash() {
camera.start(); camera.start();
CameraOptions options = waitForOpen(true); CameraOptions options = waitForOpen(true);
@ -255,7 +257,7 @@ public class IntegrationTest extends BaseTest {
} }
} }
//-@Test @Test
public void testSetWhiteBalance() { public void testSetWhiteBalance() {
camera.start(); camera.start();
CameraOptions options = waitForOpen(true); CameraOptions options = waitForOpen(true);
@ -272,7 +274,7 @@ public class IntegrationTest extends BaseTest {
} }
} }
//-@Test @Test
public void testSetHdr() { public void testSetHdr() {
camera.start(); camera.start();
CameraOptions options = waitForOpen(true); CameraOptions options = waitForOpen(true);
@ -289,7 +291,7 @@ public class IntegrationTest extends BaseTest {
} }
} }
//-@Test @Test
public void testSetAudio() { public void testSetAudio() {
// TODO: when permissions are managed, check that Audio.ON triggers the audio permission // TODO: when permissions are managed, check that Audio.ON triggers the audio permission
camera.start(); camera.start();
@ -301,7 +303,7 @@ public class IntegrationTest extends BaseTest {
} }
} }
//-@Test @Test
public void testSetLocation() { public void testSetLocation() {
camera.start(); camera.start();
waitForOpen(true); waitForOpen(true);
@ -329,7 +331,7 @@ public class IntegrationTest extends BaseTest {
camera.setVideoQuality(VideoQuality.LOWEST); camera.setVideoQuality(VideoQuality.LOWEST);
} }
//-@Test @Test
public void testSetVideoQuality_whileInPictureSessionType() { public void testSetVideoQuality_whileInPictureSessionType() {
camera.setSessionType(SessionType.PICTURE); camera.setSessionType(SessionType.PICTURE);
camera.setVideoQuality(VideoQuality.HIGHEST); camera.setVideoQuality(VideoQuality.HIGHEST);
@ -339,7 +341,7 @@ public class IntegrationTest extends BaseTest {
assertEquals(camera.getVideoQuality(), VideoQuality.LOWEST); assertEquals(camera.getVideoQuality(), VideoQuality.LOWEST);
} }
//-@Test @Test
public void testSetVideoQuality_whileNotStarted() { public void testSetVideoQuality_whileNotStarted() {
camera.setVideoQuality(VideoQuality.HIGHEST); camera.setVideoQuality(VideoQuality.HIGHEST);
assertEquals(camera.getVideoQuality(), VideoQuality.HIGHEST); assertEquals(camera.getVideoQuality(), VideoQuality.HIGHEST);
@ -347,7 +349,7 @@ public class IntegrationTest extends BaseTest {
assertEquals(camera.getVideoQuality(), VideoQuality.LOWEST); assertEquals(camera.getVideoQuality(), VideoQuality.LOWEST);
} }
//-@Test @Test
public void testSetVideoQuality_shouldRecompute() { public void testSetVideoQuality_shouldRecompute() {
// If video quality changes bring to a new capture size, // If video quality changes bring to a new capture size,
// this might bring to a new aspect ratio, // this might bring to a new aspect ratio,
@ -382,7 +384,7 @@ public class IntegrationTest extends BaseTest {
waitForVideo(true); // waits 2000 waitForVideo(true); // waits 2000
} }
//-@Test @Test
public void testEndVideo_withoutStarting() { public void testEndVideo_withoutStarting() {
camera.setSessionType(SessionType.VIDEO); camera.setSessionType(SessionType.VIDEO);
camera.start(); camera.start();
@ -396,7 +398,7 @@ public class IntegrationTest extends BaseTest {
//region startAutoFocus //region startAutoFocus
// TODO: won't test onStopAutoFocus because that is not guaranteed to be called // TODO: won't test onStopAutoFocus because that is not guaranteed to be called
//-@Test @Test
public void testStartAutoFocus() { public void testStartAutoFocus() {
camera.start(); camera.start();
CameraOptions o = waitForOpen(true); CameraOptions o = waitForOpen(true);
@ -412,13 +414,13 @@ public class IntegrationTest extends BaseTest {
//region capture //region capture
//-@Test @Test
public void testCapturePicture_beforeStarted() { public void testCapturePicture_beforeStarted() {
camera.capturePicture(); camera.capturePicture();
waitForPicture(false); waitForPicture(false);
} }
//-@Test @Test
public void testCapturePicture_concurrentCalls() throws Exception { public void testCapturePicture_concurrentCalls() throws Exception {
// Second take should fail. // Second take should fail.
camera.start(); camera.start();
@ -434,7 +436,7 @@ public class IntegrationTest extends BaseTest {
assertEquals(latch.getCount(), 1); assertEquals(latch.getCount(), 1);
} }
//-@Test @Test
public void testCapturePicture_size() throws Exception { public void testCapturePicture_size() throws Exception {
camera.setCropOutput(false); camera.setCropOutput(false);
camera.start(); camera.start();
@ -450,13 +452,13 @@ public class IntegrationTest extends BaseTest {
assertTrue(b.getHeight() == size.getHeight() || b.getHeight() == size.getWidth()); assertTrue(b.getHeight() == size.getHeight() || b.getHeight() == size.getWidth());
} }
//-@Test @Test
public void testCaptureSnapshot_beforeStarted() { public void testCaptureSnapshot_beforeStarted() {
camera.captureSnapshot(); camera.captureSnapshot();
waitForPicture(false); waitForPicture(false);
} }
//-@Test @Test
public void testCaptureSnapshot_concurrentCalls() throws Exception { public void testCaptureSnapshot_concurrentCalls() throws Exception {
// Second take should fail. // Second take should fail.
camera.start(); camera.start();
@ -472,7 +474,7 @@ public class IntegrationTest extends BaseTest {
assertEquals(latch.getCount(), 1); assertEquals(latch.getCount(), 1);
} }
//-@Test @Test
public void testCaptureSnapshot_size() throws Exception { public void testCaptureSnapshot_size() throws Exception {
camera.setCropOutput(false); camera.setCropOutput(false);
camera.start(); camera.start();

@ -66,15 +66,17 @@ class Camera1 extends CameraController {
*/ */
@Override @Override
public void onSurfaceAvailable() { public void onSurfaceAvailable() {
LOG.i("onSurfaceAvailable, size is", mPreview.getSurfaceSize()); LOG.i("onSurfaceAvailable:", "Size is", mPreview.getSurfaceSize());
if (!shouldSetup()) return; if (!shouldSetup()) return;
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
if (!shouldSetup()) return; if (!shouldSetup()) return;
LOG.i("onSurfaceAvailable:", "Inside handler. About to bind.");
try { try {
setup(); setup();
} catch (Exception e) { } catch (Exception e) {
LOG.w("onSurfaceAvailable:", "Exception while binding camera to preview.", e);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
@ -92,10 +94,13 @@ class Camera1 extends CameraController {
// Compute a new camera preview size. // Compute a new camera preview size.
Size newSize = computePreviewSize(); Size newSize = computePreviewSize();
if (!newSize.equals(mPreviewSize)) { if (!newSize.equals(mPreviewSize)) {
LOG.i("onSurfaceChanged:", "Computed a new preview size. Dispatching.");
mPreviewSize = newSize; mPreviewSize = newSize;
mCameraCallbacks.onCameraPreviewSizeChanged(); mCameraCallbacks.onCameraPreviewSizeChanged();
synchronized (mLock) { synchronized (mLock) {
LOG.i("onSurfaceChanged:", "Stopping preview.");
mCamera.stopPreview(); mCamera.stopPreview();
LOG.i("onSurfaceChanged:", "Stopped preview.");
Camera.Parameters params = mCamera.getParameters(); Camera.Parameters params = mCamera.getParameters();
params.setPreviewSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); params.setPreviewSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
mCamera.setParameters(params); mCamera.setParameters(params);
@ -105,7 +110,9 @@ class Camera1 extends CameraController {
invertPreviewSizes ? mPreviewSize.getHeight() : mPreviewSize.getWidth(), invertPreviewSizes ? mPreviewSize.getHeight() : mPreviewSize.getWidth(),
invertPreviewSizes ? mPreviewSize.getWidth() : mPreviewSize.getHeight() invertPreviewSizes ? mPreviewSize.getWidth() : mPreviewSize.getHeight()
); );
LOG.i("onSurfaceChanged:", "Restarting preview.");
mCamera.startPreview(); mCamera.startPreview();
LOG.i("onSurfaceChanged:", "Restarted preview.");
} }
} }
} }
@ -118,6 +125,7 @@ class Camera1 extends CameraController {
// These can happen at different times but we want to end up here. // These can happen at different times but we want to end up here.
@WorkerThread @WorkerThread
private void setup() throws Exception { private void setup() throws Exception {
LOG.i("setup:", "Started");
Object output = mPreview.getOutput(); Object output = mPreview.getOutput();
if (mPreview.getOutputClass() == SurfaceHolder.class) { if (mPreview.getOutputClass() == SurfaceHolder.class) {
mCamera.setPreviewDisplay((SurfaceHolder) output); mCamera.setPreviewDisplay((SurfaceHolder) output);
@ -128,6 +136,7 @@ class Camera1 extends CameraController {
boolean invertPreviewSizes = shouldFlipSizes(); boolean invertPreviewSizes = shouldFlipSizes();
mCaptureSize = computeCaptureSize(); mCaptureSize = computeCaptureSize();
mPreviewSize = computePreviewSize(); mPreviewSize = computePreviewSize();
LOG.i("setup:", "Dispatching onCameraPreviewSizeChanged.");
mCameraCallbacks.onCameraPreviewSizeChanged(); mCameraCallbacks.onCameraPreviewSizeChanged();
mPreview.setDesiredSize( mPreview.setDesiredSize(
invertPreviewSizes ? mPreviewSize.getHeight() : mPreviewSize.getWidth(), invertPreviewSizes ? mPreviewSize.getHeight() : mPreviewSize.getWidth(),
@ -139,8 +148,9 @@ class Camera1 extends CameraController {
params.setPictureSize(mCaptureSize.getWidth(), mCaptureSize.getHeight()); // <- allowed params.setPictureSize(mCaptureSize.getWidth(), mCaptureSize.getHeight()); // <- allowed
mCamera.setParameters(params); mCamera.setParameters(params);
} }
LOG.i("setup:", "Starting preview with startPreview().");
mCamera.startPreview(); mCamera.startPreview();
LOG.i("setup:", "Started preview with startPreview().");
mIsSetup = true; mIsSetup = true;
} }
@ -149,6 +159,7 @@ class Camera1 extends CameraController {
@Override @Override
void onStart() throws Exception { void onStart() throws Exception {
if (isCameraAvailable()) { if (isCameraAvailable()) {
LOG.w("onStart:", "Camera not available. Should not happen.");
onStop(); // Should not happen. onStop(); // Should not happen.
} }
if (collectCameraId()) { if (collectCameraId()) {
@ -156,6 +167,7 @@ class Camera1 extends CameraController {
// Set parameters that might have been set before the camera was opened. // Set parameters that might have been set before the camera was opened.
synchronized (mLock) { synchronized (mLock) {
LOG.i("onStart:", "Applying default parameters.");
Camera.Parameters params = mCamera.getParameters(); Camera.Parameters params = mCamera.getParameters();
mExtraProperties = new ExtraProperties(params); mExtraProperties = new ExtraProperties(params);
mOptions = new CameraOptions(params); mOptions = new CameraOptions(params);
@ -170,6 +182,7 @@ class Camera1 extends CameraController {
// Try starting preview. // Try starting preview.
mCamera.setDisplayOrientation(computeSensorToDisplayOffset()); // <- not allowed during preview mCamera.setDisplayOrientation(computeSensorToDisplayOffset()); // <- not allowed during preview
if (shouldSetup()) setup(); if (shouldSetup()) setup();
LOG.i("onStart:", "Ended");
} }
} }
@ -177,19 +190,27 @@ class Camera1 extends CameraController {
@Override @Override
void onStop() throws Exception { void onStop() throws Exception {
Exception error = null; Exception error = null;
LOG.i("onStop:", "About to clean up.");
mHandler.get().removeCallbacks(mPostFocusResetRunnable); mHandler.get().removeCallbacks(mPostFocusResetRunnable);
if (isCameraAvailable()) { if (isCameraAvailable()) {
LOG.i("onStop:", "Clean up.", "Ending video?", mIsCapturingVideo);
if (mIsCapturingVideo) endVideo(); if (mIsCapturingVideo) endVideo();
try { try {
LOG.i("onStop:", "Clean up.", "Stopping preview.");
mCamera.stopPreview(); mCamera.stopPreview();
LOG.i("onStop:", "Clean up.", "Stopped preview.");
} catch (Exception e) { } catch (Exception e) {
LOG.w("onStop:", "Clean up.", "Exception while stopping preview.");
error = e; error = e;
} }
try { try {
LOG.i("onStop:", "Clean up.", "Releasing camera.");
mCamera.release(); mCamera.release();
LOG.i("onStop:", "Clean up.", "Released camera.");
} catch (Exception e) { } catch (Exception e) {
LOG.w("onStop:", "Clean up.", "Exception while releasing camera.");
error = e; error = e;
} }
} }
@ -392,8 +413,8 @@ class Camera1 extends CameraController {
} }
onSurfaceChanged(); onSurfaceChanged();
} }
LOG.i("captureSize: "+mCaptureSize); LOG.i("setVideoQuality:", "captureSize:", mCaptureSize);
LOG.i("previewSize: "+mPreviewSize); LOG.i("setVideoQuality:", "previewSize:", mPreviewSize);
} }
} }
@ -484,8 +505,8 @@ class Camera1 extends CameraController {
@Override @Override
boolean shouldFlipSizes() { boolean shouldFlipSizes() {
int offset = computeSensorToDisplayOffset(); int offset = computeSensorToDisplayOffset();
LOG.i("shouldFlip:", "mDeviceOrientation=", mDeviceOrientation, "mSensorOffset=", mSensorOffset); LOG.i("shouldFlipSizes:", "mDeviceOrientation=", mDeviceOrientation, "mSensorOffset=", mSensorOffset);
LOG.i("shouldFlip:", "sensorToDisplay=", offset); LOG.i("shouldFlipSizes:", "sensorToDisplay=", offset);
return offset % 180 != 0; return offset % 180 != 0;
} }
@ -545,7 +566,7 @@ class Camera1 extends CameraController {
// Choose the max size. // Choose the max size.
List<Size> captureSizes = sizesFromList(params.getSupportedPictureSizes()); List<Size> captureSizes = sizesFromList(params.getSupportedPictureSizes());
Size maxSize = Collections.max(captureSizes); Size maxSize = Collections.max(captureSizes);
LOG.i("computeCaptureSize:", "computed", maxSize); LOG.i("size:", "computeCaptureSize:", "computed", maxSize);
return Collections.max(captureSizes); return Collections.max(captureSizes);
} else { } else {
// Choose according to developer choice in setVideoQuality. // Choose according to developer choice in setVideoQuality.
@ -554,7 +575,7 @@ class Camera1 extends CameraController {
List<Size> captureSizes = sizesFromList(params.getSupportedPictureSizes()); List<Size> captureSizes = sizesFromList(params.getSupportedPictureSizes());
CamcorderProfile profile = getCamcorderProfile(mVideoQuality); CamcorderProfile profile = getCamcorderProfile(mVideoQuality);
AspectRatio targetRatio = AspectRatio.of(profile.videoFrameWidth, profile.videoFrameHeight); AspectRatio targetRatio = AspectRatio.of(profile.videoFrameWidth, profile.videoFrameHeight);
LOG.i("computeCaptureSize:", "videoQuality:", mVideoQuality, "targetRatio:", targetRatio); LOG.i("size:", "computeCaptureSize:", "videoQuality:", mVideoQuality, "targetRatio:", targetRatio);
return matchSize(captureSizes, targetRatio, new Size(0, 0), true); return matchSize(captureSizes, targetRatio, new Size(0, 0), true);
} }
} }
@ -564,7 +585,7 @@ class Camera1 extends CameraController {
List<Size> previewSizes = sizesFromList(params.getSupportedPreviewSizes()); List<Size> previewSizes = sizesFromList(params.getSupportedPreviewSizes());
AspectRatio targetRatio = AspectRatio.of(mCaptureSize.getWidth(), mCaptureSize.getHeight()); AspectRatio targetRatio = AspectRatio.of(mCaptureSize.getWidth(), mCaptureSize.getHeight());
Size biggerThan = mPreview.getSurfaceSize(); Size biggerThan = mPreview.getSurfaceSize();
LOG.i("computePreviewSize:", "targetRatio:", targetRatio, "surface size:", biggerThan); LOG.i("size:", "computePreviewSize:", "targetRatio:", targetRatio, "surface size:", biggerThan);
return matchSize(previewSizes, targetRatio, biggerThan, false); return matchSize(previewSizes, targetRatio, biggerThan, false);
} }
@ -586,7 +607,7 @@ class Camera1 extends CameraController {
mMediaRecorder.start(); mMediaRecorder.start();
return true; return true;
} catch (Exception e) { } catch (Exception e) {
LOG.e("Error while starting MediaRecorder.", e); LOG.e("Error while starting MediaRecorder. Swallowing.", e);
mVideoFile = null; mVideoFile = null;
mCamera.lock(); mCamera.lock();
endVideo(); endVideo();
@ -608,7 +629,7 @@ class Camera1 extends CameraController {
} catch (Exception e) { } catch (Exception e) {
// This can happen if endVideo() is called right after startVideo(). // This can happen if endVideo() is called right after startVideo().
// We don't care. // We don't care.
LOG.w("Error while closing media recorder.", e); LOG.w("Error while closing media recorder. Swallowing", e);
} }
mMediaRecorder = null; mMediaRecorder = null;
} }
@ -781,8 +802,8 @@ class Camera1 extends CameraController {
double theta = ((double) displayToSensor) * Math.PI / 180; double theta = ((double) displayToSensor) * Math.PI / 180;
double sensorClickX = viewClickX * Math.cos(theta) - viewClickY * Math.sin(theta); double sensorClickX = viewClickX * Math.cos(theta) - viewClickY * Math.sin(theta);
double sensorClickY = viewClickX * Math.sin(theta) + viewClickY * Math.cos(theta); double sensorClickY = viewClickX * Math.sin(theta) + viewClickY * Math.cos(theta);
LOG.i("viewClickX:", viewClickX, "viewClickY:", viewClickY); LOG.i("focus:", "viewClickX:", viewClickX, "viewClickY:", viewClickY);
LOG.i("sensorClickX:", sensorClickX, "sensorClickY:", sensorClickY); LOG.i("focus:", "sensorClickX:", sensorClickX, "sensorClickY:", sensorClickY);
// Compute the rect bounds. // Compute the rect bounds.
Rect rect1 = computeMeteringArea(sensorClickX, sensorClickY, 150d); Rect rect1 = computeMeteringArea(sensorClickX, sensorClickY, 150d);
@ -803,7 +824,7 @@ class Camera1 extends CameraController {
int bottom = (int) Math.min(centerY + delta, 1000); int bottom = (int) Math.min(centerY + delta, 1000);
int left = (int) Math.max(centerX - delta, -1000); int left = (int) Math.max(centerX - delta, -1000);
int right = (int) Math.min(centerX + delta, 1000); int right = (int) Math.min(centerX + delta, 1000);
LOG.i("metering area:", "top:", top, "left:", left, "bottom:", bottom, "right:", right); LOG.i("focus:", "computeMeteringArea:", "top:", top, "left:", left, "bottom:", bottom, "right:", right);
return new Rect(left, top, right, bottom); return new Rect(left, top, right, bottom);
} }
@ -822,7 +843,7 @@ class Camera1 extends CameraController {
for (Camera.Size size : sizes) { for (Camera.Size size : sizes) {
result.add(new Size(size.width, size.height)); result.add(new Size(size.width, size.height));
} }
LOG.i("sizesFromList:", result); LOG.i("size:", "sizesFromList:", result);
return result; return result;
} }
@ -852,8 +873,8 @@ class Camera1 extends CameraController {
} }
} }
LOG.i("matchSize:", "found consistent:", consistent.size()); LOG.i("size:", "matchSize:", "found consistent:", consistent.size());
LOG.i("matchSize:", "found big enough and consistent:", bigEnoughAndConsistent.size()); LOG.i("size:", "matchSize:", "found big enough and consistent:", bigEnoughAndConsistent.size());
Size result; Size result;
if (biggestPossible) { if (biggestPossible) {
if (bigEnoughAndConsistent.size() > 0) { if (bigEnoughAndConsistent.size() > 0) {
@ -872,7 +893,7 @@ class Camera1 extends CameraController {
result = Collections.max(sizes); result = Collections.max(sizes);
} }
} }
LOG.i("matchSize:", "returning result", result); LOG.i("size", "matchSize:", "returning result", result);
return result; return result;
} }

@ -53,7 +53,9 @@ abstract class CameraController implements Preview.SurfaceCallback {
public void uncaughtException(Thread thread, Throwable throwable) { public void uncaughtException(Thread thread, Throwable throwable) {
// Something went wrong. Thread is terminated (about to?). // Something went wrong. Thread is terminated (about to?).
// Move to other thread and stop resources. // Move to other thread and stop resources.
LOG.w("Interrupting thread, due to exception.", throwable);
thread.interrupt(); thread.interrupt();
LOG.w("Interrupted thread. Posting a stopImmediately.", ss());
mHandler = WorkerHandler.get("CameraViewController"); mHandler = WorkerHandler.get("CameraViewController");
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@Override @Override
@ -67,16 +69,29 @@ abstract class CameraController implements Preview.SurfaceCallback {
//region Start&Stop //region Start&Stop
private String ss() {
switch (mState) {
case STATE_STOPPING: return "STATE_STOPPING";
case STATE_STOPPED: return "STATE_STOPPED";
case STATE_STARTING: return "STATE_STARTING";
case STATE_STARTED: return "STATE_STARTED";
}
return "null";
}
// Starts the preview asynchronously. // Starts the preview asynchronously.
final void start() { final void start() {
LOG.i("Start:", "posting runnable. State:", ss());
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
int a = mState; LOG.i("Start:", "executing. State:", ss());
if (mState >= STATE_STARTING) return; if (mState >= STATE_STARTING) return;
mState = STATE_STARTING; mState = STATE_STARTING;
LOG.i("Start:", "about to call onStart()", ss());
onStart(); onStart();
LOG.i("Start:", "returned from onStart().", "Dispatching.", ss());
mState = STATE_STARTED; mState = STATE_STARTED;
mCameraCallbacks.dispatchOnCameraOpened(mOptions); mCameraCallbacks.dispatchOnCameraOpened(mOptions);
@ -90,14 +105,17 @@ abstract class CameraController implements Preview.SurfaceCallback {
// Stops the preview asynchronously. // Stops the preview asynchronously.
final void stop() { final void stop() {
LOG.i("Stop:", "posting runnable. State:", ss());
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
int a = mState; LOG.i("Stop:", "executing. State:", ss());
if (mState <= STATE_STOPPED) return; if (mState <= STATE_STOPPED) return;
mState = STATE_STOPPING; mState = STATE_STOPPING;
LOG.i("Stop:", "about to call onStop()");
onStop(); onStop();
LOG.i("Stop:", "returned from onStop().", "Dispatching.");
mState = STATE_STOPPED; mState = STATE_STOPPED;
mCameraCallbacks.dispatchOnCameraClosed(); mCameraCallbacks.dispatchOnCameraClosed();
@ -113,31 +131,40 @@ abstract class CameraController implements Preview.SurfaceCallback {
void stopImmediately() { void stopImmediately() {
try { try {
// Don't check, try stop again. // Don't check, try stop again.
LOG.i("Stop immediately. State was:", ss());
mState = STATE_STOPPING; mState = STATE_STOPPING;
onStop(); onStop();
mState = STATE_STOPPED; mState = STATE_STOPPED;
LOG.i("Stop immediately. Stopped. State is:", ss());
} catch (Exception e) { } catch (Exception e) {
// Do nothing. // Do nothing.
LOG.i("Stop immediately. Exception while stopping.", e);
mState = STATE_STOPPED; mState = STATE_STOPPED;
} }
} }
// Forces a restart. // Forces a restart.
protected final void restart() { protected final void restart() {
LOG.i("Restart:", "posting runnable");
mHandler.post(new Runnable() { mHandler.post(new Runnable() {
@Override @Override
public void run() { public void run() {
try { try {
LOG.i("Restart:", "executing. Needs stopping:", mState > STATE_STOPPED, ss());
// Don't stop if stopped. // Don't stop if stopped.
if (mState > STATE_STOPPED) { if (mState > STATE_STOPPED) {
mState = STATE_STOPPING; mState = STATE_STOPPING;
onStop(); onStop();
mState = STATE_STOPPED; mState = STATE_STOPPED;
LOG.i("Restart:", "stopped. Dispatching.", ss());
mCameraCallbacks.dispatchOnCameraClosed(); mCameraCallbacks.dispatchOnCameraClosed();
} }
LOG.i("Restart: about to start. State:", ss());
mState = STATE_STARTING; mState = STATE_STARTING;
onStart(); onStart();
mState = STATE_STARTED; mState = STATE_STARTED;
LOG.i("Restart: returned from start. Dispatching. State:", ss());
mCameraCallbacks.dispatchOnCameraOpened(mOptions); mCameraCallbacks.dispatchOnCameraOpened(mOptions);
} catch (Exception e) { } catch (Exception e) {

Loading…
Cancel
Save