Bug 1374420 - streamline capture capabilities IPC API;r?jib draft
authorNico Grunbaum
Tue, 01 Aug 2017 13:44:14 -0700
changeset 619270 3c1429404dd8cb33dc20d4852e257d3975ed031d
parent 619065 ef9a0f01e4f68214f0ff8f4631783b8a0e075a82
child 640357 3e948f8dac49b89d35ade3b49daa26ee6a48821a
push id71635
push userna-g@nostrum.com
push dateTue, 01 Aug 2017 20:44:34 +0000
reviewersjib
bugs1374420
milestone56.0a1
Bug 1374420 - streamline capture capabilities IPC API;r?jib MozReview-Commit-ID: 2DW9dVboIoP
dom/media/systemservices/CamerasChild.cpp
dom/media/systemservices/CamerasChild.h
dom/media/systemservices/CamerasParent.cpp
dom/media/systemservices/CamerasParent.h
dom/media/systemservices/PCameras.ipdl
dom/media/systemservices/moz.build
dom/media/webrtc/MediaEngineCameraVideoSource.cpp
dom/media/webrtc/MediaEngineCameraVideoSource.h
dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
dom/media/webrtc/MediaEngineRemoteVideoSource.h
dom/media/webrtc/MediaEngineWebRTC.cpp
--- a/dom/media/systemservices/CamerasChild.cpp
+++ b/dom/media/systemservices/CamerasChild.cpp
@@ -12,16 +12,17 @@
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/PBackgroundChild.h"
 #include "mozilla/Logging.h"
 #include "mozilla/SyncRunnable.h"
 #include "mozilla/WeakPtr.h"
 #include "mozilla/Unused.h"
 #include "MediaUtils.h"
 #include "nsThreadUtils.h"
+#include "VideoCaptureUtils.h"
 
 #undef LOG
 #undef LOG_ENABLED
 mozilla::LazyLogModule gCamerasChildLog("CamerasChild");
 #define LOG(args) MOZ_LOG(gCamerasChildLog, mozilla::LogLevel::Debug, args)
 #define LOG_ENABLED() MOZ_LOG_TEST(gCamerasChildLog, mozilla::LogLevel::Debug)
 
 #define FAKE_ONDEVICECHANGE_EVENT_PERIOD_IN_MS 5000
@@ -187,28 +188,16 @@ CamerasChild::RecvReplySuccess(void)
   LOG((__PRETTY_FUNCTION__));
   MonitorAutoLock monitor(mReplyMonitor);
   mReceivedReply = true;
   mReplySuccess = true;
   monitor.Notify();
   return IPC_OK();
 }
 
-mozilla::ipc::IPCResult
-CamerasChild::RecvReplyNumberOfCapabilities(const int& numdev)
-{
-  LOG((__PRETTY_FUNCTION__));
-  MonitorAutoLock monitor(mReplyMonitor);
-  mReceivedReply = true;
-  mReplySuccess = true;
-  mReplyInteger = numdev;
-  monitor.Notify();
-  return IPC_OK();
-}
-
 // Helper function to dispatch calls to the IPC Thread and
 // CamerasChild object. Takes the needed locks and dispatches.
 // Takes a "failed" value and a reference to the output variable
 // as parameters, will return the right one depending on whether
 // dispatching succeeded.
 template <class T = int>
 class LockAndDispatch
 {
@@ -279,35 +268,16 @@ CamerasChild::DispatchToParent(nsIRunnab
   } while (!mReceivedReply && mIPCIsAlive);
   if (!mReplySuccess) {
     return false;
   }
   return true;
 }
 
 int
-CamerasChild::NumberOfCapabilities(CaptureEngine aCapEngine,
-                                   const char* deviceUniqueIdUTF8)
-{
-  LOG((__PRETTY_FUNCTION__));
-  LOG(("NumberOfCapabilities for %s", deviceUniqueIdUTF8));
-  nsCString unique_id(deviceUniqueIdUTF8);
-  nsCOMPtr<nsIRunnable> runnable =
-    mozilla::NewNonOwningRunnableMethod<CaptureEngine, nsCString>(
-      "camera::PCamerasChild::SendNumberOfCapabilities",
-      this,
-      &CamerasChild::SendNumberOfCapabilities,
-      aCapEngine,
-      unique_id);
-  LockAndDispatch<> dispatcher(this, __func__, runnable, 0, mReplyInteger);
-  LOG(("Capture capability count: %d", dispatcher.ReturnValue()));
-  return dispatcher.ReturnValue();
-}
-
-int
 CamerasChild::NumberOfCaptureDevices(CaptureEngine aCapEngine)
 {
   LOG((__PRETTY_FUNCTION__));
   nsCOMPtr<nsIRunnable> runnable =
     mozilla::NewNonOwningRunnableMethod<CaptureEngine>(
       "camera::PCamerasChild::SendNumberOfCaptureDevices",
       this,
       &CamerasChild::SendNumberOfCaptureDevices,
@@ -340,52 +310,51 @@ CamerasChild::EnsureInitialized(CaptureE
       &CamerasChild::SendEnsureInitialized,
       aCapEngine);
   LockAndDispatch<> dispatcher(this, __func__, runnable, 0, mReplyInteger);
   LOG(("Capture Devices: %d", dispatcher.ReturnValue()));
   return dispatcher.ReturnValue();
 }
 
 int
-CamerasChild::GetCaptureCapability(CaptureEngine aCapEngine,
-                                   const char* unique_idUTF8,
-                                   const unsigned int capability_number,
-                                   webrtc::VideoCaptureCapability& capability)
+CamerasChild::GetCaptureCapabilities(
+    CaptureEngine aCapEngine,
+    const char* unique_idUTF8,
+    nsTArray<webrtc::VideoCaptureCapability>& capabilityList)
 {
-  LOG(("GetCaptureCapability: %s %d", unique_idUTF8, capability_number));
+  LOG(("GetCaptureCapability: %s", unique_idUTF8));
   nsCString unique_id(unique_idUTF8);
   nsCOMPtr<nsIRunnable> runnable =
-    mozilla::NewNonOwningRunnableMethod<CaptureEngine, nsCString, unsigned int>(
-      "camera::PCamerasChild::SendGetCaptureCapability",
+    mozilla::NewNonOwningRunnableMethod<CaptureEngine, nsCString>(
+      "camera::PCamerasChild::SendGetCaptureCapabilities",
       this,
-      &CamerasChild::SendGetCaptureCapability,
+      &CamerasChild::SendGetCaptureCapabilities,
       aCapEngine,
-      unique_id,
-      capability_number);
+      unique_id);
   LockAndDispatch<> dispatcher(this, __func__, runnable);
   if (dispatcher.Success()) {
-    capability = mReplyCapability;
+    capabilityList.Clear();
+    capabilityList.SwapElements(mReplyCapabilities);
   }
   return dispatcher.ReturnValue();
 }
 
 mozilla::ipc::IPCResult
-CamerasChild::RecvReplyGetCaptureCapability(const VideoCaptureCapability& ipcCapability)
+CamerasChild::RecvReplyGetCaptureCapabilities(
+    nsTArray<VideoCaptureCapability>&& ipcCapabilityList)
 {
   LOG((__PRETTY_FUNCTION__));
   MonitorAutoLock monitor(mReplyMonitor);
   mReceivedReply = true;
-  mReplySuccess = true;
-  mReplyCapability.width = ipcCapability.width();
-  mReplyCapability.height = ipcCapability.height();
-  mReplyCapability.maxFPS = ipcCapability.maxFPS();
-  mReplyCapability.expectedCaptureDelay = ipcCapability.expectedCaptureDelay();
-  mReplyCapability.rawType = static_cast<webrtc::RawVideoType>(ipcCapability.rawType());
-  mReplyCapability.codecType = static_cast<webrtc::VideoCodecType>(ipcCapability.codecType());
-  mReplyCapability.interlaced = ipcCapability.interlaced();
+  mReplyCapabilities.Clear();
+  webrtc::VideoCaptureCapability capability;
+  for (auto& ipcCapability : ipcCapabilityList) {
+    VideoCaptureUtils::IpcToWebrtcCapability(ipcCapability, capability);
+    mReplyCapabilities.AppendElement(capability);
+  }
   monitor.Notify();
   return IPC_OK();
 }
 
 int
 CamerasChild::GetCaptureDevice(CaptureEngine aCapEngine,
                                unsigned int list_number, char* device_nameUTF8,
                                const unsigned int device_nameUTF8Length,
--- a/dom/media/systemservices/CamerasChild.h
+++ b/dom/media/systemservices/CamerasChild.h
@@ -160,47 +160,48 @@ public:
                                                       const int& w, const int& h) override;
 
   virtual mozilla::ipc::IPCResult RecvDeviceChange() override;
   virtual int AddDeviceChangeCallback(DeviceChangeCallback* aCallback) override;
   int SetFakeDeviceChangeEvents();
 
   // these are response messages to our outgoing requests
   virtual mozilla::ipc::IPCResult RecvReplyNumberOfCaptureDevices(const int&) override;
-  virtual mozilla::ipc::IPCResult RecvReplyNumberOfCapabilities(const int&) override;
   virtual mozilla::ipc::IPCResult RecvReplyAllocateCaptureDevice(const int&) override;
-  virtual mozilla::ipc::IPCResult RecvReplyGetCaptureCapability(const VideoCaptureCapability& capability) override;
+
+  virtual mozilla::ipc::IPCResult RecvReplyGetCaptureCapabilities(
+      nsTArray<VideoCaptureCapability>&& capabilities) override;
+
   virtual mozilla::ipc::IPCResult RecvReplyGetCaptureDevice(const nsCString& device_name,
                                                             const nsCString& device_id,
                                                             const bool& scary) override;
   virtual mozilla::ipc::IPCResult RecvReplyFailure(void) override;
   virtual mozilla::ipc::IPCResult RecvReplySuccess(void) override;
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   // the webrtc.org ViECapture calls are mirrored here, but with access
   // to a specific PCameras instance to communicate over. These also
   // run on the MediaManager thread
   int NumberOfCaptureDevices(CaptureEngine aCapEngine);
-  int NumberOfCapabilities(CaptureEngine aCapEngine,
-                           const char* deviceUniqueIdUTF8);
   int ReleaseCaptureDevice(CaptureEngine aCapEngine,
                            const int capture_id);
   int StartCapture(CaptureEngine aCapEngine,
                    const int capture_id, webrtc::VideoCaptureCapability& capability,
                    FrameRelay* func);
   int StopCapture(CaptureEngine aCapEngine, const int capture_id);
   int AllocateCaptureDevice(CaptureEngine aCapEngine,
                             const char* unique_idUTF8,
                             const unsigned int unique_idUTF8Length,
                             int& capture_id,
                             const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
-  int GetCaptureCapability(CaptureEngine aCapEngine,
-                           const char* unique_idUTF8,
-                           const unsigned int capability_number,
-                           webrtc::VideoCaptureCapability& capability);
+  int
+  GetCaptureCapabilities(
+      CaptureEngine aCapEngine,
+      const char* unique_idUTF8,
+      nsTArray<webrtc::VideoCaptureCapability>& capabilities);
   int GetCaptureDevice(CaptureEngine aCapEngine,
                        unsigned int list_number, char* device_nameUTF8,
                        const unsigned int device_nameUTF8Length,
                        char* unique_idUTF8,
                        const unsigned int unique_idUTF8Length,
                        bool* scary = nullptr);
   void ShutdownAll();
   int EnsureInitialized(CaptureEngine aCapEngine);
@@ -237,17 +238,17 @@ private:
   Mutex mRequestMutex;
   // Hold to wait for an async response to our calls
   Monitor mReplyMonitor;
   // Async response valid?
   bool mReceivedReply;
   // Async responses data contents;
   bool mReplySuccess;
   int mReplyInteger;
-  webrtc::VideoCaptureCapability mReplyCapability;
+  nsTArray<webrtc::VideoCaptureCapability> mReplyCapabilities;
   nsCString mReplyDeviceName;
   nsCString mReplyDeviceID;
   bool mReplyScary;
 };
 
 } // namespace camera
 } // namespace mozilla
 
--- a/dom/media/systemservices/CamerasParent.cpp
+++ b/dom/media/systemservices/CamerasParent.cpp
@@ -2,16 +2,17 @@
 /* vim: set sw=2 ts=8 et ft=cpp : */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "CamerasParent.h"
 #include "MediaEngine.h"
 #include "MediaUtils.h"
+#include "VideoCaptureUtils.h"
 #include "VideoFrameUtils.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Unused.h"
 #include "mozilla/Services.h"
 #include "mozilla/Logging.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/PBackgroundParent.h"
@@ -489,95 +490,50 @@ CamerasParent::RecvEnsureInitialized(con
         self->mPBackgroundEventTarget->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
       return NS_OK;
     });
   DispatchToVideoCaptureThread(webrtc_runnable);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-CamerasParent::RecvNumberOfCapabilities(const CaptureEngine& aCapEngine,
+CamerasParent::RecvGetCaptureCapabilities(const CaptureEngine& aCapEngine,
                                         const nsCString& unique_id)
 {
-  LOG((__PRETTY_FUNCTION__));
-  LOG(("Getting caps for %s", unique_id.get()));
-
+  LOG(("%s uid:%s", __PRETTY_FUNCTION__, unique_id.get()));
   RefPtr<CamerasParent> self(this);
   RefPtr<Runnable> webrtc_runnable =
     media::NewRunnableFrom([self, unique_id, aCapEngine]() -> nsresult {
-      int num = -1;
+      nsTArray<VideoCaptureCapability> capabilityList;
+      int error = -1;
       if (auto engine = self->EnsureInitialized(aCapEngine)) {
-        if (auto devInfo = engine->GetOrCreateVideoCaptureDeviceInfo()) {
-          num = devInfo->NumberOfCapabilities(unique_id.get());
+        if (auto devInfo = engine->GetOrCreateVideoCaptureDeviceInfo()){
+          webrtc::VideoCaptureCapability webrtcCaps;
+          VideoCaptureCapability ipcCaps;
+          int32_t num = devInfo->NumberOfCapabilities(unique_id.get());
+          for (int32_t i = 0; i < num; i++) {
+            error = devInfo->GetCapability(unique_id.get(), num, webrtcCaps);
+            if (error) {
+              break;
+            }
+            VideoCaptureUtils::WebrtcToIpcCapability(webrtcCaps, ipcCaps);
+            capabilityList.AppendElement(ipcCaps);
+          }
         }
       }
       RefPtr<nsIRunnable> ipc_runnable =
-        media::NewRunnableFrom([self, num]() -> nsresult {
+        media::NewRunnableFrom([self, capabilityList, error]() -> nsresult {
           if (self->IsShuttingDown()) {
             return NS_ERROR_FAILURE;
           }
-          if (num < 0) {
-            LOG(("RecvNumberOfCapabilities couldn't find capabilities"));
-            Unused << self->SendReplyFailure();
-            return NS_ERROR_FAILURE;
-          } else {
-            LOG(("RecvNumberOfCapabilities: %d", num));
-          }
-          Unused << self->SendReplyNumberOfCapabilities(num);
-          return NS_OK;
-        });
-      self->mPBackgroundEventTarget->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
-      return NS_OK;
-    });
-  DispatchToVideoCaptureThread(webrtc_runnable);
-  return IPC_OK();
-}
-
-mozilla::ipc::IPCResult
-CamerasParent::RecvGetCaptureCapability(const CaptureEngine& aCapEngine,
-                                        const nsCString& unique_id,
-                                        const int& num)
-{
-  LOG((__PRETTY_FUNCTION__));
-  LOG(("RecvGetCaptureCapability: %s %d", unique_id.get(), num));
-
-  RefPtr<CamerasParent> self(this);
-  RefPtr<Runnable> webrtc_runnable =
-    media::NewRunnableFrom([self, unique_id, aCapEngine, num]() -> nsresult {
-      webrtc::VideoCaptureCapability webrtcCaps;
-      int error = -1;
-      if (auto engine = self->EnsureInitialized(aCapEngine)) {
-        if (auto devInfo = engine->GetOrCreateVideoCaptureDeviceInfo()){
-          error = devInfo->GetCapability(unique_id.get(), num, webrtcCaps);
-        }
-      }
-      RefPtr<nsIRunnable> ipc_runnable =
-        media::NewRunnableFrom([self, webrtcCaps, error]() -> nsresult {
-          if (self->IsShuttingDown()) {
-            return NS_ERROR_FAILURE;
-          }
-          VideoCaptureCapability capCap(webrtcCaps.width,
-                                   webrtcCaps.height,
-                                   webrtcCaps.maxFPS,
-                                   webrtcCaps.expectedCaptureDelay,
-                                   webrtcCaps.rawType,
-                                   webrtcCaps.codecType,
-                                   webrtcCaps.interlaced);
-          LOG(("Capability: %u %u %u %u %d %d",
-               webrtcCaps.width,
-               webrtcCaps.height,
-               webrtcCaps.maxFPS,
-               webrtcCaps.expectedCaptureDelay,
-               webrtcCaps.rawType,
-               webrtcCaps.codecType));
           if (error) {
             Unused << self->SendReplyFailure();
             return NS_ERROR_FAILURE;
           }
-          Unused << self->SendReplyGetCaptureCapability(capCap);
+          Unused << self->SendReplyGetCaptureCapabilities(capabilityList);
           return NS_OK;
         });
       self->mPBackgroundEventTarget->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
       return NS_OK;
     });
   DispatchToVideoCaptureThread(webrtc_runnable);
   return IPC_OK();
 }
@@ -805,24 +761,17 @@ CamerasParent::RecvStartCapture(const Ca
       if (self->EnsureInitialized(aCapEngine)) {
         cbh = self->mCallbacks.AppendElement(
           new CallbackHelper(static_cast<CaptureEngine>(aCapEngine), capnum, self));
 
         engine = self->mEngines[aCapEngine];
         engine->WithEntry(capnum, [&engine, &error, &ipcCaps, &cbh](VideoEngine::CaptureEntry& cap) {
           error = 0;
           webrtc::VideoCaptureCapability capability;
-          capability.width = ipcCaps.width();
-          capability.height = ipcCaps.height();
-          capability.maxFPS = ipcCaps.maxFPS();
-          capability.expectedCaptureDelay = ipcCaps.expectedCaptureDelay();
-          capability.rawType = static_cast<webrtc::RawVideoType>(ipcCaps.rawType());
-          capability.codecType = static_cast<webrtc::VideoCodecType>(ipcCaps.codecType());
-          capability.interlaced = ipcCaps.interlaced();
-
+          VideoCaptureUtils::IpcToWebrtcCapability(ipcCaps, capability);
           if (!error) {
             error = cap.VideoCapture()->StartCapture(capability);
           }
           if (!error) {
             engine->Startup();
             cap.VideoCapture()->RegisterCaptureDataCallback(static_cast<rtc::VideoSinkInterface<webrtc::VideoFrame>*>(*cbh));
           }
         });
--- a/dom/media/systemservices/CamerasParent.h
+++ b/dom/media/systemservices/CamerasParent.h
@@ -85,20 +85,19 @@ public:
   // Messages received form the child. These run on the IPC/PBackground thread.
   virtual mozilla::ipc::IPCResult
   RecvAllocateCaptureDevice(const CaptureEngine& aEngine,
                             const nsCString& aUnique_idUTF8,
                             const ipc::PrincipalInfo& aPrincipalInfo) override;
   virtual mozilla::ipc::IPCResult RecvReleaseCaptureDevice(const CaptureEngine&,
                                                            const int&) override;
   virtual mozilla::ipc::IPCResult RecvNumberOfCaptureDevices(const CaptureEngine&) override;
-  virtual mozilla::ipc::IPCResult RecvNumberOfCapabilities(const CaptureEngine&,
-                                                           const nsCString&) override;
-  virtual mozilla::ipc::IPCResult RecvGetCaptureCapability(const CaptureEngine&, const nsCString&,
-                                                           const int&) override;
+  virtual mozilla::ipc::IPCResult
+  RecvGetCaptureCapabilities(const CaptureEngine&, const nsCString&) override;
+
   virtual mozilla::ipc::IPCResult RecvGetCaptureDevice(const CaptureEngine&, const int&) override;
   virtual mozilla::ipc::IPCResult RecvStartCapture(const CaptureEngine&, const int&,
                                                    const VideoCaptureCapability&) override;
   virtual mozilla::ipc::IPCResult RecvStopCapture(const CaptureEngine&, const int&) override;
   virtual mozilla::ipc::IPCResult RecvReleaseFrame(mozilla::ipc::Shmem&&) override;
   virtual mozilla::ipc::IPCResult RecvAllDone() override;
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   virtual mozilla::ipc::IPCResult RecvEnsureInitialized(const CaptureEngine&) override;
--- a/dom/media/systemservices/PCameras.ipdl
+++ b/dom/media/systemservices/PCameras.ipdl
@@ -19,17 +19,16 @@ struct VideoCaptureCapability
   int height;
   int maxFPS;
   int expectedCaptureDelay;
   int rawType;
   int codecType;
   bool interlaced;
 };
 
-
 // IPC analog for webrtc::VideoFrame
 // the described buffer is transported seperately in a Shmem
 // See VideoFrameUtils.h
 struct VideoFrameProperties
 {
   // Size of image data within the ShMem,
   // the ShMem is at least this large
   size_t bufferSize;
@@ -56,30 +55,27 @@ async protocol PCameras
 
 child:
   async FrameSizeChange(CaptureEngine capEngine, int cap_id, int w, int h);
   // transfers ownership of |buffer| from parent to child
   async DeliverFrame(CaptureEngine capEngine, int streamId,
                      Shmem buffer, VideoFrameProperties props);
   async DeviceChange();
   async ReplyNumberOfCaptureDevices(int numdev);
-  async ReplyNumberOfCapabilities(int numdev);
   async ReplyAllocateCaptureDevice(int numdev);
-  async ReplyGetCaptureCapability(VideoCaptureCapability cap);
+  async ReplyGetCaptureCapabilities(VideoCaptureCapability[] capabilities);
   async ReplyGetCaptureDevice(nsCString device_name, nsCString device_id, bool scary);
   async ReplyFailure();
   async ReplySuccess();
   async __delete__();
 
 parent:
   async NumberOfCaptureDevices(CaptureEngine engine);
-  async NumberOfCapabilities(CaptureEngine engine, nsCString deviceUniqueIdUTF8);
 
-  async GetCaptureCapability(CaptureEngine engine, nsCString unique_idUTF8,
-                             int capability_number);
+  async GetCaptureCapabilities(CaptureEngine engine, nsCString unique_idUTF8);
   async GetCaptureDevice(CaptureEngine engine, int num);
 
   async AllocateCaptureDevice(CaptureEngine engine, nsCString unique_idUTF8,
                               PrincipalInfo principal);
   async ReleaseCaptureDevice(CaptureEngine engine, int numdev);
   async StartCapture(CaptureEngine engine, int numdev, VideoCaptureCapability capability);
   async StopCapture(CaptureEngine engine, int numdev);
   // transfers frame back
--- a/dom/media/systemservices/moz.build
+++ b/dom/media/systemservices/moz.build
@@ -3,23 +3,25 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 if CONFIG['MOZ_WEBRTC']:
     EXPORTS += [
         'CamerasChild.h',
         'CamerasParent.h',
+        'VideoCaptureUtils.h',
         'VideoEngine.h',
         'VideoFrameUtils.h'
     ]
     UNIFIED_SOURCES += [
         'CamerasChild.cpp',
         'CamerasParent.cpp',
         'ShmemPool.cpp',
+        'VideoCaptureUtils.cpp',
         'VideoEngine.cpp',
         'VideoFrameUtils.cpp'
     ]
     LOCAL_INCLUDES += [
         '/media/webrtc/signaling',
         '/media/webrtc/trunk',
     ]
 if CONFIG['OS_TARGET'] == 'WINNT':
--- a/dom/media/webrtc/MediaEngineCameraVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineCameraVideoSource.cpp
@@ -1,16 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaEngineCameraVideoSource.h"
 
 #include "mozilla/IntegerPrintfMacros.h"
-
 #include <limits>
 
 namespace mozilla {
 
 using namespace mozilla::gfx;
 using namespace mozilla::dom;
 
 extern LogModule* GetMediaManagerLog();
@@ -33,30 +32,23 @@ bool MediaEngineCameraVideoSource::Appen
 
   // This is safe from any thread, and is safe if the track is Finished
   // or Destroyed.
   // This can fail if either a) we haven't added the track yet, or b)
   // we've removed or finished the track.
   return aSource->AppendToTrack(aID, &(segment));
 }
 
-// Sub-classes (B2G or desktop) should overload one of both of these two methods
-// to provide capabilities
-size_t
-MediaEngineCameraVideoSource::NumCapabilities() const
+void
+MediaEngineCameraVideoSource::GetCapabilityCandidateSet(CapabilitySet& aOut) const
 {
-  return mHardcodedCapabilities.Length();
-}
-
-void
-MediaEngineCameraVideoSource::GetCapability(size_t aIndex,
-                                            webrtc::CaptureCapability& aOut) const
-{
-  MOZ_ASSERT(aIndex < mHardcodedCapabilities.Length());
-  aOut = mHardcodedCapabilities.SafeElementAt(aIndex, webrtc::CaptureCapability());
+  aOut.Clear();
+  for (auto& cap : mHardcodedCapabilities) {
+    aOut.AppendElement(CapabilityCandidate(cap));
+  }
 }
 
 uint32_t
 MediaEngineCameraVideoSource::GetFitnessDistance(
     const webrtc::CaptureCapability& aCandidate,
     const NormalizedConstraintSet &aConstraints,
     const nsString& aDeviceId) const
 {
@@ -103,30 +95,24 @@ MediaEngineCameraVideoSource::TrimLessFi
 // Infinity = UINT32_MAX e.g. device cannot satisfy accumulated ConstraintSets.
 // A finite result may be used to calculate this device's ranking as a choice.
 
 uint32_t
 MediaEngineCameraVideoSource::GetBestFitnessDistance(
     const nsTArray<const NormalizedConstraintSet*>& aConstraintSets,
     const nsString& aDeviceId) const
 {
-  size_t num = NumCapabilities();
-
   CapabilitySet candidateSet;
-  for (size_t i = 0; i < num; i++) {
-    candidateSet.AppendElement(i);
-  }
-
+  GetCapabilityCandidateSet(candidateSet);
   bool first = true;
   for (const NormalizedConstraintSet* ns : aConstraintSets) {
     for (size_t i = 0; i < candidateSet.Length();  ) {
       auto& candidate = candidateSet[i];
-      webrtc::CaptureCapability cap;
-      GetCapability(candidate.mIndex, cap);
-      uint32_t distance = GetFitnessDistance(cap, *ns, aDeviceId);
+      uint32_t distance = GetFitnessDistance(candidate.mCapability, *ns,
+                                             aDeviceId);
       if (distance == UINT32_MAX) {
         candidateSet.RemoveElementAt(i);
       } else {
         ++i;
         if (first) {
           candidate.mDistance = distance;
         }
       }
@@ -228,52 +214,49 @@ MediaEngineCameraVideoSource::ChooseCapa
     if (aConstraints.mAdvanced.size()) {
       LOG(("Advanced array[%zu]:", aConstraints.mAdvanced.size()));
       for (auto& advanced : aConstraints.mAdvanced) {
         LogConstraints(advanced);
       }
     }
   }
 
-  size_t num = NumCapabilities();
-
   CapabilitySet candidateSet;
-  for (size_t i = 0; i < num; i++) {
-    candidateSet.AppendElement(i);
-  }
+  GetCapabilityCandidateSet(candidateSet);
+  size_t num = candidateSet.Length();
 
   // First, filter capabilities by required constraints (min, max, exact).
 
   for (size_t i = 0; i < candidateSet.Length();) {
     auto& candidate = candidateSet[i];
-    webrtc::CaptureCapability cap;
-    GetCapability(candidate.mIndex, cap);
-    candidate.mDistance = GetFitnessDistance(cap, aConstraints, aDeviceId);
-    LogCapability("Capability", cap, candidate.mDistance);
+    candidate.mDistance = GetFitnessDistance(candidate.mCapability,
+                                             aConstraints, aDeviceId);
+    LogCapability("Capability", candidate.mCapability, candidate.mDistance);
     if (candidate.mDistance == UINT32_MAX) {
       candidateSet.RemoveElementAt(i);
     } else {
       ++i;
     }
   }
 
   if (!candidateSet.Length()) {
-    LOG(("failed to find capability match from %zu choices",num));
+    
+    LOG(("failed to find capability match from %lu choices", 
+         static_cast<unsigned long>(num)));
     return false;
   }
 
   // Filter further with all advanced constraints (that don't overconstrain).
 
   for (const auto &cs : aConstraints.mAdvanced) {
     CapabilitySet rejects;
     for (size_t i = 0; i < candidateSet.Length();) {
       auto& candidate = candidateSet[i];
-      webrtc::CaptureCapability cap;
-      GetCapability(candidate.mIndex, cap);
-      if (GetFitnessDistance(cap, cs, aDeviceId) == UINT32_MAX) {
+      if (GetFitnessDistance(candidate.mCapability, cs, aDeviceId)
+              == UINT32_MAX) {
         rejects.AppendElement(candidate);
         candidateSet.RemoveElementAt(i);
       } else {
         ++i;
       }
     }
     if (!candidateSet.Length()) {
       candidateSet.AppendElements(Move(rejects));
@@ -292,41 +275,38 @@ MediaEngineCameraVideoSource::ChooseCapa
   {
     MediaTrackConstraintSet prefs;
     prefs.mWidth.SetAsLong() = aPrefs.GetWidth();
     prefs.mHeight.SetAsLong() = aPrefs.GetHeight();
     prefs.mFrameRate.SetAsDouble() = aPrefs.mFPS;
     NormalizedConstraintSet normPrefs(prefs, false);
 
     for (auto& candidate : candidateSet) {
-      webrtc::CaptureCapability cap;
-      GetCapability(candidate.mIndex, cap);
-      candidate.mDistance = GetFitnessDistance(cap, normPrefs, aDeviceId);
+      candidate.mDistance = GetFitnessDistance(candidate.mCapability, normPrefs,
+                                               aDeviceId);
     }
     TrimLessFitCandidates(candidateSet);
   }
 
   // Any remaining multiples all have the same distance, but may vary on
   // format. Some formats are more desirable for certain use like WebRTC.
   // E.g. I420 over RGB24 can remove a needless format conversion.
 
   bool found = false;
   for (auto& candidate : candidateSet) {
-    webrtc::CaptureCapability cap;
-    GetCapability(candidate.mIndex, cap);
-    if (cap.rawType == webrtc::RawVideoType::kVideoI420 ||
-        cap.rawType == webrtc::RawVideoType::kVideoYUY2 ||
-        cap.rawType == webrtc::RawVideoType::kVideoYV12) {
-      mCapability = cap;
+    if (candidate.mCapability.rawType == webrtc::RawVideoType::kVideoI420 ||
+        candidate.mCapability.rawType == webrtc::RawVideoType::kVideoYUY2 ||
+        candidate.mCapability.rawType == webrtc::RawVideoType::kVideoYV12) {
+      mCapability = candidate.mCapability;
       found = true;
       break;
     }
   }
   if (!found) {
-    GetCapability(candidateSet[0].mIndex, mCapability);
+    mCapability = candidateSet[0].mCapability;
   }
 
   LogCapability("Chosen capability", mCapability, sameDistance);
   return true;
 }
 
 void
 MediaEngineCameraVideoSource::SetName(nsString aName)
--- a/dom/media/webrtc/MediaEngineCameraVideoSource.h
+++ b/dom/media/webrtc/MediaEngineCameraVideoSource.h
@@ -57,20 +57,20 @@ public:
   }
 
   uint32_t GetBestFitnessDistance(
       const nsTArray<const NormalizedConstraintSet*>& aConstraintSets,
       const nsString& aDeviceId) const override;
 
 protected:
   struct CapabilityCandidate {
-    explicit CapabilityCandidate(uint8_t index, uint32_t distance = 0)
-    : mIndex(index), mDistance(distance) {}
-
-    size_t mIndex;
+    explicit CapabilityCandidate(const webrtc::CaptureCapability cap,
+                                 uint32_t distance = 0)
+    : mCapability(cap), mDistance(distance) {}
+    const webrtc::CaptureCapability mCapability;
     uint32_t mDistance;
   };
   typedef nsTArray<CapabilityCandidate> CapabilitySet;
 
   ~MediaEngineCameraVideoSource() {}
 
   // guts for appending data to the MSG track
   virtual bool AppendToTrack(SourceMediaStream* aSource,
@@ -81,18 +81,17 @@ protected:
   uint32_t GetFitnessDistance(const webrtc::CaptureCapability& aCandidate,
                               const NormalizedConstraintSet &aConstraints,
                               const nsString& aDeviceId) const;
   static void TrimLessFitCandidates(CapabilitySet& set);
   static void LogConstraints(const NormalizedConstraintSet& aConstraints);
   static void LogCapability(const char* aHeader,
                             const webrtc::CaptureCapability &aCapability,
                             uint32_t aDistance);
-  virtual size_t NumCapabilities() const;
-  virtual void GetCapability(size_t aIndex, webrtc::CaptureCapability& aOut) const;
+  virtual void GetCapabilityCandidateSet(CapabilitySet& aOut) const;
   virtual bool ChooseCapability(const NormalizedConstraints &aConstraints,
                                 const MediaEnginePrefs &aPrefs,
                                 const nsString& aDeviceId);
   void SetName(nsString aName);
   void SetUUID(const char* aUUID);
   const nsCString& GetUUID() const; // protected access
 
   // Engine variables.
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -429,34 +429,16 @@ MediaEngineRemoteVideoSource::DeliverFra
 
   // We'll push the frame into the MSG on the next NotifyPull. This will avoid
   // swamping the MSG with frames should it be taking longer than normal to run
   // an iteration.
 
   return 0;
 }
 
-size_t
-MediaEngineRemoteVideoSource::NumCapabilities() const
-{
-  mHardcodedCapabilities.Clear();
-  int num = mozilla::camera::GetChildAndCall(
-      &mozilla::camera::CamerasChild::NumberOfCapabilities,
-      mCapEngine,
-      GetUUID().get());
-  if (num < 1) {
-    // The default for devices that don't return discrete capabilities: treat
-    // them as supporting all capabilities orthogonally. E.g. screensharing.
-    // CaptureCapability defaults key values to 0, which means accept any value.
-    mHardcodedCapabilities.AppendElement(webrtc::CaptureCapability());
-    num = mHardcodedCapabilities.Length(); // 1
-  }
-  return num;
-}
-
 bool
 MediaEngineRemoteVideoSource::ChooseCapability(
     const NormalizedConstraints &aConstraints,
     const MediaEnginePrefs &aPrefs,
     const nsString& aDeviceId)
 {
   AssertIsOnOwningThread();
 
@@ -477,29 +459,40 @@ MediaEngineRemoteVideoSource::ChooseCapa
       return true;
     }
     default:
       return MediaEngineCameraVideoSource::ChooseCapability(aConstraints, aPrefs, aDeviceId);
   }
 
 }
 
-void
-MediaEngineRemoteVideoSource::GetCapability(size_t aIndex,
-                                            webrtc::CaptureCapability& aOut) const
+void MediaEngineRemoteVideoSource::GetCapabilityCandidateSet(
+    CapabilitySet& aOut) const
 {
-  if (!mHardcodedCapabilities.IsEmpty()) {
-    MediaEngineCameraVideoSource::GetCapability(aIndex, aOut);
+    aOut.Clear();
+    nsTArray<webrtc::CaptureCapability> caps;
+    mozilla::camera::GetChildAndCall(
+      &mozilla::camera::CamerasChild::GetCaptureCapabilities,
+      mCapEngine,
+      GetUUID().get(),
+      caps);
+    for (auto& cap : caps) {
+      aOut.AppendElement(CapabilityCandidate(cap));
+    }
+  if (aOut.IsEmpty()) {
+    if (mHardcodedCapabilities.IsEmpty()) {
+      // The default for devices that don't return discrete capabilities: treat
+      // them as supporting all capabilities orthogonally. E.g. screensharing.
+      // CaptureCapability defaults key values to 0, which means accept any
+      // value.
+      mHardcodedCapabilities.AppendElement(webrtc::CaptureCapability());
+    }
+    // Return the hardcoded set of capabilities (now of size 1)
+    MediaEngineCameraVideoSource::GetCapabilityCandidateSet(aOut);
   }
-  mozilla::camera::GetChildAndCall(
-    &mozilla::camera::CamerasChild::GetCaptureCapability,
-    mCapEngine,
-    GetUUID().get(),
-    aIndex,
-    aOut);
 }
 
 void MediaEngineRemoteVideoSource::Refresh(int aIndex) {
   // NOTE: mCaptureIndex might have changed when allocated!
   // Use aIndex to update information, but don't change mCaptureIndex!!
   // Caller looked up this source by uniqueId, so it shouldn't change
   char deviceName[kMaxDeviceNameLength];
   char uniqueId[kMaxUniqueIdLength];
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.h
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.h
@@ -95,18 +95,17 @@ public:
   bool GetScary() const override { return mScary; }
 
 protected:
   ~MediaEngineRemoteVideoSource() { }
 
 private:
   // Initialize the needed Video engine interfaces.
   void Init();
-  size_t NumCapabilities() const override;
-  void GetCapability(size_t aIndex, webrtc::CaptureCapability& aOut) const override;
+  virtual void GetCapabilityCandidateSet(CapabilitySet& aOut) const override;
   void SetLastCapability(const webrtc::CaptureCapability& aCapability);
 
   nsresult
   UpdateSingleSource(const AllocationHandle* aHandle,
                      const NormalizedConstraints& aNetConstraints,
                      const MediaEnginePrefs& aPrefs,
                      const nsString& aDeviceId,
                      const char** aOutBadConstraint) override;
--- a/dom/media/webrtc/MediaEngineWebRTC.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTC.cpp
@@ -6,17 +6,17 @@
 
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 
 #include "CSFLog.h"
 #include "prenv.h"
 
 #include "mozilla/Logging.h"
-
+  
 static mozilla::LazyLogModule sGetUserMediaLog("GetUserMedia");
 
 #include "MediaEngineWebRTC.h"
 #include "ImageContainer.h"
 #include "nsIComponentRegistrar.h"
 #include "MediaEngineTabVideoSource.h"
 #include "MediaEngineRemoteVideoSource.h"
 #include "CamerasChild.h"
@@ -208,33 +208,27 @@ MediaEngineWebRTC::EnumerateVideoDevices
       sizeof(uniqueId),
       &scarySource);
     if (error) {
       LOG(("camera:GetCaptureDevice: Failed %d", error ));
       continue;
     }
 #ifdef DEBUG
     LOG(("  Capture Device Index %d, Name %s", i, deviceName));
-
-    webrtc::CaptureCapability cap;
-    int numCaps = mozilla::camera::GetChildAndCall(
-      &mozilla::camera::CamerasChild::NumberOfCapabilities,
-      capEngine,
-      uniqueId);
-    LOG(("Number of Capabilities %d", numCaps));
-    for (int j = 0; j < numCaps; j++) {
-      if (mozilla::camera::GetChildAndCall(
-            &mozilla::camera::CamerasChild::GetCaptureCapability,
-            capEngine,
-            uniqueId,
-            j, cap) != 0) {
-       break;
+    nsTArray<webrtc::CaptureCapability> capList;
+    if (!mozilla::camera::GetChildAndCall(
+          &mozilla::camera::CamerasChild::GetCaptureCapabilities,
+          capEngine, uniqueId, capList))
+    {
+      LOG(("Number of Capabilities %lu",
+           static_cast<unsigned long>(capList.Length())));
+      for (auto& cap : capList) {
+        LOG(("type=%d width=%d height=%d maxFPS=%d",
+             cap.rawType, cap.width, cap.height, cap.maxFPS));
       }
-      LOG(("type=%d width=%d height=%d maxFPS=%d",
-           cap.rawType, cap.width, cap.height, cap.maxFPS ));
     }
 #endif
 
     if (uniqueId[0] == '\0') {
       // In case a device doesn't set uniqueId!
       strncpy(uniqueId, deviceName, sizeof(uniqueId));
       uniqueId[sizeof(uniqueId)-1] = '\0'; // strncpy isn't safe
     }