Bug 1089423 - Catch MediaCodec exceptions r=gcp a=lsblakk
authorJames Willcox <snorp@snorp.net>
Wed, 05 Nov 2014 10:17:52 -0600
changeset 225944 cd94c836426e
parent 225943 5813f7c574ce
child 225945 5811de401315
push id4076
push userjwillcox@mozilla.com
push date2014-11-05 21:30 +0000
treeherdermozilla-beta@5811de401315 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgcp, lsblakk
bugs1089423
milestone34.0
Bug 1089423 - Catch MediaCodec exceptions r=gcp a=lsblakk
content/media/fmp4/android/AndroidDecoderModule.cpp
widget/android/GeneratedSDKWrappers.cpp
widget/android/GeneratedSDKWrappers.h
--- a/content/media/fmp4/android/AndroidDecoderModule.cpp
+++ b/content/media/fmp4/android/AndroidDecoderModule.cpp
@@ -271,17 +271,21 @@ nsresult MediaCodecDataDecoder::InitDeco
 {
   JNIEnv* env = GetJNIForThread();
   mDecoder = CreateDecoder(env, mMimeType);
   if (!mDecoder) {
     mCallback->Error();
     return NS_ERROR_FAILURE;
   }
 
-  mDecoder->Configure(mFormat->wrappedObject(), aSurface, nullptr, 0);
+  if (!mDecoder->Configure(mFormat->wrappedObject(), aSurface, nullptr, 0)) {
+    mCallback->Error();
+    return NS_ERROR_FAILURE;
+  }
+
   mDecoder->Start();
 
   ResetInputBuffers();
   ResetOutputBuffers();
 
   NS_NewNamedThread("MC Decoder", getter_AddRefs(mThread),
                     NS_NewRunnableMethod(this, &MediaCodecDataDecoder::DecoderLoop));
 
--- a/widget/android/GeneratedSDKWrappers.cpp
+++ b/widget/android/GeneratedSDKWrappers.cpp
@@ -80,32 +80,37 @@ void MediaCodec::InitStubs(JNIEnv *jEnv)
 
 MediaCodec* MediaCodec::Wrap(jobject obj) {
     JNIEnv *env = GetJNIForThread();
     MediaCodec* ret = new MediaCodec(obj, env);
     env->DeleteLocalRef(obj);
     return ret;
 }
 
-void MediaCodec::Configure(jobject a0, jobject a1, jobject a2, int32_t a3) {
+bool MediaCodec::Configure(jobject a0, jobject a1, jobject a2, int32_t a3) {
     JNIEnv *env = GetJNIForThread();
     if (env->PushLocalFrame(3) != 0) {
         AndroidBridge::HandleUncaughtException(env);
         MOZ_CRASH("Exception should have caused crash.");
     }
 
     jvalue args[4];
     args[0].l = a0;
     args[1].l = a1;
     args[2].l = a2;
     args[3].i = a3;
 
     env->CallVoidMethodA(wrapped_obj, jConfigure, args);
-    AndroidBridge::HandleUncaughtException(env);
+    if (env->ExceptionCheck()) {
+        env->ExceptionClear();
+        env->PopLocalFrame(nullptr);
+        return false;
+    }
     env->PopLocalFrame(nullptr);
+    return true;
 }
 
 jobject MediaCodec::CreateByCodecName(const nsAString& a0) {
     JNIEnv *env = GetJNIForThread();
     if (env->PushLocalFrame(2) != 0) {
         AndroidBridge::HandleUncaughtException(env);
         MOZ_CRASH("Exception should have caused crash.");
     }
@@ -151,30 +156,38 @@ jobject MediaCodec::CreateEncoderByType(
 int32_t MediaCodec::DequeueInputBuffer(int64_t a0) {
     JNIEnv *env = GetJNIForThread();
     if (env->PushLocalFrame(0) != 0) {
         AndroidBridge::HandleUncaughtException(env);
         MOZ_CRASH("Exception should have caused crash.");
     }
 
     int32_t temp = env->CallIntMethod(wrapped_obj, jDequeueInputBuffer, a0);
-    AndroidBridge::HandleUncaughtException(env);
+    if (env->ExceptionCheck()) {
+        env->ExceptionClear();
+        env->PopLocalFrame(nullptr);
+        return MEDIACODEC_EXCEPTION_INDEX;
+    }
     env->PopLocalFrame(nullptr);
     return temp;
 }
 
 int32_t MediaCodec::DequeueOutputBuffer(jobject a0, int64_t a1) {
     JNIEnv *env = GetJNIForThread();
     if (env->PushLocalFrame(1) != 0) {
         AndroidBridge::HandleUncaughtException(env);
         MOZ_CRASH("Exception should have caused crash.");
     }
 
     int32_t temp = env->CallIntMethod(wrapped_obj, jDequeueOutputBuffer, a0, a1);
-    AndroidBridge::HandleUncaughtException(env);
+    if (env->ExceptionCheck()) {
+        env->ExceptionClear();
+        env->PopLocalFrame(nullptr);
+        return MEDIACODEC_EXCEPTION_INDEX;
+    }
     env->PopLocalFrame(nullptr);
     return temp;
 }
 
 void MediaCodec::Finalize() {
     JNIEnv *env = GetJNIForThread();
     if (env->PushLocalFrame(0) != 0) {
         AndroidBridge::HandleUncaughtException(env);
@@ -306,26 +319,31 @@ void MediaCodec::SetVideoScalingMode(int
         MOZ_CRASH("Exception should have caused crash.");
     }
 
     env->CallVoidMethod(wrapped_obj, jSetVideoScalingMode, a0);
     AndroidBridge::HandleUncaughtException(env);
     env->PopLocalFrame(nullptr);
 }
 
-void MediaCodec::Start() {
+bool MediaCodec::Start() {
     JNIEnv *env = GetJNIForThread();
     if (env->PushLocalFrame(0) != 0) {
         AndroidBridge::HandleUncaughtException(env);
         MOZ_CRASH("Exception should have caused crash.");
     }
 
     env->CallVoidMethod(wrapped_obj, jStart);
-    AndroidBridge::HandleUncaughtException(env);
+    if (env->ExceptionCheck()) {
+        env->ExceptionClear();
+        env->PopLocalFrame(nullptr);
+        return false;
+    }
     env->PopLocalFrame(nullptr);
+    return true;
 }
 
 void MediaCodec::Stop() {
     JNIEnv *env = GetJNIForThread();
     if (env->PushLocalFrame(0) != 0) {
         AndroidBridge::HandleUncaughtException(env);
         MOZ_CRASH("Exception should have caused crash.");
     }
--- a/widget/android/GeneratedSDKWrappers.h
+++ b/widget/android/GeneratedSDKWrappers.h
@@ -12,40 +12,43 @@
 #define GeneratedSDKWrappers_h__
 
 #include "nsXPCOMStrings.h"
 #include "AndroidJavaWrappers.h"
 
 namespace mozilla {
 namespace widget {
 namespace android {
+
+#define MEDIACODEC_EXCEPTION_INDEX -255
+
 void InitSDKStubs(JNIEnv *jEnv);
 
 class MediaCodec : public AutoGlobalWrappedJavaObject {
 public:
     static void InitStubs(JNIEnv *jEnv);
     static MediaCodec* Wrap(jobject obj);
     MediaCodec(jobject obj, JNIEnv* env) : AutoGlobalWrappedJavaObject(obj, env) {};
-    void Configure(jobject a0, jobject a1, jobject a2, int32_t a3);
+    bool Configure(jobject a0, jobject a1, jobject a2, int32_t a3);
     static jobject CreateByCodecName(const nsAString& a0);
     static jobject CreateDecoderByType(const nsAString& a0);
     static jobject CreateEncoderByType(const nsAString& a0);
     int32_t DequeueInputBuffer(int64_t a0);
     int32_t DequeueOutputBuffer(jobject a0, int64_t a1);
     void Finalize();
     void Flush();
     jobjectArray GetInputBuffers();
     jobjectArray GetOutputBuffers();
     jobject GetOutputFormat();
     void QueueInputBuffer(int32_t a0, int32_t a1, int32_t a2, int64_t a3, int32_t a4);
     void QueueSecureInputBuffer(int32_t a0, int32_t a1, jobject a2, int64_t a3, int32_t a4);
     void Release();
     void ReleaseOutputBuffer(int32_t a0, bool a1);
     void SetVideoScalingMode(int32_t a0);
-    void Start();
+    bool Start();
     void Stop();
     static int32_t getBUFFER_FLAG_CODEC_CONFIG();
     static int32_t getBUFFER_FLAG_END_OF_STREAM();
     static int32_t getBUFFER_FLAG_SYNC_FRAME();
     static int32_t getCONFIGURE_FLAG_ENCODE();
     static int32_t getCRYPTO_MODE_AES_CTR();
     static int32_t getCRYPTO_MODE_UNENCRYPTED();
     static int32_t getINFO_OUTPUT_BUFFERS_CHANGED();