Bug 1306186. Part 5 - add MaybeStopPrerolling() to check if we can stop prerolling. draft
authorJW Wang <jwwang@mozilla.com>
Mon, 03 Oct 2016 14:04:27 +0800
changeset 420066 d9ea0e523c33ccff9f4177baa196ad3093308b8d
parent 419973 6ade0a74ae34f01819b4714fcfcf599eb392fdba
child 420069 485c3af111499a52a82f2cb40f6874bc94b85661
child 420111 98d128872bbe32bb057942e0d0830b5f580f7f1a
push id31080
push userjwwang@mozilla.com
push dateMon, 03 Oct 2016 07:50:04 +0000
bugs1306186
milestone52.0a1
Bug 1306186. Part 5 - add MaybeStopPrerolling() to check if we can stop prerolling. MozReview-Commit-ID: 15Y5e4DUr4S
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1044,20 +1044,17 @@ MediaDecoderStateMachine::OnAudioDecoded
     case DECODER_STATE_DECODING_FIRSTFRAME: {
       Push(audio, MediaData::AUDIO_DATA);
       MaybeFinishDecodeFirstFrame();
       return;
     }
 
     case DECODER_STATE_DECODING: {
       Push(audio, MediaData::AUDIO_DATA);
-      if (mIsPrerolling) {
-        // Schedule next cycle to check if we can stop prerolling.
-        ScheduleStateMachine();
-      }
+      MaybeStopPrerolling();
       return;
     }
 
     default: {
       // Ignore other cases.
       return;
     }
   }
@@ -1123,22 +1120,17 @@ MediaDecoderStateMachine::OnNotDecoded(M
   }
 
   // If the decoder is waiting for data, we tell it to call us back when the
   // data arrives.
   if (aError == NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA) {
     MOZ_ASSERT(mReader->IsWaitForDataSupported(),
                "Readers that send WAITING_FOR_DATA need to implement WaitForData");
     mReader->WaitForData(aType);
-
-    if (mIsPrerolling) {
-      // Schedule next cycle to stop prerolling so we can play the frames we've
-      // decoded so far.
-      ScheduleStateMachine();
-    }
+    MaybeStopPrerolling();
     return;
   }
 
   if (aError == NS_ERROR_DOM_MEDIA_CANCELED) {
     if (isAudio) {
       EnsureAudioDecodeTaskQueued();
     } else {
       EnsureVideoDecodeTaskQueued();
@@ -1155,21 +1147,17 @@ MediaDecoderStateMachine::OnNotDecoded(M
   // This is an EOS. Finish off the queue, and then handle things based on our
   // state.
   if (isAudio) {
     AudioQueue().Finish();
   } else {
     VideoQueue().Finish();
   }
 
-  if (mIsPrerolling) {
-    // No more data to decode. Schedule next cycle to stop prerolling
-    // and start playback.
-    ScheduleStateMachine();
-  }
+  MaybeStopPrerolling();
 
   switch (mState) {
     case DECODER_STATE_DECODING_FIRSTFRAME:
       MaybeFinishDecodeFirstFrame();
       return;
     case DECODER_STATE_BUFFERING:
     case DECODER_STATE_DECODING: {
       if (CheckIfDecodeComplete()) {
@@ -1235,20 +1223,17 @@ MediaDecoderStateMachine::OnVideoDecoded
     case DECODER_STATE_DECODING_FIRSTFRAME: {
       Push(video, MediaData::VIDEO_DATA);
       MaybeFinishDecodeFirstFrame();
       return;
     }
 
     case DECODER_STATE_DECODING: {
       Push(video, MediaData::VIDEO_DATA);
-      if (mIsPrerolling) {
-        // Schedule next cycle to check if we can stop prerolling.
-        ScheduleStateMachine();
-      }
+      MaybeStopPrerolling();
 
       // For non async readers, if the requested video sample was slow to
       // arrive, increase the amount of audio we buffer to ensure that we
       // don't run out of audio. This is unnecessary for async readers,
       // since they decode audio and video on different threads so they
       // are unlikely to run out of decoded audio.
       if (mReader->IsAsync()) {
         return;
@@ -1400,35 +1385,42 @@ void MediaDecoderStateMachine::StopPlayb
   if (IsPlaying()) {
     mMediaSink->SetPlaying(false);
     MOZ_ASSERT(!IsPlaying());
   }
 
   DispatchDecodeTasksIfNeeded();
 }
 
+void
+MediaDecoderStateMachine::MaybeStopPrerolling()
+{
+  MOZ_ASSERT(OnTaskQueue());
+  if (mIsPrerolling &&
+      (DonePrerollingAudio() || mReader->IsWaitingAudioData()) &&
+      (DonePrerollingVideo() || mReader->IsWaitingVideoData())) {
+    mIsPrerolling = false;
+    // Check if we can start playback.
+    ScheduleStateMachine();
+  }
+}
+
 void MediaDecoderStateMachine::MaybeStartPlayback()
 {
   MOZ_ASSERT(OnTaskQueue());
   // Should try to start playback only after decoding first frames.
   MOZ_ASSERT(mSentFirstFrameLoadedEvent);
   MOZ_ASSERT(mState == DECODER_STATE_DECODING ||
              mState == DECODER_STATE_COMPLETED);
 
   if (IsPlaying()) {
     // Logging this case is really spammy - don't do it.
     return;
   }
 
-  if (mIsPrerolling &&
-      (DonePrerollingAudio() || mReader->IsWaitingAudioData()) &&
-      (DonePrerollingVideo() || mReader->IsWaitingVideoData())) {
-    mIsPrerolling = false;
-  }
-
   bool playStatePermits = mPlayState == MediaDecoder::PLAY_STATE_PLAYING;
   if (!playStatePermits || mIsPrerolling || mAudioOffloading) {
     DECODER_LOG("Not starting playback [playStatePermits: %d, "
                 "mIsPrerolling: %d, mAudioOffloading: %d]",
                 playStatePermits, mIsPrerolling, mAudioOffloading);
     return;
   }
 
@@ -2927,20 +2919,17 @@ MediaDecoderStateMachine::SetAudioCaptur
   ScheduleStateMachine();
 
   // Don't buffer as much when audio is captured because we don't need to worry
   // about high latency audio devices.
   mAmpleAudioThresholdUsecs = mAudioCaptured ?
                               detail::AMPLE_AUDIO_USECS / 2 :
                               detail::AMPLE_AUDIO_USECS;
 
-  if (mIsPrerolling) {
-    // Schedule next cycle to check if we can stop prerolling.
-    ScheduleStateMachine();
-  }
+  MaybeStopPrerolling();
 }
 
 uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const
 {
   MOZ_ASSERT(OnTaskQueue());
   return (mReader->IsAsync() && mReader->VideoIsHardwareAccelerated())
     ? std::max<uint32_t>(sVideoQueueHWAccelSize, MIN_VIDEO_QUEUE_SIZE)
     : std::max<uint32_t>(sVideoQueueDefaultSize, MIN_VIDEO_QUEUE_SIZE);
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -725,16 +725,18 @@ private:
   {
     MOZ_ASSERT(OnTaskQueue());
     return !mIsVisible ||
         !IsVideoDecoding() ||
         static_cast<uint32_t>(VideoQueue().GetSize()) >=
             VideoPrerollFrames() * mPlaybackRate + 1;
   }
 
+  void MaybeStopPrerolling();
+
   // When we start decoding (either for the first time, or after a pause)
   // we may be low on decoded data. We don't want our "low data" logic to
   // kick in and decide that we're low on decoded data because the download
   // can't keep up with the decode, and cause us to pause playback. So we
   // have a "preroll" stage, where we ignore the results of our "low data"
   // logic during the first few frames of our decode. This occurs during
   // playback.
   bool mIsPrerolling = false;