Bug 1300711 - Remove MediaDecoderStateMachine::mQuickBuffering. draft
authorJW Wang <jwwang@mozilla.com>
Tue, 06 Sep 2016 16:28:20 +0800
changeset 415329 e660acc2b4b19c41f52ca7f40e508a995354135e
parent 415328 702dbbbfcd193e7c88e5912af81e1653dbb05dd5
child 415333 c0799cf593ae60cc6c0b5e10a536d426601ed923
push id29848
push userjwwang@mozilla.com
push dateTue, 20 Sep 2016 06:16:26 +0000
bugs1300711
milestone51.0a1
Bug 1300711 - Remove MediaDecoderStateMachine::mQuickBuffering. MozReview-Commit-ID: GW7bhY6ruKG
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaDecoderStateMachine.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -137,46 +137,16 @@ static const int64_t LOW_DATA_THRESHOLD_
 static_assert(LOW_DATA_THRESHOLD_USECS > AMPLE_AUDIO_USECS,
               "LOW_DATA_THRESHOLD_USECS is too small");
 
 } // namespace detail
 
 // Amount of excess usecs of data to add in to the "should we buffer" calculation.
 static const uint32_t EXHAUSTED_DATA_MARGIN_USECS = 100000;
 
-// If we enter buffering within QUICK_BUFFER_THRESHOLD_USECS seconds of starting
-// decoding, we'll enter "quick buffering" mode, which exits a lot sooner than
-// normal buffering mode. This exists so that if the decode-ahead exhausts the
-// downloaded data while decode/playback is just starting up (for example
-// after a seek while the media is still playing, or when playing a media
-// as soon as it's load started), we won't necessarily stop for 30s and wait
-// for buffering. We may actually be able to playback in this case, so exit
-// buffering early and try to play. If it turns out we can't play, we'll fall
-// back to buffering normally.
-static const uint32_t QUICK_BUFFER_THRESHOLD_USECS = 2000000;
-
-namespace detail {
-
-// If we're quick buffering, we'll remain in buffering mode while we have less than
-// QUICK_BUFFERING_LOW_DATA_USECS of decoded data available.
-static const uint32_t QUICK_BUFFERING_LOW_DATA_USECS = 1000000;
-
-// If QUICK_BUFFERING_LOW_DATA_USECS is > AMPLE_AUDIO_USECS, we won't exit
-// quick buffering in a timely fashion, as the decode pauses when it
-// reaches AMPLE_AUDIO_USECS decoded data, and thus we'll never reach
-// QUICK_BUFFERING_LOW_DATA_USECS.
-static_assert(QUICK_BUFFERING_LOW_DATA_USECS <= AMPLE_AUDIO_USECS,
-              "QUICK_BUFFERING_LOW_DATA_USECS is too large");
-
-} // namespace detail
-
-static TimeDuration UsecsToDuration(int64_t aUsecs) {
-  return TimeDuration::FromMicroseconds(aUsecs);
-}
-
 static int64_t DurationToUsecs(TimeDuration aDuration) {
   return static_cast<int64_t>(aDuration.ToSeconds() * USECS_PER_S);
 }
 
 static const uint32_t MIN_VIDEO_QUEUE_SIZE = 3;
 static const uint32_t MAX_VIDEO_QUEUE_SIZE = 10;
 #ifdef MOZ_APPLEMEDIA
 static const uint32_t HW_VIDEO_QUEUE_SIZE = 10;
@@ -606,24 +576,22 @@ MediaDecoderStateMachine::MediaDecoderSt
   INIT_WATCHABLE(mObservedDuration, TimeUnit()),
   mFragmentEndTime(-1),
   mReader(new MediaDecoderReaderWrapper(mTaskQueue, aReader)),
   mDecodedAudioEndTime(0),
   mDecodedVideoEndTime(0),
   mPlaybackRate(1.0),
   mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS),
   mAmpleAudioThresholdUsecs(detail::AMPLE_AUDIO_USECS),
-  mQuickBufferingLowDataThresholdUsecs(detail::QUICK_BUFFERING_LOW_DATA_USECS),
   mIsAudioPrerolling(false),
   mIsVideoPrerolling(false),
   mAudioCaptured(false),
   INIT_WATCHABLE(mAudioCompleted, false),
   INIT_WATCHABLE(mVideoCompleted, false),
   mNotifyMetadataBeforeFirstFrame(false),
-  mQuickBuffering(false),
   mMinimizePreroll(false),
   mDecodeThreadWaiting(false),
   mSentLoadedMetadataEvent(false),
   mSentFirstFrameLoadedEvent(false),
   mSentPlaybackEndedEvent(false),
   mVideoDecodeSuspended(false),
   mVideoDecodeSuspendTimer(mTaskQueue),
   mOutputStreamManager(new OutputStreamManager()),
@@ -1381,17 +1349,17 @@ MediaDecoderStateMachine::MaybeStartBuff
   // No more data to download. No need to enter buffering.
   if (!mResource->IsExpectingMoreData()) {
     return;
   }
 
   bool shouldBuffer;
   if (mReader->UseBufferingHeuristics()) {
     shouldBuffer = HasLowDecodedData(EXHAUSTED_DATA_MARGIN_USECS) &&
-                   (JustExitedQuickBuffering() || HasLowBufferedData());
+                   HasLowBufferedData();
   } else {
     MOZ_ASSERT(mReader->IsWaitForDataSupported());
     shouldBuffer = (OutOfDecodedAudio() && mReader->IsWaitingAudioData()) ||
                    (OutOfDecodedVideo() && mReader->IsWaitingVideoData());
   }
   if (shouldBuffer) {
     SetState(DECODER_STATE_BUFFERING);
   }
@@ -2465,21 +2433,16 @@ MediaDecoderStateMachine::SeekCompleted(
   }
 
   // Ensure timestamps are up to date.
   UpdatePlaybackPositionInternal(newCurrentTime);
 
   // Try to decode another frame to detect if we're at the end...
   DECODER_LOG("Seek completed, mCurrentPosition=%lld", mCurrentPosition.Ref());
 
-  // Reset quick buffering status. This ensures that if we began the
-  // seek while quick-buffering, we won't bypass quick buffering mode
-  // if we need to buffer after the seek.
-  mQuickBuffering = false;
-
   if (video) {
     mMediaSink->Redraw(mInfo.mVideo);
     mOnPlaybackEvent.Notify(MediaEventType::Invalidate);
   }
 
   SetState(nextState);
   MOZ_ASSERT(IsStateMachineScheduled());
 }
@@ -2545,22 +2508,20 @@ MediaDecoderStateMachine::StepBuffering(
   // With buffering heuristics we will remain in the buffering state if
   // we've not decoded enough data to begin playback, or if we've not
   // downloaded a reasonable amount of data inside our buffering time.
   if (mReader->UseBufferingHeuristics()) {
     TimeDuration elapsed = now - mBufferingStart;
     bool isLiveStream = mResource->IsLiveStream();
     if ((isLiveStream || !CanPlayThrough()) &&
         elapsed < TimeDuration::FromSeconds(mBufferingWait * mPlaybackRate) &&
-        (mQuickBuffering ? HasLowDecodedData(mQuickBufferingLowDataThresholdUsecs)
-                         : HasLowBufferedData(mBufferingWait * USECS_PER_S)) &&
+        HasLowBufferedData(mBufferingWait * USECS_PER_S) &&
         mResource->IsExpectingMoreData()) {
-      DECODER_LOG("Buffering: wait %ds, timeout in %.3lfs %s",
-                  mBufferingWait, mBufferingWait - elapsed.ToSeconds(),
-                  (mQuickBuffering ? "(quick exit)" : ""));
+      DECODER_LOG("Buffering: wait %ds, timeout in %.3lfs",
+                  mBufferingWait, mBufferingWait - elapsed.ToSeconds());
       ScheduleStateMachineIn(USECS_PER_S);
       return;
     }
   } else if (OutOfDecodedAudio() || OutOfDecodedVideo()) {
     MOZ_ASSERT(mReader->IsWaitForDataSupported(),
                "Don't yet have a strategy for non-heuristic + non-WaitForData");
     DispatchDecodeTasksIfNeeded();
     MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mReader->IsRequestingAudioData() || mReader->IsWaitingAudioData());
@@ -2750,24 +2711,16 @@ void MediaDecoderStateMachine::UpdateNex
       // the MediaDecoderOwner fire events at correct currentTime.
       UpdatePlaybackPositionPeriodically();
     }
   }
 
   mNextFrameStatus = status;
 }
 
-bool MediaDecoderStateMachine::JustExitedQuickBuffering()
-{
-  MOZ_ASSERT(OnTaskQueue());
-  return !mDecodeStartTime.IsNull() &&
-    mQuickBuffering &&
-    (TimeStamp::Now() - mDecodeStartTime) < TimeDuration::FromMicroseconds(QUICK_BUFFER_THRESHOLD_USECS);
-}
-
 bool
 MediaDecoderStateMachine::CanPlayThrough()
 {
   MOZ_ASSERT(OnTaskQueue());
   return GetStatistics().CanPlayThrough();
 }
 
 MediaStatistics
@@ -2791,22 +2744,16 @@ MediaDecoderStateMachine::StartBuffering
   MOZ_ASSERT(OnTaskQueue());
   MOZ_ASSERT(mState == DECODER_STATE_BUFFERING);
 
   if (IsPlaying()) {
     StopPlayback();
   }
 
   TimeDuration decodeDuration = TimeStamp::Now() - mDecodeStartTime;
-  // Go into quick buffering mode provided we've not just left buffering using
-  // a "quick exit". This stops us flip-flopping between playing and buffering
-  // when the download speed is similar to the decode speed.
-  mQuickBuffering =
-    !JustExitedQuickBuffering() &&
-    decodeDuration < UsecsToDuration(QUICK_BUFFER_THRESHOLD_USECS);
   mBufferingStart = TimeStamp::Now();
 
   DECODER_LOG("Changed state from DECODING to BUFFERING, decoded for %.3lfs",
               decodeDuration.ToSeconds());
   MediaStatistics stats = GetStatistics();
   DECODER_LOG("Playback rate: %.1lfKB/s%s download rate: %.1lfKB/s%s",
               stats.mPlaybackRate/1024, stats.mPlaybackRateReliable ? "" : " (unreliable)",
               stats.mDownloadRate/1024, stats.mDownloadRateReliable ? "" : " (unreliable)");
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -406,19 +406,16 @@ protected:
 
   // Returns true if we have less than aUsecs of buffered data available.
   bool HasLowBufferedData(int64_t aUsecs);
 
   // Returns true when there's decoded audio waiting to play.
   // The decoder monitor must be held.
   bool HasFutureAudio();
 
-  // Returns true if we recently exited "quick buffering" mode.
-  bool JustExitedQuickBuffering();
-
   // Recomputes mNextFrameStatus, possibly dispatching notifications to interested
   // parties.
   void UpdateNextFrameStatus();
 
   // Return the current time, either the audio clock if available (if the media
   // has audio, and the playback is possible), or a clock for the video.
   // Called on the state machine thread.
   // If aTimeStamp is non-null, set *aTimeStamp to the TimeStamp corresponding
@@ -707,20 +704,16 @@ private:
   // Our "ample" audio threshold. Once we've this much audio decoded, we
   // pause decoding. If we increase mLowAudioThresholdUsecs, we'll also
   // increase this too appropriately (we don't want mLowAudioThresholdUsecs
   // to be greater than ampleAudioThreshold, else we'd stop decoding!).
   // Note that we don't ever reset this threshold, it only ever grows as
   // we detect that the decode can't keep up with rendering.
   int64_t mAmpleAudioThresholdUsecs;
 
-  // If we're quick buffering, we'll remain in buffering mode while we have less than
-  // QUICK_BUFFERING_LOW_DATA_USECS of decoded data available.
-  int64_t mQuickBufferingLowDataThresholdUsecs;
-
   // At the start of decoding we want to "preroll" the decode until we've
   // got a few frames decoded before we consider whether decode is falling
   // behind. Otherwise our "we're falling behind" logic will trigger
   // unnecessarily if we start playing as soon as the first sample is
   // decoded. These two fields store how many video frames and audio
   // samples we must consume before are considered to be finished prerolling.
   uint32_t AudioPrerollUsecs() const
   {
@@ -813,23 +806,16 @@ private:
   // Flag whether we notify metadata before decoding the first frame or after.
   //
   // Note that the odd semantics here are designed to replicate the current
   // behavior where we notify the decoder each time we come out of dormant, but
   // send suppressed event visibility for those cases. This code can probably be
   // simplified.
   bool mNotifyMetadataBeforeFirstFrame;
 
-  // If this is true while we're in buffering mode, we can exit early,
-  // as it's likely we may be able to playback. This happens when we enter
-  // buffering mode soon after the decode starts, because the decode-ahead
-  // ran fast enough to exhaust all data while the download is starting up.
-  // Synchronised via decoder monitor.
-  bool mQuickBuffering;
-
   // True if we should not decode/preroll unnecessary samples, unless we're
   // played. "Prerolling" in this context refers to when we decode and
   // buffer decoded samples in advance of when they're needed for playback.
   // This flag is set for preload=metadata media, and means we won't
   // decode more than the first video frame and first block of audio samples
   // for that media when we startup, or after a seek. When Play() is called,
   // we reset this flag, as we assume the user is playing the media, so
   // prerolling is appropriate then. This flag is used to reduce the overhead