author | JW Wang <jwwang@mozilla.com> |
Fri, 30 Sep 2016 16:53:33 +0800 | |
changeset 316380 | e145b5d95343e92b8c9d7af7b763f1df0f05b060 |
parent 316379 | 4e654ea0dfa6b0b3396cbeac3dff9fc5700a30a9 |
child 316381 | 1ebe25b02ffe62f641963e6877e3bba9f133ef91 |
push id | 30770 |
push user | kwierso@gmail.com |
push date | Wed, 05 Oct 2016 00:00:48 +0000 |
treeherder | mozilla-central@3470e326025c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | kaku |
bugs | 1307022 |
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
|
--- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -209,16 +209,21 @@ public: SetState(DECODER_STATE_DORMANT); return true; } virtual bool HandleCDMProxyReady() { return false; } virtual bool HandleAudioDecoded(MediaData* aAudio) { return false; } + virtual bool HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) + { + return false; + } + protected: using Master = MediaDecoderStateMachine; explicit StateObject(Master* aPtr) : mMaster(aPtr) {} TaskQueue* OwnerThread() const { return mMaster->mTaskQueue; } MediaResource* Resource() const { return mMaster->mResource; } MediaDecoderReaderWrapper* Reader() const { return mMaster->mReader; } // Note this function will delete the current state object. @@ -419,16 +424,23 @@ public: } bool HandleAudioDecoded(MediaData* aAudio) override { mMaster->Push(aAudio, MediaData::AUDIO_DATA); mMaster->MaybeFinishDecodeFirstFrame(); return true; } + + bool HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) override + { + mMaster->Push(aVideo, MediaData::VIDEO_DATA); + mMaster->MaybeFinishDecodeFirstFrame(); + return true; + } }; class MediaDecoderStateMachine::DecodingState : public MediaDecoderStateMachine::StateObject { public: explicit DecodingState(Master* aPtr) : StateObject(aPtr) {} @@ -492,17 +504,56 @@ public: bool HandleAudioDecoded(MediaData* aAudio) override { mMaster->Push(aAudio, MediaData::AUDIO_DATA); mMaster->MaybeStopPrerolling(); return true; } + bool HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) override + { + mMaster->Push(aVideo, MediaData::VIDEO_DATA); + mMaster->MaybeStopPrerolling(); + CheckSlowDecoding(aDecodeStart); + return true; + } + private: + void CheckSlowDecoding(TimeStamp aDecodeStart) + { + // 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 (Reader()->IsAsync()) { + return; + } + + TimeDuration decodeTime = TimeStamp::Now() - aDecodeStart; + int64_t adjustedTime = THRESHOLD_FACTOR * DurationToUsecs(decodeTime); + if (adjustedTime > mMaster->mLowAudioThresholdUsecs && + !mMaster->HasLowBufferedData()) + { + mMaster->mLowAudioThresholdUsecs = + std::min(adjustedTime, mMaster->mAmpleAudioThresholdUsecs); + + mMaster->mAmpleAudioThresholdUsecs = + std::max(THRESHOLD_FACTOR * mMaster->mLowAudioThresholdUsecs, + mMaster->mAmpleAudioThresholdUsecs); + + SLOG("Slow video decode, set " + "mLowAudioThresholdUsecs=%lld " + "mAmpleAudioThresholdUsecs=%lld", + mMaster->mLowAudioThresholdUsecs, + mMaster->mAmpleAudioThresholdUsecs); + } + } + // Time at which we started decoding. TimeStamp mDecodeStartTime; }; class MediaDecoderStateMachine::SeekingState : public MediaDecoderStateMachine::StateObject { public: @@ -533,16 +584,22 @@ public: return true; } bool HandleAudioDecoded(MediaData* aAudio) override { MOZ_ASSERT(false); return true; } + + bool HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) override + { + MOZ_ASSERT(false); + return true; + } }; class MediaDecoderStateMachine::BufferingState : public MediaDecoderStateMachine::StateObject { public: explicit BufferingState(Master* aPtr) : StateObject(aPtr) {} @@ -614,16 +671,25 @@ public: { // This might be the sample we need to exit buffering. // Schedule Step() to check it. mMaster->Push(aAudio, MediaData::AUDIO_DATA); mMaster->ScheduleStateMachine(); return true; } + bool HandleVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStart) override + { + // This might be the sample we need to exit buffering. + // Schedule Step() to check it. + mMaster->Push(aVideo, MediaData::VIDEO_DATA); + mMaster->ScheduleStateMachine(); + return true; + } + private: TimeStamp mBufferingStart; }; class MediaDecoderStateMachine::CompletedState : public MediaDecoderStateMachine::StateObject { public: @@ -1195,69 +1261,24 @@ MediaDecoderStateMachine::MaybeFinishDec } } void MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideo, TimeStamp aDecodeStartTime) { MOZ_ASSERT(OnTaskQueue()); - MOZ_ASSERT(mState != DECODER_STATE_SEEKING); MOZ_ASSERT(aVideo); // Handle abnormal or negative timestamps. mDecodedVideoEndTime = std::max(mDecodedVideoEndTime, aVideo->GetEndTime()); SAMPLE_LOG("OnVideoDecoded [%lld,%lld]", aVideo->mTime, aVideo->GetEndTime()); - switch (mState) { - case DECODER_STATE_BUFFERING: { - // If we're buffering, this may be the sample we need to stop buffering. - // Save it and schedule the state machine. - Push(aVideo, MediaData::VIDEO_DATA); - ScheduleStateMachine(); - return; - } - - case DECODER_STATE_DECODING_FIRSTFRAME: { - Push(aVideo, MediaData::VIDEO_DATA); - MaybeFinishDecodeFirstFrame(); - return; - } - - case DECODER_STATE_DECODING: { - Push(aVideo, MediaData::VIDEO_DATA); - 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; - } - TimeDuration decodeTime = TimeStamp::Now() - aDecodeStartTime; - if (THRESHOLD_FACTOR * DurationToUsecs(decodeTime) > mLowAudioThresholdUsecs && - !HasLowBufferedData()) - { - mLowAudioThresholdUsecs = - std::min(THRESHOLD_FACTOR * DurationToUsecs(decodeTime), mAmpleAudioThresholdUsecs); - mAmpleAudioThresholdUsecs = std::max(THRESHOLD_FACTOR * mLowAudioThresholdUsecs, - mAmpleAudioThresholdUsecs); - DECODER_LOG("Slow video decode, set mLowAudioThresholdUsecs=%lld mAmpleAudioThresholdUsecs=%lld", - mLowAudioThresholdUsecs, mAmpleAudioThresholdUsecs); - } - return; - } - default: { - // Ignore other cases. - return; - } - } + mStateObj->HandleVideoDecoded(aVideo, aDecodeStartTime); } bool MediaDecoderStateMachine::IsAudioDecoding() { MOZ_ASSERT(OnTaskQueue()); return HasAudio() && !AudioQueue().IsFinished(); }