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
--- 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;