Bug 1262456 - [1.1] Prevent interruption of the decoder shutdown procedure and early shutdown return. r=snorp a=ritu
authorEugen Sawin <esawin@mozilla.com>
Thu, 07 Apr 2016 22:25:52 +0200
changeset 326380 3d2d1c251cc80f8288cc7b320703e55c37a606fd
parent 326379 e40d0d6bd40d1259aa266c96c226a0b88a9f7945
child 326381 12f8a808055570d529ec20a0da8dc9830c60b803
push id1128
push userjlund@mozilla.com
push dateWed, 01 Jun 2016 01:31:59 +0000
treeherdermozilla-release@fe0d30de989d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp, ritu
bugs1262456
milestone47.0
Bug 1262456 - [1.1] Prevent interruption of the decoder shutdown procedure and early shutdown return. r=snorp a=ritu
dom/media/platforms/android/AndroidDecoderModule.cpp
dom/media/platforms/android/AndroidDecoderModule.h
--- a/dom/media/platforms/android/AndroidDecoderModule.cpp
+++ b/dom/media/platforms/android/AndroidDecoderModule.cpp
@@ -350,20 +350,21 @@ MediaCodecDataDecoder::InitDecoder(Surfa
 
   nsresult rv;
   NS_ENSURE_SUCCESS(rv = mDecoder->Configure(mFormat, aSurface, nullptr, 0), rv);
   NS_ENSURE_SUCCESS(rv = mDecoder->Start(), rv);
 
   NS_ENSURE_SUCCESS(rv = ResetInputBuffers(), rv);
   NS_ENSURE_SUCCESS(rv = ResetOutputBuffers(), rv);
 
-  NS_NewNamedThread("MC Decoder", getter_AddRefs(mThread),
-                    NS_NewRunnableMethod(this, &MediaCodecDataDecoder::DecoderLoop));
+  rv = NS_NewNamedThread(
+      "MC Decoder", getter_AddRefs(mThread),
+      NS_NewRunnableMethod(this, &MediaCodecDataDecoder::DecoderLoop));
 
-  return NS_OK;
+  return rv;
 }
 
 // This is in usec, so that's 10ms.
 static const int64_t kDecoderTimeout = 10000;
 
 #define BREAK_ON_DECODER_ERROR() \
   if (NS_FAILED(res)) { \
     NS_WARNING("Exiting decoder loop due to exception"); \
@@ -643,28 +644,37 @@ MediaCodecDataDecoder::ModuleStateStr(Mo
 }
 
 MediaCodecDataDecoder::ModuleState
 MediaCodecDataDecoder::State() const
 {
   return mState;
 }
 
-void
+bool
 MediaCodecDataDecoder::State(ModuleState aState)
 {
-  LOG("%s -> %s", ModuleStateStr(mState), ModuleStateStr(aState));
+  bool ok = true;
 
-  if (aState == kDrainDecoder) {
-    MOZ_ASSERT(mState == kDrainQueue);
+  if (mState == kShutdown) {
+    ok = false;
+  } else if (mState == kStopping) {
+    ok = aState == kShutdown;
+  } else if (aState == kDrainDecoder) {
+    ok = mState == kDrainQueue;
   } else if (aState == kDrainWaitEOS) {
-    MOZ_ASSERT(mState == kDrainDecoder);
+    ok = mState == kDrainDecoder;
   }
 
-  mState = aState;
+  if (ok) {
+    LOG("%s -> %s", ModuleStateStr(mState), ModuleStateStr(aState));
+    mState = aState;
+  }
+
+  return ok;
 }
 
 template<typename T>
 void
 Clear(T& aCont)
 {
   T aEmpty = T();
   swap(aCont, aEmpty);
@@ -700,17 +710,19 @@ MediaCodecDataDecoder::ResetOutputBuffer
 {
   return mDecoder->GetOutputBuffers(ReturnTo(&mOutputBuffers));
 }
 
 nsresult
 MediaCodecDataDecoder::Flush()
 {
   MonitorAutoLock lock(mMonitor);
-  State(kFlushing);
+  if (!State(kFlushing)) {
+    return NS_OK;
+  }
   lock.Notify();
 
   while (State() == kFlushing) {
     lock.Wait();
   }
 
   return NS_OK;
 }
@@ -730,25 +742,20 @@ MediaCodecDataDecoder::Drain()
 }
 
 
 nsresult
 MediaCodecDataDecoder::Shutdown()
 {
   MonitorAutoLock lock(mMonitor);
 
-  if (State() == kStopping) {
-    // Already shutdown or in the process of doing so
-    return NS_OK;
-  }
-
   State(kStopping);
   lock.Notify();
 
-  while (mThread && State() == kStopping) {
+  while (mThread && State() != kShutdown) {
     lock.Wait();
   }
 
   if (mThread) {
     mThread->Shutdown();
     mThread = nullptr;
   }
 
--- a/dom/media/platforms/android/AndroidDecoderModule.h
+++ b/dom/media/platforms/android/AndroidDecoderModule.h
@@ -102,17 +102,18 @@ protected:
   nsresult QueueSample(const MediaRawData* aSample);
   nsresult QueueEOS();
   void HandleEOS(int32_t aOutputStatus);
   media::TimeUnit GetOutputDuration();
   nsresult ProcessOutput(widget::sdk::BufferInfo::Param aInfo,
                          widget::sdk::MediaFormat::Param aFormat,
                          int32_t aStatus);
   ModuleState State() const;
-  void State(ModuleState aState);
+  // Sets decoder state and returns whether the new state has become effective.
+  bool State(ModuleState aState);
   void DecoderLoop();
 
   virtual void ClearQueue();
 
   MediaData::Type mType;
 
   nsAutoCString mMimeType;
   widget::sdk::MediaFormat::GlobalRef mFormat;