Bug 1213517 - Report correct constraint in OverconstrainedError when constraints conflict directly. r=padenot

MozReview-Commit-ID: 2bVaSvntc8g

--HG--
extra : rebase_source : cf1724b5db8852ca05248b67380899e4a16c7725
This commit is contained in:
Jan-Ivar Bruaroey 2016-06-15 19:25:07 -04:00
Родитель 5d2ce17581
Коммит bd5e812679
13 изменённых файлов: 159 добавлений и 84 удалений

Просмотреть файл

@ -888,14 +888,18 @@ AudioDevice::GetSource()
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() {
@ -1428,10 +1432,10 @@ public:
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,
@ -1441,10 +1445,10 @@ public:
}
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,
@ -3435,16 +3439,16 @@ GetUserMediaCallbackMediaStreamListener::ApplyConstraintsToTrack(
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,

Просмотреть файл

@ -74,9 +74,11 @@ public:
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() {}

Просмотреть файл

@ -152,7 +152,8 @@ public:
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
@ -189,7 +190,8 @@ public:
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,

Просмотреть файл

@ -90,7 +90,8 @@ MediaEngineDefaultVideoSource::Allocate(const dom::MediaTrackConstraints &aConst
const MediaEnginePrefs &aPrefs,
const nsString& aDeviceId,
const nsACString& aOrigin,
BaseAllocationHandle** aOutHandle)
BaseAllocationHandle** aOutHandle,
const char** aOutBadConstraint)
{
if (mState != kReleased) {
return NS_ERROR_FAILURE;
@ -221,7 +222,8 @@ MediaEngineDefaultVideoSource::Restart(
BaseAllocationHandle* aHandle,
const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs &aPrefs,
const nsString& aDeviceId)
const nsString& aDeviceId,
const char** aOutBadConstraint)
{
return NS_OK;
}
@ -416,7 +418,8 @@ MediaEngineDefaultAudioSource::Allocate(const dom::MediaTrackConstraints &aConst
const MediaEnginePrefs &aPrefs,
const nsString& aDeviceId,
const nsACString& aOrigin,
BaseAllocationHandle** aOutHandle)
BaseAllocationHandle** aOutHandle,
const char** aOutBadConstraint)
{
if (mState != kReleased) {
return NS_ERROR_FAILURE;
@ -530,7 +533,8 @@ nsresult
MediaEngineDefaultAudioSource::Restart(BaseAllocationHandle* aHandle,
const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs &aPrefs,
const nsString& aDeviceId)
const nsString& aDeviceId,
const char** aOutBadConstraint)
{
return NS_OK;
}

Просмотреть файл

@ -48,14 +48,16 @@ public:
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,
@ -121,14 +123,16 @@ public:
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);

Просмотреть файл

@ -103,7 +103,8 @@ MediaEngineRemoteVideoSource::Allocate(
const MediaEnginePrefs& aPrefs,
const nsString& aDeviceId,
const nsACString& aOrigin,
BaseAllocationHandle** aOutHandle)
BaseAllocationHandle** aOutHandle,
const char** aOutBadConstraint)
{
LOG((__PRETTY_FUNCTION__));
AssertIsOnOwningThread();
@ -121,7 +122,8 @@ MediaEngineRemoteVideoSource::Allocate(
allConstraints.AppendElement(&handle->mConstraints);
NormalizedConstraints netConstraints(allConstraints);
if (netConstraints.mOverconstrained) {
if (netConstraints.mBadConstraint) {
*aOutBadConstraint = netConstraints.mBadConstraint;
return NS_ERROR_NOT_AVAILABLE;
}
@ -283,7 +285,8 @@ nsresult
MediaEngineRemoteVideoSource::Restart(BaseAllocationHandle* aHandle,
const dom::MediaTrackConstraints& aConstraints,
const MediaEnginePrefs& aPrefs,
const nsString& aDeviceId)
const nsString& aDeviceId,
const char** aOutBadConstraint)
{
AssertIsOnOwningThread();
if (!mInitDone) {
@ -305,7 +308,8 @@ MediaEngineRemoteVideoSource::Restart(BaseAllocationHandle* aHandle,
allConstraints.AppendElement(&temp->mConstraints);
NormalizedConstraints netConstraints(allConstraints);
if (netConstraints.mOverconstrained) {
if (netConstraints.mBadConstraint) {
*aOutBadConstraint = netConstraints.mBadConstraint;
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -86,14 +86,16 @@ public:
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,

Просмотреть файл

@ -140,7 +140,8 @@ MediaEngineTabVideoSource::Allocate(const dom::MediaTrackConstraints& aConstrain
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.
@ -148,14 +149,15 @@ MediaEngineTabVideoSource::Allocate(const dom::MediaTrackConstraints& aConstrain
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);

Просмотреть файл

@ -26,7 +26,8 @@ class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventList
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 {};
@ -35,7 +36,8 @@ class MediaEngineTabVideoSource : public MediaEngineVideoSource, nsIDOMEventList
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;

Просмотреть файл

@ -78,7 +78,8 @@ public:
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;
@ -101,7 +102,8 @@ public:
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,
@ -456,7 +458,8 @@ public:
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,
@ -465,7 +468,8 @@ public:
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,

Просмотреть файл

@ -223,7 +223,8 @@ MediaEngineWebRTCMicrophoneSource::Allocate(const dom::MediaTrackConstraints &aC
const MediaEnginePrefs &aPrefs,
const nsString& aDeviceId,
const nsACString& aOrigin,
BaseAllocationHandle** aOutHandle)
BaseAllocationHandle** aOutHandle,
const char** aOutBadConstraint)
{
AssertIsOnOwningThread();
if (mState == kReleased) {
@ -260,14 +261,15 @@ MediaEngineWebRTCMicrophoneSource::Allocate(const dom::MediaTrackConstraints &aC
}
++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);
@ -848,7 +850,8 @@ 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;

Просмотреть файл

@ -6,6 +6,8 @@
#include "MediaTrackConstraints.h"
#include <limits>
#include <algorithm>
#include <iterator>
namespace mozilla {
@ -200,12 +202,12 @@ NormalizedConstraintSet::StringRange::Intersects(const StringRange& aOther) cons
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
@ -214,15 +216,32 @@ 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()) {
@ -236,27 +255,63 @@ NormalizedConstraints::NormalizedConstraints(const dom::MediaTrackConstraints& a
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;
}

Просмотреть файл

@ -123,20 +123,7 @@ struct NormalizedConstraintSet
}
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() {}
};
@ -183,7 +170,7 @@ struct NormalizedConstraints : public NormalizedConstraintSet
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.