Bug 1306186. Part 2 - reset prerolling flags in MaybeStartPlayback(). draft
authorJW Wang <jwwang@mozilla.com>
Thu, 29 Sep 2016 11:34:54 +0800
changeset 419971 03aa59e75347cdafb33792bc8fe08c5824dfaede
parent 419970 b344f86fc7f2221c6a4e5c61197aec635236ec48
child 419972 08f9f4bd1b0644cbe540019b55ae087ec3670088
push id31057
push userjwwang@mozilla.com
push dateMon, 03 Oct 2016 02:44:04 +0000
bugs1306186
milestone52.0a1
Bug 1306186. Part 2 - reset prerolling flags in MaybeStartPlayback(). MozReview-Commit-ID: 8cVfjRAsPk2
dom/media/MediaDecoderStateMachine.cpp
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -437,34 +437,33 @@ public:
 
     if (mMaster->CheckIfDecodeComplete()) {
       SetState(DECODER_STATE_COMPLETED);
       return;
     }
 
     mDecodeStartTime = TimeStamp::Now();
 
-    // Reset other state to pristine values before starting decode.
-    mMaster->mIsAudioPrerolling = !mMaster->DonePrerollingAudio() &&
-                                  !Reader()->IsWaitingAudioData();
-    mMaster->mIsVideoPrerolling = !mMaster->DonePrerollingVideo() &&
-                                  !Reader()->IsWaitingVideoData();
+    mMaster->mIsAudioPrerolling = true;
+    mMaster->mIsVideoPrerolling = true;
 
     // Ensure that we've got tasks enqueued to decode data if we need to.
     mMaster->DispatchDecodeTasksIfNeeded();
 
     mMaster->ScheduleStateMachine();
   }
 
   void Exit() override
   {
     if (!mDecodeStartTime.IsNull()) {
       TimeDuration decodeDuration = TimeStamp::Now() - mDecodeStartTime;
       SLOG("Exiting DECODING, decoded for %.3lfs", decodeDuration.ToSeconds());
     }
+    mMaster->mIsAudioPrerolling = false;
+    mMaster->mIsVideoPrerolling = false;
   }
 
   void Step() override
   {
     if (mMaster->mPlayState != MediaDecoder::PLAY_STATE_PLAYING &&
         mMaster->IsPlaying()) {
       // We're playing, but the element/decoder is in paused state. Stop
       // playing!
@@ -1049,18 +1048,19 @@ MediaDecoderStateMachine::OnAudioDecoded
     case DECODER_STATE_DECODING_FIRSTFRAME: {
       Push(audio, MediaData::AUDIO_DATA);
       MaybeFinishDecodeFirstFrame();
       return;
     }
 
     case DECODER_STATE_DECODING: {
       Push(audio, MediaData::AUDIO_DATA);
-      if (mIsAudioPrerolling && DonePrerollingAudio()) {
-        StopPrerollingAudio();
+      if (mIsAudioPrerolling) {
+        // Schedule next cycle to check if we can stop prerolling.
+        ScheduleStateMachine();
       }
       return;
     }
 
     default: {
       // Ignore other cases.
       return;
     }
@@ -1237,18 +1237,19 @@ MediaDecoderStateMachine::OnVideoDecoded
     case DECODER_STATE_DECODING_FIRSTFRAME: {
       Push(video, MediaData::VIDEO_DATA);
       MaybeFinishDecodeFirstFrame();
       return;
     }
 
     case DECODER_STATE_DECODING: {
       Push(video, MediaData::VIDEO_DATA);
-      if (mIsVideoPrerolling && DonePrerollingVideo()) {
-        StopPrerollingVideo();
+      if (mIsVideoPrerolling) {
+        // Schedule next cycle to check if we can stop prerolling.
+        ScheduleStateMachine();
       }
 
       // 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()) {
@@ -1414,16 +1415,26 @@ void MediaDecoderStateMachine::MaybeStar
   MOZ_ASSERT(mState == DECODER_STATE_DECODING ||
              mState == DECODER_STATE_COMPLETED);
 
   if (IsPlaying()) {
     // Logging this case is really spammy - don't do it.
     return;
   }
 
+  if (mIsAudioPrerolling &&
+      (DonePrerollingAudio() || mReader->IsWaitingAudioData())) {
+    mIsAudioPrerolling = false;
+  }
+
+  if (mIsVideoPrerolling &&
+      (DonePrerollingVideo() || mReader->IsWaitingVideoData())) {
+    mIsVideoPrerolling = false;
+  }
+
   bool playStatePermits = mPlayState == MediaDecoder::PLAY_STATE_PLAYING;
   if (!playStatePermits || mIsAudioPrerolling ||
       mIsVideoPrerolling || mAudioOffloading) {
     DECODER_LOG("Not starting playback [playStatePermits: %d, "
                 "mIsAudioPrerolling: %d, mIsVideoPrerolling: %d, "
                 "mAudioOffloading: %d]",
                 (int)playStatePermits, (int)mIsAudioPrerolling,
                 (int)mIsVideoPrerolling, (int)mAudioOffloading);
@@ -2764,23 +2775,17 @@ void
 MediaDecoderStateMachine::SetPlaybackRate(double aPlaybackRate)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(aPlaybackRate != 0, "Should be handled by MediaDecoder::Pause()");
 
   mPlaybackRate = aPlaybackRate;
   mMediaSink->SetPlaybackRate(mPlaybackRate);
 
-  if (mIsAudioPrerolling && DonePrerollingAudio()) {
-    StopPrerollingAudio();
-  }
-  if (mIsVideoPrerolling && DonePrerollingVideo()) {
-    StopPrerollingVideo();
-  }
-
+  // Schedule next cycle to check if we can stop prerolling.
   ScheduleStateMachine();
 }
 
 void MediaDecoderStateMachine::PreservesPitchChanged()
 {
   MOZ_ASSERT(OnTaskQueue());
   mMediaSink->SetPreservesPitch(mPreservesPitch);
 }
@@ -2934,18 +2939,20 @@ MediaDecoderStateMachine::SetAudioCaptur
   mAudioCaptured = aCaptured;
   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 (mIsAudioPrerolling && DonePrerollingAudio()) {
-    StopPrerollingAudio();
+
+  if (mIsAudioPrerolling) {
+    // Schedule next cycle to check if we can stop prerolling.
+    ScheduleStateMachine();
   }
 }
 
 uint32_t MediaDecoderStateMachine::GetAmpleVideoFrames() const
 {
   MOZ_ASSERT(OnTaskQueue());
   return (mReader->IsAsync() && mReader->VideoIsHardwareAccelerated())
     ? std::max<uint32_t>(sVideoQueueHWAccelSize, MIN_VIDEO_QUEUE_SIZE)