Bug 1300711 - Remove MediaDecoderStateMachine::mQuickBuffering.
MozReview-Commit-ID: GW7bhY6ruKG
--- 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