Bug 1341200. Part 8 - let DecoderData::ShutdownDecoder() handle shutdown in the middle of flush. draft
authorJW Wang <jwwang@mozilla.com>
Sun, 26 Feb 2017 22:51:22 +0800
changeset 493140 8a21649b36a0bbe11c7efb788bcc57bcb471977d
parent 493139 7eb24cfdaad873f9335ca3ca90e38947ea3ad085
child 493141 6ef163dbeecce91ce91efec55db48f24869913ec
push id47651
push userjwwang@mozilla.com
push dateFri, 03 Mar 2017 09:41:12 +0000
bugs1341200
milestone54.0a1
Bug 1341200. Part 8 - let DecoderData::ShutdownDecoder() handle shutdown in the middle of flush. MozReview-Commit-ID: FW23TFQLStR
dom/media/MediaFormatReader.cpp
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -373,33 +373,46 @@ MediaFormatReader::ShutdownPromisePool::
       }
     });
 }
 
 void
 MediaFormatReader::DecoderData::ShutdownDecoder()
 {
   MutexAutoLock lock(mMutex);
-  if (mDecoder) {
-    RefPtr<MediaFormatReader> owner = mOwner;
-    TrackType type = mType == MediaData::AUDIO_DATA
-                     ? TrackType::kAudioTrack
-                     : TrackType::kVideoTrack;
-    mShuttingDown = true;
-    mDecoder->Shutdown()
-      ->Then(mOwner->OwnerThread(), __func__,
-             [owner, this, type]() {
-               mShuttingDown = false;
-               mShutdownPromise.ResolveIfExists(true, __func__);
-               owner->ScheduleUpdate(type);
-             },
-             []() { MOZ_RELEASE_ASSERT(false, "Can't ever be here"); });
+
+  if (!mDecoder) {
+    // No decoder to shut down.
+    return;
+  }
+
+  if (mFlushing) {
+    // Flush is is in action. Shutdown will be initiated after flush completes.
+    if (mShutdownPromise.IsEmpty()) {
+      mOwner->mShutdownPromisePool->Track(mShutdownPromise.Ensure(__func__));
+    }
+    return;
   }
+
+  if (!mShutdownPromise.IsEmpty()) {
+    // This is called from the resolve/reject function of Flush.
+    // Let's continue shutdown.
+    mDecoder->Shutdown()->ChainTo(mShutdownPromise.Steal(), __func__);
+  } else {
+    // No flush is in action. We can shut down the decoder now.
+    mOwner->mShutdownPromisePool->Track(mDecoder->Shutdown());
+  }
+
+  // mShutdownPromisePool will handle the order of decoder shutdown so
+  // we can forget mDecoder and be ready to create a new one.
+  mDecoder = nullptr;
   mDescription = "shutdown";
-  mDecoder = nullptr;
+  mOwner->ScheduleUpdate(mType == MediaData::AUDIO_DATA
+                         ? TrackType::kAudioTrack
+                         : TrackType::kVideoTrack);
 }
 
 void
 MediaFormatReader::DecoderData::Flush()
 {
   if (mFlushing || mFlushed) {
     // Flush still pending or already flushed, nothing more to do.
     return;
@@ -1137,54 +1150,24 @@ MediaFormatReader::Shutdown()
            &MediaFormatReader::TearDownDecoders);
 }
 
 void
 MediaFormatReader::ShutdownDecoder(TrackType aTrack)
 {
   LOGV("%s", TrackTypeToStr(aTrack));
 
+  // Shut down the pending decoder if any.
+  mDecoderFactory->ShutdownDecoder(aTrack);
+
   auto& decoder = GetDecoderData(aTrack);
-  if (!decoder.mDecoder) {
-    LOGV("Already shut down");
-    return;
-  }
-  if (!decoder.mShutdownPromise.IsEmpty()) {
-    LOGV("Shutdown already in progress");
-    return;
-  }
-
-  if (!decoder.mFlushed && decoder.mDecoder) {
-    // The decoder has yet to be flushed.
-    // We always flush the decoder prior to a shutdown to ensure that all the
-    // potentially pending operations on the decoder are completed.
-    decoder.Flush();
-    mShutdownPromisePool->Track(decoder.mShutdownPromise.Ensure(__func__));
-    return;
-  }
-
-  if (decoder.mFlushing || decoder.mShuttingDown) {
-    // Let the current flush or shutdown operation complete, Flush will continue
-    // shutting down the current decoder now that the shutdown promise is set.
-    mShutdownPromisePool->Track(decoder.mShutdownPromise.Ensure(__func__));
-    return;
-  }
-
-  if (!decoder.mDecoder) {
-    // Shutdown any decoders that may be in the process of being initialized
-    // in the Decoder Factory.
-    // This will be a no-op until we're processing the final decoder shutdown
-    // prior to the MediaFormatReader being shutdown.
-    mDecoderFactory->ShutdownDecoder(aTrack);
-    return;
-  }
-
-  // Finally, let's just shut down the currently active decoder.
+  // Flush the decoder if necessary.
+  decoder.Flush();
+  // Shut down the decoder if any.
   decoder.ShutdownDecoder();
-  mShutdownPromisePool->Track(decoder.mShutdownPromise.Ensure(__func__));
 }
 
 RefPtr<ShutdownPromise>
 MediaFormatReader::TearDownDecoders()
 {
   if (mAudio.mTaskQueue) {
     mAudio.mTaskQueue->BeginShutdown();
     mAudio.mTaskQueue->AwaitShutdownAndIdle();