diff --git a/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java b/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java index 80f6f63233..0e555f9083 100644 --- a/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java +++ b/webrtc/modules/video_capture/android/java/src/org/webrtc/videoengine/VideoCaptureAndroid.java @@ -66,10 +66,6 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback { this.native_capturer = native_capturer; this.info = new Camera.CameraInfo(); Camera.getCameraInfo(id, info); - Exchanger handlerExchanger = new Exchanger(); - cameraThread = new CameraThread(handlerExchanger); - cameraThread.start(); - cameraThreadHandler = exchange(handlerExchanger, null); } private class CameraThread extends Thread { @@ -93,6 +89,14 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback { private synchronized boolean startCapture( final int width, final int height, final int min_mfps, final int max_mfps) { + if (cameraThread != null || cameraThreadHandler != null) { + throw new RuntimeException("Camera thread already started!"); + } + Exchanger handlerExchanger = new Exchanger(); + cameraThread = new CameraThread(handlerExchanger); + cameraThread.start(); + cameraThreadHandler = exchange(handlerExchanger, null); + final Exchanger result = new Exchanger(); cameraThreadHandler.post(new Runnable() { @Override public void run() { @@ -174,12 +178,21 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback { stopCaptureOnCameraThread(result); } }); - return exchange(result, false); // |false| is a dummy value here. + boolean status = exchange(result, false); // |false| is a dummy value here. + try { + cameraThread.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + cameraThreadHandler = null; + cameraThread = null; + return status; } private void stopCaptureOnCameraThread( Exchanger result) { Log.d(TAG, "stopCapture"); + Looper.myLooper().quit(); if (camera == null) { throw new RuntimeException("Camera is already stopped!"); } @@ -225,19 +238,24 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback { // Does not affect the captured video image. // Called by native code. private synchronized void setPreviewRotation(final int rotation) { - cameraThreadHandler.post(new Runnable() { - @Override public void run() { - setPreviewRotationOnCameraThread(rotation); - } - }); - } - - private void setPreviewRotationOnCameraThread(int rotation) { - Log.v(TAG, "setPreviewRotation:" + rotation); - - if (camera == null) { + if (camera == null || cameraThreadHandler == null) { return; } + final Exchanger result = new Exchanger(); + cameraThreadHandler.post(new Runnable() { + @Override public void run() { + setPreviewRotationOnCameraThread(rotation, result); + } + }); + // Use the exchanger below to block this function until + // setPreviewRotationOnCameraThread() completes, holding the synchronized + // lock for the duration. The exchanged value itself is ignored. + exchange(result, null); + } + + private void setPreviewRotationOnCameraThread( + int rotation, Exchanger result) { + Log.v(TAG, "setPreviewRotation:" + rotation); int resultRotation = 0; if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { @@ -249,6 +267,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback { resultRotation = rotation; } camera.setDisplayOrientation(resultRotation); + exchange(result, null); } public synchronized void surfaceChanged( @@ -259,7 +278,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback { public synchronized void surfaceCreated(final SurfaceHolder holder) { Log.d(TAG, "VideoCaptureAndroid::surfaceCreated"); - if (camera == null) { + if (camera == null || cameraThreadHandler == null) { return; } final Exchanger result = new Exchanger(); @@ -276,7 +295,7 @@ public class VideoCaptureAndroid implements PreviewCallback, Callback { public synchronized void surfaceDestroyed(SurfaceHolder holder) { Log.d(TAG, "VideoCaptureAndroid::surfaceDestroyed"); - if (camera == null) { + if (camera == null || cameraThreadHandler == null) { return; } final Exchanger result = new Exchanger();