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 347514 c613c94abee0d5b6344313640f4e0497a6ab54b8
parent 347513 84fb1be97595f6fdccbc49d8c3ec8d7b34bef37c
child 347515 cfc68e9868d99ccafbaf900792856eb6fb573a8d
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs1213517
milestone50.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 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