Make CameraCapturer.switchCamera try again if session is still opening.
R=magjed@webrtc.org
Review-Url: https://codereview.webrtc.org/2238263002
Cr-Original-Commit-Position: refs/heads/master@{#13747}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: 92c09509bdf0287c7af5c1bbde87dd188acf1879
diff --git a/api/android/java/src/org/webrtc/Camera2Session.java b/api/android/java/src/org/webrtc/Camera2Session.java
index 5e32c27..9bcdfaf 100644
--- a/api/android/java/src/org/webrtc/Camera2Session.java
+++ b/api/android/java/src/org/webrtc/Camera2Session.java
@@ -318,21 +318,35 @@
@Override
public void stop() {
Logging.d(TAG, "Stop camera2 session on camera " + cameraId);
- final CountDownLatch stopLatch = new CountDownLatch(1);
-
- cameraThreadHandler.post(new Runnable() {
- @Override
- public void run() {
- if (state != SessionState.STOPPED) {
- state = SessionState.STOPPED;
- capturerObserver.onCapturerStopped();
- stopLatch.countDown();
- stopInternal();
- }
+ if (Thread.currentThread() == cameraThreadHandler.getLooper().getThread()) {
+ if (state != SessionState.STOPPED) {
+ state = SessionState.STOPPED;
+ capturerObserver.onCapturerStopped();
+ // Post the stopInternal to return earlier.
+ cameraThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ stopInternal();
+ }
+ });
}
- });
+ } else {
+ final CountDownLatch stopLatch = new CountDownLatch(1);
- ThreadUtils.awaitUninterruptibly(stopLatch);
+ cameraThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (state != SessionState.STOPPED) {
+ state = SessionState.STOPPED;
+ capturerObserver.onCapturerStopped();
+ stopLatch.countDown();
+ stopInternal();
+ }
+ }
+ });
+
+ ThreadUtils.awaitUninterruptibly(stopLatch);
+ }
}
private void stopInternal() {
diff --git a/api/android/java/src/org/webrtc/CameraCapturer.java b/api/android/java/src/org/webrtc/CameraCapturer.java
index 75712cc..7e7d236 100644
--- a/api/android/java/src/org/webrtc/CameraCapturer.java
+++ b/api/android/java/src/org/webrtc/CameraCapturer.java
@@ -10,17 +10,19 @@
package org.webrtc;
-import org.webrtc.CameraEnumerationAndroid.CaptureFormat;
-
import android.content.Context;
import android.os.Handler;
-import android.os.SystemClock;
import java.util.Arrays;
-import java.util.List;
@SuppressWarnings("deprecation")
public abstract class CameraCapturer implements CameraVideoCapturer {
+ enum SwitchState {
+ IDLE, // No switch requested.
+ PENDING, // Waiting for previous capture session to open.
+ IN_PROGRESS, // Waiting for new switched capture session to start.
+ }
+
private static final String TAG = "CameraCapturer";
private final static int MAX_OPEN_CAMERA_ATTEMPTS = 3;
private final static int OPEN_CAMERA_DELAY_MS = 500;
@@ -39,12 +41,17 @@
currentSession = session;
stateLock.notifyAll();
- if (switchEventsHandler != null) {
- switchEventsHandler.onCameraSwitchDone(
- cameraEnumerator.isFrontFacing(cameraName));
- switchEventsHandler = null;
+ if (switchState == SwitchState.IN_PROGRESS) {
+ if (switchEventsHandler != null) {
+ switchEventsHandler.onCameraSwitchDone(
+ cameraEnumerator.isFrontFacing(cameraName));
+ switchEventsHandler = null;
+ }
+ switchState = SwitchState.IDLE;
+ } else if (switchState == SwitchState.PENDING) {
+ switchState = SwitchState.IDLE;
+ switchCameraInternal(switchEventsHandler);
}
- switchInProgress = false;
}
}
@@ -58,11 +65,13 @@
sessionOpening = false;
stateLock.notifyAll();
- if (switchEventsHandler != null) {
- switchEventsHandler.onCameraSwitchError(error);
- switchEventsHandler = null;
+ if (switchState != SwitchState.IDLE) {
+ if (switchEventsHandler != null) {
+ switchEventsHandler.onCameraSwitchError(error);
+ switchEventsHandler = null;
+ }
+ switchState = SwitchState.IDLE;
}
- switchInProgress = false;
eventsHandler.onCameraError(error);
} else {
@@ -76,8 +85,6 @@
// Initialized on initialize
// -------------------------
- // Use postOnCameraThread() instead of posting directly to the handler - this way all
- // callbacks with a specifed token can be removed at once.
private Handler cameraThreadHandler;
private Context applicationContext;
private CapturerObserver capturerObserver;
@@ -91,7 +98,7 @@
private int height; /* guarded by stateLock */
private int framerate; /* guarded by stateLock */
private int openAttemptsRemaining; /* guarded by stateLock */
- private boolean switchInProgress; /* guarded by stateLock */
+ private SwitchState switchState = SwitchState.IDLE; /* guarded by stateLock */
private CameraSwitchHandler switchEventsHandler; /* guarded by stateLock */
public CameraCapturer(
@@ -219,6 +226,16 @@
@Override
public void switchCamera(final CameraSwitchHandler switchEventsHandler) {
Logging.d(TAG, "switchCamera");
+ cameraThreadHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ switchCameraInternal(switchEventsHandler);
+ }
+ });
+ }
+
+ private void switchCameraInternal(final CameraSwitchHandler switchEventsHandler) {
+ Logging.d(TAG, "switchCamera internal");
final String[] deviceNames = cameraEnumerator.getDeviceNames();
@@ -230,7 +247,7 @@
}
synchronized (stateLock) {
- if (switchInProgress) {
+ if (switchState != SwitchState.IDLE) {
Logging.d(TAG, "switchCamera switchInProgress");
if (switchEventsHandler != null) {
switchEventsHandler.onCameraSwitchError("Camera switch already in progress.");
@@ -238,12 +255,12 @@
return;
}
+ this.switchEventsHandler = switchEventsHandler;
if (sessionOpening) {
- Logging.d(TAG, "switchCamera sessionOpening");
- if (switchEventsHandler != null) {
- switchEventsHandler.onCameraSwitchError("Session is still opening.");
- }
+ switchState = SwitchState.PENDING;
return;
+ } else {
+ switchState = SwitchState.IN_PROGRESS;
}
if (currentSession == null) {
@@ -261,8 +278,6 @@
int cameraNameIndex = Arrays.asList(deviceNames).indexOf(cameraName);
cameraName = deviceNames[(cameraNameIndex + 1) % deviceNames.length];
- switchInProgress = true;
- this.switchEventsHandler = switchEventsHandler;
sessionOpening = true;
openAttemptsRemaining = 1;
createSessionInternal(0);