author | Kaku Kuo <kaku@mozilla.com> |
Wed, 08 Mar 2017 21:28:01 +0800 | |
changeset 347389 | 850a10a1e44fa6c8bd60d44e6735f26eb3f638b7 |
parent 347388 | 7f9def21c5b721cbd9967b009a7bfd27a1a83707 |
child 347390 | be9cfb690427c87cc94352b9848c099a99ffa112 |
push id | 31496 |
push user | cbook@mozilla.com |
push date | Tue, 14 Mar 2017 13:21:57 +0000 |
treeherder | mozilla-central@9a26ed658fdc [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jwwang |
bugs | 1345403 |
milestone | 55.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/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -572,16 +572,21 @@ MediaDecoder::OnPlaybackEvent(MediaEvent Invalidate(); break; case MediaEventType::EnterVideoSuspend: GetOwner()->DispatchAsyncEvent(NS_LITERAL_STRING("mozentervideosuspend")); break; case MediaEventType::ExitVideoSuspend: GetOwner()->DispatchAsyncEvent(NS_LITERAL_STRING("mozexitvideosuspend")); break; + case MediaEventType::StartVideoSuspendTimer: + GetOwner()->DispatchAsyncEvent(NS_LITERAL_STRING("mozstartvideosuspendtimer")); + break; + case MediaEventType::CancelVideoSuspendTimer: + GetOwner()->DispatchAsyncEvent(NS_LITERAL_STRING("mozcancelvideosuspendtimer")); } } void MediaDecoder::OnPlaybackErrorEvent(const MediaResult& aError) { DecodeError(aError); }
--- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -2515,17 +2515,17 @@ ShutdownState::Enter() { auto master = mMaster; master->mIsShutdown = true; master->mDelayedScheduler.Reset(); // Shutdown happens while decode timer is active, we need to disconnect and // dispose of the timer. - master->mVideoDecodeSuspendTimer.Reset(); + master->CancelSuspendTimer(); master->mCDMProxyPromise.DisconnectIfExists(); if (master->IsPlaying()) { master->StopPlayback(); } master->mAudioDataRequest.DisconnectIfExists(); @@ -2695,16 +2695,18 @@ MediaDecoderStateMachine::Initialization &MediaDecoderStateMachine::RecomputeDuration); mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::PlayStateChanged); if (MediaPrefs::MDSMSuspendBackgroundVideoEnabled()) { mIsVisible.Connect(aDecoder->CanonicalIsVisible()); mHasSuspendTaint.Connect(aDecoder->CanonicalHasSuspendTaint()); mWatchManager.Watch(mIsVisible, &MediaDecoderStateMachine::VisibilityChanged); + mWatchManager.Watch(mHasSuspendTaint, + &MediaDecoderStateMachine::SuspendTaintChanged); } MOZ_ASSERT(!mStateObj); auto* s = new DecodeMetadataState(this); mStateObj.reset(s); s->Enter(); } @@ -3009,17 +3011,17 @@ MediaDecoderStateMachine::Shutdown() return mStateObj->HandleShutdown(); } void MediaDecoderStateMachine::PlayStateChanged() { MOZ_ASSERT(OnTaskQueue()); if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING) { - mVideoDecodeSuspendTimer.Reset(); + CancelSuspendTimer(); } else if (mMinimizePreroll) { // Once we start playing, we don't want to minimize our prerolling, as we // assume the user is likely to want to keep playing in future. This needs // to happen before we invoke StartDecoding(). mMinimizePreroll = false; } mStateObj->HandlePlayStateChanged(mPlayState); @@ -3033,25 +3035,39 @@ void MediaDecoderStateMachine::Visibilit // Start timer to trigger suspended decoding state when going invisible. if (!mIsVisible) { TimeStamp target = TimeStamp::Now() + SuspendBackgroundVideoDelay(); RefPtr<MediaDecoderStateMachine> self = this; mVideoDecodeSuspendTimer.Ensure(target, [=]() { self->OnSuspendTimerResolved(); }, - [=]() { self->OnSuspendTimerRejected(); }); + [] () { MOZ_DIAGNOSTIC_ASSERT(false); }); + mOnPlaybackEvent.Notify(MediaEventType::StartVideoSuspendTimer); return; } // Resuming from suspended decoding // If suspend timer exists, destroy it. - mVideoDecodeSuspendTimer.Reset(); - + CancelSuspendTimer(); + + if (mVideoDecodeSuspended) { + mStateObj->HandleResumeVideoDecoding(); + } +} + +void MediaDecoderStateMachine::SuspendTaintChanged() +{ + MOZ_ASSERT(OnTaskQueue()); + MOZ_ASSERT(mHasSuspendTaint); // Suspend taint is only ever set. + + CancelSuspendTimer(); + + // Resume from suspended decoding. if (mVideoDecodeSuspended) { mStateObj->HandleResumeVideoDecoding(); } } void MediaDecoderStateMachine::BufferedRangeUpdated() { MOZ_ASSERT(OnTaskQueue()); @@ -3904,19 +3920,23 @@ void MediaDecoderStateMachine::OnSuspendTimerResolved() { DECODER_LOG("OnSuspendTimerResolved"); mVideoDecodeSuspendTimer.CompleteRequest(); mStateObj->HandleVideoSuspendTimeout(); } void -MediaDecoderStateMachine::OnSuspendTimerRejected() +MediaDecoderStateMachine::CancelSuspendTimer() { - DECODER_LOG("OnSuspendTimerRejected"); + DECODER_LOG("CancelSuspendTimer: State: %s, Timer.IsScheduled: %c", + ToStateStr(mStateObj->GetState()), + mVideoDecodeSuspendTimer.IsScheduled() ? 'T' : 'F'); MOZ_ASSERT(OnTaskQueue()); - MOZ_ASSERT(!mVideoDecodeSuspended); - mVideoDecodeSuspendTimer.CompleteRequest(); + if (mVideoDecodeSuspendTimer.IsScheduled()) { + mOnPlaybackEvent.Notify(MediaEventType::CancelVideoSuspendTimer); + } + mVideoDecodeSuspendTimer.Reset(); } } // namespace mozilla #undef NS_DispatchToMainThread
--- a/dom/media/MediaDecoderStateMachine.h +++ b/dom/media/MediaDecoderStateMachine.h @@ -117,17 +117,19 @@ extern LazyLogModule gMediaSampleLog; enum class MediaEventType : int8_t { PlaybackStarted, PlaybackStopped, PlaybackEnded, SeekStarted, Invalidate, EnterVideoSuspend, - ExitVideoSuspend + ExitVideoSuspend, + StartVideoSuspendTimer, + CancelVideoSuspendTimer }; /* The state machine class. This manages the decoding and seeking in the MediaDecoderReader on the decode task queue, and A/V sync on the shared state machine thread, and controls the audio "push" thread. All internal state is synchronised via the decoder monitor. State changes @@ -389,16 +391,19 @@ protected: void StartMediaSink(); // Notification method invoked when mPlayState changes. void PlayStateChanged(); // Notification method invoked when mIsVisible changes. void VisibilityChanged(); + // Notification method invoked when mHasSuspendTaint changes. + void SuspendTaintChanged(); + // Sets internal state which causes playback of media to pause. // The decoder monitor must be held. void StopPlayback(); // If the conditions are right, sets internal state which causes playback // of media to begin or resume. // Must be called with the decode monitor held. void MaybeStartPlayback(); @@ -606,17 +611,17 @@ private: MozPromiseRequestHolder<MediaDataPromise> mVideoDataRequest; MozPromiseRequestHolder<WaitForDataPromise> mAudioWaitRequest; MozPromiseRequestHolder<WaitForDataPromise> mVideoWaitRequest; const char* AudioRequestStatus() const; const char* VideoRequestStatus() const; void OnSuspendTimerResolved(); - void OnSuspendTimerRejected(); + void CancelSuspendTimer(); // True if we shouldn't play our audio (but still write it to any capturing // streams). When this is true, the audio thread will never start again after // it has stopped. bool mAudioCaptured; // True if all audio frames are already rendered. bool mAudioCompleted = false;