Bug 1322087. Part 2 - move readyState to HAVE_ENOUGH_DATA when we have no more data to fetch. r=cpearce
authorJW Wang <jwwang@mozilla.com>
Wed, 07 Dec 2016 10:41:33 -1000
changeset 325427 f988f0ed610f7194157c0825c792de963e5ff1e6
parent 325426 fa8864946562294976beb473fb7c21df3d0a2ba6
child 325428 8ded70fe72120a5459451919d88602c8b86bb926
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
Bug 1322087. Part 2 - move readyState to HAVE_ENOUGH_DATA when we have no more data to fetch. r=cpearce http://searchfox.org/mozilla-central/rev/dc8cf05768b83a6ef0b4039edd6efddd56ee4109/dom/media/MediaDecoderStateMachine.cpp#1065 Changing nextFrameStatus to UNAVAILABLE might change readyState to HAVE_CURRENT_DATA and cause 'waiting' to fire. It doesn't make sense to fire 'waiting' at the end of playback. http://searchfox.org/mozilla-central/rev/dc8cf05768b83a6ef0b4039edd6efddd56ee4109/dom/html/HTMLMediaElement.cpp#5423 Note the check for Ended() doesn't work as expected to prevent 'waiting' from firing at the end of playback because of the way how TailDispatcher schedules stateChange tasks. This patch keeps readyState in HAVE_ENOUGH_DATA when playback is near the end for wanting no more data. readyState will change to HAVE_CURRENT_DATA when the playing state of MediaDecoder is changed to PLAY_STATE_ENDED. MozReview-Commit-ID: 6EspaD2hhx
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -5324,32 +5324,46 @@ HTMLMediaElement::UpdateReadyStateIntern
   if (!mFirstFrameLoaded) {
     // We haven't yet loaded the first frame, making us unable to determine
     // if we have enough valid data at the present stage.
+    // Force HAVE_CURRENT_DATA when buffering.
+    ChangeReadyState(nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA);
+    return;
+  }
   if (mDownloadSuspendedByCache && mDecoder && !mDecoder->IsEnded()) {
     // The decoder has signaled that the download has been suspended by the
     // media cache. So move readyState into HAVE_ENOUGH_DATA, in case there's
     // script waiting for a "canplaythrough" event; without this forced
     // transition, we will never fire the "canplaythrough" event if the
     // media cache is too small, and scripts are bound to fail. Don't force
     // this transition if the decoder is in ended state; the readyState
     // should remain at HAVE_CURRENT_DATA in this case.
     // 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));
+  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));
   if (mSrcStream) {