Bug 1221587: add per-platform prefs to control full-duplex cubeb input r=jib draft
authorRandell Jesup <rjesup@jesup.org>
Tue, 12 Jan 2016 18:14:14 -0500
changeset 321202 e83fa940db034828fa79612c6b9f3c9371883f6d
parent 321201 edb51bb165e7ad752c905e880f55835440b8174f
child 321203 0976334fd451924c7f0c04579239b7b7e64e7096
push id9349
push userrjesup@wgate.com
push dateWed, 13 Jan 2016 06:48:48 +0000
reviewersjib
bugs1221587
milestone46.0a1
Bug 1221587: add per-platform prefs to control full-duplex cubeb input r=jib
dom/media/MediaManager.cpp
dom/media/webrtc/MediaEngine.h
dom/media/webrtc/MediaEngineWebRTC.cpp
dom/media/webrtc/MediaEngineWebRTC.h
dom/media/webrtc/MediaEngineWebRTCAudio.cpp
modules/libpref/init/all.js
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -840,16 +840,17 @@ public:
   }
 
   RefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
   RefPtr<AudioDevice> mAudioDevice; // so we can turn on AEC
   RefPtr<VideoDevice> mVideoDevice;
   bool mEchoOn;
   bool mAgcOn;
   bool mNoiseOn;
+  bool mFullDuplex;
   uint32_t mEcho;
   uint32_t mAgc;
   uint32_t mNoise;
   uint32_t mPlayoutDelay;
 };
 
 
 void
@@ -1510,26 +1511,28 @@ MediaManager::EnumerateRawDevices(uint64
 MediaManager::MediaManager()
   : mMediaThread(nullptr)
   , mBackend(nullptr) {
   mPrefs.mFreq   = 1000; // 1KHz test tone
   mPrefs.mWidth  = 0; // adaptive default
   mPrefs.mHeight = 0; // adaptive default
   mPrefs.mFPS    = MediaEngine::DEFAULT_VIDEO_FPS;
   mPrefs.mMinFPS = MediaEngine::DEFAULT_VIDEO_MIN_FPS;
+  mPrefs.mFullDuplex = false;
   nsresult rv;
   nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
   if (NS_SUCCEEDED(rv)) {
     nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
     if (branch) {
       GetPrefs(branch, nullptr);
     }
   }
-  LOG(("%s: default prefs: %dx%d @%dfps (min %d), %dHz test tones", __FUNCTION__,
-       mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mMinFPS, mPrefs.mFreq));
+  LOG(("%s: default prefs: %dx%d @%dfps (min %d), %dHz test tones, %sfull-duplex", __FUNCTION__,
+       mPrefs.mWidth, mPrefs.mHeight, mPrefs.mFPS, mPrefs.mMinFPS, mPrefs.mFreq,
+       mPrefs.mFullDuplex ? "" : "not "));
 }
 
 NS_IMPL_ISUPPORTS(MediaManager, nsIMediaManagerService, nsIObserver)
 
 /* static */ StaticRefPtr<MediaManager> MediaManager::sSingleton;
 
 #ifdef DEBUG
 /* static */ bool
@@ -1581,16 +1584,18 @@ MediaManager::Get() {
     }
     // else MediaManager won't work properly and will leak (see bug 837874)
     nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
     if (prefs) {
       prefs->AddObserver("media.navigator.video.default_width", sSingleton, false);
       prefs->AddObserver("media.navigator.video.default_height", sSingleton, false);
       prefs->AddObserver("media.navigator.video.default_fps", sSingleton, false);
       prefs->AddObserver("media.navigator.video.default_minfps", sSingleton, false);
+      prefs->AddObserver("media.navigator.audio.fake_frequency", sSingleton, false);
+      prefs->AddObserver("media.navigator.audio.full_duplex", sSingleton, false);
     }
 
     // Prepare async shutdown
 
     nsCOMPtr<nsIAsyncShutdownClient> shutdownPhase = GetShutdownPhase();
 
     class Blocker : public media::ShutdownBlocker
     {
@@ -2612,16 +2617,17 @@ MediaManager::GetPrefBool(nsIPrefBranch 
 void
 MediaManager::GetPrefs(nsIPrefBranch *aBranch, const char *aData)
 {
   GetPref(aBranch, "media.navigator.video.default_width", aData, &mPrefs.mWidth);
   GetPref(aBranch, "media.navigator.video.default_height", aData, &mPrefs.mHeight);
   GetPref(aBranch, "media.navigator.video.default_fps", aData, &mPrefs.mFPS);
   GetPref(aBranch, "media.navigator.video.default_minfps", aData, &mPrefs.mMinFPS);
   GetPref(aBranch, "media.navigator.audio.fake_frequency", aData, &mPrefs.mFreq);
+  GetPrefBool(aBranch, "media.navigator.audio.full_duplex", aData, &mPrefs.mFullDuplex);
 }
 
 void
 MediaManager::Shutdown()
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (sInShutdown) {
     return;
@@ -2638,16 +2644,17 @@ MediaManager::Shutdown()
 
   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
   if (prefs) {
     prefs->RemoveObserver("media.navigator.video.default_width", this);
     prefs->RemoveObserver("media.navigator.video.default_height", this);
     prefs->RemoveObserver("media.navigator.video.default_fps", this);
     prefs->RemoveObserver("media.navigator.video.default_minfps", this);
     prefs->RemoveObserver("media.navigator.audio.fake_frequency", this);
+    prefs->RemoveObserver("media.navigator.audio.full_duplex", this);
   }
 
   // Close off any remaining active windows.
   GetActiveWindows()->Clear();
   mActiveCallbacks.Clear();
   mCallIds.Clear();
 
   // Because mMediaThread is not an nsThread, we must dispatch to it so it can
@@ -3111,20 +3118,20 @@ MediaManager::IsActivelyCapturingOrHasAP
     }
   }
   return audio == nsIPermissionManager::ALLOW_ACTION ||
          video == nsIPermissionManager::ALLOW_ACTION;
 }
 
 void
 GetUserMediaCallbackMediaStreamListener::AudioConfig(bool aEchoOn,
-              uint32_t aEcho,
-              bool aAgcOn, uint32_t aAGC,
-              bool aNoiseOn, uint32_t aNoise,
-              int32_t aPlayoutDelay)
+                                                     uint32_t aEcho,
+                                                     bool aAgcOn, uint32_t aAGC,
+                                                     bool aNoiseOn, uint32_t aNoise,
+                                                     int32_t aPlayoutDelay)
 {
   if (mAudioDevice) {
 #ifdef MOZ_WEBRTC
     MediaManager::PostTask(FROM_HERE,
       NewRunnableMethod(mAudioDevice->GetSource(), &MediaEngineSource::Config,
                         aEchoOn, aEcho, aAgcOn, aAGC, aNoiseOn,
                         aNoise, aPlayoutDelay));
 #endif
--- a/dom/media/webrtc/MediaEngine.h
+++ b/dom/media/webrtc/MediaEngine.h
@@ -210,16 +210,17 @@ protected:
  */
 class MediaEnginePrefs {
 public:
   int32_t mWidth;
   int32_t mHeight;
   int32_t mFPS;
   int32_t mMinFPS;
   int32_t mFreq; // for test tones (fake:true)
+  bool mFullDuplex;
 
   // mWidth and/or mHeight may be zero (=adaptive default), so use functions.
 
   int32_t GetWidth(bool aHD = false) const {
     return mWidth? mWidth : (mHeight?
                              (mHeight * GetDefWidth(aHD)) / GetDefHeight(aHD) :
                              GetDefWidth(aHD));
   }
--- a/dom/media/webrtc/MediaEngineWebRTC.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTC.cpp
@@ -46,17 +46,18 @@ namespace mozilla {
 
 cubeb_device_collection* AudioInputCubeb::mDevices = nullptr;
 bool AudioInputCubeb::mAnyInUse = false;
 
 MediaEngineWebRTC::MediaEngineWebRTC(MediaEnginePrefs &aPrefs)
   : mMutex("mozilla::MediaEngineWebRTC"),
     mVoiceEngine(nullptr),
     mAudioInput(nullptr),
-    mAudioEngineInit(false)
+    mAudioEngineInit(false),
+    mFullDuplex(aPrefs.mFullDuplex)
 {
 #ifndef MOZ_B2G_CAMERA
   nsCOMPtr<nsIComponentRegistrar> compMgr;
   NS_GetComponentRegistrar(getter_AddRefs(compMgr));
   if (compMgr) {
     compMgr->IsContractIDRegistered(NS_TABSOURCESERVICE_CONTRACTID, &mHasTabVideoSource);
   }
 #else
@@ -275,17 +276,18 @@ MediaEngineWebRTC::EnumerateAudioDevices
   if (!mAudioEngineInit) {
     if (ptrVoEBase->Init() < 0) {
       return;
     }
     mAudioEngineInit = true;
   }
 
   if (!mAudioInput) {
-    if (true /*platform_supports_full_duplex*/) {
+    if (mFullDuplex) {
+      // The platform_supports_full_duplex.
       mAudioInput = new mozilla::AudioInputCubeb(mVoiceEngine);
     } else {
       mAudioInput = new mozilla::AudioInputWebRTC(mVoiceEngine);
     }
   }
 
   int nDevices = 0;
   mAudioInput->GetNumOfRecordingDevices(nDevices);
@@ -318,18 +320,20 @@ MediaEngineWebRTC::EnumerateAudioDevices
 
     RefPtr<MediaEngineAudioSource> aSource;
     NS_ConvertUTF8toUTF16 uuid(uniqueId);
     if (mAudioSources.Get(uuid, getter_AddRefs(aSource))) {
       // We've already seen this device, just append.
       aASources->AppendElement(aSource.get());
     } else {
       AudioInput* audioinput = mAudioInput;
-      if (true /*platform_supports_full_duplex*/) {
-        // For cubeb, it has state (the selected ID
+      if (mFullDuplex) {
+        // The platform_supports_full_duplex.
+
+        // For cubeb, it has state (the selected ID)
         // XXX just use the uniqueID for cubeb and support it everywhere, and get rid of this
         // XXX Small window where the device list/index could change!
         audioinput = new mozilla::AudioInputCubeb(mVoiceEngine);
       }
       aSource = new MediaEngineWebRTCMicrophoneSource(mThread, mVoiceEngine, audioinput,
                                                       i, deviceName, uniqueId);
       mAudioSources.Put(uuid, aSource); // Hashtable takes ownership.
       aASources->AppendElement(aSource);
--- a/dom/media/webrtc/MediaEngineWebRTC.h
+++ b/dom/media/webrtc/MediaEngineWebRTC.h
@@ -523,17 +523,17 @@ private:
 
   nsCOMPtr<nsIThread> mThread;
 
   // gUM runnables can e.g. Enumerate from multiple threads
   Mutex mMutex;
   webrtc::VoiceEngine* mVoiceEngine;
   RefPtr<mozilla::AudioInput> mAudioInput;
   bool mAudioEngineInit;
-
+  bool mFullDuplex;
   bool mHasTabVideoSource;
 
   // Store devices we've already seen in a hashtable for quick return.
   // Maps UUID to MediaEngineSource (one set for audio, one for video).
   nsRefPtrHashtable<nsStringHashKey, MediaEngineVideoSource> mVideoSources;
   nsRefPtrHashtable<nsStringHashKey, MediaEngineAudioSource> mAudioSources;
 };
 
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -197,20 +197,21 @@ MediaEngineWebRTCMicrophoneSource::GetUU
 }
 
 nsresult
 MediaEngineWebRTCMicrophoneSource::Config(bool aEchoOn, uint32_t aEcho,
                                           bool aAgcOn, uint32_t aAGC,
                                           bool aNoiseOn, uint32_t aNoise,
                                           int32_t aPlayoutDelay)
 {
-  LOG(("Audio config: aec: %d, agc: %d, noise: %d",
+  LOG(("Audio config: aec: %d, agc: %d, noise: %d, delay: %d",
        aEchoOn ? aEcho : -1,
        aAgcOn ? aAGC : -1,
-       aNoiseOn ? aNoise : -1));
+       aNoiseOn ? aNoise : -1,
+       aPlayoutDelay));
 
   bool update_echo = (mEchoOn != aEchoOn);
   bool update_agc = (mAgcOn != aAgcOn);
   bool update_noise = (mNoiseOn != aNoiseOn);
   mEchoOn = aEchoOn;
   mAgcOn = aAgcOn;
   mNoiseOn = aNoiseOn;
 
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -424,37 +424,43 @@ pref("media.getusermedia.noise_enabled",
 pref("media.getusermedia.aec_enabled", true);
 pref("media.getusermedia.noise_enabled", true);
 #endif
 pref("media.getusermedia.aec_extended_filter", true);
 pref("media.getusermedia.aec_delay_agnostic", true);
 pref("media.getusermedia.noise", 1);
 pref("media.getusermedia.agc_enabled", false);
 pref("media.getusermedia.agc", 1);
-// Adjustments for OS-specific input delay (lower bound)
-// Adjustments for OS-specific AudioStream+cubeb+output delay (lower bound)
+// capture_delay: Adjustments for OS-specific input delay (lower bound)
+// playout_delay: Adjustments for OS-specific AudioStream+cubeb+output delay (lower bound)
+// full_duplex: enable cubeb full-duplex capture/playback
 #if defined(XP_MACOSX)
 pref("media.peerconnection.capture_delay", 50);
 pref("media.getusermedia.playout_delay", 10);
+pref("media.navigator.audio.full_duplex", false);
 #elif defined(XP_WIN)
 pref("media.peerconnection.capture_delay", 50);
 pref("media.getusermedia.playout_delay", 40);
+pref("media.navigator.audio.full_duplex", false);
 #elif defined(ANDROID)
 pref("media.peerconnection.capture_delay", 100);
 pref("media.getusermedia.playout_delay", 100);
+pref("media.navigator.audio.full_duplex", false);
 // Whether to enable Webrtc Hardware acceleration support
 pref("media.navigator.hardware.vp8_encode.acceleration_enabled", false);
 pref("media.navigator.hardware.vp8_decode.acceleration_enabled", false);
 #elif defined(XP_LINUX)
 pref("media.peerconnection.capture_delay", 70);
 pref("media.getusermedia.playout_delay", 50);
+pref("media.navigator.audio.full_duplex", false);
 #else
 // *BSD, others - merely a guess for now
 pref("media.peerconnection.capture_delay", 50);
 pref("media.getusermedia.playout_delay", 50);
+pref("media.navigator.audio.full_duplex", false);
 #endif
 #endif
 
 #if !defined(ANDROID)
 pref("media.getusermedia.screensharing.enabled", true);
 #endif
 
 #ifdef RELEASE_BUILD