Reorder actions on stopCapturer, to avoid crashing on camera timeout.

BUG=

Review-Url: https://codereview.webrtc.org/2003973003
Cr-Commit-Position: refs/heads/master@{#12963}
This commit is contained in:
nisse 2016-05-30 23:36:01 -07:00 committed by Commit bot
parent 2d3aae5a84
commit 92379de5c6

View File

@ -372,12 +372,7 @@ public class VideoCapturerAndroid implements
}
Logging.e(TAG, "startCapture failed", error);
// Make sure the camera is released.
stopCaptureOnCameraThread();
synchronized (handlerLock) {
// Remove all pending Runnables posted from |this|.
cameraThreadHandler.removeCallbacksAndMessages(this /* token */);
cameraThreadHandler = null;
}
stopCaptureOnCameraThread(true /* stopHandler */);
frameObserver.onCapturerStarted(false);
if (eventsHandler != null) {
eventsHandler.onCameraError("Camera can not be started.");
@ -488,13 +483,7 @@ public class VideoCapturerAndroid implements
final CountDownLatch barrier = new CountDownLatch(1);
final boolean didPost = maybePostOnCameraThread(new Runnable() {
@Override public void run() {
stopCaptureOnCameraThread();
synchronized (handlerLock) {
// Remove all pending Runnables posted from |this|.
cameraThreadHandler.removeCallbacksAndMessages(this /* token */);
cameraThreadHandler = null;
surfaceHelper = null;
}
stopCaptureOnCameraThread(true /* stopHandler */);
barrier.countDown();
}
});
@ -512,7 +501,7 @@ public class VideoCapturerAndroid implements
Logging.d(TAG, "stopCapture done");
}
private void stopCaptureOnCameraThread() {
private void stopCaptureOnCameraThread(boolean stopHandler) {
checkIsOnCameraThread();
Logging.d(TAG, "stopCaptureOnCameraThread");
// Note that the camera might still not be started here if startCaptureOnCameraThread failed
@ -522,6 +511,21 @@ public class VideoCapturerAndroid implements
if (surfaceHelper != null) {
surfaceHelper.stopListening();
}
if (stopHandler) {
synchronized (handlerLock) {
// Clear the cameraThreadHandler first, in case stopPreview or
// other driver code deadlocks. Deadlock in
// android.hardware.Camera._stopPreview(Native Method) has
// been observed on Nexus 5 (hammerhead), OS version LMY48I.
// The camera might post another one or two preview frames
// before stopped, so we have to check for a null
// cameraThreadHandler in our handler. Remove all pending
// Runnables posted from |this|.
cameraThreadHandler.removeCallbacksAndMessages(this /* token */);
cameraThreadHandler = null;
surfaceHelper = null;
}
}
if (cameraStatistics != null) {
cameraStatistics.release();
cameraStatistics = null;
@ -548,7 +552,7 @@ public class VideoCapturerAndroid implements
private void switchCameraOnCameraThread() {
checkIsOnCameraThread();
Logging.d(TAG, "switchCameraOnCameraThread");
stopCaptureOnCameraThread();
stopCaptureOnCameraThread(false /* stopHandler */);
synchronized (cameraIdLock) {
id = (id + 1) % android.hardware.Camera.getNumberOfCameras();
}
@ -637,9 +641,7 @@ public class VideoCapturerAndroid implements
@Override
public void onTextureFrameAvailable(
int oesTextureId, float[] transformMatrix, long timestampNs) {
if (cameraThreadHandler == null) {
throw new RuntimeException("onTextureFrameAvailable() called after stopCapture().");
}
checkIsOnCameraThread();
if (eventsHandler != null && !firstFrameReported) {
eventsHandler.onFirstFrameAvailable();