Bug 1213517 - Use NormalizedConstraints in low-level code. r=jesup
authorJan-Ivar Bruaroey <jib@mozilla.com>
Wed, 25 May 2016 01:52:15 -0400
changeset 389173 c613c94abee0d5b6344313640f4e0497a6ab54b8
parent 389172 84fb1be97595f6fdccbc49d8c3ec8d7b34bef37c
child 389174 cfc68e9868d99ccafbaf900792856eb6fb573a8d
push id23312
push userdmitchell@mozilla.com
push dateMon, 18 Jul 2016 17:58:50 +0000
reviewersjesup
bugs1213517
milestone50.0a1
Bug 1213517 - Use NormalizedConstraints in low-level code. r=jesup MozReview-Commit-ID: 3F9ZmHMKAFZ
dom/media/MediaManager.cpp
dom/media/webrtc/MediaEngine.h
dom/media/webrtc/MediaEngineCameraVideoSource.cpp
dom/media/webrtc/MediaEngineCameraVideoSource.h
dom/media/webrtc/MediaEngineDefault.cpp
dom/media/webrtc/MediaEngineDefault.h
dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
dom/media/webrtc/MediaEngineRemoteVideoSource.h
dom/media/webrtc/MediaEngineTabVideoSource.cpp
dom/media/webrtc/MediaEngineTabVideoSource.h
dom/media/webrtc/MediaEngineWebRTC.h
dom/media/webrtc/MediaEngineWebRTCAudio.cpp
dom/media/webrtc/MediaTrackConstraints.cpp
dom/media/webrtc/MediaTrackConstraints.h
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -890,17 +890,17 @@ nsresult MediaDevice::Allocate(const dom
                                const MediaEnginePrefs &aPrefs,
                                const nsACString& aOrigin) {
   return GetSource()->Allocate(aConstraints, aPrefs, mID, aOrigin,
                                getter_AddRefs(mAllocationHandle));
 }
 
 nsresult MediaDevice::Restart(const dom::MediaTrackConstraints &aConstraints,
                               const MediaEnginePrefs &aPrefs) {
-  return GetSource()->Restart(aConstraints, aPrefs, mID);
+  return GetSource()->Restart(mAllocationHandle, aConstraints, aPrefs, mID);
 }
 
 nsresult MediaDevice::Deallocate() {
   return GetSource()->Deallocate(mAllocationHandle);
 }
 
 void
 MediaOperationTask::ReturnCallbackError(nsresult rv, const char* errorLog)
--- a/dom/media/webrtc/MediaEngine.h
+++ b/dom/media/webrtc/MediaEngine.h
@@ -144,17 +144,18 @@ public:
                           TrackID aId,
                           StreamTime aDesiredTime,
                           const PrincipalHandle& aPrincipalHandle) = 0;
 
   /* Stop the device and release the corresponding MediaStream */
   virtual nsresult Stop(SourceMediaStream *aSource, TrackID aID) = 0;
 
   /* Restart with new capability */
-  virtual nsresult Restart(const dom::MediaTrackConstraints& aConstraints,
+  virtual nsresult Restart(BaseAllocationHandle* aHandle,
+                           const dom::MediaTrackConstraints& aConstraints,
                            const MediaEnginePrefs &aPrefs,
                            const nsString& aDeviceId) = 0;
 
   /* Returns true if a source represents a fake capture device and
    * false otherwise
    */
   virtual bool IsFake() = 0;
 
--- a/dom/media/webrtc/MediaEngineCameraVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineCameraVideoSource.cpp
@@ -48,36 +48,33 @@ void
 MediaEngineCameraVideoSource::GetCapability(size_t aIndex,
                                             webrtc::CaptureCapability& aOut)
 {
   MOZ_ASSERT(aIndex < mHardcodedCapabilities.Length());
   aOut = mHardcodedCapabilities[aIndex];
 }
 
 uint32_t
-MediaEngineCameraVideoSource::GetFitnessDistance(const webrtc::CaptureCapability& aCandidate,
-                                                 const MediaTrackConstraintSet &aConstraints,
-                                                 bool aAdvanced,
-                                                 const nsString& aDeviceId)
+MediaEngineCameraVideoSource::GetFitnessDistance(
+    const webrtc::CaptureCapability& aCandidate,
+    const NormalizedConstraintSet &aConstraints,
+    const nsString& aDeviceId)
 {
   // Treat width|height|frameRate == 0 on capability as "can do any".
   // This allows for orthogonal capabilities that are not in discrete steps.
 
   uint64_t distance =
-    uint64_t(FitnessDistance(aDeviceId, aConstraints.mDeviceId, aAdvanced)) +
-    uint64_t(FitnessDistance(mFacingMode, aConstraints.mFacingMode, aAdvanced)) +
+    uint64_t(FitnessDistance(aDeviceId, aConstraints.mDeviceId)) +
+    uint64_t(FitnessDistance(mFacingMode, aConstraints.mFacingMode)) +
     uint64_t(aCandidate.width? FitnessDistance(int32_t(aCandidate.width),
-                                               aConstraints.mWidth,
-                                               aAdvanced) : 0) +
+                                               aConstraints.mWidth) : 0) +
     uint64_t(aCandidate.height? FitnessDistance(int32_t(aCandidate.height),
-                                                aConstraints.mHeight,
-                                                aAdvanced) : 0) +
+                                                aConstraints.mHeight) : 0) +
     uint64_t(aCandidate.maxFPS? FitnessDistance(double(aCandidate.maxFPS),
-                                                aConstraints.mFrameRate,
-                                                aAdvanced) : 0);
+                                                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
 MediaEngineCameraVideoSource::TrimLessFitCandidates(CapabilitySet& set) {
   uint32_t best = UINT32_MAX;
@@ -113,21 +110,22 @@ MediaEngineCameraVideoSource::GetBestFit
 
   CapabilitySet candidateSet;
   for (size_t i = 0; i < num; i++) {
     candidateSet.AppendElement(i);
   }
 
   bool first = true;
   for (const MediaTrackConstraintSet* cs : aConstraintSets) {
+    NormalizedConstraintSet ns(*cs, !first);
     for (size_t i = 0; i < candidateSet.Length();  ) {
       auto& candidate = candidateSet[i];
       webrtc::CaptureCapability cap;
       GetCapability(candidate.mIndex, cap);
-      uint32_t distance = GetFitnessDistance(cap, *cs, !first, aDeviceId);
+      uint32_t distance = GetFitnessDistance(cap, ns, aDeviceId);
       if (distance == UINT32_MAX) {
         candidateSet.RemoveElementAt(i);
       } else {
         ++i;
         if (first) {
           candidate.mDistance = distance;
         }
       }
@@ -138,19 +136,19 @@ MediaEngineCameraVideoSource::GetBestFit
     return UINT32_MAX;
   }
   TrimLessFitCandidates(candidateSet);
   return candidateSet[0].mDistance;
 }
 
 void
 MediaEngineCameraVideoSource::LogConstraints(
-    const MediaTrackConstraintSet& aConstraints, bool aAdvanced)
+    const NormalizedConstraintSet& aConstraints)
 {
-  NormalizedConstraintSet c(aConstraints, aAdvanced);
+  auto& c = aConstraints;
   LOG(((c.mWidth.mIdeal.isSome()?
         "Constraints: width: { min: %d, max: %d, ideal: %d }" :
         "Constraints: width: { min: %d, max: %d }"),
        c.mWidth.mMin, c.mWidth.mMax,
        c.mWidth.mIdeal.valueOr(0)));
   LOG(((c.mHeight.mIdeal.isSome()?
         "             height: { min: %d, max: %d, ideal: %d }" :
         "             height: { min: %d, max: %d }"),
@@ -203,29 +201,29 @@ MediaEngineCameraVideoSource::LogCapabil
                       uint32_t(sizeof(types) / sizeof(*types) - 1))],
        codec[std::min(std::max(uint32_t(0), uint32_t(aCapability.codecType)),
                       uint32_t(sizeof(codec) / sizeof(*codec) - 1))],
        aDistance));
 }
 
 bool
 MediaEngineCameraVideoSource::ChooseCapability(
-    const MediaTrackConstraints &aConstraints,
+    const NormalizedConstraints &aConstraints,
     const MediaEnginePrefs &aPrefs,
     const nsString& aDeviceId)
 {
   if (MOZ_LOG_TEST(GetMediaManagerLog(), LogLevel::Debug)) {
     LOG(("ChooseCapability: prefs: %dx%d @%d-%dfps",
          aPrefs.GetWidth(), aPrefs.GetHeight(),
          aPrefs.mFPS, aPrefs.mMinFPS));
-    LogConstraints(aConstraints, false);
-    if (aConstraints.mAdvanced.WasPassed()) {
-      LOG(("Advanced array[%u]:", aConstraints.mAdvanced.Value().Length()));
-      for (auto& advanced : aConstraints.mAdvanced.Value()) {
-        LogConstraints(advanced, true);
+    LogConstraints(aConstraints);
+    if (aConstraints.mAdvanced.Length()) {
+      LOG(("Advanced array[%u]:", aConstraints.mAdvanced.Length()));
+      for (auto& advanced : aConstraints.mAdvanced) {
+        LogConstraints(advanced);
       }
     }
   }
 
   size_t num = NumCapabilities();
 
   CapabilitySet candidateSet;
   for (size_t i = 0; i < num; i++) {
@@ -233,44 +231,42 @@ MediaEngineCameraVideoSource::ChooseCapa
   }
 
   // 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, false, aDeviceId);
+    candidate.mDistance = GetFitnessDistance(cap, aConstraints, aDeviceId);
     LogCapability("Capability", cap, candidate.mDistance);
     if (candidate.mDistance == UINT32_MAX) {
       candidateSet.RemoveElementAt(i);
     } else {
       ++i;
     }
   }
 
   // Filter further with all advanced constraints (that don't overconstrain).
 
-  if (aConstraints.mAdvanced.WasPassed()) {
-    for (const MediaTrackConstraintSet &cs : aConstraints.mAdvanced.Value()) {
-      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, true, aDeviceId) == UINT32_MAX) {
-          rejects.AppendElement(candidate);
-          candidateSet.RemoveElementAt(i);
-        } else {
-          ++i;
-        }
+  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) {
+        rejects.AppendElement(candidate);
+        candidateSet.RemoveElementAt(i);
+      } else {
+        ++i;
       }
-      if (!candidateSet.Length()) {
-        candidateSet.AppendElements(Move(rejects));
-      }
+    }
+    if (!candidateSet.Length()) {
+      candidateSet.AppendElements(Move(rejects));
     }
   }
   if (!candidateSet.Length()) {
     LOG(("failed to find capability match from %d choices",num));
     return false;
   }
 
   // Remaining algorithm is up to the UA.
@@ -280,21 +276,22 @@ MediaEngineCameraVideoSource::ChooseCapa
   // Any remaining multiples all have the same distance. A common case of this
   // occurs when no ideal is specified. Lean toward defaults.
   uint32_t sameDistance = candidateSet[0].mDistance;
   {
     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, prefs, false, aDeviceId);
+      candidate.mDistance = GetFitnessDistance(cap, 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.
 
--- a/dom/media/webrtc/MediaEngineCameraVideoSource.h
+++ b/dom/media/webrtc/MediaEngineCameraVideoSource.h
@@ -68,30 +68,28 @@ protected:
 
   // guts for appending data to the MSG track
   virtual bool AppendToTrack(SourceMediaStream* aSource,
                              layers::Image* aImage,
                              TrackID aID,
                              StreamTime delta,
                              const PrincipalHandle& aPrincipalHandle);
   uint32_t GetFitnessDistance(const webrtc::CaptureCapability& aCandidate,
-                              const dom::MediaTrackConstraintSet &aConstraints,
-                              bool aAdvanced,
+                              const NormalizedConstraintSet &aConstraints,
                               const nsString& aDeviceId);
   static void TrimLessFitCandidates(CapabilitySet& set);
-  static void LogConstraints(const dom::MediaTrackConstraintSet& aConstraints,
-                             bool aAdvanced);
+  static void LogConstraints(const NormalizedConstraintSet& aConstraints);
   static void LogCapability(const char* aHeader,
                             const webrtc::CaptureCapability &aCapability,
                             uint32_t aDistance);
   virtual size_t NumCapabilities();
   virtual void GetCapability(size_t aIndex, webrtc::CaptureCapability& aOut);
-  virtual bool ChooseCapability(const dom::MediaTrackConstraints &aConstraints,
-                        const MediaEnginePrefs &aPrefs,
-                        const nsString& aDeviceId);
+  virtual bool ChooseCapability(const NormalizedConstraints &aConstraints,
+                                const MediaEnginePrefs &aPrefs,
+                                const nsString& aDeviceId);
   void SetName(nsString aName);
   void SetUUID(const char* aUUID);
   const nsCString& GetUUID(); // protected access
 
   // Engine variables.
 
   // mMonitor protects mImage access/changes, and transitions of mState
   // from kStarted to kStopped (which are combined with EndTrack() and
--- a/dom/media/webrtc/MediaEngineDefault.cpp
+++ b/dom/media/webrtc/MediaEngineDefault.cpp
@@ -212,19 +212,21 @@ MediaEngineDefaultVideoSource::Stop(Sour
   }
 
   mState = kStopped;
   mImage = nullptr;
   return NS_OK;
 }
 
 nsresult
-MediaEngineDefaultVideoSource::Restart(const dom::MediaTrackConstraints& aConstraints,
-                                       const MediaEnginePrefs &aPrefs,
-                                       const nsString& aDeviceId)
+MediaEngineDefaultVideoSource::Restart(
+    BaseAllocationHandle* aHandle,
+    const dom::MediaTrackConstraints& aConstraints,
+    const MediaEnginePrefs &aPrefs,
+    const nsString& aDeviceId)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MediaEngineDefaultVideoSource::Notify(nsITimer* aTimer)
 {
   // Update the target color
@@ -520,17 +522,18 @@ MediaEngineDefaultAudioSource::Stop(Sour
     }
   }
 
   mState = kStopped;
   return NS_OK;
 }
 
 nsresult
-MediaEngineDefaultAudioSource::Restart(const dom::MediaTrackConstraints& aConstraints,
+MediaEngineDefaultAudioSource::Restart(BaseAllocationHandle* aHandle,
+                                       const dom::MediaTrackConstraints& aConstraints,
                                        const MediaEnginePrefs &aPrefs,
                                        const nsString& aDeviceId)
 {
   return NS_OK;
 }
 
 void
 MediaEngineDefaultAudioSource::AppendToSegment(AudioSegment& aSegment,
--- a/dom/media/webrtc/MediaEngineDefault.h
+++ b/dom/media/webrtc/MediaEngineDefault.h
@@ -47,17 +47,18 @@ public:
   nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
                     const MediaEnginePrefs &aPrefs,
                     const nsString& aDeviceId,
                     const nsACString& aOrigin,
                     BaseAllocationHandle** aOutHandle) override;
   nsresult Deallocate(BaseAllocationHandle* aHandle) override;
   nsresult Start(SourceMediaStream*, TrackID, const PrincipalHandle&) override;
   nsresult Stop(SourceMediaStream*, TrackID) override;
-  nsresult Restart(const dom::MediaTrackConstraints& aConstraints,
+  nsresult Restart(BaseAllocationHandle* aHandle,
+                   const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
                    const nsString& aDeviceId) override;
   void SetDirectListeners(bool aHasDirectListeners) override {};
   void NotifyPull(MediaStreamGraph* aGraph,
                   SourceMediaStream *aSource,
                   TrackID aId,
                   StreamTime aDesiredTime,
                   const PrincipalHandle& aPrincipalHandle) override;
@@ -119,17 +120,18 @@ public:
   nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
                     const MediaEnginePrefs &aPrefs,
                     const nsString& aDeviceId,
                     const nsACString& aOrigin,
                     BaseAllocationHandle** aOutHandle) override;
   nsresult Deallocate(BaseAllocationHandle* aHandle) override;
   nsresult Start(SourceMediaStream*, TrackID, const PrincipalHandle&) override;
   nsresult Stop(SourceMediaStream*, TrackID) override;
-  nsresult Restart(const dom::MediaTrackConstraints& aConstraints,
+  nsresult Restart(BaseAllocationHandle* aHandle,
+                   const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
                    const nsString& aDeviceId) override;
   void SetDirectListeners(bool aHasDirectListeners) override {};
   void AppendToSegment(AudioSegment& aSegment,
                        TrackTicks aSamples);
   void NotifyPull(MediaStreamGraph* aGraph,
                   SourceMediaStream *aSource,
                   TrackID aId,
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -115,17 +115,17 @@ MediaEngineRemoteVideoSource::Allocate(
 
   RefPtr<AllocationHandle> handle = new AllocationHandle(aConstraints);
   mRegisteredHandles.AppendElement(handle);
 
   if (mState == kReleased) {
     // Note: if shared, we don't allow a later opener to affect the resolution.
     // (This may change depending on spec changes for Constraints/settings)
 
-    if (!ChooseCapability(aConstraints, aPrefs, aDeviceId)) {
+    if (!ChooseCapability(handle->mConstraints, aPrefs, aDeviceId)) {
       return NS_ERROR_UNEXPECTED;
     }
 
     if (mozilla::camera::GetChildAndCall(
       &mozilla::camera::CamerasChild::AllocateCaptureDevice,
       mCapEngine, GetUUID().get(), kMaxUniqueIdLength, mCaptureIndex, aOrigin)) {
       return NS_ERROR_FAILURE;
     }
@@ -259,26 +259,30 @@ MediaEngineRemoteVideoSource::Stop(mozil
   mozilla::camera::GetChildAndCall(
     &mozilla::camera::CamerasChild::StopCapture,
     mCapEngine, mCaptureIndex);
 
   return NS_OK;
 }
 
 nsresult
-MediaEngineRemoteVideoSource::Restart(const dom::MediaTrackConstraints& aConstraints,
+MediaEngineRemoteVideoSource::Restart(BaseAllocationHandle* aHandle,
+                                      const dom::MediaTrackConstraints& aConstraints,
                                       const MediaEnginePrefs& aPrefs,
                                       const nsString& aDeviceId)
 {
   AssertIsOnOwningThread();
   if (!mInitDone) {
     LOG(("Init not done"));
     return NS_ERROR_FAILURE;
   }
-  if (!ChooseCapability(aConstraints, aPrefs, aDeviceId)) {
+  MOZ_ASSERT(aHandle);
+  auto handle = static_cast<AllocationHandle*>(aHandle);
+  handle->mConstraints = NormalizedConstraints(aConstraints);
+  if (!ChooseCapability(handle->mConstraints, aPrefs, aDeviceId)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   if (mState != kStarted) {
     return NS_OK;
   }
 
   mozilla::camera::GetChildAndCall(
     &mozilla::camera::CamerasChild::StopCapture,
@@ -432,17 +436,18 @@ MediaEngineRemoteVideoSource::NumCapabil
     mHardcodedCapabilities.AppendElement(c);
     break;
   }
 
   return mHardcodedCapabilities.Length();
 }
 
 bool
-MediaEngineRemoteVideoSource::ChooseCapability(const MediaTrackConstraints &aConstraints,
+MediaEngineRemoteVideoSource::ChooseCapability(
+    const NormalizedConstraints &aConstraints,
     const MediaEnginePrefs &aPrefs,
     const nsString& aDeviceId)
 {
   AssertIsOnOwningThread();
 
   switch(mMediaSource) {
     case dom::MediaSourceEnum::Screen:
     case dom::MediaSourceEnum::Window:
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.h
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.h
@@ -82,32 +82,33 @@ public:
     NormalizedConstraints mConstraints;
   };
 
   nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
                     const MediaEnginePrefs& aPrefs,
                     const nsString& aDeviceId,
                     const nsACString& aOrigin,
                     BaseAllocationHandle** aOutHandle) override;
-  nsresult Deallocate(BaseAllocationHandle* aHandle) override;;
+  nsresult Deallocate(BaseAllocationHandle* aHandle) override;
   nsresult Start(SourceMediaStream*, TrackID, const PrincipalHandle&) override;
   nsresult Stop(SourceMediaStream*, TrackID) override;
-  nsresult Restart(const dom::MediaTrackConstraints& aConstraints,
+  nsresult Restart(BaseAllocationHandle* aHandle,
+                   const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
                    const nsString& aDeviceId) override;
   void NotifyPull(MediaStreamGraph* aGraph,
                   SourceMediaStream* aSource,
                   TrackID aId,
                   StreamTime aDesiredTime,
                   const PrincipalHandle& aPrincipalHandle) override;
   dom::MediaSourceEnum GetMediaSource() const override {
     return mMediaSource;
   }
 
-  bool ChooseCapability(const dom::MediaTrackConstraints &aConstraints,
+  bool ChooseCapability(const NormalizedConstraints &aConstraints,
                         const MediaEnginePrefs &aPrefs,
                         const nsString& aDeviceId) override;
 
   void Refresh(int aIndex);
 
   void Shutdown() override;
 
 protected:
--- a/dom/media/webrtc/MediaEngineTabVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.cpp
@@ -143,24 +143,27 @@ MediaEngineTabVideoSource::Allocate(cons
                                     BaseAllocationHandle** aOutHandle)
 {
   // windowId is not a proper constraint, so just read it.
   // It has no well-defined behavior in advanced, so ignore it there.
 
   mWindowId = aConstraints.mBrowserWindow.WasPassed() ?
               aConstraints.mBrowserWindow.Value() : -1;
   aOutHandle = nullptr;
-  return Restart(aConstraints, aPrefs, aDeviceId);
+  return Restart(nullptr, aConstraints, aPrefs, aDeviceId);
 }
 
 nsresult
-MediaEngineTabVideoSource::Restart(const dom::MediaTrackConstraints& aConstraints,
+MediaEngineTabVideoSource::Restart(BaseAllocationHandle* aHandle,
+                                   const dom::MediaTrackConstraints& aConstraints,
                                    const mozilla::MediaEnginePrefs& aPrefs,
                                    const nsString& aDeviceId)
 {
+  MOZ_ASSERT(!aHandle);
+
   // scrollWithPage is not proper a constraint, so just read it.
   // It has no well-defined behavior in advanced, so ignore it there.
 
   mScrollWithPage = aConstraints.mScrollWithPage.WasPassed() ?
                     aConstraints.mScrollWithPage.Value() : false;
 
   FlattenedConstraints c(aConstraints);
 
--- a/dom/media/webrtc/MediaEngineTabVideoSource.h
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.h
@@ -27,17 +27,18 @@ class MediaEngineTabVideoSource : public
                       const nsString& aDeviceId,
                       const nsACString& aOrigin,
                       BaseAllocationHandle** aOutHandle) override;
     nsresult Deallocate(BaseAllocationHandle* aHandle) override;
     nsresult Start(mozilla::SourceMediaStream*, mozilla::TrackID, const mozilla::PrincipalHandle&) override;
     void SetDirectListeners(bool aHasDirectListeners) override {};
     void NotifyPull(mozilla::MediaStreamGraph*, mozilla::SourceMediaStream*, mozilla::TrackID, mozilla::StreamTime, const mozilla::PrincipalHandle& aPrincipalHandle) override;
     nsresult Stop(mozilla::SourceMediaStream*, mozilla::TrackID) override;
-    nsresult Restart(const dom::MediaTrackConstraints& aConstraints,
+    nsresult Restart(BaseAllocationHandle* aHandle,
+                     const dom::MediaTrackConstraints& aConstraints,
                      const mozilla::MediaEnginePrefs& aPrefs,
                      const nsString& aDeviceId) override;
     bool IsFake() override;
     dom::MediaSourceEnum GetMediaSource() const override {
       return dom::MediaSourceEnum::Browser;
     }
     uint32_t GetBestFitnessDistance(
       const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets,
--- a/dom/media/webrtc/MediaEngineWebRTC.h
+++ b/dom/media/webrtc/MediaEngineWebRTC.h
@@ -93,17 +93,18 @@ public:
   void Shutdown() override
   {
     // Nothing to do here, everything is managed in MediaManager.cpp
   }
   nsresult Start(SourceMediaStream* aMediaStream,
                  TrackID aId,
                  const PrincipalHandle& aPrincipalHandle) override;
   nsresult Stop(SourceMediaStream* aMediaStream, TrackID aId) override;
-  nsresult Restart(const dom::MediaTrackConstraints& aConstraints,
+  nsresult Restart(BaseAllocationHandle* aHandle,
+                   const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
                    const nsString& aDeviceId) override;
   void SetDirectListeners(bool aDirect) override
   {}
   void NotifyOutputData(MediaStreamGraph* aGraph,
                         AudioDataValue* aBuffer, size_t aFrames,
                         TrackRate aRate, uint32_t aChannels) override
   {}
@@ -456,17 +457,18 @@ public:
                     const nsString& aDeviceId,
                     const nsACString& aOrigin,
                     BaseAllocationHandle** aOutHandle) override;
   nsresult Deallocate(BaseAllocationHandle* aHandle) override;
   nsresult Start(SourceMediaStream* aStream,
                  TrackID aID,
                  const PrincipalHandle& aPrincipalHandle) override;
   nsresult Stop(SourceMediaStream* aSource, TrackID aID) override;
-  nsresult Restart(const dom::MediaTrackConstraints& aConstraints,
+  nsresult Restart(BaseAllocationHandle* aHandle,
+                   const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
                    const nsString& aDeviceId) override;
   void SetDirectListeners(bool aHasDirectListeners) override {};
 
   void NotifyPull(MediaStreamGraph* aGraph,
                   SourceMediaStream* aSource,
                   TrackID aId,
                   StreamTime aDesiredTime,
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -255,24 +255,26 @@ MediaEngineWebRTCMicrophoneSource::Alloc
     if (mSources.IsEmpty()) {
       LOG(("Audio device %d reallocated", mCapIndex));
     } else {
       LOG(("Audio device %d allocated shared", mCapIndex));
     }
   }
   ++mNrAllocations;
   aOutHandle = nullptr;
-  return Restart(aConstraints, aPrefs, aDeviceId);
+  return Restart(nullptr, aConstraints, aPrefs, aDeviceId);
 }
 
 nsresult
-MediaEngineWebRTCMicrophoneSource::Restart(const dom::MediaTrackConstraints& aConstraints,
+MediaEngineWebRTCMicrophoneSource::Restart(BaseAllocationHandle* aHandle,
+                                           const dom::MediaTrackConstraints& aConstraints,
                                            const MediaEnginePrefs &aPrefs,
                                            const nsString& aDeviceId)
 {
+  MOZ_ASSERT(!aHandle);
   FlattenedConstraints c(aConstraints);
 
   bool aec_on = c.mEchoCancellation.Get(aPrefs.mAecOn);
   bool agc_on = c.mMozAutoGainControl.Get(aPrefs.mAgcOn);
   bool noise_on = c.mMozNoiseSuppression.Get(aPrefs.mNoiseOn);
 
   LOG(("Audio config: aec: %d, agc: %d, noise: %d, delay: %d",
        aec_on ? aPrefs.mAec : -1,
@@ -838,20 +840,22 @@ MediaEngineWebRTCAudioCaptureSource::Sto
 {
   AssertIsOnOwningThread();
   aMediaStream->EndAllTrackAndFinish();
   return NS_OK;
 }
 
 nsresult
 MediaEngineWebRTCAudioCaptureSource::Restart(
+    BaseAllocationHandle* aHandle,
     const dom::MediaTrackConstraints& aConstraints,
     const MediaEnginePrefs &aPrefs,
     const nsString& aDeviceId)
 {
+  MOZ_ASSERT(!aHandle);
   return NS_OK;
 }
 
 uint32_t
 MediaEngineWebRTCAudioCaptureSource::GetBestFitnessDistance(
     const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets,
     const nsString& aDeviceId)
 {
--- a/dom/media/webrtc/MediaTrackConstraints.cpp
+++ b/dom/media/webrtc/MediaTrackConstraints.cpp
@@ -224,119 +224,45 @@ FlattenedConstraints::FlattenedConstrain
 // If you have no other constraints, use this one. Reused by all device types.
 
 uint32_t
 MediaConstraintsHelper::GetMinimumFitnessDistance(
     const dom::MediaTrackConstraintSet &aConstraints,
     bool aAdvanced,
     const nsString& aDeviceId)
 {
-  uint64_t distance =
-    uint64_t(FitnessDistance(aDeviceId, aConstraints.mDeviceId, aAdvanced));
-
-  // This function is modeled on MediaEngineCameraVideoSource::GetFitnessDistance
-  // and will make more sense once more audio constraints are added.
-
-  return uint32_t(std::min(distance, uint64_t(UINT32_MAX)));
-}
+  NormalizedConstraintSet ns(aConstraints, aAdvanced);
 
-template<class ValueType, class ConstrainRange>
-/* static */ uint32_t
-MediaConstraintsHelper::FitnessDistance(ValueType aN,
-                                        const ConstrainRange& aRange)
-{
-  if ((aRange.mExact.WasPassed() && aRange.mExact.Value() != aN) ||
-      (aRange.mMin.WasPassed() && aRange.mMin.Value() > aN) ||
-      (aRange.mMax.WasPassed() && aRange.mMax.Value() < aN)) {
-    return UINT32_MAX;
-  }
-  if (!aRange.mIdeal.WasPassed() || aN == aRange.mIdeal.Value()) {
-    return 0;
-  }
-  return uint32_t(ValueType((std::abs(aN - aRange.mIdeal.Value()) * 1000) /
-                            std::max(std::abs(aN), std::abs(aRange.mIdeal.Value()))));
+  return FitnessDistance(aDeviceId, ns.mDeviceId);
 }
 
-// Binding code doesn't templatize well...
-
-/*static*/ uint32_t
-MediaConstraintsHelper::FitnessDistance(int32_t aN,
-    const OwningLongOrConstrainLongRange& aConstraint, bool aAdvanced)
+template<class ValueType, class NormalizedRange>
+/* static */ uint32_t
+MediaConstraintsHelper::FitnessDistance(ValueType aN,
+                                        const NormalizedRange& aRange)
 {
-  if (aConstraint.IsLong()) {
-    ConstrainLongRange range;
-    (aAdvanced ? range.mExact : range.mIdeal).Construct(aConstraint.GetAsLong());
-    return FitnessDistance(aN, range);
-  } else {
-    return FitnessDistance(aN, aConstraint.GetAsConstrainLongRange());
+  if (aRange.mMin > aN || aRange.mMax < aN) {
+    return UINT32_MAX;
   }
-}
-
-/*static*/ uint32_t
-MediaConstraintsHelper::FitnessDistance(double aN,
-    const OwningDoubleOrConstrainDoubleRange& aConstraint,
-    bool aAdvanced)
-{
-  if (aConstraint.IsDouble()) {
-    ConstrainDoubleRange range;
-    (aAdvanced ? range.mExact : range.mIdeal).Construct(aConstraint.GetAsDouble());
-    return FitnessDistance(aN, range);
-  } else {
-    return FitnessDistance(aN, aConstraint.GetAsConstrainDoubleRange());
+  if (aN == aRange.mIdeal.valueOr(aN)) {
+    return 0;
   }
+  return uint32_t(ValueType((std::abs(aN - aRange.mIdeal.value()) * 1000) /
+                            std::max(std::abs(aN), std::abs(aRange.mIdeal.value()))));
 }
 
 // Fitness distance returned as integer math * 1000. Infinity = UINT32_MAX
 
 /* static */ uint32_t
-MediaConstraintsHelper::FitnessDistance(nsString aN,
-                             const ConstrainDOMStringParameters& aParams)
+MediaConstraintsHelper::FitnessDistance(
+    nsString aN,
+    const NormalizedConstraintSet::StringRange& aParams)
 {
-  struct Func
-  {
-    static bool
-    Contains(const OwningStringOrStringSequence& aStrings, nsString aN)
-    {
-      return aStrings.IsString() ? aStrings.GetAsString() == aN
-                                 : aStrings.GetAsStringSequence().Contains(aN);
-    }
-  };
-
-  if (aParams.mExact.WasPassed() && !Func::Contains(aParams.mExact.Value(), aN)) {
+  if (aParams.mExact.size() && aParams.mExact.find(aN) == aParams.mExact.end()) {
     return UINT32_MAX;
   }
-  if (aParams.mIdeal.WasPassed() && !Func::Contains(aParams.mIdeal.Value(), aN)) {
+  if (aParams.mIdeal.size() && aParams.mIdeal.find(aN) == aParams.mIdeal.end()) {
     return 1000;
   }
   return 0;
 }
 
-/* static */ uint32_t
-MediaConstraintsHelper::FitnessDistance(nsString aN,
-    const OwningStringOrStringSequenceOrConstrainDOMStringParameters& aConstraint,
-    bool aAdvanced)
-{
-  if (aConstraint.IsString()) {
-    ConstrainDOMStringParameters params;
-    if (aAdvanced) {
-      params.mExact.Construct();
-      params.mExact.Value().SetAsString() = aConstraint.GetAsString();
-    } else {
-      params.mIdeal.Construct();
-      params.mIdeal.Value().SetAsString() = aConstraint.GetAsString();
-    }
-    return FitnessDistance(aN, params);
-  } else if (aConstraint.IsStringSequence()) {
-    ConstrainDOMStringParameters params;
-    if (aAdvanced) {
-      params.mExact.Construct();
-      params.mExact.Value().SetAsStringSequence() = aConstraint.GetAsStringSequence();
-    } else {
-      params.mIdeal.Construct();
-      params.mIdeal.Value().SetAsStringSequence() = aConstraint.GetAsStringSequence();
-    }
-    return FitnessDistance(aN, params);
-  } else {
-    return FitnessDistance(aN, aConstraint.GetAsConstrainDOMStringParameters());
-  }
 }
-
-}
--- a/dom/media/webrtc/MediaTrackConstraints.h
+++ b/dom/media/webrtc/MediaTrackConstraints.h
@@ -145,27 +145,20 @@ struct FlattenedConstraints : public Nor
     : FlattenedConstraints(NormalizedConstraints(aOther)) {}
 };
 
 // A helper class for MediaEngines
 
 class MediaConstraintsHelper
 {
 protected:
-  template<class ValueType, class ConstrainRange>
-  static uint32_t FitnessDistance(ValueType aN, const ConstrainRange& aRange);
-  static uint32_t FitnessDistance(int32_t aN,
-      const dom::OwningLongOrConstrainLongRange& aConstraint, bool aAdvanced);
-  static uint32_t FitnessDistance(double aN,
-      const dom::OwningDoubleOrConstrainDoubleRange& aConstraint, bool aAdvanced);
+  template<class ValueType, class NormalizedRange>
+  static uint32_t FitnessDistance(ValueType aN, const NormalizedRange& aRange);
   static uint32_t FitnessDistance(nsString aN,
-    const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters& aConstraint,
-    bool aAdvanced);
-  static uint32_t FitnessDistance(nsString aN,
-      const dom::ConstrainDOMStringParameters& aParams);
+      const NormalizedConstraintSet::StringRange& aConstraint);
 
   static uint32_t
   GetMinimumFitnessDistance(const dom::MediaTrackConstraintSet &aConstraints,
                             bool aAdvanced,
                             const nsString& aDeviceId);
 
   template<class DeviceType>
   static bool