Bug 1300446 - Keep explicit cubeb state - r?kinetik draft
authorGerald Squelart <gsquelart@mozilla.com>
Tue, 30 Aug 2016 17:03:04 -0700
changeset 409738 396ad56d67f8fe48c7f9807d239024b49d4ad9bd
parent 409737 dbe4b47941c7b3d6298a0ead5e40dd828096c808
child 409739 13efd4025f11f0091ee30cb94295a2f421863191
push id28527
push usergsquelart@mozilla.com
push dateMon, 05 Sep 2016 01:07:03 +0000
reviewerskinetik
bugs1300446
milestone51.0a1
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,