author | JW Wang <jwwang@mozilla.com> |
Thu, 20 Oct 2016 14:45:05 +0800 | |
changeset 363632 | 80ee79d7a32a5bc2f811f067e6f63e72f71eb14c |
parent 363631 | 1ed409c6df2f34d65febea744539e9a22901e1f1 |
child 363633 | 159aabd71aaae58c90bdb3fe5058a8426a5d26dc |
push id | 6795 |
push user | jlund@mozilla.com |
push date | Mon, 23 Jan 2017 14:19:46 +0000 |
treeherder | mozilla-beta@76101b503191 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | cpearce, jya |
bugs | 1311872 |
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 @@ -557,26 +557,31 @@ private: * SHUTDOWN if any decode error. * BUFFERING if playback can't continue due to lack of decoded data. * COMPLETED when having decoded all audio/video data. */ class MediaDecoderStateMachine::DecodingState : public MediaDecoderStateMachine::StateObject { public: - explicit DecodingState(Master* aPtr) : StateObject(aPtr) {} + explicit DecodingState(Master* aPtr) + : StateObject(aPtr) + , mDormantTimer(OwnerThread()) + { + } void Enter(); void Exit() override { if (!mDecodeStartTime.IsNull()) { TimeDuration decodeDuration = TimeStamp::Now() - mDecodeStartTime; SLOG("Exiting DECODING, decoded for %.3lfs", decodeDuration.ToSeconds()); } + mDormantTimer.Reset(); } void Step() override { if (mMaster->mPlayState != MediaDecoder::PLAY_STATE_PLAYING && mMaster->IsPlaying()) { // We're playing, but the element/decoder is in paused state. Stop // playing! @@ -645,16 +650,22 @@ public: } void HandlePlayStateChanged(MediaDecoder::PlayState aPlayState) override { if (aPlayState == MediaDecoder::PLAY_STATE_PLAYING) { // Schedule Step() to check if we can start playback. mMaster->ScheduleStateMachine(); } + + if (aPlayState == MediaDecoder::PLAY_STATE_PAUSED) { + StartDormantTimer(); + } else { + mDormantTimer.Reset(); + } } void DumpDebugInfo() override { SDUMP("mIsPrerolling=%d", mIsPrerolling); } private: @@ -711,27 +722,54 @@ private: (DonePrerollingAudio() || Reader()->IsWaitingAudioData()) && (DonePrerollingVideo() || Reader()->IsWaitingVideoData())) { mIsPrerolling = false; // Check if we can start playback. mMaster->ScheduleStateMachine(); } } + void StartDormantTimer() + { + auto timeout = MediaPrefs::DormantOnPauseTimeout(); + if (timeout < 0) { + // Disabled when timeout is negative. + return; + } else if (timeout == 0) { + // Enter dormant immediately without scheduling a timer. + HandleDormant(true); + return; + } + + TimeStamp target = TimeStamp::Now() + + TimeDuration::FromMilliseconds(timeout); + + mDormantTimer.Ensure(target, + [this] () { + mDormantTimer.CompleteRequest(); + HandleDormant(true); + }, [this] () { + mDormantTimer.CompleteRequest(); + }); + } + // Time at which we started decoding. TimeStamp mDecodeStartTime; // 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 = true; + + // Fired when playback is paused for a while to enter dormant. + DelayedScheduler mDormantTimer; }; /** * Purpose: seek to a particular new playback position. * * Transition to: * DORMANT if any dormant request. * SEEKING if any new seek request. @@ -1437,16 +1475,21 @@ DecodingState::Enter() mDecodeStartTime = TimeStamp::Now(); MaybeStopPrerolling(); // Ensure that we've got tasks enqueued to decode data if we need to. mMaster->DispatchDecodeTasksIfNeeded(); mMaster->ScheduleStateMachine(); + + // Will enter dormant when playback is paused for a while. + if (mMaster->mPlayState == MediaDecoder::PLAY_STATE_PAUSED) { + StartDormantTimer(); + } } RefPtr<MediaDecoder::SeekPromise> MediaDecoderStateMachine:: DecodingState::HandleSeek(SeekTarget aTarget) { SLOG("Changed state to SEEKING (to %lld)", aTarget.GetTime().ToMicroseconds()); SeekJob seekJob;
--- a/dom/media/MediaPrefs.h +++ b/dom/media/MediaPrefs.h @@ -131,16 +131,17 @@ private: DECL_MEDIA_PREF("media.decoder.fuzzing.dont-delay-inputexhausted", PDMFuzzingDelayInputExhausted, bool, true); DECL_MEDIA_PREF("media.gmp.decoder.enabled", PDMGMPEnabled, bool, true); DECL_MEDIA_PREF("media.gmp.decoder.aac", GMPAACPreferred, uint32_t, 0); DECL_MEDIA_PREF("media.gmp.decoder.h264", GMPH264Preferred, uint32_t, 0); // MediaDecoderStateMachine DECL_MEDIA_PREF("media.suspend-bkgnd-video.enabled", MDSMSuspendBackgroundVideoEnabled, bool, false); DECL_MEDIA_PREF("media.suspend-bkgnd-video.delay-ms", MDSMSuspendBackgroundVideoDelay, AtomicUint32, SUSPEND_BACKGROUND_VIDEO_DELAY_MS); + DECL_MEDIA_PREF("media.dormant-on-pause-timeout-ms", DormantOnPauseTimeout, int32_t, 5000); // WebSpeech DECL_MEDIA_PREF("media.webspeech.synth.force_global_queue", WebSpeechForceGlobal, bool, false); DECL_MEDIA_PREF("media.webspeech.test.enable", WebSpeechTestEnabled, bool, false); DECL_MEDIA_PREF("media.webspeech.test.fake_fsm_events", WebSpeechFakeFSMEvents, bool, false); DECL_MEDIA_PREF(TEST_PREFERENCE_FAKE_RECOGNITION_SERVICE, WebSpeechFakeRecognitionService, bool, false); DECL_MEDIA_PREF("media.webspeech.recognition.enable", WebSpeechRecognitionEnabled, bool, false); DECL_MEDIA_PREF("media.webspeech.recognition.force_enable", WebSpeechRecognitionForceEnabled, bool, false);
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -306,16 +306,23 @@ pref("mathml.scale_stretchy_operators.en // Disable MediaError.message. #ifdef RELEASE_OR_BETA pref("dom.MediaError.message.enabled", false); #else pref("dom.MediaError.message.enabled", true); #endif +// Enabled on nightly only until we fix mochitest failures. +#ifdef NIGHTLY_BUILD +pref("media.dormant-on-pause-timeout-ms", 5000); +#else +pref("media.dormant-on-pause-timeout-ms", -1); +#endif + // Media cache size in kilobytes pref("media.cache_size", 512000); // When a network connection is suspended, don't resume it until the // amount of buffered data falls below this threshold (in seconds). pref("media.cache_resume_threshold", 999999); // Stop reading ahead when our buffered data is this many seconds ahead // of the current playback position. This limit can stop us from using arbitrary // amounts of network bandwidth prefetching huge videos.