--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -883,24 +883,28 @@ 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 nsACString& aOrigin,
+ const char** aOutBadConstraint) {
return GetSource()->Allocate(aConstraints, aPrefs, mID, aOrigin,
- getter_AddRefs(mAllocationHandle));
+ getter_AddRefs(mAllocationHandle),
+ aOutBadConstraint);
}
nsresult MediaDevice::Restart(const dom::MediaTrackConstraints &aConstraints,
- const MediaEnginePrefs &aPrefs) {
- return GetSource()->Restart(mAllocationHandle, aConstraints, aPrefs, mID);
+ const MediaEnginePrefs &aPrefs,
+ const char** aOutBadConstraint) {
+ return GetSource()->Restart(mAllocationHandle, aConstraints, aPrefs, mID,
+ aOutBadConstraint);
}
nsresult MediaDevice::Deallocate() {
return GetSource()->Deallocate(mAllocationHandle);
}
void
MediaOperationTask::ReturnCallbackError(nsresult rv, const char* errorLog)
@@ -1423,33 +1427,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);
+ rv = mAudioDevice->Allocate(constraints, mPrefs, mOrigin, &badConstraint);
if (NS_FAILED(rv)) {
errorMsg = "Failed to allocate audiosource";
- if (rv == NS_ERROR_NOT_AVAILABLE) {
+ if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) {
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);
+ rv = mVideoDevice->Allocate(constraints, mPrefs, mOrigin, &badConstraint);
if (NS_FAILED(rv)) {
errorMsg = "Failed to allocate videosource";
- if (rv == NS_ERROR_NOT_AVAILABLE) {
+ if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) {
nsTArray<RefPtr<VideoDevice>> videos;
videos.AppendElement(mVideoDevice);
badConstraint = MediaConstraintsHelper::SelectSettings(constraints,
videos);
}
if (mAudioDevice) {
mAudioDevice->Deallocate();
}
@@ -3430,26 +3434,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);
- if (rv == NS_ERROR_NOT_AVAILABLE) {
+ rv = audioDevice->Restart(aConstraints, mgr->mPrefs, &badConstraint);
+ if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) {
nsTArray<RefPtr<AudioDevice>> audios;
audios.AppendElement(audioDevice);
badConstraint = MediaConstraintsHelper::SelectSettings(aConstraints,
audios);
}
} else {
- rv = videoDevice->Restart(aConstraints, mgr->mPrefs);
- if (rv == NS_ERROR_NOT_AVAILABLE) {
+ rv = videoDevice->Restart(aConstraints, mgr->mPrefs, &badConstraint);
+ if (rv == NS_ERROR_NOT_AVAILABLE && !badConstraint) {
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,19 +69,21 @@ 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 nsACString& aOrigin,
+ const char** aOutBadConstraint);
nsresult Restart(const dom::MediaTrackConstraints &aConstraints,
- const MediaEnginePrefs &aPrefs);
+ const MediaEnginePrefs &aPrefs,
+ const char** aOutBadConstraint);
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,17 +147,18 @@ 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) = 0;
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint) = 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;
@@ -184,17 +185,18 @@ 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) = 0;
+ BaseAllocationHandle** aOutHandle,
+ const char** aOutBadConstraint) = 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,17 +85,18 @@ MediaEngineDefaultVideoSource::GetBestFi
return distance;
}
nsresult
MediaEngineDefaultVideoSource::Allocate(const dom::MediaTrackConstraints &aConstraints,
const MediaEnginePrefs &aPrefs,
const nsString& aDeviceId,
const nsACString& aOrigin,
- BaseAllocationHandle** aOutHandle)
+ BaseAllocationHandle** aOutHandle,
+ const char** aOutBadConstraint)
{
if (mState != kReleased) {
return NS_ERROR_FAILURE;
}
// Mock failure for automated tests.
if (aConstraints.mDeviceId.IsString() &&
aConstraints.mDeviceId.GetAsString().EqualsASCII("bad device")) {
@@ -216,17 +217,18 @@ MediaEngineDefaultVideoSource::Stop(Sour
return NS_OK;
}
nsresult
MediaEngineDefaultVideoSource::Restart(
BaseAllocationHandle* aHandle,
const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs &aPrefs,
- const nsString& aDeviceId)
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint)
{
return NS_OK;
}
NS_IMETHODIMP
MediaEngineDefaultVideoSource::Notify(nsITimer* aTimer)
{
// Update the target color
@@ -411,17 +413,18 @@ MediaEngineDefaultAudioSource::GetBestFi
return distance;
}
nsresult
MediaEngineDefaultAudioSource::Allocate(const dom::MediaTrackConstraints &aConstraints,
const MediaEnginePrefs &aPrefs,
const nsString& aDeviceId,
const nsACString& aOrigin,
- BaseAllocationHandle** aOutHandle)
+ BaseAllocationHandle** aOutHandle,
+ const char** aOutBadConstraint)
{
if (mState != kReleased) {
return NS_ERROR_FAILURE;
}
// Mock failure for automated tests.
if (aConstraints.mDeviceId.IsString() &&
aConstraints.mDeviceId.GetAsString().EqualsASCII("bad device")) {
@@ -525,17 +528,18 @@ MediaEngineDefaultAudioSource::Stop(Sour
mState = kStopped;
return NS_OK;
}
nsresult
MediaEngineDefaultAudioSource::Restart(BaseAllocationHandle* aHandle,
const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs &aPrefs,
- const nsString& aDeviceId)
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint)
{
return NS_OK;
}
void
MediaEngineDefaultAudioSource::AppendToSegment(AudioSegment& aSegment,
TrackTicks aSamples)
{
--- a/dom/media/webrtc/MediaEngineDefault.h
+++ b/dom/media/webrtc/MediaEngineDefault.h
@@ -43,24 +43,26 @@ 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) override;
+ BaseAllocationHandle** aOutHandle,
+ const char** aOutBadConstraint) 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) override;
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint) 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,
@@ -116,24 +118,26 @@ 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) override;
+ BaseAllocationHandle** aOutHandle,
+ const char** aOutBadConstraint) 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) override;
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint) 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,17 +98,18 @@ MediaEngineRemoteVideoSource::Shutdown()
}
nsresult
MediaEngineRemoteVideoSource::Allocate(
const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs& aPrefs,
const nsString& aDeviceId,
const nsACString& aOrigin,
- BaseAllocationHandle** aOutHandle)
+ BaseAllocationHandle** aOutHandle,
+ const char** aOutBadConstraint)
{
LOG((__PRETTY_FUNCTION__));
AssertIsOnOwningThread();
if (!mInitDone) {
LOG(("Init not done"));
return NS_ERROR_FAILURE;
}
@@ -116,17 +117,18 @@ MediaEngineRemoteVideoSource::Allocate(
AutoTArray<const NormalizedConstraints*, 10> allConstraints;
for (auto& registered : mRegisteredHandles) {
allConstraints.AppendElement(®istered->mConstraints);
}
RefPtr<AllocationHandle> handle = new AllocationHandle(aConstraints);
allConstraints.AppendElement(&handle->mConstraints);
NormalizedConstraints netConstraints(allConstraints);
- if (netConstraints.mOverconstrained) {
+ if (netConstraints.mBadConstraint) {
+ *aOutBadConstraint = netConstraints.mBadConstraint;
return NS_ERROR_NOT_AVAILABLE;
}
if (!ChooseCapability(netConstraints, aPrefs, aDeviceId)) {
return NS_ERROR_NOT_AVAILABLE;
}
if (mState == kReleased) {
@@ -278,17 +280,18 @@ MediaEngineRemoteVideoSource::Stop(mozil
return NS_OK;
}
nsresult
MediaEngineRemoteVideoSource::Restart(BaseAllocationHandle* aHandle,
const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs& aPrefs,
- const nsString& aDeviceId)
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint)
{
AssertIsOnOwningThread();
if (!mInitDone) {
LOG(("Init not done"));
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(aHandle);
auto handle = static_cast<AllocationHandle*>(aHandle);
@@ -300,17 +303,18 @@ MediaEngineRemoteVideoSource::Restart(Ba
if (registered.get() == handle) {
continue; // Don't count old constraints
}
allConstraints.AppendElement(®istered->mConstraints);
}
allConstraints.AppendElement(&temp->mConstraints);
NormalizedConstraints netConstraints(allConstraints);
- if (netConstraints.mOverconstrained) {
+ if (netConstraints.mBadConstraint) {
+ *aOutBadConstraint = netConstraints.mBadConstraint;
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,24 +81,26 @@ public:
public:
NormalizedConstraints mConstraints;
};
nsresult Allocate(const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs& aPrefs,
const nsString& aDeviceId,
const nsACString& aOrigin,
- BaseAllocationHandle** aOutHandle) override;
+ BaseAllocationHandle** aOutHandle,
+ const char** aOutBadConstraint) 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) override;
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint) 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,32 +135,34 @@ 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)
+ BaseAllocationHandle** aOutHandle,
+ const char** aOutBadConstraint)
{
// 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);
+ return Restart(nullptr, aConstraints, aPrefs, aDeviceId, aOutBadConstraint);
}
nsresult
MediaEngineTabVideoSource::Restart(BaseAllocationHandle* aHandle,
const dom::MediaTrackConstraints& aConstraints,
const mozilla::MediaEnginePrefs& aPrefs,
- const nsString& aDeviceId)
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint)
{
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,26 +21,28 @@ 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) override;
+ BaseAllocationHandle** aOutHandle,
+ const char** aOutBadConstraint) 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) override;
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint) 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,17 +73,18 @@ 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) override
+ BaseAllocationHandle** aOutHandle,
+ const char** aOutBadConstraint) 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
@@ -96,17 +97,18 @@ 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) override;
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint) override;
void SetDirectListeners(bool aDirect) override
{}
void NotifyOutputData(MediaStreamGraph* aGraph,
AudioDataValue* aBuffer, size_t aFrames,
TrackRate aRate, uint32_t aChannels) override
{}
void DeviceChanged() override
{}
@@ -451,26 +453,28 @@ 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) override;
+ BaseAllocationHandle** aOutHandle,
+ const char** aOutBadConstraint) 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) override;
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint) 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,17 +218,18 @@ uint32_t MediaEngineWebRTCMicrophoneSour
return distance;
}
nsresult
MediaEngineWebRTCMicrophoneSource::Allocate(const dom::MediaTrackConstraints &aConstraints,
const MediaEnginePrefs &aPrefs,
const nsString& aDeviceId,
const nsACString& aOrigin,
- BaseAllocationHandle** aOutHandle)
+ BaseAllocationHandle** aOutHandle,
+ const char** aOutBadConstraint)
{
AssertIsOnOwningThread();
if (mState == kReleased) {
if (sChannelsOpen == 0) {
if (!InitEngine()) {
LOG(("Audio engine is not initalized"));
return NS_ERROR_FAILURE;
}
@@ -255,24 +256,25 @@ 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);
+ return Restart(nullptr, aConstraints, aPrefs, aDeviceId, aOutBadConstraint);
}
nsresult
MediaEngineWebRTCMicrophoneSource::Restart(BaseAllocationHandle* aHandle,
const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs &aPrefs,
- const nsString& aDeviceId)
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint)
{
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);
@@ -843,17 +845,18 @@ MediaEngineWebRTCAudioCaptureSource::Sto
return NS_OK;
}
nsresult
MediaEngineWebRTCAudioCaptureSource::Restart(
BaseAllocationHandle* aHandle,
const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs &aPrefs,
- const nsString& aDeviceId)
+ const nsString& aDeviceId,
+ const char** aOutBadConstraint)
{
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,16 +1,18 @@
/* -*- 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)
{
@@ -195,73 +197,126 @@ NormalizedConstraintSet::StringRange::Cl
}
bool
NormalizedConstraintSet::StringRange::Intersects(const StringRange& aOther) const
{
if (!mExact.size() || !aOther.mExact.size()) {
return true;
}
- for (auto& entry : aOther.mExact) {
- if (mExact.find(entry) != mExact.end()) {
- return true;
- }
- }
- return false;
+
+ ValueType intersection;
+ set_intersection(mExact.begin(), mExact.end(),
+ aOther.mExact.begin(), aOther.mExact.end(),
+ std::inserter(intersection, intersection.begin()));
+ return !!intersection.size();
}
void
NormalizedConstraintSet::StringRange::Intersect(const StringRange& aOther)
{
if (!aOther.mExact.size()) {
return;
}
- for (auto& entry : mExact) {
- if (aOther.mExact.find(entry) == aOther.mExact.end()) {
- mExact.erase(entry);
- }
+
+ 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;
}
+ 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), mOverconstrained(false)
+: NormalizedConstraintSet(aOther, false), mBadConstraint(nullptr)
{
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])
- , mOverconstrained(false)
+ , mBadConstraint(nullptr)
{
// 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) ||
- !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;
+ 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";
return;
}
for (auto& entry : set.mAdvanced) {
mAdvanced.AppendElement(entry);
}
}
mWidth.FinalizeMerge();
--- a/dom/media/webrtc/MediaTrackConstraints.h
+++ b/dom/media/webrtc/MediaTrackConstraints.h
@@ -118,30 +118,17 @@ 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)
- {
- if (!Intersects(aOther)) {
- return false;
- }
- Intersect(aOther);
-
- for (auto& entry : aOther.mIdeal) {
- if (mIdeal.find(entry) == mIdeal.end()) {
- mIdeal.insert(entry);
- }
- }
- return true;
- }
+ bool Merge(const StringRange& aOther);
void FinalizeMerge() {}
};
// All new constraints should be added here whether they use flattening or not
LongRange mWidth, mHeight;
DoubleRange mFrameRate;
StringRange mFacingMode;
nsString mMediaSource;
@@ -178,17 +165,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;
- bool mOverconstrained;
+ const char* mBadConstraint;
};
// 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)