Changes in VideoCapturerAndroid.

- Do not handle more than one camera switch request at a time
to avoid blocking camera thread with multiple switch requests.
- Add a callback to notify when camera switch has been done.

R=perkj@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/46859004

Cr-Commit-Position: refs/heads/master@{#8978}
This commit is contained in:
Alex Glaznev 2015-04-10 11:19:52 -07:00
parent f4acf46c86
commit e4ae8d8558
3 changed files with 25 additions and 7 deletions

View File

@ -201,9 +201,9 @@ public class VideoCapturerAndroidTest extends ActivityTestCase {
VideoTrack track = factory.createVideoTrack("dummy", source);
if (HaveTwoCameras())
assertTrue(capturer.switchCamera());
assertTrue(capturer.switchCamera(null));
else
assertFalse(capturer.switchCamera());
assertFalse(capturer.switchCamera(null));
// Wait until the camera have been switched.
capturer.runCameraThreadUntilIdle();

View File

@ -86,6 +86,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
private int width;
private int height;
private int framerate;
private volatile boolean pendingCameraSwitch;
private CapturerObserver frameObserver = null;
// List of formats supported by all cameras. This list is filled once in order
// to be able to switch cameras.
@ -165,7 +166,7 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
// the camera is running.
// Returns true on success. False if the next camera does not support the
// current resolution.
public synchronized boolean switchCamera() {
public synchronized boolean switchCamera(final Runnable switchDoneEvent) {
if (Camera.getNumberOfCameras() < 2 )
return false;
@ -173,6 +174,12 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
Log.e(TAG, "Camera has not been started");
return false;
}
if (pendingCameraSwitch) {
// Do not handle multiple camera switch request to avoid blocking
// camera thread by handling too many switch request from a queue.
Log.w(TAG, "Ignoring camera switch request.");
return false;
}
int new_id = (id + 1) % Camera.getNumberOfCameras();
@ -190,10 +197,11 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
return false;
}
pendingCameraSwitch = true;
id = new_id;
cameraThreadHandler.post(new Runnable() {
@Override public void run() {
switchCameraOnCameraThread();
switchCameraOnCameraThread(switchDoneEvent);
}
});
return true;
@ -347,6 +355,9 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
if (width % 16 != 0) {
throw new RuntimeException("width must be a multiple of 16." );
}
if (cameraThreadHandler != null) {
throw new RuntimeException("Camera has already been started.");
}
this.width = width;
this.height = height;
this.framerate = framerate;
@ -442,7 +453,6 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
Log.e(TAG, "startCapture failed", error);
if (camera != null) {
stopCaptureOnCameraThread();
frameObserver.OnCapturerStarted(false);
}
frameObserver.OnCapturerStarted(false);
return;
@ -450,6 +460,9 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
// Called by native code. Returns true when camera is known to be stopped.
synchronized void stopCapture() throws InterruptedException {
if (cameraThreadHandler == null) {
throw new RuntimeException("Calling stopCapture() for already stopped camera.");
}
Log.d(TAG, "stopCapture");
cameraThreadHandler.post(new Runnable() {
@Override public void run() {
@ -488,12 +501,17 @@ public class VideoCapturerAndroid extends VideoCapturer implements PreviewCallba
}
}
private void switchCameraOnCameraThread() {
private void switchCameraOnCameraThread(Runnable switchDoneEvent) {
Log.d(TAG, "switchCameraOnCameraThread");
doStopCaptureOnCamerathread();
startCaptureOnCameraThread(width, height, framerate, frameObserver,
applicationContext);
pendingCameraSwitch = false;
Log.d(TAG, "switchCameraOnCameraThread done");
if (switchDoneEvent != null) {
switchDoneEvent.run();
}
}
synchronized void returnBuffer(final long timeStamp) {

View File

@ -818,7 +818,7 @@ public class PeerConnectionClient {
return; // No video is sent or only one camera is available or error happened.
}
Log.d(TAG, "Switch camera");
videoCapturer.switchCamera();
videoCapturer.switchCamera(null);
}
public void switchCamera() {