shithub: openh264

Download patch

ref: d58ac746a0be98fcf429a156e1a077b0e621fa82
parent: 92729951435f4548f51138a596bfafde06d21de9
author: Hank Peng <hankpeng@cisco.com>
date: Wed Dec 2 18:46:43 EST 2015

Avoid a potential deadlock between the main thread and worker thread when encoding or decoding complete

--- a/module/gmp-openh264.cpp
+++ b/module/gmp-openh264.cpp
@@ -187,7 +187,8 @@
     encoder_ (nullptr),
     max_payload_size_ (0),
     callback_ (nullptr),
-    stats_ ("Encoder") {
+    stats_ ("Encoder"),
+    shutting_down(false) {
       AddRef();
     }
 
@@ -361,6 +362,8 @@
   }
 
   virtual void EncodingComplete() {
+    shutting_down = true;
+
     // Release the reference to the external objects, because it is no longer safe to call them
     host_     = nullptr;
     callback_ = nullptr;
@@ -389,6 +392,12 @@
      }
    }
 
+  void TrySyncRunOnMainThread(GMPTask* aTask) {
+    if (!shutting_down && g_platform_api) {
+      g_platform_api->syncrunonmainthread (aTask);
+    }
+  }
+
   void Error (GMPErr error) {
     if (callback_) {
       callback_->Error (error);
@@ -466,20 +475,20 @@
 
     if (!has_frame) {
       // This frame must be destroyed on the main thread.
-      g_platform_api->syncrunonmainthread (WrapTask (
-                                             this,
-                                             &OpenH264VideoEncoder::DestroyInputFrame_m,
-                                             inputImage));
+      TrySyncRunOnMainThread (WrapTask (
+                                   this,
+                                   &OpenH264VideoEncoder::DestroyInputFrame_m,
+                                   inputImage));
       return;
     }
 
     // Synchronously send this back to the main thread for delivery.
-    g_platform_api->syncrunonmainthread (WrapTask (
-                                           this,
-                                           &OpenH264VideoEncoder::Encode_m,
-                                           inputImage,
-                                           &encoded,
-                                           encoded_type));
+    TrySyncRunOnMainThread (WrapTask (
+                                   this,
+                                   &OpenH264VideoEncoder::Encode_m,
+                                   inputImage,
+                                   &encoded,
+                                   encoded_type));
   }
 
   void Encode_m (GMPVideoi420Frame* frame, SFrameBSInfo* encoded,
@@ -574,6 +583,7 @@
   uint32_t max_payload_size_;
   GMPVideoEncoderCallback* callback_;
   FrameStats stats_;
+  bool shutting_down;
 };
 
 uint16_t readU16BE(const uint8_t* in) {
@@ -593,7 +603,8 @@
     worker_thread_ (nullptr),
     callback_ (nullptr),
     decoder_ (nullptr),
-    stats_ ("Decoder") {
+    stats_ ("Decoder"),
+    shutting_down(false) {
       AddRef();
     }
 
@@ -739,6 +750,8 @@
   }
 
   virtual void DecodingComplete() {
+    shutting_down = true;
+
     // Release the reference to the external objects, because it is no longer safe to call them
     host_     = nullptr;
     callback_ = nullptr;
@@ -766,6 +779,13 @@
       decoder_ = nullptr;
     }
   }
+
+  void TrySyncRunOnMainThread(GMPTask* aTask) {
+    if (!shutting_down && g_platform_api) {
+      g_platform_api->syncrunonmainthread (aTask);
+    }
+  }
+
   void Error (GMPErr error) {
     if (callback_) {
       callback_->Error (error);
@@ -795,14 +815,14 @@
       valid = true;
     }
 
-    g_platform_api->syncrunonmainthread (WrapTask (
-                                           this,
-                                           &OpenH264VideoDecoder::Decode_m,
-                                           inputFrame,
-                                           &decoded,
-                                           data,
-                                           renderTimeMs,
-                                           valid));
+    TrySyncRunOnMainThread (WrapTask (
+                                 this,
+                                 &OpenH264VideoDecoder::Decode_m,
+                                 inputFrame,
+                                 &decoded,
+                                 data,
+                                 renderTimeMs,
+                                 valid));
   }
 
   // Return the decoded data back to the parent.
@@ -883,6 +903,7 @@
   GMPVideoDecoderCallback* callback_;
   ISVCDecoder* decoder_;
   FrameStats stats_;
+  bool shutting_down;
 };
 
 extern "C" {