Bug 1430856 - Cache CaptureCapability in CapabilityCandidate. r=jib
authorAndreas Pehrson <pehrsons@mozilla.com>
Tue, 13 Feb 2018 20:13:47 +0100
changeset 404402 445276274143b5e2d4dcf8f0afc13df28530e378
parent 404401 5b8dd2380f3eda126be82974414577a53ca64a27
child 404403 12b8e4ad2fdc00a75fb9852cacf7d4b72f2b8bfb
push id33473
push userncsoregi@mozilla.com
push dateMon, 19 Feb 2018 16:45:12 +0000
treeherdermozilla-central@f60cfdc81e94 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjib
bugs1430856
milestone60.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 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.