Bug 1390443. P1 - don't change nextFrameStatus when MDSM reaches the end of playback. draft
authorJW Wang <jwwang@mozilla.com>
Wed, 16 Aug 2017 15:33:58 +0800
changeset 648149 6f60fad11b65e75b456e128f8414fe2ea545455f
parent 648046 932388b8c22c9775264e543697ce918415db9e23
child 648150 498e2844d2d0d1cee087552f5aaf5aac7e34c3bf
push id74645
push userjwwang@mozilla.com
push dateThu, 17 Aug 2017 09:28:47 +0000
bugs1390443
milestone57.0a1
Bug 1390443. P1 - don't change nextFrameStatus when MDSM reaches the end of playback. Instead, MediaDecoder::NextFrameStatus() checks IsEnded() and returns NEXT_FRAME_UNAVAILABLE to ensure we have HAVE_CURRENT_DATA when playback is ended on the main thread. This will fix the timing issue (comment 0) which causes 'waiting' to fire. MozReview-Commit-ID: 7O21x2q0lb8
dom/html/HTMLMediaElement.cpp
dom/media/MediaDecoder.h
dom/media/MediaDecoderStateMachine.cpp
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -5818,24 +5818,16 @@ HTMLMediaElement::UpdateReadyStateIntern
     // Note that this state transition includes the case where we finished
     // downloaded the whole data stream.
     LOG(LogLevel::Debug, ("MediaElement %p UpdateReadyStateInternal() "
                           "Decoder download suspended by cache", this));
     ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
     return;
   }
 
-  if (mDecoder && !mDecoder->IsEnded() &&
-      !mDecoder->GetResource()->IsExpectingMoreData()) {
-    LOG(LogLevel::Debug, ("MediaElement %p UpdateReadyStateInternal() "
-                          "Decoder fetched all data for media resource", this));
-    ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_ENOUGH_DATA);
-    return;
-  }
-
   if (nextFrameStatus != MediaDecoderOwner::NEXT_FRAME_AVAILABLE) {
     LOG(LogLevel::Debug, ("MediaElement %p UpdateReadyStateInternal() "
                           "Next frame not available", this));
     ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA);
     return;
   }
 
   if (mSrcStream) {
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -400,18 +400,19 @@ private:
   {
     MOZ_ASSERT(NS_IsMainThread());
     MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
     GetOwner()->UpdateReadyState();
   }
 
   virtual MediaDecoderOwner::NextFrameStatus NextFrameStatus()
   {
-    return mNextFrameStatus;
+    return !IsEnded() ? mNextFrameStatus : MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
   }
+
   virtual MediaDecoderOwner::NextFrameStatus NextFrameBufferedStatus();
 
   // Returns a string describing the state of the media player internal
   // data. Used for debugging purposes.
   virtual void GetMozDebugReaderData(nsACString& aString) { }
 
   virtual void DumpDebugInfo();
 
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2001,19 +2001,16 @@ public:
       auto clockTime =
         std::max(mMaster->AudioEndTime(), mMaster->VideoEndTime());
       if (mMaster->mDuration.Ref()->IsInfinite()) {
         // We have a finite duration when playback reaches the end.
         mMaster->mDuration = Some(clockTime);
       }
       mMaster->UpdatePlaybackPosition(clockTime);
 
-      // Ensure readyState is updated before firing the 'ended' event.
-      mMaster->UpdateNextFrameStatus(MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE);
-
       mMaster->mOnPlaybackEvent.Notify(MediaEventType::PlaybackEnded);
 
       mSentPlaybackEndedEvent = true;
 
       // MediaSink::GetEndTime() must be called before stopping playback.
       mMaster->StopMediaSink();
     }
   }