Backed out changeset e4829b553f9e (bug 1213517)
authorIris Hsiao <ihsiao@mozilla.com>
Mon, 18 Jul 2016 15:40:20 +0800
changeset 347388 75e965332b72f80457cf2f69ae44658a30b61a7b
parent 347387 1adb5905697d107fab50193ca93ecf340e72349d
child 347389 f925108ff4d308487c870d196d7f4cf98dbbcde8
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)
bugs1213517
milestone50.0a1
backs oute4829b553f9e1bd78246476942bcedfad3011d16
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
Backed out changeset e4829b553f9e (bug 1213517)
dom/media/MediaManager.cpp
dom/media/MediaManager.h
dom/media/webrtc/MediaEngine.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
@@ -883,28 +883,24 @@ VideoDevice::GetSource()
 AudioDevice::Source*
 AudioDevice::GetSource()
 {
   return static_cast<Source*>(&*mSource);
 }
 
 nsresult MediaDevice::Allocate(const dom::MediaTrackConstraints &aConstraints,
                                const MediaEnginePrefs &aPrefs,
-                               const nsACString& aOrigin,
-                               const char** aOutBadConstraint) {
+                               const nsACString& aOrigin) {
   return GetSource()->Allocate(aConstraints, aPrefs, mID, aOrigin,
-                               getter_AddRefs(mAllocationHandle),
-                               aOutBadConstraint);
+                               getter_AddRefs(mAllocationHandle));
 }
 
 nsresult MediaDevice::Restart(const dom::MediaTrackConstraints &aConstraints,
-                              const MediaEnginePrefs &aPrefs,
-                              const char** aOutBadConstraint) {
-  return GetSource()->Restart(mAllocationHandle, aConstraints, aPrefs, mID,
-                              aOutBadConstraint);
+                              const MediaEnginePrefs &aPrefs) {
+  return GetSource()->Restart(mAllocationHandle, aConstraints, aPrefs, mID);
 }
 
 nsresult MediaDevice::Deallocate() {
   return GetSource()->Deallocate(mAllocationHandle);
 }
 
 void
 MediaOperationTask::ReturnCallbackError(nsresult rv, const char* errorLog)
@@ -1427,33 +1423,33 @@ public:
     // a GetUserMediaStreamRunnable.
 
     nsresult rv;
     const char* errorMsg = nullptr;
     const char* badConstraint = nullptr;
 
     if (mAudioDevice) {
       auto& constraints = GetInvariant(mConstraints.mAudio);
-      rv = mAudioDevice->Allocate(constraints, mPrefs, mOrigin, &badConstraint);
+      rv = mAudioDevice->Allocate(constraints, mPrefs, mOrigin);
       if (NS_FAILED(rv)) {
         errorMsg = "Failed to allocate audiosource";
-        if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) {
+        if (rv == NS_ERROR_NOT_AVAILABLE) {
           nsTArray<RefPtr<AudioDevice>> audios;
           audios.AppendElement(mAudioDevice);
           badConstraint = MediaConstraintsHelper::SelectSettings(constraints,
                                                                  audios);
         }
       }
     }
     if (!errorMsg && mVideoDevice) {
       auto& constraints = GetInvariant(mConstraints.mVideo);
-      rv = mVideoDevice->Allocate(constraints, mPrefs, mOrigin, &badConstraint);
+      rv = mVideoDevice->Allocate(constraints, mPrefs, mOrigin);
       if (NS_FAILED(rv)) {
         errorMsg = "Failed to allocate videosource";
-        if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) {
+        if (rv == NS_ERROR_NOT_AVAILABLE) {
           nsTArray<RefPtr<VideoDevice>> videos;
           videos.AppendElement(mVideoDevice);
           badConstraint = MediaConstraintsHelper::SelectSettings(constraints,
                                                                  videos);
         }
         if (mAudioDevice) {
           mAudioDevice->Deallocate();
         }
@@ -3434,26 +3430,26 @@ GetUserMediaCallbackMediaStreamListener:
                                       audioDevice, videoDevice,
                                       aConstraints]() mutable {
     MOZ_ASSERT(MediaManager::IsInMediaThread());
     RefPtr<MediaManager> mgr = MediaManager::GetInstance();
     const char* badConstraint = nullptr;
     nsresult rv = NS_OK;
 
     if (audioDevice) {
-      rv = audioDevice->Restart(aConstraints, mgr->mPrefs, &badConstraint);
-      if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) {
+      rv = audioDevice->Restart(aConstraints, mgr->mPrefs);
+      if (rv == NS_ERROR_NOT_AVAILABLE) {
         nsTArray<RefPtr<AudioDevice>> audios;
         audios.AppendElement(audioDevice);
         badConstraint = MediaConstraintsHelper::SelectSettings(aConstraints,
                                                                audios);
       }
     } else {
-      rv = videoDevice->Restart(aConstraints, mgr->mPrefs, &badConstraint);
-      if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) {
+      rv = videoDevice->Restart(aConstraints, mgr->mPrefs);
+      if (rv == NS_ERROR_NOT_AVAILABLE) {
         nsTArray<RefPtr<VideoDevice>> videos;
         videos.AppendElement(videoDevice);
         badConstraint = MediaConstraintsHelper::SelectSettings(aConstraints,
                                                                videos);
       }
     }
     NS_DispatchToMainThread(NewRunnableFrom([id, windowId, rv,
                                              badConstraint]() mutable {
--- a/dom/media/MediaManager.h
+++ b/dom/media/MediaManager.h
@@ -69,21 +69,19 @@ public:
   NS_DECL_NSIMEDIADEVICE
 
   void SetId(const nsAString& aID);
   virtual uint32_t GetBestFitnessDistance(
       const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets);
   virtual Source* GetSource() = 0;
   nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
                     const MediaEnginePrefs &aPrefs,
-                    const nsACString& aOrigin,
-                    const char** aOutBadConstraint);
+                    const nsACString& aOrigin);
   nsresult Restart(const dom::MediaTrackConstraints &aConstraints,
-                   const MediaEnginePrefs &aPrefs,
-                   const char** aOutBadConstraint);
+                   const MediaEnginePrefs &aPrefs);
   nsresult Deallocate();
 protected:
   virtual ~MediaDevice() {}
   explicit MediaDevice(MediaEngineSource* aSource, bool aIsVideo);
 
   static uint32_t FitnessDistance(nsString aN,
     const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters& aConstraint);
 private:
--- a/dom/media/webrtc/MediaEngine.h
+++ b/dom/media/webrtc/MediaEngine.h
@@ -147,18 +147,17 @@ public:
 
   /* Stop the device and release the corresponding MediaStream */
   virtual nsresult Stop(SourceMediaStream *aSource, TrackID aID) = 0;
 
   /* Restart with new capability */
   virtual nsresult Restart(BaseAllocationHandle* aHandle,
                            const dom::MediaTrackConstraints& aConstraints,
                            const MediaEnginePrefs &aPrefs,
-                           const nsString& aDeviceId,
-                           const char** aOutBadConstraint) = 0;
+                           const nsString& aDeviceId) = 0;
 
   /* Returns true if a source represents a fake capture device and
    * false otherwise
    */
   virtual bool IsFake() = 0;
 
   /* Returns the type of media source (camera, microphone, screen, window, etc) */
   virtual dom::MediaSourceEnum GetMediaSource() const = 0;
@@ -185,18 +184,17 @@ public:
     mHasFakeTracks = aHasFakeTracks;
   }
 
   /* This call reserves but does not start the device. */
   virtual nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
                             const MediaEnginePrefs &aPrefs,
                             const nsString& aDeviceId,
                             const nsACString& aOrigin,
-                            BaseAllocationHandle** aOutHandle,
-                            const char** aOutBadConstraint) = 0;
+                            BaseAllocationHandle** aOutHandle) = 0;
 
   virtual uint32_t GetBestFitnessDistance(
       const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets,
       const nsString& aDeviceId) = 0;
 
 protected:
   // Only class' own members can be initialized in constructor initializer list.
   explicit MediaEngineSource(MediaEngineState aState)
--- a/dom/media/webrtc/MediaEngineDefault.cpp
+++ b/dom/media/webrtc/MediaEngineDefault.cpp
@@ -85,18 +85,17 @@ MediaEngineDefaultVideoSource::GetBestFi
   return distance;
 }
 
 nsresult
 MediaEngineDefaultVideoSource::Allocate(const dom::MediaTrackConstraints &aConstraints,
                                         const MediaEnginePrefs &aPrefs,
                                         const nsString& aDeviceId,
                                         const nsACString& aOrigin,
-                                        BaseAllocationHandle** aOutHandle,
-                                        const char** aOutBadConstraint)
+                                        BaseAllocationHandle** aOutHandle)
 {
   if (mState != kReleased) {
     return NS_ERROR_FAILURE;
   }
 
   // Mock failure for automated tests.
   if (aConstraints.mDeviceId.IsString() &&
       aConstraints.mDeviceId.GetAsString().EqualsASCII("bad device")) {
@@ -217,18 +216,17 @@ MediaEngineDefaultVideoSource::Stop(Sour
   return NS_OK;
 }
 
 nsresult
 MediaEngineDefaultVideoSource::Restart(
     BaseAllocationHandle* aHandle,
     const dom::MediaTrackConstraints& aConstraints,
     const MediaEnginePrefs &aPrefs,
-    const nsString& aDeviceId,
-    const char** aOutBadConstraint)
+    const nsString& aDeviceId)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 MediaEngineDefaultVideoSource::Notify(nsITimer* aTimer)
 {
   // Update the target color
@@ -413,18 +411,17 @@ MediaEngineDefaultAudioSource::GetBestFi
   return distance;
 }
 
 nsresult
 MediaEngineDefaultAudioSource::Allocate(const dom::MediaTrackConstraints &aConstraints,
                                         const MediaEnginePrefs &aPrefs,
                                         const nsString& aDeviceId,
                                         const nsACString& aOrigin,
-                                        BaseAllocationHandle** aOutHandle,
-                                        const char** aOutBadConstraint)
+                                        BaseAllocationHandle** aOutHandle)
 {
   if (mState != kReleased) {
     return NS_ERROR_FAILURE;
   }
 
   // Mock failure for automated tests.
   if (aConstraints.mDeviceId.IsString() &&
       aConstraints.mDeviceId.GetAsString().EqualsASCII("bad device")) {
@@ -528,18 +525,17 @@ MediaEngineDefaultAudioSource::Stop(Sour
   mState = kStopped;
   return NS_OK;
 }
 
 nsresult
 MediaEngineDefaultAudioSource::Restart(BaseAllocationHandle* aHandle,
                                        const dom::MediaTrackConstraints& aConstraints,
                                        const MediaEnginePrefs &aPrefs,
-                                       const nsString& aDeviceId,
-                                       const char** aOutBadConstraint)
+                                       const nsString& aDeviceId)
 {
   return NS_OK;
 }
 
 void
 MediaEngineDefaultAudioSource::AppendToSegment(AudioSegment& aSegment,
                                                TrackTicks aSamples)
 {
--- a/dom/media/webrtc/MediaEngineDefault.h
+++ b/dom/media/webrtc/MediaEngineDefault.h
@@ -43,26 +43,24 @@ public:
 
   void GetName(nsAString&) override;
   void GetUUID(nsACString&) override;
 
   nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
                     const MediaEnginePrefs &aPrefs,
                     const nsString& aDeviceId,
                     const nsACString& aOrigin,
-                    BaseAllocationHandle** aOutHandle,
-                    const char** aOutBadConstraint) override;
+                    BaseAllocationHandle** aOutHandle) override;
   nsresult Deallocate(BaseAllocationHandle* aHandle) override;
   nsresult Start(SourceMediaStream*, TrackID, const PrincipalHandle&) override;
   nsresult Stop(SourceMediaStream*, TrackID) override;
   nsresult Restart(BaseAllocationHandle* aHandle,
                    const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
-                   const nsString& aDeviceId,
-                   const char** aOutBadConstraint) override;
+                   const nsString& aDeviceId) override;
   void SetDirectListeners(bool aHasDirectListeners) override {};
   void NotifyPull(MediaStreamGraph* aGraph,
                   SourceMediaStream *aSource,
                   TrackID aId,
                   StreamTime aDesiredTime,
                   const PrincipalHandle& aPrincipalHandle) override;
   uint32_t GetBestFitnessDistance(
       const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets,
@@ -118,26 +116,24 @@ public:
 
   void GetName(nsAString&) override;
   void GetUUID(nsACString&) override;
 
   nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
                     const MediaEnginePrefs &aPrefs,
                     const nsString& aDeviceId,
                     const nsACString& aOrigin,
-                    BaseAllocationHandle** aOutHandle,
-                    const char** aOutBadConstraint) override;
+                    BaseAllocationHandle** aOutHandle) override;
   nsresult Deallocate(BaseAllocationHandle* aHandle) override;
   nsresult Start(SourceMediaStream*, TrackID, const PrincipalHandle&) override;
   nsresult Stop(SourceMediaStream*, TrackID) override;
   nsresult Restart(BaseAllocationHandle* aHandle,
                    const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
-                   const nsString& aDeviceId,
-                   const char** aOutBadConstraint) override;
+                   const nsString& aDeviceId) override;
   void SetDirectListeners(bool aHasDirectListeners) override {};
   void AppendToSegment(AudioSegment& aSegment,
                        TrackTicks aSamples);
   void NotifyPull(MediaStreamGraph* aGraph,
                   SourceMediaStream *aSource,
                   TrackID aId,
                   StreamTime aDesiredTime,
                   const PrincipalHandle& aPrincipalHandle) override
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -98,18 +98,17 @@ MediaEngineRemoteVideoSource::Shutdown()
 }
 
 nsresult
 MediaEngineRemoteVideoSource::Allocate(
     const dom::MediaTrackConstraints& aConstraints,
     const MediaEnginePrefs& aPrefs,
     const nsString& aDeviceId,
     const nsACString& aOrigin,
-    BaseAllocationHandle** aOutHandle,
-    const char** aOutBadConstraint)
+    BaseAllocationHandle** aOutHandle)
 {
   LOG((__PRETTY_FUNCTION__));
   AssertIsOnOwningThread();
 
   if (!mInitDone) {
     LOG(("Init not done"));
     return NS_ERROR_FAILURE;
   }
@@ -117,18 +116,17 @@ MediaEngineRemoteVideoSource::Allocate(
   AutoTArray<const NormalizedConstraints*, 10> allConstraints;
   for (auto& registered : mRegisteredHandles) {
     allConstraints.AppendElement(&registered->mConstraints);
   }
   RefPtr<AllocationHandle> handle = new AllocationHandle(aConstraints);
   allConstraints.AppendElement(&handle->mConstraints);
 
   NormalizedConstraints netConstraints(allConstraints);
-  if (netConstraints.mBadConstraint) {
-    *aOutBadConstraint = netConstraints.mBadConstraint;
+  if (netConstraints.mOverconstrained) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   if (!ChooseCapability(netConstraints, aPrefs, aDeviceId)) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   if (mState == kReleased) {
@@ -280,18 +278,17 @@ MediaEngineRemoteVideoSource::Stop(mozil
 
   return NS_OK;
 }
 
 nsresult
 MediaEngineRemoteVideoSource::Restart(BaseAllocationHandle* aHandle,
                                       const dom::MediaTrackConstraints& aConstraints,
                                       const MediaEnginePrefs& aPrefs,
-                                      const nsString& aDeviceId,
-                                      const char** aOutBadConstraint)
+                                      const nsString& aDeviceId)
 {
   AssertIsOnOwningThread();
   if (!mInitDone) {
     LOG(("Init not done"));
     return NS_ERROR_FAILURE;
   }
   MOZ_ASSERT(aHandle);
   auto handle = static_cast<AllocationHandle*>(aHandle);
@@ -303,18 +300,17 @@ MediaEngineRemoteVideoSource::Restart(Ba
     if (registered.get() == handle) {
       continue; // Don't count old constraints
     }
     allConstraints.AppendElement(&registered->mConstraints);
   }
   allConstraints.AppendElement(&temp->mConstraints);
 
   NormalizedConstraints netConstraints(allConstraints);
-  if (netConstraints.mBadConstraint) {
-    *aOutBadConstraint = netConstraints.mBadConstraint;
+  if (netConstraints.mOverconstrained) {
     return NS_ERROR_FAILURE;
   }
 
   if (!ChooseCapability(netConstraints, aPrefs, aDeviceId)) {
     return NS_ERROR_FAILURE;
   }
   if (mState != kStarted) {
     return NS_OK;
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.h
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.h
@@ -81,26 +81,24 @@ public:
   public:
     NormalizedConstraints mConstraints;
   };
 
   nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
                     const MediaEnginePrefs& aPrefs,
                     const nsString& aDeviceId,
                     const nsACString& aOrigin,
-                    BaseAllocationHandle** aOutHandle,
-                    const char** aOutBadConstraint) override;
+                    BaseAllocationHandle** aOutHandle) override;
   nsresult Deallocate(BaseAllocationHandle* aHandle) override;
   nsresult Start(SourceMediaStream*, TrackID, const PrincipalHandle&) override;
   nsresult Stop(SourceMediaStream*, TrackID) override;
   nsresult Restart(BaseAllocationHandle* aHandle,
                    const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
-                   const nsString& aDeviceId,
-                   const char** aOutBadConstraint) override;
+                   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;
   }
--- a/dom/media/webrtc/MediaEngineTabVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.cpp
@@ -135,34 +135,32 @@ MediaEngineTabVideoSource::GetUUID(nsACS
 #define DEFAULT_TABSHARE_VIDEO_MAX_HEIGHT 4096
 #define DEFAULT_TABSHARE_VIDEO_FRAMERATE 30
 
 nsresult
 MediaEngineTabVideoSource::Allocate(const dom::MediaTrackConstraints& aConstraints,
                                     const MediaEnginePrefs& aPrefs,
                                     const nsString& aDeviceId,
                                     const nsACString& aOrigin,
-                                    BaseAllocationHandle** aOutHandle,
-                                    const char** aOutBadConstraint)
+                                    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(nullptr, aConstraints, aPrefs, aDeviceId, aOutBadConstraint);
+  return Restart(nullptr, aConstraints, aPrefs, aDeviceId);
 }
 
 nsresult
 MediaEngineTabVideoSource::Restart(BaseAllocationHandle* aHandle,
                                    const dom::MediaTrackConstraints& aConstraints,
                                    const mozilla::MediaEnginePrefs& aPrefs,
-                                   const nsString& aDeviceId,
-                                   const char** aOutBadConstraint)
+                                   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;
--- a/dom/media/webrtc/MediaEngineTabVideoSource.h
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.h
@@ -21,28 +21,26 @@ class MediaEngineTabVideoSource : public
 
     void Shutdown() override {};
     void GetName(nsAString_internal&) override;
     void GetUUID(nsACString_internal&) override;
     nsresult Allocate(const dom::MediaTrackConstraints &,
                       const mozilla::MediaEnginePrefs&,
                       const nsString& aDeviceId,
                       const nsACString& aOrigin,
-                      BaseAllocationHandle** aOutHandle,
-                      const char** aOutBadConstraint) override;
+                      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(BaseAllocationHandle* aHandle,
                      const dom::MediaTrackConstraints& aConstraints,
                      const mozilla::MediaEnginePrefs& aPrefs,
-                     const nsString& aDeviceId,
-                     const char** aOutBadConstraint) override;
+                     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,
       const nsString& aDeviceId) override
     {
--- a/dom/media/webrtc/MediaEngineWebRTC.h
+++ b/dom/media/webrtc/MediaEngineWebRTC.h
@@ -73,18 +73,17 @@ public:
   {
   }
   void GetName(nsAString& aName) override;
   void GetUUID(nsACString& aUUID) override;
   nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
                     const MediaEnginePrefs& aPrefs,
                     const nsString& aDeviceId,
                     const nsACString& aOrigin,
-                    BaseAllocationHandle** aOutHandle,
-                    const char** aOutBadConstraint) override
+                    BaseAllocationHandle** aOutHandle) override
   {
     // Nothing to do here, everything is managed in MediaManager.cpp
     aOutHandle = nullptr;
     return NS_OK;
   }
   nsresult Deallocate(BaseAllocationHandle* aHandle) override
   {
     // Nothing to do here, everything is managed in MediaManager.cpp
@@ -97,18 +96,17 @@ public:
   }
   nsresult Start(SourceMediaStream* aMediaStream,
                  TrackID aId,
                  const PrincipalHandle& aPrincipalHandle) override;
   nsresult Stop(SourceMediaStream* aMediaStream, TrackID aId) override;
   nsresult Restart(BaseAllocationHandle* aHandle,
                    const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
-                   const nsString& aDeviceId,
-                   const char** aOutBadConstraint) override;
+                   const nsString& aDeviceId) override;
   void SetDirectListeners(bool aDirect) override
   {}
   void NotifyOutputData(MediaStreamGraph* aGraph,
                         AudioDataValue* aBuffer, size_t aFrames,
                         TrackRate aRate, uint32_t aChannels) override
   {}
   void DeviceChanged() override
   {}
@@ -453,28 +451,26 @@ public:
 
   void GetName(nsAString& aName) override;
   void GetUUID(nsACString& aUUID) override;
 
   nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
                     const MediaEnginePrefs& aPrefs,
                     const nsString& aDeviceId,
                     const nsACString& aOrigin,
-                    BaseAllocationHandle** aOutHandle,
-                    const char** aOutBadConstraint) override;
+                    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(BaseAllocationHandle* aHandle,
                    const dom::MediaTrackConstraints& aConstraints,
                    const MediaEnginePrefs &aPrefs,
-                   const nsString& aDeviceId,
-                   const char** aOutBadConstraint) override;
+                   const nsString& aDeviceId) override;
   void SetDirectListeners(bool aHasDirectListeners) override {};
 
   void NotifyPull(MediaStreamGraph* aGraph,
                   SourceMediaStream* aSource,
                   TrackID aId,
                   StreamTime aDesiredTime,
                   const PrincipalHandle& aPrincipalHandle) override;
 
--- a/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
+++ b/dom/media/webrtc/MediaEngineWebRTCAudio.cpp
@@ -218,18 +218,17 @@ uint32_t MediaEngineWebRTCMicrophoneSour
   return distance;
 }
 
 nsresult
 MediaEngineWebRTCMicrophoneSource::Allocate(const dom::MediaTrackConstraints &aConstraints,
                                             const MediaEnginePrefs &aPrefs,
                                             const nsString& aDeviceId,
                                             const nsACString& aOrigin,
-                                            BaseAllocationHandle** aOutHandle,
-                                            const char** aOutBadConstraint)
+                                            BaseAllocationHandle** aOutHandle)
 {
   AssertIsOnOwningThread();
   if (mState == kReleased) {
     if (sChannelsOpen == 0) {
       if (!InitEngine()) {
         LOG(("Audio engine is not initalized"));
         return NS_ERROR_FAILURE;
       }
@@ -256,25 +255,24 @@ MediaEngineWebRTCMicrophoneSource::Alloc
     if (mSources.IsEmpty()) {
       LOG(("Audio device %d reallocated", mCapIndex));
     } else {
       LOG(("Audio device %d allocated shared", mCapIndex));
     }
   }
   ++mNrAllocations;
   aOutHandle = nullptr;
-  return Restart(nullptr, aConstraints, aPrefs, aDeviceId, aOutBadConstraint);
+  return Restart(nullptr, aConstraints, aPrefs, aDeviceId);
 }
 
 nsresult
 MediaEngineWebRTCMicrophoneSource::Restart(BaseAllocationHandle* aHandle,
                                            const dom::MediaTrackConstraints& aConstraints,
                                            const MediaEnginePrefs &aPrefs,
-                                           const nsString& aDeviceId,
-                                           const char** aOutBadConstraint)
+                                           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);
 
@@ -845,18 +843,17 @@ MediaEngineWebRTCAudioCaptureSource::Sto
   return NS_OK;
 }
 
 nsresult
 MediaEngineWebRTCAudioCaptureSource::Restart(
     BaseAllocationHandle* aHandle,
     const dom::MediaTrackConstraints& aConstraints,
     const MediaEnginePrefs &aPrefs,
-    const nsString& aDeviceId,
-    const char** aOutBadConstraint)
+    const nsString& aDeviceId)
 {
   MOZ_ASSERT(!aHandle);
   return NS_OK;
 }
 
 uint32_t
 MediaEngineWebRTCAudioCaptureSource::GetBestFitnessDistance(
     const nsTArray<const dom::MediaTrackConstraintSet*>& aConstraintSets,
--- a/dom/media/webrtc/MediaTrackConstraints.cpp
+++ b/dom/media/webrtc/MediaTrackConstraints.cpp
@@ -1,18 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaTrackConstraints.h"
 
 #include <limits>
-#include <algorithm>
-#include <iterator>
 
 namespace mozilla {
 
 template<class ValueType>
 template<class ConstrainRange>
 void
 NormalizedConstraintSet::Range<ValueType>::SetFrom(const ConstrainRange& aOther)
 {
@@ -197,126 +195,73 @@ NormalizedConstraintSet::StringRange::Cl
 }
 
 bool
 NormalizedConstraintSet::StringRange::Intersects(const StringRange& aOther) const
 {
   if (!mExact.size() || !aOther.mExact.size()) {
     return true;
   }
-
-  ValueType intersection;
-  set_intersection(mExact.begin(), mExact.end(),
-                   aOther.mExact.begin(), aOther.mExact.end(),
-                   std::inserter(intersection, intersection.begin()));
-  return !!intersection.size();
+  for (auto& entry : aOther.mExact) {
+    if (mExact.find(entry) != mExact.end()) {
+      return true;
+    }
+  }
+  return false;
 }
 
 void
 NormalizedConstraintSet::StringRange::Intersect(const StringRange& aOther)
 {
   if (!aOther.mExact.size()) {
     return;
   }
-
-  ValueType intersection;
-  set_intersection(mExact.begin(), mExact.end(),
-                   aOther.mExact.begin(), aOther.mExact.end(),
-                   std::inserter(intersection, intersection.begin()));
-  mExact = intersection;
-}
-
-bool
-NormalizedConstraintSet::StringRange::Merge(const StringRange& aOther)
-{
-  if (!Intersects(aOther)) {
-    return false;
+  for (auto& entry : mExact) {
+    if (aOther.mExact.find(entry) == aOther.mExact.end()) {
+      mExact.erase(entry);
+    }
   }
-  Intersect(aOther);
-
-  ValueType unioned;
-  set_union(mIdeal.begin(), mIdeal.end(),
-            aOther.mIdeal.begin(), aOther.mIdeal.end(),
-            std::inserter(unioned, unioned.begin()));
-  mIdeal = unioned;
-  return true;
 }
 
 NormalizedConstraints::NormalizedConstraints(const dom::MediaTrackConstraints& aOther)
-: NormalizedConstraintSet(aOther, false), mBadConstraint(nullptr)
+: NormalizedConstraintSet(aOther, false), mOverconstrained(false)
 {
   if (aOther.mAdvanced.WasPassed()) {
     for (auto& entry : aOther.mAdvanced.Value()) {
       mAdvanced.AppendElement(NormalizedConstraintSet(entry, true));
     }
   }
 }
 
 // Merge constructor. Create net constraints out of merging a set of others.
 
 NormalizedConstraints::NormalizedConstraints(
     const nsTArray<const NormalizedConstraints*>& aOthers)
   : NormalizedConstraintSet(*aOthers[0])
-  , mBadConstraint(nullptr)
+  , mOverconstrained(false)
 {
   // Do intersection of all required constraints, and average of ideals.
 
   for (uint32_t i = 1; i < aOthers.Length(); i++) {
     auto& set = *aOthers[i];
 
-    if (!mWidth.Merge(set.mWidth)) {
-      mBadConstraint = "width";
-      return;
-    }
-    if (!mHeight.Merge(set.mHeight)) {
-      mBadConstraint = "height";
-      return;
-    }
-    if (!mFrameRate.Merge(set.mFrameRate)) {
-      mBadConstraint = "frameRate";
-      return;
-    }
-    if (!mFacingMode.Merge(set.mFacingMode)) {
-      mBadConstraint = "facingMode";
-      return;
-    }
-    if (mMediaSource != set.mMediaSource) {
-      mBadConstraint = "mediaSource";
-      return;
-    }
-    if (mBrowserWindow != set.mBrowserWindow) {
-      mBadConstraint = "browserWindow";
-      return;
-    }
-    if (!mViewportOffsetX.Merge(set.mViewportOffsetX)) {
-      mBadConstraint = "viewportOffsetX";
-      return;
-    }
-    if (!mViewportOffsetY.Merge(set.mViewportOffsetY)) {
-      mBadConstraint = "viewportOffsetY";
-      return;
-    }
-    if (!mViewportWidth.Merge(set.mViewportWidth)) {
-      mBadConstraint = "viewportWidth";
-      return;
-    }
-    if (!mViewportHeight.Merge(set.mViewportHeight)) {
-      mBadConstraint = "viewportHeight";
-      return;
-    }
-    if (!mEchoCancellation.Merge(set.mEchoCancellation)) {
-      mBadConstraint = "echoCancellation";
-      return;
-    }
-    if (!mMozNoiseSuppression.Merge(set.mMozNoiseSuppression)) {
-      mBadConstraint = "mozNoiseSuppression";
-      return;
-    }
-    if (!mMozAutoGainControl.Merge(set.mMozAutoGainControl)) {
-      mBadConstraint = "mozAutoGainControl";
+    if (!mWidth.Merge(set.mWidth) ||
+        !mHeight.Merge(set.mHeight) ||
+        !mFrameRate.Merge(set.mFrameRate) ||
+        !mFacingMode.Merge(set.mFacingMode) ||
+        mMediaSource != set.mMediaSource ||
+        mBrowserWindow != set.mBrowserWindow ||
+        !mViewportOffsetX.Merge(set.mViewportOffsetX) ||
+        !mViewportOffsetY.Merge(set.mViewportOffsetY) ||
+        !mViewportWidth.Merge(set.mViewportWidth) ||
+        !mViewportHeight.Merge(set.mViewportHeight) ||
+        !mEchoCancellation.Merge(set.mEchoCancellation) ||
+        !mMozNoiseSuppression.Merge(set.mMozNoiseSuppression) ||
+        !mMozAutoGainControl.Merge(set.mMozAutoGainControl)) {
+      mOverconstrained = true;
       return;
     }
 
     for (auto& entry : set.mAdvanced) {
       mAdvanced.AppendElement(entry);
     }
   }
   mWidth.FinalizeMerge();
--- a/dom/media/webrtc/MediaTrackConstraints.h
+++ b/dom/media/webrtc/MediaTrackConstraints.h
@@ -118,17 +118,30 @@ struct NormalizedConstraintSet
 
     void SetFrom(const dom::ConstrainDOMStringParameters& aOther);
     ValueType Clamp(const ValueType& n) const;
     ValueType Get(const ValueType& defaultValue) const {
       return Clamp(mIdeal.size() ? mIdeal : defaultValue);
     }
     bool Intersects(const StringRange& aOther) const;
     void Intersect(const StringRange& aOther);
-    bool Merge(const StringRange& aOther);
+    bool Merge(const StringRange& aOther)
+    {
+      if (!Intersects(aOther)) {
+        return false;
+      }
+      Intersect(aOther);
+
+      for (auto& entry : aOther.mIdeal) {
+        if (mIdeal.find(entry) == mIdeal.end()) {
+          mIdeal.insert(entry);
+        }
+      }
+      return true;
+    }
     void FinalizeMerge() {}
   };
 
   // All new constraints should be added here whether they use flattening or not
   LongRange mWidth, mHeight;
   DoubleRange mFrameRate;
   StringRange mFacingMode;
   nsString mMediaSource;
@@ -165,17 +178,17 @@ template<> void NormalizedConstraintSet:
 // Used instead of MediaTrackConstraints in lower-level code.
 struct NormalizedConstraints : public NormalizedConstraintSet
 {
   explicit NormalizedConstraints(const dom::MediaTrackConstraints& aOther);
   explicit NormalizedConstraints(
       const nsTArray<const NormalizedConstraints*>& aOthers);
 
   nsTArray<NormalizedConstraintSet> mAdvanced;
-  const char* mBadConstraint;
+  bool mOverconstrained;
 };
 
 // Flattened version is used in low-level code with orthogonal constraints only.
 struct FlattenedConstraints : public NormalizedConstraintSet
 {
   explicit FlattenedConstraints(const NormalizedConstraints& aOther);
 
   explicit FlattenedConstraints(const dom::MediaTrackConstraints& aOther)