Bug 1300446 - Keep explicit cubeb state - r=kinetik
authorGerald Squelart <gsquelart@mozilla.com>
Tue, 30 Aug 2016 17:03:04 -0700
changeset 312660 c3b79bc8557c2976522aaa948b47e8fa14b7ca04
parent 312659 5cf6587f7f07e013c39c8cabcc33399c06767814
child 312661 f0a2a1052c7fcfef5bdbb192c84f081e90814694
push id32003
push usergsquelart@mozilla.com
push dateMon, 05 Sep 2016 06:57:58 +0000
treeherderautoland@03056868056e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs1300446
milestone51.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
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
dom/media/CubebUtils.cpp
--- 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,