Bug 863290 - Correctly detect failure to initialize Android capture objects. Fix crashers. r=jesup a=lsblakk
authorGian-Carlo Pascutto <gpascutto@mozilla.com>
Wed, 15 May 2013 18:50:42 +0200
changeset 142737 67f17b73c834dd9910b80a24d4783caeb201e3b9
parent 142736 3bacaedcbba908a261af99becbbfe0343d56a0fc
child 142738 9d3e8e88a722cdd324fe6cf744c1d3efe6f38fe9
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup, lsblakk
bugs863290
milestone23.0a2
Bug 863290 - Correctly detect failure to initialize Android capture objects. Fix crashers. r=jesup a=lsblakk
content/media/webrtc/MediaEngineWebRTC.cpp
media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
media/webrtc/signaling/src/media-conduit/VideoConduit.h
media/webrtc/trunk/webrtc/modules/video_capture/android/java/org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java
media/webrtc/trunk/webrtc/modules/video_capture/android/video_capture_android.cc
--- a/content/media/webrtc/MediaEngineWebRTC.cpp
+++ b/content/media/webrtc/MediaEngineWebRTC.cpp
@@ -92,17 +92,20 @@ MediaEngineWebRTC::EnumerateVideoDevices
   jobject context = mozilla::AndroidBridge::Bridge()->GetGlobalContextRef();
 
   // get the JVM
   JavaVM *jvm = mozilla::AndroidBridge::Bridge()->GetVM();
 
   JNIEnv *env;
   jint res = jvm->AttachCurrentThread(&env, NULL);
 
-  webrtc::VideoEngine::SetAndroidObjects(jvm, (void*)context);
+  if (webrtc::VideoEngine::SetAndroidObjects(jvm, (void*)context) != 0) {
+    LOG(("VieCapture:SetAndroidObjects Failed"));
+    return;
+  }
 
   env->DeleteGlobalRef(context);
 #endif
 
   if (!mVideoEngine) {
     if (!(mVideoEngine = webrtc::VideoEngine::Create())) {
       return;
     }
@@ -225,17 +228,20 @@ MediaEngineWebRTC::EnumerateAudioDevices
   jobject context = mozilla::AndroidBridge::Bridge()->GetGlobalContextRef();
 
   // get the JVM
   JavaVM *jvm = mozilla::AndroidBridge::Bridge()->GetVM();
 
   JNIEnv *env;
   jvm->AttachCurrentThread(&env, NULL);
 
-  webrtc::VoiceEngine::SetAndroidObjects(jvm, (void*)context);
+  if (webrtc::VoiceEngine::SetAndroidObjects(jvm, (void*)context) != 0) {
+    LOG(("VoiceEngine:SetAndroidObjects Failed"));
+    return;
+  }
 
   env->DeleteGlobalRef(context);
 #endif
 
   if (!mVoiceEngine) {
     mVoiceEngine = webrtc::VoiceEngine::Create();
     if (!mVoiceEngine) {
       return;
--- a/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/AudioConduit.cpp
@@ -142,22 +142,25 @@ MediaConduitErrorCode WebrtcAudioConduit
 #ifdef MOZ_WIDGET_ANDROID
       jobject context = jsjni_GetGlobalContextRef();
 
       // get the JVM
       JavaVM *jvm = jsjni_GetVM();
 
       JNIEnv* env;
       if (jvm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
-          CSFLogError(logTag,  "%s: could not get Java environment", __FUNCTION__);
-          return kMediaConduitSessionNotInited;
+        CSFLogError(logTag,  "%s: could not get Java environment", __FUNCTION__);
+        return kMediaConduitSessionNotInited;
       }
       jvm->AttachCurrentThread(&env, NULL);
 
-      webrtc::VoiceEngine::SetAndroidObjects(jvm, (void*)context);
+      if (webrtc::VoiceEngine::SetAndroidObjects(jvm, (void*)context) != 0) {
+        CSFLogError(logTag, "%s Unable to set Android objects", __FUNCTION__);
+        return kMediaConduitSessionNotInited;
+      }
 
       env->DeleteGlobalRef(context);
 #endif
 
     //Per WebRTC APIs below function calls return NULL on failure
     if(!(mVoiceEngine = webrtc::VoiceEngine::Create()))
     {
       CSFLogError(logTag, "%s Unable to create voice engine", __FUNCTION__);
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.cpp
@@ -112,17 +112,20 @@ MediaConduitErrorCode WebrtcVideoConduit
 
   JNIEnv* env;
   if (jvm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {
       CSFLogError(logTag,  "%s: could not get Java environment", __FUNCTION__);
       return kMediaConduitSessionNotInited;
   }
   jvm->AttachCurrentThread(&env, nullptr);
 
-  webrtc::VideoEngine::SetAndroidObjects(jvm, (void*)context);
+  if (webrtc::VideoEngine::SetAndroidObjects(jvm, (void*)context) != 0) {
+    CSFLogError(logTag,  "%s: could not set Android objects", __FUNCTION__);
+    return kMediaConduitSessionNotInited;
+  }
 
   env->DeleteGlobalRef(context);
 #endif
 
   if( !(mVideoEngine = webrtc::VideoEngine::Create()) )
   {
     CSFLogError(logTag, "%s Unable to create video engine ", __FUNCTION__);
      return kMediaConduitSessionNotInited;
--- a/media/webrtc/signaling/src/media-conduit/VideoConduit.h
+++ b/media/webrtc/signaling/src/media-conduit/VideoConduit.h
@@ -141,25 +141,31 @@ public:
    * Raw I420 Frames are delivred to the VideoConduit by the VideoEngine
    */
   virtual int FrameSizeChange(unsigned int, unsigned int, unsigned int);
 
   virtual int DeliverFrame(unsigned char*,int, uint32_t , int64_t);
 
 
   WebrtcVideoConduit():
-                      mVideoEngine(NULL),
-                      mTransport(NULL),
-                      mRenderer(NULL),
+                      mVideoEngine(nullptr),
+                      mTransport(nullptr),
+                      mRenderer(nullptr),
                       mEngineTransmitting(false),
                       mEngineReceiving(false),
                       mChannel(-1),
                       mCapId(-1),
-                      mCurSendCodecConfig(NULL)
-
+                      mCurSendCodecConfig(nullptr),
+                      mPtrViEBase(nullptr),
+                      mPtrViECapture(nullptr),
+                      mPtrViECodec(nullptr),
+                      mPtrViENetwork(nullptr),
+                      mPtrViERender(nullptr),
+                      mPtrExtCapture(nullptr),
+                      mPtrRTP(nullptr)
   {
   }
 
 
   virtual ~WebrtcVideoConduit() ;
 
 
 
--- a/media/webrtc/trunk/webrtc/modules/video_capture/android/java/org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/android/java/org/webrtc/videoengine/VideoCaptureDeviceInfoAndroid.java
@@ -113,37 +113,51 @@ public class VideoCaptureDeviceInfoAndro
 
                     camera = Camera.open(i);
                     Camera.Parameters parameters = camera.getParameters();
                     AddDeviceInfo(newDevice, parameters);
                     camera.release();
                     camera = null;
                     deviceList.add(newDevice);
                 }
+            } else {
+                camera = Camera.open();
+                Camera.Parameters parameters = camera.getParameters();
+                AndroidVideoCaptureDevice newDevice = new AndroidVideoCaptureDevice();
+                AddDeviceInfo(newDevice, parameters);
+                newDevice.deviceUniqueName = "Camera";
+                camera.release();
+                camera = null;
+                deviceList.add(newDevice);
             }
         }
         catch (Exception ex) {
-            Log.e(TAG, "Failed to init VideoCaptureDeviceInfo ex" +
-                    ex.getLocalizedMessage());
+            Log.e(TAG, "Failed to init VideoCaptureDeviceInfo exception: " +
+                    ex.getMessage());
+            if (camera != null) {
+                camera.release();
+            }
             return -1;
         }
         VerifyCapabilities();
         return 0;
     }
 
     // Adds the capture capabilities of the currently opened device
     private void AddDeviceInfo(AndroidVideoCaptureDevice newDevice,
             Camera.Parameters parameters) {
 
         List<Size> sizes = parameters.getSupportedPreviewSizes();
         List<Integer> frameRates = parameters.getSupportedPreviewFrameRates();
         int maxFPS = 0;
-        for(Integer frameRate:frameRates) {
-            if(frameRate > maxFPS) {
-                maxFPS = frameRate;
+        if (frameRates != null) {
+            for(Integer frameRate:frameRates) {
+                if(frameRate > maxFPS) {
+                    maxFPS = frameRate;
+                }
             }
         }
 
         newDevice.captureCapabilies = new CaptureCapabilityAndroid[sizes.size()];
         for(int i = 0; i < sizes.size(); ++i) {
             Size s = sizes.get(i);
             newDevice.captureCapabilies[i] = new CaptureCapabilityAndroid();
             newDevice.captureCapabilies[i].height = s.height;
--- 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
@@ -396,43 +396,45 @@ VideoCaptureAndroid::~VideoCaptureAndroi
                      "%s: Could not attach thread to JVM (%d, %p)",
                      __FUNCTION__, res, env);
       }
       else {
         isAttached = true;
       }
     }
 
-    // get the method ID for the Android Java CaptureClass static
-    // DeleteVideoCaptureAndroid  method. Call this to release the camera so
-    // another application can use it.
-    jmethodID cid = env->GetStaticMethodID(
-        g_javaCmClass,
-        "DeleteVideoCaptureAndroid",
-        "(Lorg/webrtc/videoengine/VideoCaptureAndroid;)V");
-    if (cid != NULL) {
-      WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
-                   "%s: Call DeleteVideoCaptureAndroid", __FUNCTION__);
-      // Close the camera by calling the static destruct function.
-      env->CallStaticVoidMethod(g_javaCmClass, cid, _javaCaptureObj);
+    if (env) {
+      // get the method ID for the Android Java CaptureClass static
+      // DeleteVideoCaptureAndroid  method. Call this to release the camera so
+      // another application can use it.
+      jmethodID cid = env->GetStaticMethodID(
+          g_javaCmClass,
+          "DeleteVideoCaptureAndroid",
+          "(Lorg/webrtc/videoengine/VideoCaptureAndroid;)V");
+      if (cid != NULL) {
+        WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, -1,
+                     "%s: Call DeleteVideoCaptureAndroid", __FUNCTION__);
+        // Close the camera by calling the static destruct function.
+        env->CallStaticVoidMethod(g_javaCmClass, cid, _javaCaptureObj);
 
-      // Delete global object ref to the camera.
-      env->DeleteGlobalRef(_javaCaptureObj);
-      // Clean up the global class references
-      env->DeleteGlobalRef(g_javaCmClass);
-      env->DeleteGlobalRef(g_javaCmDevInfoClass);
+        // Delete global object ref to the camera.
+        env->DeleteGlobalRef(_javaCaptureObj);
+        // Clean up the global class references
+        env->DeleteGlobalRef(g_javaCmClass);
+        env->DeleteGlobalRef(g_javaCmDevInfoClass);
 
-      _javaCaptureObj = NULL;
-      VideoCaptureAndroid::g_javaCmClass = NULL;
-      VideoCaptureAndroid::g_javaCmDevInfoClass = NULL;
-    }
-    else {
-      WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
-                   "%s: Failed to find DeleteVideoCaptureAndroid id",
-                   __FUNCTION__);
+        _javaCaptureObj = NULL;
+        VideoCaptureAndroid::g_javaCmClass = NULL;
+        VideoCaptureAndroid::g_javaCmDevInfoClass = NULL;
+      }
+      else {
+        WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, -1,
+                     "%s: Failed to find DeleteVideoCaptureAndroid id",
+                     __FUNCTION__);
+      }
     }
 
     // Detach this thread if it was attached
     if (isAttached) {
       if (g_jvm->DetachCurrentThread() < 0) {
         WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceAudioDevice,
                      _id, "%s: Could not detach thread from JVM",
                      __FUNCTION__);