Bug 1391523 - P6: Integrate audioipc into CubebUtils. r=jya,padenot draft
authorDan Glastonbury <dan.glastonbury@gmail.com>
Thu, 27 Jul 2017 18:12:07 +1000
changeset 652729 58b855e514c99406d98993803e6d043524c2b290
parent 652728 6203fa31c9eea8cf7e9f0b02fbd923d755ee56cc
child 728166 845ccda5f9bdc07faf81e59ff218ddcf6e227b01
push id76138
push userbmo:dglastonbury@mozilla.com
push dateFri, 25 Aug 2017 06:15:19 +0000
reviewersjya, padenot
bugs1391523
milestone57.0a1
Bug 1391523 - P6: Integrate audioipc into CubebUtils. r=jya,padenot Enable client/server using: media.cubeb.sandbox = true This pref is only read at start up, so requires restarting firefox for a change in value to take effect. MozReview-Commit-ID: 36L4vR5QEDJ
dom/ipc/ContentPrefs.cpp
dom/media/CubebUtils.cpp
dom/media/MediaPrefs.h
--- a/dom/ipc/ContentPrefs.cpp
+++ b/dom/ipc/ContentPrefs.cpp
@@ -119,16 +119,17 @@ const char* mozilla::dom::ContentPrefs::
   "javascript.use_us_english_locale",
   "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.sandbox",
   "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
@@ -24,16 +24,17 @@
 #include <algorithm>
 #include <stdint.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_LOGGING_LEVEL "media.cubeb.logging_level"
+#define PREF_CUBEB_SANDBOX "media.cubeb.sandbox"
 
 #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))
 #define MASK_3F         (MASK_STEREO | (1 << AudioConfig::CHANNEL_CENTER))
 #define MASK_3F_LFE     (MASK_3F | (1 << AudioConfig::CHANNEL_LFE))
 #define MASK_2F1        (MASK_STEREO | (1 << AudioConfig::CHANNEL_RCENTER))
@@ -42,20 +43,53 @@
 #define MASK_3F1_LFE    (MASK_3F1 | (1 << AudioConfig::CHANNEL_LFE))
 #define MASK_2F2        (MASK_STEREO | (1 << AudioConfig::CHANNEL_LS) | (1 << AudioConfig::CHANNEL_RS))
 #define MASK_2F2_LFE    (MASK_2F2 | (1 << AudioConfig::CHANNEL_LFE))
 #define MASK_3F2        (MASK_3F | (1 << AudioConfig::CHANNEL_LS) | (1 << AudioConfig::CHANNEL_RS))
 #define MASK_3F2_LFE    (MASK_3F2 | (1 << AudioConfig::CHANNEL_LFE))
 #define MASK_3F3R_LFE   (MASK_3F2_LFE | (1 << AudioConfig::CHANNEL_RCENTER))
 #define MASK_3F4_LFE    (MASK_3F2_LFE | (1 << AudioConfig::CHANNEL_RLS) | (1 << AudioConfig::CHANNEL_RRS))
 
+extern "C" {
+// These functions are provided by audioipc-server crate
+extern void* audioipc_server_start();
+extern void audioipc_server_stop(void*);
+// These functions are provided by audioipc-client crate
+extern int audioipc_client_init(cubeb**, const char*);
+}
+
 namespace mozilla {
 
 namespace {
 
+#ifdef MOZ_CUBEB_REMOTING
+////////////////////////////////////////////////////////////////////////////////
+// Cubeb Sound Server Thread
+void* sServerHandle = nullptr;
+
+static bool
+StartSoundServer()
+{
+  sServerHandle = audioipc_server_start();
+  return sServerHandle != nullptr;
+}
+
+static void
+ShutdownSoundServer()
+{
+  if (!sServerHandle)
+    return;
+
+  audioipc_server_stop(sServerHandle);
+  sServerHandle = nullptr;
+}
+#endif // MOZ_CUBEB_REMOTING
+
+////////////////////////////////////////////////////////////////////////////////
+
 LazyLogModule gCubebLog("cubeb");
 
 void CubebLogCallback(const char* aFmt, ...)
 {
   char buffer[256];
 
   va_list arglist;
   va_start(arglist, aFmt);
@@ -208,16 +242,28 @@ void PrefChanged(const char* aPref, void
     if (value.IsEmpty()) {
       sCubebBackendName = nullptr;
     } else {
       sCubebBackendName = new char[value.Length() + 1];
       PodCopy(sCubebBackendName.get(), value.get(), value.Length());
       sCubebBackendName[value.Length()] = 0;
     }
   }
+#ifdef MOZ_CUBEB_REMOTING
+  else if (strcmp(aPref, PREF_CUBEB_SANDBOX) == 0) {
+    bool cubebSandbox = false;
+    Preferences::GetBool(aPref, cubebSandbox);
+    MOZ_LOG(gCubebLog, LogLevel::Verbose, ("%s: %s", PREF_CUBEB_SANDBOX, cubebSandbox ? "true" : "false"));
+
+    if (cubebSandbox && !sServerHandle && XRE_IsParentProcess()) {
+      MOZ_LOG(gCubebLog, LogLevel::Debug, ("Starting cubeb server..."));
+      StartSoundServer();
+    }
+  }
+#endif
 }
 
 bool GetFirstStream()
 {
   static bool sFirstStream = true;
 
   StaticMutexAutoLock lock(sMutex);
   bool result = sFirstStream;
@@ -338,17 +384,27 @@ cubeb* GetCubebContextUnlocked()
 
   if (!sBrandName && NS_IsMainThread()) {
     InitBrandName();
   } else {
     NS_WARNING_ASSERTION(
       sBrandName, "Did not initialize sbrandName, and not on the main thread?");
   }
 
+#ifdef MOZ_CUBEB_REMOTING
+  bool cubebSandbox = false;
+  Preferences::GetBool(PREF_CUBEB_SANDBOX, cubebSandbox);
+  MOZ_LOG(gCubebLog, LogLevel::Info, ("%s: %s", PREF_CUBEB_SANDBOX, cubebSandbox ? "true" : "false"));
+
+  int rv = cubebSandbox
+    ? audioipc_client_init(&sCubebContext, sBrandName)
+    : cubeb_init(&sCubebContext, sBrandName, sCubebBackendName.get());
+#else // !MOZ_CUBEB_REMOTING
   int rv = cubeb_init(&sCubebContext, sBrandName, sCubebBackendName.get());
+#endif // MOZ_CUBEB_REMOTING
   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);
   }
@@ -418,44 +474,50 @@ Maybe<uint32_t> GetCubebMSGLatencyInFram
 }
 
 void InitLibrary()
 {
   Preferences::RegisterCallbackAndCall(PrefChanged, PREF_VOLUME_SCALE);
   Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_LATENCY_PLAYBACK);
   Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_LATENCY_MSG);
   Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_BACKEND);
+  Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_SANDBOX);
   // We don't want to call the callback on startup, because the pref is the
   // empty string by default ("", which means "logging disabled"). Because the
   // logging can be enabled via environment variables (MOZ_LOG="module:5"),
   // calling this callback on init would immediately re-disble the logging.
   Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_LOGGING_LEVEL);
 #ifndef MOZ_WIDGET_ANDROID
   AbstractThread::MainThread()->Dispatch(
     NS_NewRunnableFunction("CubebUtils::InitLibrary", &InitBrandName));
 #endif
 }
 
 void ShutdownLibrary()
 {
   Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE);
+  Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_SANDBOX);
   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_LOGGING_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;
+
+#ifdef MOZ_CUBEB_REMOTING
+  ShutdownSoundServer();
+#endif
 }
 
 uint32_t MaxNumberOfChannels()
 {
   cubeb* cubebContext = GetCubebContext();
   uint32_t maxNumberOfChannels;
   if (cubebContext &&
       cubeb_get_max_channel_count(cubebContext,
--- a/dom/media/MediaPrefs.h
+++ b/dom/media/MediaPrefs.h
@@ -202,16 +202,21 @@ private:
 
   // Error/warning handling, Decoder Doctor
   DECL_MEDIA_PREF("media.playback.warnings-as-errors",        MediaWarningsAsErrors, bool, false);
   DECL_MEDIA_PREF("media.playback.warnings-as-errors.stagefright-vs-rust",
                                                               MediaWarningsAsErrorsStageFrightVsRust, bool, false);
 
   // resume background video decoding when the cursor is hovering over the tab.
   DECL_MEDIA_PREF("media.resume-bkgnd-video-on-tabhover",     ResumeVideoDecodingOnTabHover, bool, false);
+
+#ifdef MOZ_CUBEB_REMOTING
+  DECL_MEDIA_PREF("media.cubeb.sandbox",                      CubebSandbox, bool, false);
+#endif // MOZ_CUBEB_REMOTING
+
 public:
   // Manage the singleton:
   static MediaPrefs& GetSingleton();
   static bool SingletonExists();
 
 private:
   template<class T> friend class StaticAutoPtr;
   static StaticAutoPtr<MediaPrefs> sInstance;