Bug 1452048 - Leave critical section before calling into java StartCapture(). r?dminor draft
authorAndreas Pehrson <pehrsons@mozilla.com>
Fri, 06 Apr 2018 15:49:24 +0200
changeset 779267 d1f09e0adfc2fb8c0ff795d473712c5b93ff7b73
parent 779266 f9e890d8421b2755b9301d86993faba8f0aefa6d
child 779268 408bc11ed0481138416d45143ac1af67f58b7e31
push id105725
push userbmo:apehrson@mozilla.com
push dateMon, 09 Apr 2018 15:22:26 +0000
reviewersdminor
bugs1452048
milestone61.0a1
Bug 1452048 - Leave critical section before calling into java StartCapture(). r?dminor If we stay in the critical section, and the StartCapture() is a reconfiguring one, we risk deadlocking with IncomingFrame which runs on the camera thread. MozReview-Commit-ID: 5rU4urrBWxr
media/webrtc/trunk/webrtc/modules/video_capture/android/video_capture_android.cc
--- a/media/webrtc/trunk/webrtc/modules/video_capture/android/video_capture_android.cc
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/video_capture_android.cc
@@ -180,42 +180,51 @@ VideoCaptureAndroid::~VideoCaptureAndroi
     env->GetMethodID(g_java_capturer_class, "unlinkCapturer", "()V");
   env->CallVoidMethod(_jCapturer, j_unlink);
 
   env->DeleteGlobalRef(_jCapturer);
 }
 
 int32_t VideoCaptureAndroid::StartCapture(
     const VideoCaptureCapability& capability) {
-  CriticalSectionScoped cs(&_apiCs);
+  _apiCs.Enter();
   AttachThreadScoped ats(g_jvm_capture);
   JNIEnv* env = ats.env();
 
   if (_deviceInfo.GetBestMatchedCapability(
           _deviceUniqueId, capability, _captureCapability) < 0) {
     WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
                  "%s: GetBestMatchedCapability failed: %dx%d",
                  __FUNCTION__, capability.width, capability.height);
+    // Manual exit of critical section
+    _apiCs.Leave();
     return -1;
   }
 
   _captureDelay = _captureCapability.expectedCaptureDelay;
 
-  jmethodID j_start =
-      env->GetMethodID(g_java_capturer_class, "startCapture", "(IIII)Z");
-  assert(j_start);
+  int width = _captureCapability.width;
+  int height = _captureCapability.height;
   int min_mfps = 0;
   int max_mfps = 0;
   _deviceInfo.GetMFpsRange(_deviceUniqueId, _captureCapability.maxFPS,
                            &min_mfps, &max_mfps);
+
+  // Exit critical section to avoid blocking camera thread inside
+  // onIncomingFrame() call.
+  _apiCs.Leave();
+
+  jmethodID j_start =
+      env->GetMethodID(g_java_capturer_class, "startCapture", "(IIII)Z");
+  assert(j_start);
   bool started = env->CallBooleanMethod(_jCapturer, j_start,
-                                        _captureCapability.width,
-                                        _captureCapability.height,
+                                        width, height,
                                         min_mfps, max_mfps);
   if (started) {
+    CriticalSectionScoped cs(&_apiCs);
     _requestedCapability = capability;
     _captureStarted = true;
   }
   return started ? 0 : -1;
 }
 
 int32_t VideoCaptureAndroid::StopCapture() {
   _apiCs.Enter();