Bug 1341238 - Introduce (hidden) pref to force a particular libcubeb backend. r=kinetik,ehsan draft
authorDamien Zammit <damien@zamaudio.com>
Tue, 14 Mar 2017 17:57:03 +0000
changeset 499653 454c997fec10a7c7edda7fab0cd1a994b187f185
parent 499652 c549edb066cbb990d8d9c1e72b0318b1b151a01c
child 499654 2637f6d8110045b500da1148afc3b8eeba3595eb
push id49464
push userbmo:kinetik@flim.org
push dateThu, 16 Mar 2017 01:49:25 +0000
reviewerskinetik, ehsan
bugs1341238
milestone55.0a1
Bug 1341238 - Introduce (hidden) pref to force a particular libcubeb backend. r=kinetik,ehsan This adds 'media.cubeb.backend' to ContentPrefs, which is necessary because `cubeb_init` is called _very_ early in the lifetime of a content process, because it needs to be called before enabling seccomp.
dom/ipc/ContentPrefs.cpp
dom/media/CubebUtils.cpp
--- a/dom/ipc/ContentPrefs.cpp
+++ b/dom/ipc/ContentPrefs.cpp
@@ -148,16 +148,17 @@ const char* mozilla::dom::ContentPrefs::
   "layout.css.variables.enabled",
   "layout.css.visited_links_enabled",
   "layout.idle_period.required_quiescent_frames",
   "layout.idle_period.time_limit",
   "layout.interruptible-reflow.enabled",
   "mathml.disabled",
   "media.apple.forcevda",
   "media.clearkey.persistent-license.enabled",
+  "media.cubeb.backend",
   "media.cubeb_latency_msg_frames",
   "media.cubeb_latency_playback_ms",
   "media.decoder-doctor.wmf-disabled-is-failure",
   "media.decoder.fuzzing.dont-delay-inputexhausted",
   "media.decoder.fuzzing.enabled",
   "media.decoder.fuzzing.video-output-minimum-interval-ms",
   "media.decoder.limit",
   "media.decoder.recycle.enabled",
--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -15,16 +15,17 @@
 #include "mozilla/Telemetry.h"
 #include "mozilla/Logging.h"
 #include "nsThreadUtils.h"
 #include "CubebUtils.h"
 #include "nsAutoRef.h"
 #include "prdtoa.h"
 
 #define PREF_VOLUME_SCALE "media.volume_scale"
+#define PREF_CUBEB_BACKEND "media.cubeb.backend"
 #define PREF_CUBEB_LATENCY_PLAYBACK "media.cubeb_latency_playback_ms"
 #define PREF_CUBEB_LATENCY_MSG "media.cubeb_latency_msg_frames"
 #define PREF_CUBEB_LOG_LEVEL "media.cubeb.log_level"
 
 #define MASK_MONO       (1 << AudioConfig::CHANNEL_MONO)
 #define MASK_MONO_LFE   (MASK_MONO | (1 << AudioConfig::CHANNEL_LFE))
 #define MASK_STEREO     ((1 << AudioConfig::CHANNEL_LEFT) | (1 << AudioConfig::CHANNEL_RIGHT))
 #define MASK_STEREO_LFE (MASK_STEREO | (1 << AudioConfig::CHANNEL_LFE))
@@ -68,16 +69,17 @@ enum class CubebState {
 cubeb* sCubebContext;
 double sVolumeScale;
 uint32_t sCubebPlaybackLatencyInMilliseconds;
 uint32_t sCubebMSGLatencyInFrames;
 bool sCubebPlaybackLatencyPrefSet;
 bool sCubebMSGLatencyPrefSet;
 bool sAudioStreamInitEverSucceeded = false;
 StaticAutoPtr<char> sBrandName;
+StaticAutoPtr<char> sCubebBackendName;
 
 const char kBrandBundleURL[]      = "chrome://branding/locale/brand.properties";
 
 const char* AUDIOSTREAM_BACKEND_ID_STR[] = {
   "jack",
   "pulse",
   "alsa",
   "audiounit",
@@ -163,16 +165,27 @@ void PrefChanged(const char* aPref, void
       cubebLog->SetLevel(LogLevel::Verbose);
     } else if (strcmp(utf8.get(), "normal") == 0) {
       cubeb_set_log_callback(CUBEB_LOG_NORMAL, CubebLogCallback);
       cubebLog->SetLevel(LogLevel::Error);
     } else if (utf8.IsEmpty()) {
       cubeb_set_log_callback(CUBEB_LOG_DISABLED, nullptr);
       cubebLog->SetLevel(LogLevel::Disabled);
     }
+  } else if (strcmp(aPref, PREF_CUBEB_BACKEND) == 0) {
+    nsAdoptingString value = Preferences::GetString(aPref);
+    if (value.IsEmpty()) {
+      sCubebBackendName = nullptr;
+    } else {
+      /* cubeb expects a c-string. */
+      const char* ascii = NS_LossyConvertUTF16toASCII(value).get();
+      sCubebBackendName = new char[value.Length() + 1];
+      PodCopy(sCubebBackendName.get(), ascii, value.Length());
+      sCubebBackendName[value.Length()] = 0;
+    }
   }
 }
 
 bool GetFirstStream()
 {
   static bool sFirstStream = true;
 
   StaticMutexAutoLock lock(sMutex);
@@ -323,17 +336,17 @@ cubeb* GetCubebContextUnlocked()
 
   if (!sBrandName && NS_IsMainThread()) {
     InitBrandName();
   } else {
     NS_WARNING_ASSERTION(
       sBrandName, "Did not initialize sbrandName, and not on the main thread?");
   }
 
-  int rv = cubeb_init(&sCubebContext, sBrandName);
+  int rv = cubeb_init(&sCubebContext, sBrandName, sCubebBackendName.get());
   NS_WARNING_ASSERTION(rv == CUBEB_OK, "Could not get a cubeb context.");
   sCubebState = (rv == CUBEB_OK) ? CubebState::Initialized : CubebState::Uninitialized;
 
   if (MOZ_LOG_TEST(gCubebLog, LogLevel::Verbose)) {
     cubeb_set_log_callback(CUBEB_LOG_VERBOSE, CubebLogCallback);
   } else if (MOZ_LOG_TEST(gCubebLog, LogLevel::Error)) {
     cubeb_set_log_callback(CUBEB_LOG_NORMAL, CubebLogCallback);
   }
@@ -403,37 +416,41 @@ Maybe<uint32_t> GetCubebMSGLatencyInFram
 }
 
 void InitLibrary()
 {
   PrefChanged(PREF_VOLUME_SCALE, nullptr);
   Preferences::RegisterCallback(PrefChanged, PREF_VOLUME_SCALE);
   PrefChanged(PREF_CUBEB_LATENCY_PLAYBACK, nullptr);
   PrefChanged(PREF_CUBEB_LATENCY_MSG, nullptr);
+  PrefChanged(PREF_CUBEB_BACKEND, nullptr);
+  Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_BACKEND);
   Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LATENCY_PLAYBACK);
   Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LATENCY_MSG);
   Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LOG_LEVEL);
 #ifndef MOZ_WIDGET_ANDROID
   NS_DispatchToMainThread(NS_NewRunnableFunction(&InitBrandName));
 #endif
 }
 
 void ShutdownLibrary()
 {
   Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE);
+  Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_BACKEND);
   Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY_PLAYBACK);
   Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY_MSG);
   Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LOG_LEVEL);
 
   StaticMutexAutoLock lock(sMutex);
   if (sCubebContext) {
     cubeb_destroy(sCubebContext);
     sCubebContext = nullptr;
   }
   sBrandName = nullptr;
+  sCubebBackendName = 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;