Backed out changeset e4829b553f9e (bug 1213517)
authorIris Hsiao <ihsiao@mozilla.com>
Mon, 18 Jul 2016 15:40:20 +0800
changeset 330352 75e965332b72f80457cf2f69ae44658a30b61a7b
parent 330351 1adb5905697d107fab50193ca93ecf340e72349d
child 330353 f925108ff4d308487c870d196d7f4cf98dbbcde8
push id9858
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 14:37:10 +0000
treeherdermozilla-aurora@203106ef6cb6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1213517
milestone50.0a1
backs oute4829b553f9e1bd78246476942bcedfad3011d16
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)