--- a/dom/media/CubebUtils.cpp
+++ b/dom/media/CubebUtils.cpp
@@ -24,25 +24,30 @@
#include "nsThreadUtils.h"
#include "prdtoa.h"
#include <algorithm>
#include <stdint.h>
#ifdef MOZ_WIDGET_ANDROID
#include "GeneratedJNIWrappers.h"
#endif
+#define AUDIOIPC_POOL_SIZE_DEFAULT 1
+#define AUDIOIPC_STACK_SIZE_DEFAULT (64*1024)
+
#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"
// Allows to get something non-default for the preferred sample-rate, to allow
// troubleshooting in the field and testing.
#define PREF_CUBEB_FORCE_SAMPLE_RATE "media.cubeb.force_sample_rate"
#define PREF_CUBEB_LOGGING_LEVEL "media.cubeb.logging_level"
#define PREF_CUBEB_SANDBOX "media.cubeb.sandbox"
+#define PREF_AUDIOIPC_POOL_SIZE "media.audioipc.pool_size"
+#define PREF_AUDIOIPC_STACK_SIZE "media.audioipc.stack_size"
#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))
@@ -56,22 +61,29 @@
#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))
#if (defined(XP_LINUX) && !defined(MOZ_WIDGET_ANDROID)) || defined(XP_MACOSX)
#define MOZ_CUBEB_REMOTING
#endif
extern "C" {
+
+struct AudioIpcInitParams {
+ int mServerConnection;
+ size_t mPoolSize;
+ size_t mStackSize;
+};
+
// These functions are provided by audioipc-server crate
extern void* audioipc_server_start();
extern mozilla::ipc::FileDescriptor::PlatformHandleType audioipc_server_new_client(void*);
extern void audioipc_server_stop(void*);
// These functions are provided by audioipc-client crate
-extern int audioipc_client_init(cubeb**, const char*, int);
+extern int audioipc_client_init(cubeb**, const char*, const AudioIpcInitParams*);
}
namespace mozilla {
namespace {
#ifdef MOZ_CUBEB_REMOTING
////////////////////////////////////////////////////////////////////////////////
@@ -128,17 +140,19 @@ uint32_t sCubebMSGLatencyInFrames = 512;
// If sCubebForcedSampleRate is zero, PreferredSampleRate will return the
// preferred sample-rate for the audio backend in use. Otherwise, it will be
// used as the preferred sample-rate.
uint32_t sCubebForcedSampleRate = 0;
bool sCubebPlaybackLatencyPrefSet = false;
bool sCubebMSGLatencyPrefSet = false;
bool sAudioStreamInitEverSucceeded = false;
#ifdef MOZ_CUBEB_REMOTING
-bool sCubebSandbox;
+bool sCubebSandbox = false;
+size_t sAudioIPCPoolSize;
+size_t sAudioIPCStackSize;
#endif
StaticAutoPtr<char> sBrandName;
StaticAutoPtr<char> sCubebBackendName;
const char kBrandBundleURL[] = "chrome://branding/locale/brand.properties";
const char* AUDIOSTREAM_BACKEND_ID_STR[] = {
"jack",
@@ -278,16 +292,26 @@ void PrefChanged(const char* aPref, void
sCubebSandbox = Preferences::GetBool(aPref);
MOZ_LOG(gCubebLog, LogLevel::Verbose, ("%s: %s", PREF_CUBEB_SANDBOX, sCubebSandbox ? "true" : "false"));
if (sCubebSandbox && !sServerHandle && XRE_IsParentProcess()) {
MOZ_LOG(gCubebLog, LogLevel::Debug, ("Starting cubeb server..."));
StartSoundServer();
}
}
+ else if (strcmp(aPref, PREF_AUDIOIPC_POOL_SIZE) == 0) {
+ StaticMutexAutoLock lock(sMutex);
+ sAudioIPCPoolSize = Preferences::GetUint(PREF_AUDIOIPC_POOL_SIZE,
+ AUDIOIPC_POOL_SIZE_DEFAULT);
+ }
+ else if (strcmp(aPref, PREF_AUDIOIPC_STACK_SIZE) == 0) {
+ StaticMutexAutoLock lock(sMutex);
+ sAudioIPCStackSize = Preferences::GetUint(PREF_AUDIOIPC_STACK_SIZE,
+ AUDIOIPC_STACK_SIZE_DEFAULT);
+ }
#endif
}
bool GetFirstStream()
{
static bool sFirstStream = true;
StaticMutexAutoLock lock(sMutex);
@@ -465,32 +489,40 @@ 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
+ MOZ_LOG(gCubebLog, LogLevel::Info, ("%s: %s", PREF_CUBEB_SANDBOX, sCubebSandbox ? "true" : "false"));
+
+ int rv = CUBEB_OK;
if (sCubebSandbox) {
if (XRE_IsParentProcess()) {
// TODO: Don't use audio IPC when within the same process.
MOZ_ASSERT(!sIPCConnection);
sIPCConnection = new ipc::FileDescriptor(CreateAudioIPCConnection());
} else {
MOZ_DIAGNOSTIC_ASSERT(sIPCConnection);
}
- }
- MOZ_LOG(gCubebLog, LogLevel::Info, ("%s: %s", PREF_CUBEB_SANDBOX, sCubebSandbox ? "true" : "false"));
+ AudioIpcInitParams initParams;
+ initParams.mPoolSize = sAudioIPCPoolSize;
+ initParams.mStackSize = sAudioIPCStackSize;
+ initParams.mServerConnection = sIPCConnection->ClonePlatformHandle().release();
- int rv = sCubebSandbox
- ? audioipc_client_init(&sCubebContext, sBrandName,
- sIPCConnection->ClonePlatformHandle().release())
- : cubeb_init(&sCubebContext, sBrandName, sCubebBackendName.get());
+ MOZ_LOG(gCubebLog, LogLevel::Debug, ("%s: %d", PREF_AUDIOIPC_POOL_SIZE, (int) initParams.mPoolSize));
+ MOZ_LOG(gCubebLog, LogLevel::Debug, ("%s: %d", PREF_AUDIOIPC_STACK_SIZE, (int) initParams.mStackSize));
+
+ rv = audioipc_client_init(&sCubebContext, sBrandName, &initParams);
+ } else {
+ rv = cubeb_init(&sCubebContext, sBrandName, sCubebBackendName.get());
+ }
sIPCConnection = nullptr;
#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;
return sCubebContext;
@@ -574,16 +606,18 @@ uint32_t GetCubebMSGLatencyInFrames(cube
void InitLibrary()
{
Preferences::RegisterCallbackAndCall(PrefChanged, PREF_VOLUME_SCALE);
Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_LATENCY_PLAYBACK);
Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_LATENCY_MSG);
Preferences::RegisterCallback(PrefChanged, PREF_CUBEB_FORCE_SAMPLE_RATE);
Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_BACKEND);
Preferences::RegisterCallbackAndCall(PrefChanged, PREF_CUBEB_SANDBOX);
+ Preferences::RegisterCallbackAndCall(PrefChanged, PREF_AUDIOIPC_POOL_SIZE);
+ Preferences::RegisterCallbackAndCall(PrefChanged, PREF_AUDIOIPC_STACK_SIZE);
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);
}
// 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"),
@@ -598,16 +632,18 @@ void InitLibrary()
InitAudioIPCConnection();
}
#endif
}
void ShutdownLibrary()
{
Preferences::UnregisterCallback(PrefChanged, PREF_VOLUME_SCALE);
+ Preferences::UnregisterCallback(PrefChanged, PREF_AUDIOIPC_STACK_SIZE);
+ Preferences::UnregisterCallback(PrefChanged, PREF_AUDIOIPC_POOL_SIZE);
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_SANDBOX);
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_BACKEND);
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY_PLAYBACK);
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_FORCE_SAMPLE_RATE);
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LATENCY_MSG);
Preferences::UnregisterCallback(PrefChanged, PREF_CUBEB_LOGGING_LEVEL);
StaticMutexAutoLock lock(sMutex);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -661,16 +661,21 @@ pref("media.decoder.skip-to-next-key-fra
// Log level for cubeb, the audio input/output system. Valid values are
// "verbose", "normal" and "" (log disabled).
pref("media.cubeb.logging_level", "");
// Cubeb sandbox (remoting) control
#ifdef XP_LINUX
pref("media.cubeb.sandbox", true);
+// The cubeb pulse audio backend effectively serializes callbacks so
+// only 1 thread is required.
+pref("media.audioipc.pool_size", 1);
+// 64 kB stack per pool thread.
+pref("media.audioipc.stack_size", 65536);
#else
pref("media.cubeb.sandbox", false);
#endif
// Set to true to force demux/decode warnings to be treated as errors.
pref("media.playback.warnings-as-errors", false);
// Weather we allow AMD switchable graphics