Bug 1361629 - Only call timeBeginPeriod/timeEndPeriod when media playback starts/stops. r=jwwang
MozReview-Commit-ID: B3YCoGMY5Ab
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2653,43 +2653,37 @@ MediaDecoderStateMachine::MediaDecoderSt
INIT_MIRROR(mPlaybackRateReliable, true),
INIT_MIRROR(mDecoderPosition, 0),
INIT_CANONICAL(mDuration, NullableTimeUnit()),
INIT_CANONICAL(mIsShutdown, false),
INIT_CANONICAL(mNextFrameStatus, MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE),
INIT_CANONICAL(mCurrentPosition, TimeUnit::Zero()),
INIT_CANONICAL(mPlaybackOffset, 0),
INIT_CANONICAL(mIsAudioDataAudible, false)
+#ifdef XP_WIN
+ , mShouldUseHiResTimers(Preferences::GetBool("media.hi-res-timers.enabled", true))
+#endif
{
MOZ_COUNT_CTOR(MediaDecoderStateMachine);
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
InitVideoQueuePrefs();
-
-#ifdef XP_WIN
- // Ensure high precision timers are enabled on Windows, otherwise the state
- // machine isn't woken up at reliable intervals to set the next frame, and we
- // drop frames while painting. Note that multiple calls to this function
- // per-process is OK, provided each call is matched by a corresponding
- // timeEndPeriod() call.
- timeBeginPeriod(1);
-#endif
}
#undef INIT_WATCHABLE
#undef INIT_MIRROR
#undef INIT_CANONICAL
MediaDecoderStateMachine::~MediaDecoderStateMachine()
{
MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread.");
MOZ_COUNT_DTOR(MediaDecoderStateMachine);
#ifdef XP_WIN
- timeEndPeriod(1);
+ MOZ_ASSERT(!mHiResTimersRequested);
#endif
}
void
MediaDecoderStateMachine::InitializationTask(MediaDecoder* aDecoder)
{
MOZ_ASSERT(OnTaskQueue());
@@ -2890,16 +2884,22 @@ MediaDecoderStateMachine::StopPlayback()
MOZ_ASSERT(OnTaskQueue());
LOG("StopPlayback()");
mOnPlaybackEvent.Notify(MediaEventType::PlaybackStopped);
if (IsPlaying()) {
mMediaSink->SetPlaying(false);
MOZ_ASSERT(!IsPlaying());
+#ifdef XP_WIN
+ if (mHiResTimersRequested) {
+ mHiResTimersRequested = false;
+ timeEndPeriod(1);
+ }
+#endif
}
}
void MediaDecoderStateMachine::MaybeStartPlayback()
{
MOZ_ASSERT(OnTaskQueue());
// Should try to start playback only after decoding first frames.
MOZ_ASSERT(mSentFirstFrameLoadedEvent);
@@ -2913,16 +2913,30 @@ void MediaDecoderStateMachine::MaybeStar
LOG("Not starting playback [mPlayState=%d]", mPlayState.Ref());
return;
}
LOG("MaybeStartPlayback() starting playback");
mOnPlaybackEvent.Notify(MediaEventType::PlaybackStarted);
StartMediaSink();
+#ifdef XP_WIN
+ if (!mHiResTimersRequested && mShouldUseHiResTimers) {
+ mHiResTimersRequested = true;
+ // Ensure high precision timers are enabled on Windows, otherwise the state
+ // machine isn't woken up at reliable intervals to set the next frame, and we
+ // drop frames while painting. Note that each call must be matched by a
+ // corresponding timeEndPeriod() call. Enabling high precision timers causes
+ // the CPU to wake up more frequently on Windows 7 and earlier, which causes
+ // more CPU load and battery use. So we only enable high precision timers
+ // when we're actually playing.
+ timeBeginPeriod(1);
+ }
+#endif
+
if (!IsPlaying()) {
mMediaSink->SetPlaying(true);
MOZ_ASSERT(IsPlaying());
}
}
void
MediaDecoderStateMachine::UpdatePlaybackPositionInternal(const TimeUnit& aTime)
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -774,13 +774,24 @@ public:
AbstractCanonical<int64_t>* CanonicalPlaybackOffset()
{
return &mPlaybackOffset;
}
AbstractCanonical<bool>* CanonicalIsAudioDataAudible()
{
return &mIsAudioDataAudible;
}
+
+#ifdef XP_WIN
+ // Whether we've called timeBeginPeriod(1) to request high resolution
+ // timers. We request high resolution timers when playback starts, and
+ // turn them off when playback is paused. Enabling high resolution
+ // timers can cause higher CPU usage and battery drain on Windows 7.
+ bool mHiResTimersRequested = false;
+ // Whether we should enable high resolution timers. This is initialized at
+ // MDSM construction, and mirrors the value of media.hi-res-timers.enabled.
+ const bool mShouldUseHiResTimers;
+#endif
};
} // namespace mozilla
#endif