Bug 1300446 - Keep explicit cubeb state - r?kinetik
Cubeb can be in three states: Uninitialized, initialized (or in
error), or shutdown.
This will ensure that we only initialized cubeb once, and that
we don't attempt to re-initialize it after shutdown.
MozReview-Commit-ID: 8LhRe7bvS4K
--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -22,16 +22,22 @@
#define PREF_CUBEB_LATENCY "media.cubeb_latency_ms"
namespace mozilla {
namespace {
// This mutex protects the variables below.
StaticMutex sMutex;
+enum class CubebState {
+ Uninitialized = 0,
+ Initialized,
+ Error,
+ Shutdown
+} sCubebState = CubebState::Uninitialized;
cubeb* sCubebContext;
double sVolumeScale;
uint32_t sCubebLatency;
bool sCubebLatencyPrefSet;
bool sAudioStreamInitEverSucceeded = false;
StaticAutoPtr<char> sBrandName;
const char kBrandBundleURL[] = "chrome://branding/locale/brand.properties";
@@ -158,29 +164,32 @@ void InitBrandName()
sBrandName = new char[brandName.Length() + 1];
PodCopy(sBrandName.get(), ascii, brandName.Length());
sBrandName[brandName.Length()] = 0;
}
cubeb* GetCubebContextUnlocked()
{
sMutex.AssertCurrentThreadOwns();
- if (sCubebContext) {
+ if (sCubebState != CubebState::Uninitialized) {
+ // If we have already passed the initialization point (below), just return
+ // the current context, which may be null (e.g., after error or shutdown.)
return sCubebContext;
}
if (!sBrandName && NS_IsMainThread()) {
InitBrandName();
} else {
NS_WARNING_ASSERTION(
sBrandName, "Did not initialize sbrandName, and not on the main thread?");
}
- DebugOnly<int> rv = cubeb_init(&sCubebContext, sBrandName);
+ int rv = cubeb_init(&sCubebContext, sBrandName);
NS_WARNING_ASSERTION(rv == CUBEB_OK, "Could not get a cubeb context.");
+ sCubebState = (rv == CUBEB_OK) ? CubebState::Initialized : CubebState::Error;
return sCubebContext;
}
void ReportCubebBackendUsed()
{
StaticMutexAutoLock lock(sMutex);
@@ -242,16 +251,18 @@ void ShutdownLibrary()
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY);
StaticMutexAutoLock lock(sMutex);
if (sCubebContext) {
cubeb_destroy(sCubebContext);
sCubebContext = nullptr;
}
sBrandName = nullptr;
+ // This will ensure we don't try to re-create a context.
+ sCubebState = CubebState::Shutdown;
}
uint32_t MaxNumberOfChannels()
{
cubeb* cubebContext = GetCubebContext();
uint32_t maxNumberOfChannels;
if (cubebContext &&
cubeb_get_max_channel_count(cubebContext,