Bug 1229987: P4. Stop pre-rolling when encountering WAITING_FOR_DATA. r=cpearce a=sylvestre
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 09 Dec 2015 08:53:26 -0500
changeset 310528 50de8c9efef869a5b26fd91b1481639b351e3634
parent 310527 9fa906dfe06d967c7ddf553af682a629a391b872
child 310529 aa47aa5c7a22a4ce7ab1bcfe5119b5b944b4ef38
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce, sylvestre
bugs1229987
milestone45.0a2
Bug 1229987: P4. Stop pre-rolling when encountering WAITING_FOR_DATA. r=cpearce a=sylvestre This allows to start displaying frames even when we have less than 5 frames.
dom/media/MediaDecoder.cpp
dom/media/MediaDecoderStateMachine.cpp
dom/media/mediasource/test/test_PlayEvents.html
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -785,16 +785,17 @@ MediaDecoder::Play()
 nsresult
 MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType)
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_TRUE(!mShuttingDown, NS_ERROR_FAILURE);
 
   UpdateDormantState(false /* aDormantTimeout */, true /* aActivity */);
 
+  MOZ_ASSERT(!mIsDormant, "should be out of dormant by now");
   MOZ_ASSERT(aTime >= 0.0, "Cannot seek to a negative value.");
 
   int64_t timeUsecs = 0;
   nsresult rv = SecondsToUsecs(aTime, timeUsecs);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mLogicalPosition = aTime;
   mWasEndedWhenEnteredDormant = false;
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -778,16 +778,27 @@ MediaDecoderStateMachine::OnNotDecoded(M
              [self] (MediaData::Type aType) -> void {
                self->WaitRequestRef(aType).Complete();
                self->DispatchDecodeTasksIfNeeded();
              },
              [self] (WaitForDataRejectValue aRejection) -> void {
                self->WaitRequestRef(aRejection.mType).Complete();
              }));
 
+    // We are out of data to decode and will enter buffering mode soon.
+    // We want to play the frames we have already decoded, so we stop pre-rolling
+    // and ensure that loadeddata is fired as required.
+    if (isAudio) {
+      StopPrerollingAudio();
+    } else {
+      StopPrerollingVideo();
+    }
+    if (mState == DECODER_STATE_BUFFERING || mState == DECODER_STATE_DECODING) {
+        MaybeFinishDecodeFirstFrame();
+    }
     return;
   }
 
   if (aReason == MediaDecoderReader::CANCELED) {
     DispatchDecodeTasksIfNeeded();
     return;
   }
 
@@ -1477,17 +1488,17 @@ MediaDecoderStateMachine::Seek(SeekTarge
 
   // We need to be able to seek both at a transport level and at a media level
   // to seek.
   if (!mMediaSeekable) {
     DECODER_WARN("Seek() function should not be called on a non-seekable state machine");
     return MediaDecoder::SeekPromise::CreateAndReject(/* aIgnored = */ true, __func__);
   }
 
-  NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA,
+  MOZ_ASSERT(mState > DECODER_STATE_DECODING_METADATA,
                "We should have got duration already");
 
   if (mState < DECODER_STATE_DECODING ||
       (IsDecodingFirstFrame() && !mReader->ForceZeroStartTime())) {
     DECODER_LOG("Seek() Not Enough Data to continue at this stage, queuing seek");
     mQueuedSeek.RejectIfExists(__func__);
     mQueuedSeek.mTarget = aTarget;
     return mQueuedSeek.mPromise.Ensure(__func__);
--- a/dom/media/mediasource/test/test_PlayEvents.html
+++ b/dom/media/mediasource/test/test_PlayEvents.html
@@ -19,16 +19,28 @@ SimpleTest.waitForExplicitFinish();
 // 4. Load 1.6s of data at the seek position and ensure that canplay is fired and that readyState is now HAVE_FUTURE_DATA
 // 5. Start playing video and check that once it reaches a position with no data, readyState goes back to HAVE_CURRENT_DATA and waiting event is fired.
 // 6. Add 1.6s of data once video element fired waiting, that canplay is fired once readyState is HAVE_FUTURE_DATA.
 // 7. Finally load data to the end and ensure that canplaythrough is fired and that readyState is now HAVE_ENOUGH_DATA
 
 runWithMSE(function(ms, el) {
   el.controls = true;
   once(ms, 'sourceopen').then(function() {
+    // Log events for debugging.
+    var events = ["suspend", "play", "canplay", "canplaythrough", "loadstart", "loadedmetadata",
+                  "loadeddata", "playing", "ended", "error", "stalled", "emptied", "abort",
+                  "waiting", "pause", "durationchange", "seeking", "seeked"];
+    function logEvent(e) {
+      var v = e.target;
+      info("got " + e.type + " event");
+    }
+    events.forEach(function(e) {
+      el.addEventListener(e, logEvent, false);
+    });
+
     ok(true, "Receive a sourceopen event");
     var videosb = ms.addSourceBuffer("video/mp4");
     el.addEventListener("error", function(e) {
       ok(false, "should not fire '" + e + "' event");
     });
     is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
     fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4')
     .then(once.bind(null, el, 'loadedmetadata'))