author | JW Wang <jwwang@mozilla.com> |
Mon, 03 Oct 2016 14:04:27 +0800 | |
changeset 316177 | 0621d50a7455c7200988e13d48ff9a0a0aadece2 |
parent 316176 | b19f904b612736e56b8a02eea687c53b002de811 |
child 316178 | 73e1dac8253d1c57cef65bd88f923738b7b84de0 |
push id | 30765 |
push user | philringnalda@gmail.com |
push date | Tue, 04 Oct 2016 03:06:46 +0000 |
treeherder | mozilla-central@adb484f84dec [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | kikuo |
bugs | 1306186 |
milestone | 52.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
dom/media/MediaDecoderStateMachine.cpp | file | annotate | diff | comparison | revisions | |
dom/media/MediaDecoderStateMachine.h | file | annotate | diff | comparison | revisions |
--- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -1039,20 +1039,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; } } @@ -1118,22 +1115,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(); @@ -1150,21 +1142,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()) { @@ -1230,20 +1218,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; @@ -1393,35 +1378,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; } @@ -2920,20 +2912,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;