Bug 934667 - Add preferences to enable loopback devices. r=jesup
authorSuhas Nandakumar <snandaku@cisco.com>
Mon, 11 Nov 2013 02:39:54 -0800
changeset 160286 622e6c1191ebd40cfdc063526316aae660ad0789
parent 160285 1733cf3b70e912ec9ba98aae36bf73c58a066b54
child 160287 064eb6b0604d11a411cef41d9f9cef4c2b53f748
push id25827
push userkwierso@gmail.com
push dateFri, 13 Dec 2013 03:13:04 +0000
treeherdermozilla-central@1bc33fa19b24 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs934667
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 934667 - Add preferences to enable loopback devices. r=jesup
dom/media/MediaManager.cpp
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -657,35 +657,46 @@ static bool SatisfyConstraint(const Medi
 typedef nsTArray<nsCOMPtr<nsIMediaDevice> > SourceSet;
 
 // Source getter that constrains list returned
 
 template<class SourceType>
 static SourceSet *
   GetSources(MediaEngine *engine,
              const MediaTrackConstraintsInternal &aConstraints,
-             void (MediaEngine::* aEnumerate)(nsTArray<nsRefPtr<SourceType> >*))
+             void (MediaEngine::* aEnumerate)(nsTArray<nsRefPtr<SourceType> >*),
+             char* media_device_name = nullptr)
 {
   const SourceType * const type = nullptr;
-
+  nsString deviceName;
   // First collect sources
   SourceSet candidateSet;
   {
     nsTArray<nsRefPtr<SourceType> > sources;
     (engine->*aEnumerate)(&sources);
-
     /**
       * We're allowing multiple tabs to access the same camera for parity
       * with Chrome.  See bug 811757 for some of the issues surrounding
       * this decision.  To disallow, we'd filter by IsAvailable() as we used
       * to.
       */
-
     for (uint32_t len = sources.Length(), i = 0; i < len; i++) {
-      candidateSet.AppendElement(new MediaDevice(sources[i]));
+#ifdef DEBUG
+      sources[i]->GetName(deviceName);
+      if (media_device_name && strlen(media_device_name) > 0)  {
+        if (deviceName.EqualsASCII(media_device_name)) {
+          candidateSet.AppendElement(new MediaDevice(sources[i]));
+          break;
+        }
+      } else {
+#endif
+        candidateSet.AppendElement(new MediaDevice(sources[i]));
+#ifdef DEBUG
+      }
+#endif
     }
   }
 
   // Then apply mandatory constraints
 
   // Note: Iterator must be signed as it can dip below zero
   for (int i = 0; i < int(candidateSet.Length()); i++) {
     // Overloading instead of template specialization keeps things local
@@ -998,47 +1009,57 @@ private:
  */
 class GetUserMediaDevicesRunnable : public nsRunnable
 {
 public:
   GetUserMediaDevicesRunnable(
     const MediaStreamConstraintsInternal& aConstraints,
     already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> aSuccess,
     already_AddRefed<nsIDOMGetUserMediaErrorCallback> aError,
-    uint64_t aWindowId)
+    uint64_t aWindowId, char* aAudioLoopbackDev, char* aVideoLoopbackDev)
     : mConstraints(aConstraints)
     , mSuccess(aSuccess)
     , mError(aError)
     , mManager(MediaManager::GetInstance())
-    , mWindowId(aWindowId) {}
+    , mWindowId(aWindowId)
+    , mLoopbackAudioDevice(aAudioLoopbackDev)
+    , mLoopbackVideoDevice(aVideoLoopbackDev) {}
 
   NS_IMETHOD
   Run()
   {
     NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
+
     MediaEngine *backend = mManager->GetBackend(mWindowId);
 
     ScopedDeletePtr<SourceSet> final (GetSources(backend, mConstraints.mVideom,
-                                          &MediaEngine::EnumerateVideoDevices));
+                                          &MediaEngine::EnumerateVideoDevices,
+                                          mLoopbackVideoDevice));
     {
       ScopedDeletePtr<SourceSet> s (GetSources(backend, mConstraints.mAudiom,
-                                        &MediaEngine::EnumerateAudioDevices));
+                                        &MediaEngine::EnumerateAudioDevices,
+                                        mLoopbackAudioDevice));
       final->MoveElementsFrom(*s);
     }
     NS_DispatchToMainThread(new DeviceSuccessCallbackRunnable(mSuccess, mError,
                                                               final.forget()));
     return NS_OK;
   }
 
 private:
   MediaStreamConstraintsInternal mConstraints;
   already_AddRefed<nsIGetUserMediaDevicesSuccessCallback> mSuccess;
   already_AddRefed<nsIDOMGetUserMediaErrorCallback> mError;
   nsRefPtr<MediaManager> mManager;
   uint64_t mWindowId;
+  // Audio & Video loopback devices to be used based on
+  // the preference settings. This is currently used for
+  // automated media tests only.
+  char* mLoopbackAudioDevice;
+  char* mLoopbackVideoDevice;
 };
 
 MediaManager::MediaManager()
   : mMediaThread(nullptr)
   , mMutex("mozilla::MediaManager")
   , mBackend(nullptr) {
   mPrefs.mWidth  = MediaEngine::DEFAULT_VIDEO_WIDTH;
   mPrefs.mHeight = MediaEngine::DEFAULT_VIDEO_HEIGHT;
@@ -1387,23 +1408,38 @@ MediaManager::GetUserMediaDevices(nsPIDO
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
 
   NS_ENSURE_TRUE(aOnError, NS_ERROR_NULL_POINTER);
   NS_ENSURE_TRUE(aOnSuccess, NS_ERROR_NULL_POINTER);
 
   nsCOMPtr<nsIGetUserMediaDevicesSuccessCallback> onSuccess(aOnSuccess);
   nsCOMPtr<nsIDOMGetUserMediaErrorCallback> onError(aOnError);
+  char* loopbackAudioDevice = nullptr;
+  char* loopbackVideoDevice = nullptr;
+  nsresult rv;
+#ifdef DEBUG
+  // Check if the preference for using loopback devices is enabled.
+  nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
+  if (NS_SUCCEEDED(rv)) {
+    nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
+    if (branch) {
+      branch->GetCharPref("media.audio_loopback_dev", &loopbackAudioDevice);
+      branch->GetCharPref("media.video_loopback_dev", &loopbackVideoDevice);
+    }
+  }
+#endif
 
   nsCOMPtr<nsIRunnable> gUMDRunnable = new GetUserMediaDevicesRunnable(
-    aConstraints, onSuccess.forget(), onError.forget(), aWindow->WindowID()
+    aConstraints, onSuccess.forget(), onError.forget(), aWindow->WindowID(),
+    loopbackAudioDevice, loopbackVideoDevice
   );
 
   nsCOMPtr<nsIThread> deviceThread;
-  nsresult rv = NS_NewThread(getter_AddRefs(deviceThread));
+  rv = NS_NewThread(getter_AddRefs(deviceThread));
   NS_ENSURE_SUCCESS(rv, rv);
 
 
   deviceThread->Dispatch(gUMDRunnable, NS_DISPATCH_NORMAL);
   return NS_OK;
 }
 
 MediaEngine*