Bug 1286766 - make MediaPrefs::MDSMSuspendBackgroundVideoDelay() safe to read off main thread using Preferences::AddAtomicUintVarCache(). r?gerald
MozReview-Commit-ID: FAplUTE07l0
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -201,25 +201,21 @@ static void InitVideoQueuePrefs() {
"media.video-queue.hw-accel-size", HW_VIDEO_QUEUE_SIZE);
sVideoQueueSendToCompositorSize = Preferences::GetUint(
"media.video-queue.send-to-compositor-size", VIDEO_QUEUE_SEND_TO_COMPOSITOR_SIZE);
}
}
// Delay, in milliseconds, that tabs needs to be in background before video
// decoding is suspended.
-static TimeDuration sSuspendBackgroundVideoDelay;
-
-static void
-InitSuspendBackgroundPref()
+static TimeDuration
+SuspendBackgroundVideoDelay()
{
- MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
-
- sSuspendBackgroundVideoDelay = TimeDuration::FromMilliseconds(
- MediaPrefs::MDSMSuspendBackgroundVideoDelay());
+ return TimeDuration::FromMilliseconds(
+ MediaPrefs::MDSMSuspendBackgroundVideoDelay());
}
#define INIT_WATCHABLE(name, val) \
name(val, "MediaDecoderStateMachine::" #name)
#define INIT_MIRROR(name, val) \
name(mTaskQueue, val, "MediaDecoderStateMachine::" #name " (Mirror)")
#define INIT_CANONICAL(name, val) \
name(mTaskQueue, val, "MediaDecoderStateMachine::" #name " (Canonical)")
@@ -290,17 +286,16 @@ MediaDecoderStateMachine::MediaDecoderSt
INIT_CANONICAL(mCurrentPosition, 0),
INIT_CANONICAL(mPlaybackOffset, 0),
INIT_CANONICAL(mIsAudioDataAudible, false)
{
MOZ_COUNT_CTOR(MediaDecoderStateMachine);
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
InitVideoQueuePrefs();
- InitSuspendBackgroundPref();
mBufferingWait = IsRealTime() ? 0 : 15;
mLowDataThresholdUsecs = IsRealTime() ? 0 : detail::LOW_DATA_THRESHOLD_USECS;
#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
@@ -1349,17 +1344,17 @@ void MediaDecoderStateMachine::Visibilit
// If not playing then there's nothing to do.
if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING) {
return;
}
// Start timer to trigger suspended decoding state when going invisible.
if (!mIsVisible) {
- TimeStamp target = TimeStamp::Now() + sSuspendBackgroundVideoDelay;
+ TimeStamp target = TimeStamp::Now() + SuspendBackgroundVideoDelay();
RefPtr<MediaDecoderStateMachine> self = this;
mVideoDecodeSuspendTimer.Ensure(target,
[=]() { self->OnSuspendTimerResolved(); },
[=]() { self->OnSuspendTimerRejected(); });
return;
}
--- a/dom/media/MediaPrefs.cpp
+++ b/dom/media/MediaPrefs.cpp
@@ -64,9 +64,16 @@ void MediaPrefs::PrefAddVarCache(uint32_
void MediaPrefs::PrefAddVarCache(float* aVariable,
const char* aPref,
float aDefault)
{
Preferences::AddFloatVarCache(aVariable, aPref, aDefault);
}
+void MediaPrefs::PrefAddVarCache(AtomicUint32* aVariable,
+ const char* aPref,
+ uint32_t aDefault)
+{
+ Preferences::AddAtomicUintVarCache(aVariable, aPref, aDefault);
+}
+
} // namespace mozilla
--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -5,16 +5,18 @@
#ifndef MEDIA_PREFS_H
#define MEDIA_PREFS_H
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#endif
+#include "mozilla/Atomics.h"
+
// First time MediaPrefs::GetSingleton() needs to be called on the main thread,
// before any of the methods accessing the values are used, but after
// the Preferences system has been initialized.
// The static methods to access the preference value are safe to call
// from any thread after that first call.
// To register a preference, you need to add a line in this file using
@@ -28,34 +30,48 @@
// "media.resampling.enabled". If the value is not set, the default would be
// false.
#define DECL_MEDIA_PREF(Pref, Name, Type, Default) \
public: \
static const Type& Name() { MOZ_ASSERT(SingletonExists()); return GetSingleton().mPref##Name.mValue; } \
private: \
static const char* Get##Name##PrefName() { return Pref; } \
-static Type Get##Name##PrefDefault() { return Default; } \
+static StripAtomic<Type> Get##Name##PrefDefault() { return Default; } \
PrefTemplate<Type, Get##Name##PrefDefault, Get##Name##PrefName> mPref##Name
// Custom Definitions.
#define GMP_DEFAULT_ASYNC_SHUTDOWN_TIMEOUT 3000
#define SUSPEND_BACKGROUND_VIDEO_DELAY_MS 10000
#define TEST_PREFERENCE_FAKE_RECOGNITION_SERVICE "media.webspeech.test.fake_recognition_service"
namespace mozilla {
template<class T> class StaticAutoPtr;
class MediaPrefs final
{
+ typedef Atomic<uint32_t, Relaxed> AtomicUint32;
+
+ template <typename T>
+ struct StripAtomicImpl {
+ typedef T Type;
+ };
+
+ template <typename T, MemoryOrdering Order>
+ struct StripAtomicImpl<Atomic<T, Order>> {
+ typedef T Type;
+ };
+
+ template <typename T>
+ using StripAtomic = typename StripAtomicImpl<T>::Type;
private:
// Since we cannot use const char*, use a function that returns it.
- template <class T, T Default(), const char* Pref()>
+ template <class T, StripAtomic<T> Default(), const char* Pref()>
class PrefTemplate
{
public:
PrefTemplate()
: mValue(Default())
{
Register(Pref());
}
@@ -109,17 +125,17 @@ private:
DECL_MEDIA_PREF("media.decoder.fuzzing.video-output-minimum-interval-ms", PDMFuzzingInterval, uint32_t, 0);
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, uint32_t, SUSPEND_BACKGROUND_VIDEO_DELAY_MS);
+ DECL_MEDIA_PREF("media.suspend-bkgnd-video.delay-ms", MDSMSuspendBackgroundVideoDelay, AtomicUint32, SUSPEND_BACKGROUND_VIDEO_DELAY_MS);
// 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);
@@ -151,16 +167,17 @@ private:
return -1;
}
// Creating these to avoid having to include Preferences.h in the .h
static void PrefAddVarCache(bool*, const char*, bool);
static void PrefAddVarCache(int32_t*, const char*, int32_t);
static void PrefAddVarCache(uint32_t*, const char*, uint32_t);
static void PrefAddVarCache(float*, const char*, float);
+ static void PrefAddVarCache(AtomicUint32*, const char*, uint32_t);
static void AssertMainThread();
MediaPrefs();
MediaPrefs(const MediaPrefs&) = delete;
MediaPrefs& operator=(const MediaPrefs&) = delete;
};