Bug 1430856 - Cache CaptureCapability in CapabilityCandidate. r?jib draft
authorAndreas Pehrson <pehrsons@mozilla.com>
Tue, 13 Feb 2018 20:13:47 +0100
changeset 756915 eeb2c9784d7bb546a94f42bbf7eb5a1d45b84390
parent 753815 3ee38289dac8838fe848f7234d75f3cef5d3dbc7
child 756916 cdc065464e94dd486735388df0d62b4766a887cd
push id99581
push userbmo:apehrson@mozilla.com
push dateMon, 19 Feb 2018 09:43:12 +0000
reviewersjib
bugs1430856
milestone60.0a1
Bug 1430856 - Cache CaptureCapability in CapabilityCandidate. r?jib This will lead to less ipc calls, hopefully speeding up getUserMedia for many devices. This also lets us inject any hardcoded capabilities into the candidateSet in the future (read: next patch). MozReview-Commit-ID: HjIhRK1nVA1
dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
dom/media/webrtc/MediaEngineRemoteVideoSource.h
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -408,27 +408,28 @@ MediaEngineRemoteVideoSource::NumCapabil
 
   // 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 mHardcodedCapabilities.Length(); // 1
 }
 
-void
-MediaEngineRemoteVideoSource::GetCapability(size_t aIndex,
-                                            webrtc::CaptureCapability& aOut) const
+webrtc::CaptureCapability
+MediaEngineRemoteVideoSource::GetCapability(size_t aIndex) const
 {
   AssertIsOnOwningThread();
+  webrtc::CaptureCapability result;
   if (!mHardcodedCapabilities.IsEmpty()) {
     MOZ_ASSERT(aIndex < mHardcodedCapabilities.Length());
-    aOut = mHardcodedCapabilities.SafeElementAt(aIndex, webrtc::CaptureCapability());
+    result = mHardcodedCapabilities.SafeElementAt(aIndex, webrtc::CaptureCapability());
   }
   camera::GetChildAndCall(&camera::CamerasChild::GetCaptureCapability,
-                          mCapEngine, mUniqueId.get(), aIndex, aOut);
+                          mCapEngine, mUniqueId.get(), aIndex, result);
+  return result;
 }
 
 void
 MediaEngineRemoteVideoSource::Pull(const RefPtr<const AllocationHandle>& aHandle,
                                    const RefPtr<SourceMediaStream>& aStream,
                                    TrackID aTrackID,
                                    StreamTime aDesiredTime,
                                    const PrincipalHandle& aPrincipalHandle)
@@ -632,55 +633,53 @@ MediaEngineRemoteVideoSource::GetFeasibi
     uint64_t(aCandidate.maxFPS ? H::FeasibilityDistance(double(aCandidate.maxFPS),
                                                         aConstraints.mFrameRate) : 0);
   return uint32_t(std::min(distance, uint64_t(UINT32_MAX)));
 }
 
 // Find best capability by removing inferiors. May leave >1 of equal distance
 
 /* static */ void
-MediaEngineRemoteVideoSource::TrimLessFitCandidates(nsTArray<CapabilityCandidate>& set)
+MediaEngineRemoteVideoSource::TrimLessFitCandidates(nsTArray<CapabilityCandidate>& aSet)
 {
   uint32_t best = UINT32_MAX;
-  for (auto& candidate : set) {
+  for (auto& candidate : aSet) {
     if (best > candidate.mDistance) {
       best = candidate.mDistance;
     }
   }
-  for (size_t i = 0; i < set.Length();) {
-    if (set[i].mDistance > best) {
-      set.RemoveElementAt(i);
+  for (size_t i = 0; i < aSet.Length();) {
+    if (aSet[i].mDistance > best) {
+      aSet.RemoveElementAt(i);
     } else {
       ++i;
     }
   }
-  MOZ_ASSERT(set.Length());
+  MOZ_ASSERT(aSet.Length());
 }
 
 uint32_t
 MediaEngineRemoteVideoSource::GetBestFitnessDistance(
     const nsTArray<const NormalizedConstraintSet*>& aConstraintSets,
     const nsString& aDeviceId) const
 {
   AssertIsOnOwningThread();
 
   size_t num = NumCapabilities();
-
   nsTArray<CapabilityCandidate> candidateSet;
   for (size_t i = 0; i < num; i++) {
-    candidateSet.AppendElement(i);
+    candidateSet.AppendElement(CapabilityCandidate(GetCapability(i)));
   }
 
   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;
         }
       }
@@ -808,53 +807,49 @@ MediaEngineRemoteVideoSource::ChooseCapa
       aCapability.maxFPS =
         c.mFrameRate.Clamp(c.mFrameRate.mIdeal.valueOr(aPrefs.mFPS));
       return true;
     }
     default:
       break;
   }
 
+  nsTArray<CapabilityCandidate> candidateSet;
   size_t num = NumCapabilities();
-
-  nsTArray<CapabilityCandidate> candidateSet;
   for (size_t i = 0; i < num; i++) {
-    candidateSet.AppendElement(i);
+    candidateSet.AppendElement(CapabilityCandidate(GetCapability(i)));
   }
 
   // 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 = GetDistance(cap, aConstraints, aDeviceId, aCalculate);
-    LogCapability("Capability", cap, candidate.mDistance);
+    candidate.mDistance =
+      GetDistance(candidate.mCapability, aConstraints, aDeviceId, aCalculate);
+    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));
+  if (candidateSet.IsEmpty()) {
+    LOG(("failed to find capability match from %zu choices", candidateSet.Length()));
     return false;
   }
 
   // Filter further with all advanced constraints (that don't overconstrain).
 
   for (const auto &cs : aConstraints.mAdvanced) {
     nsTArray<CapabilityCandidate> rejects;
     for (size_t i = 0; i < candidateSet.Length();) {
-      auto& candidate = candidateSet[i];
-      webrtc::CaptureCapability cap;
-      GetCapability(candidate.mIndex, cap);
-      if (GetDistance(cap, cs, aDeviceId, aCalculate) == UINT32_MAX) {
-        rejects.AppendElement(candidate);
+      if (GetDistance(candidateSet[i].mCapability,
+                      cs, aDeviceId, aCalculate) == UINT32_MAX) {
+        rejects.AppendElement(candidateSet[i]);
         candidateSet.RemoveElementAt(i);
       } else {
         ++i;
       }
     }
     if (!candidateSet.Length()) {
       candidateSet.AppendElements(Move(rejects));
     }
@@ -872,41 +867,39 @@ MediaEngineRemoteVideoSource::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 = GetDistance(cap, normPrefs, aDeviceId, aCalculate);
+      candidate.mDistance =
+        GetDistance(candidate.mCapability, normPrefs, aDeviceId, aCalculate);
     }
     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);
+    const webrtc::CaptureCapability& cap = candidate.mCapability;
     if (cap.rawType == webrtc::RawVideoType::kVideoI420 ||
         cap.rawType == webrtc::RawVideoType::kVideoYUY2 ||
         cap.rawType == webrtc::RawVideoType::kVideoYV12) {
       aCapability = cap;
       found = true;
       break;
     }
   }
   if (!found) {
-    GetCapability(candidateSet[0].mIndex, aCapability);
+    aCapability = candidateSet[0].mCapability;
   }
 
   LogCapability("Chosen capability", aCapability, sameDistance);
   return true;
 }
 
 void
 MediaEngineRemoteVideoSource::GetSettings(MediaTrackSettings& aOutSettings) const
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.h
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.h
@@ -64,23 +64,24 @@ enum DistanceCalculation {
  * The WebRTC implementation of the MediaEngine interface.
  */
 class MediaEngineRemoteVideoSource : public MediaEngineSource,
                                      public camera::FrameRelay
 {
   ~MediaEngineRemoteVideoSource() = default;
 
   struct CapabilityCandidate {
-    explicit CapabilityCandidate(uint8_t index, uint32_t distance = 0)
-    : mIndex(index), mDistance(distance) {}
+    explicit CapabilityCandidate(webrtc::CaptureCapability&& aCapability,
+                                 uint32_t aDistance = 0)
+    : mCapability(Forward<webrtc::CaptureCapability>(aCapability))
+    , mDistance(aDistance) {}
 
-    size_t mIndex;
+    const webrtc::CaptureCapability mCapability;
     uint32_t mDistance;
   };
-  typedef nsTArray<CapabilityCandidate> CapabilitySet;
 
   bool ChooseCapability(const NormalizedConstraints& aConstraints,
                         const MediaEnginePrefs& aPrefs,
                         const nsString& aDeviceId,
                         webrtc::CaptureCapability& aCapability,
                         const DistanceCalculation aCalculate);
 
   uint32_t GetDistance(const webrtc::CaptureCapability& aCandidate,
@@ -91,17 +92,17 @@ class MediaEngineRemoteVideoSource : pub
   uint32_t GetFitnessDistance(const webrtc::CaptureCapability& aCandidate,
                               const NormalizedConstraintSet &aConstraints,
                               const nsString& aDeviceId) const;
 
   uint32_t GetFeasibilityDistance(const webrtc::CaptureCapability& aCandidate,
                               const NormalizedConstraintSet &aConstraints,
                               const nsString& aDeviceId) const;
 
-  static void TrimLessFitCandidates(CapabilitySet& set);
+  static void TrimLessFitCandidates(nsTArray<CapabilityCandidate>& aSet);
 
   uint32_t GetBestFitnessDistance(
       const nsTArray<const NormalizedConstraintSet*>& aConstraintSets,
       const nsString& aDeviceId) const override;
 
 public:
   MediaEngineRemoteVideoSource(int aIndex,
                                camera::CaptureEngine aCapEngine,
@@ -163,22 +164,21 @@ private:
   /**
    * Returns the number of capabilities for the underlying device.
    *
    * Guaranteed to return at least one capability.
    */
   size_t NumCapabilities() const;
 
   /**
-   * Fills `aOut` with the capability properties of the device capability with
-   * index `aIndex`.
+   * Returns the capability with index `aIndex` for our assigned device.
    *
    * It is an error to call this with `aIndex >= NumCapabilities()`.
    */
-  void GetCapability(size_t aIndex, webrtc::CaptureCapability& aOut) const;
+  webrtc::CaptureCapability GetCapability(size_t aIndex) const;
 
   int mCaptureIndex;
   const dom::MediaSourceEnum mMediaSource; // source of media (camera | application | screen)
   const camera::CaptureEngine mCapEngine;
   const bool mScary;
 
   // mMutex protects certain members on 3 threads:
   // MediaManager, Cameras IPC and MediaStreamGraph.