--- a/dom/media/webrtc/MediaTrackConstraints.cpp
+++ b/dom/media/webrtc/MediaTrackConstraints.cpp
@@ -71,49 +71,75 @@ NormalizedConstraintSet::Range<bool>::Fi
uint32_t denominator = mMergeDenominator & 0xffff;
*mIdeal = !!(counter / denominator);
mMergeDenominator = 0;
}
}
NormalizedConstraintSet::LongRange::LongRange(
- const dom::OwningLongOrConstrainLongRange& aOther, bool advanced)
-: Range<int32_t>(1 + INT32_MIN, INT32_MAX) // +1 avoids Windows compiler bug
+ LongPtrType aMemberPtr,
+ const char* aName,
+ const dom::OwningLongOrConstrainLongRange& aOther,
+ bool advanced,
+ nsTArray<MemberPtrType>* aList)
+: Range<int32_t>((MemberPtrType)aMemberPtr, aName,
+ 1 + INT32_MIN, INT32_MAX, // +1 avoids Windows compiler bug
+ aList)
{
if (aOther.IsLong()) {
if (advanced) {
mMin = mMax = aOther.GetAsLong();
} else {
mIdeal.emplace(aOther.GetAsLong());
}
} else {
SetFrom(aOther.GetAsConstrainLongRange());
}
}
+NormalizedConstraintSet::LongLongRange::LongLongRange(
+ LongLongPtrType aMemberPtr,
+ const char* aName,
+ const long long& aOther,
+ nsTArray<MemberPtrType>* aList)
+: Range<int64_t>((MemberPtrType)aMemberPtr, aName,
+ 1 + INT64_MIN, INT64_MAX, // +1 avoids Windows compiler bug
+ aList)
+{
+ mIdeal.emplace(aOther);
+}
+
NormalizedConstraintSet::DoubleRange::DoubleRange(
- const dom::OwningDoubleOrConstrainDoubleRange& aOther, bool advanced)
-: Range<double>(-std::numeric_limits<double>::infinity(),
- std::numeric_limits<double>::infinity())
+ DoublePtrType aMemberPtr,
+ const char* aName,
+ const dom::OwningDoubleOrConstrainDoubleRange& aOther, bool advanced,
+ nsTArray<MemberPtrType>* aList)
+: Range<double>((MemberPtrType)aMemberPtr, aName,
+ -std::numeric_limits<double>::infinity(),
+ std::numeric_limits<double>::infinity(), aList)
{
if (aOther.IsDouble()) {
if (advanced) {
mMin = mMax = aOther.GetAsDouble();
} else {
mIdeal.emplace(aOther.GetAsDouble());
}
} else {
SetFrom(aOther.GetAsConstrainDoubleRange());
}
}
NormalizedConstraintSet::BooleanRange::BooleanRange(
- const dom::OwningBooleanOrConstrainBooleanParameters& aOther, bool advanced)
-: Range<bool>(false, true)
+ BooleanPtrType aMemberPtr,
+ const char* aName,
+ const dom::OwningBooleanOrConstrainBooleanParameters& aOther,
+ bool advanced,
+ nsTArray<MemberPtrType>* aList)
+: Range<bool>((MemberPtrType)aMemberPtr, aName, false, true, aList)
{
if (aOther.IsBoolean()) {
if (advanced) {
mMin = mMax = aOther.GetAsBoolean();
} else {
mIdeal.emplace(aOther.GetAsBoolean());
}
} else {
@@ -124,18 +150,22 @@ NormalizedConstraintSet::BooleanRange::B
if (r.mExact.WasPassed()) {
mMin = r.mExact.Value();
mMax = r.mExact.Value();
}
}
}
NormalizedConstraintSet::StringRange::StringRange(
+ StringPtrType aMemberPtr,
+ const char* aName,
const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters& aOther,
- bool advanced)
+ bool advanced,
+ nsTArray<MemberPtrType>* aList)
+ : BaseRange((MemberPtrType)aMemberPtr, aName, aList)
{
if (aOther.IsString()) {
if (advanced) {
mExact.insert(aOther.GetAsString());
} else {
mIdeal.insert(aOther.GetAsString());
}
} else if (aOther.IsStringSequence()) {
@@ -235,106 +265,62 @@ NormalizedConstraintSet::StringRange::Me
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)
+NormalizedConstraints::NormalizedConstraints(
+ const dom::MediaTrackConstraints& aOther,
+ nsTArray<MemberPtrType>* aList)
+ : NormalizedConstraintSet(aOther, false, aList)
+ , 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])
, mBadConstraint(nullptr)
{
+ // Create a list of member pointers.
+ nsTArray<MemberPtrType> list;
+ NormalizedConstraints dummy(MediaTrackConstraints(), &list);
+
// Do intersection of all required constraints, and average of ideals.
for (uint32_t i = 1; i < aOthers.Length(); i++) {
- auto& set = *aOthers[i];
+ auto& other = *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";
- return;
+ for (auto& memberPtr : list) {
+ auto& member = this->*memberPtr;
+ auto& otherMember = other.*memberPtr;
+
+ if (!member.Merge(otherMember)) {
+ mBadConstraint = member.mName;
+ return;
+ }
}
- for (auto& entry : set.mAdvanced) {
+ for (auto& entry : other.mAdvanced) {
mAdvanced.AppendElement(entry);
}
}
- mWidth.FinalizeMerge();
- mHeight.FinalizeMerge();
- mFrameRate.FinalizeMerge();
- mFacingMode.FinalizeMerge();
- mViewportOffsetX.FinalizeMerge();
- mViewportOffsetY.FinalizeMerge();
- mViewportWidth.FinalizeMerge();
- mViewportHeight.FinalizeMerge();
- mEchoCancellation.FinalizeMerge();
- mMozNoiseSuppression.FinalizeMerge();
- mMozAutoGainControl.FinalizeMerge();
+ for (auto& memberPtr : list) {
+ (this->*memberPtr).FinalizeMerge();
+ }
}
FlattenedConstraints::FlattenedConstraints(const NormalizedConstraints& aOther)
: NormalizedConstraintSet(aOther)
{
for (auto& set : aOther.mAdvanced) {
// Must only apply compatible i.e. inherently non-overconstraining sets
// This rule is pretty much why this code is centralized here.
--- a/dom/media/webrtc/MediaTrackConstraints.h
+++ b/dom/media/webrtc/MediaTrackConstraints.h
@@ -31,27 +31,53 @@ static Enum StringToEnum(const EnumValue
}
}
return aDefaultValue;
}
// Helper classes for orthogonal constraints without interdependencies.
// Instead of constraining values, constrain the constraints themselves.
-struct NormalizedConstraintSet
+class NormalizedConstraintSet
{
+protected:
+ class BaseRange
+ {
+ protected:
+ typedef BaseRange NormalizedConstraintSet::* MemberPtrType;
+
+ BaseRange(MemberPtrType aMemberPtr, const char* aName,
+ nsTArray<MemberPtrType>* aList) : mName(aName) {
+ if (aList) {
+ aList->AppendElement(aMemberPtr);
+ }
+ }
+ virtual ~BaseRange() {}
+ public:
+ virtual bool Merge(const BaseRange& aOther) = 0;
+ virtual void FinalizeMerge() = 0;
+
+ const char* mName;
+ };
+
+ typedef BaseRange NormalizedConstraintSet::* MemberPtrType;
+
+public:
template<class ValueType>
- class Range
+ class Range : public BaseRange
{
public:
ValueType mMin, mMax;
Maybe<ValueType> mIdeal;
- Range(ValueType aMin, ValueType aMax)
- : mMin(aMin), mMax(aMax), mMergeDenominator(0) {}
+ Range(MemberPtrType aMemberPtr, const char* aName, ValueType aMin,
+ ValueType aMax, nsTArray<MemberPtrType>* aList)
+ : BaseRange(aMemberPtr, aName, aList)
+ , mMin(aMin), mMax(aMax), mMergeDenominator(0) {}
+ virtual ~Range() {};
template<class ConstrainRange>
void SetFrom(const ConstrainRange& aOther);
ValueType Clamp(ValueType n) const { return std::max(mMin, std::min(n, mMax)); }
ValueType Get(ValueType defaultValue) const {
return Clamp(mIdeal.valueOr(defaultValue));
}
bool Intersects(const Range& aOther) const {
@@ -74,103 +100,166 @@ struct NormalizedConstraintSet
mMergeDenominator = 1;
} else {
*mIdeal += aOther.mIdeal.value();
mMergeDenominator = std::max(2U, mMergeDenominator + 1);
}
}
return true;
}
- void FinalizeMerge()
+ void FinalizeMerge() override
{
if (mMergeDenominator) {
*mIdeal /= mMergeDenominator;
mMergeDenominator = 0;
}
}
private:
+ bool Merge(const BaseRange& aOther) override {
+ return Merge(static_cast<const Range&>(aOther));
+ }
+
uint32_t mMergeDenominator;
};
struct LongRange : public Range<int32_t>
{
- LongRange(const dom::OwningLongOrConstrainLongRange& aOther, bool advanced);
+ typedef LongRange NormalizedConstraintSet::* LongPtrType;
+
+ LongRange(LongPtrType aMemberPtr, const char* aName,
+ const dom::OwningLongOrConstrainLongRange& aOther, bool advanced,
+ nsTArray<MemberPtrType>* aList);
+ };
+
+ struct LongLongRange : public Range<int64_t>
+ {
+ typedef LongLongRange NormalizedConstraintSet::* LongLongPtrType;
+
+ LongLongRange(LongLongPtrType aMemberPtr, const char* aName,
+ const long long& aOther,
+ nsTArray<MemberPtrType>* aList);
};
struct DoubleRange : public Range<double>
{
- DoubleRange(const dom::OwningDoubleOrConstrainDoubleRange& aOther,
- bool advanced);
+ typedef DoubleRange NormalizedConstraintSet::* DoublePtrType;
+
+ DoubleRange(DoublePtrType aMemberPtr,
+ const char* aName,
+ const dom::OwningDoubleOrConstrainDoubleRange& aOther,
+ bool advanced,
+ nsTArray<MemberPtrType>* aList);
};
struct BooleanRange : public Range<bool>
{
- BooleanRange(const dom::OwningBooleanOrConstrainBooleanParameters& aOther,
- bool advanced);
+ typedef BooleanRange NormalizedConstraintSet::* BooleanPtrType;
+
+ BooleanRange(BooleanPtrType aMemberPtr, const char* aName,
+ const dom::OwningBooleanOrConstrainBooleanParameters& aOther,
+ bool advanced,
+ nsTArray<MemberPtrType>* aList);
+
+ BooleanRange(BooleanPtrType aMemberPtr, const char* aName, const bool& aOther,
+ nsTArray<MemberPtrType>* aList)
+ : Range<bool>((MemberPtrType)aMemberPtr, aName, false, true, aList) {
+ mIdeal.emplace(aOther);
+ }
};
- struct StringRange
+ struct StringRange : public BaseRange
{
typedef std::set<nsString> ValueType;
ValueType mExact, mIdeal;
- StringRange(
+ typedef StringRange NormalizedConstraintSet::* StringPtrType;
+
+ StringRange(StringPtrType aMemberPtr, const char* aName,
const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters& aOther,
- bool advanced);
+ bool advanced,
+ nsTArray<MemberPtrType>* aList);
+
+ StringRange(StringPtrType aMemberPtr, const char* aName,
+ const nsString& aOther, nsTArray<MemberPtrType>* aList)
+ : BaseRange((MemberPtrType)aMemberPtr, aName, aList) {
+ mIdeal.insert(aOther);
+ }
+
+ ~StringRange() {}
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);
- void FinalizeMerge() {}
+ void FinalizeMerge() override {}
+ private:
+ bool Merge(const BaseRange& aOther) override {
+ return Merge(static_cast<const StringRange&>(aOther));
+ }
};
// All new constraints should be added here whether they use flattening or not
LongRange mWidth, mHeight;
DoubleRange mFrameRate;
StringRange mFacingMode;
- nsString mMediaSource;
- long long mBrowserWindow;
- bool mScrollWithPage;
+ StringRange mMediaSource;
+ LongLongRange mBrowserWindow;
+ BooleanRange mScrollWithPage;
StringRange mDeviceId;
LongRange mViewportOffsetX, mViewportOffsetY, mViewportWidth, mViewportHeight;
BooleanRange mEchoCancellation, mMozNoiseSuppression, mMozAutoGainControl;
-
+private:
+ typedef NormalizedConstraintSet T;
+public:
NormalizedConstraintSet(const dom::MediaTrackConstraintSet& aOther,
- bool advanced)
- : mWidth(aOther.mWidth, advanced)
- , mHeight(aOther.mHeight, advanced)
- , mFrameRate(aOther.mFrameRate, advanced)
- , mFacingMode(aOther.mFacingMode, advanced)
- , mMediaSource(aOther.mMediaSource)
- , mBrowserWindow(aOther.mBrowserWindow.WasPassed() ?
- aOther.mBrowserWindow.Value() : 0)
- , mScrollWithPage(aOther.mScrollWithPage.WasPassed() ?
- aOther.mScrollWithPage.Value() : false)
- , mDeviceId(aOther.mDeviceId, advanced)
- , mViewportOffsetX(aOther.mViewportOffsetX, advanced)
- , mViewportOffsetY(aOther.mViewportOffsetY, advanced)
- , mViewportWidth(aOther.mViewportWidth, advanced)
- , mViewportHeight(aOther.mViewportHeight, advanced)
- , mEchoCancellation(aOther.mEchoCancellation, advanced)
- , mMozNoiseSuppression(aOther.mMozNoiseSuppression, advanced)
- , mMozAutoGainControl(aOther.mMozAutoGainControl, advanced) {}
+ bool advanced,
+ nsTArray<MemberPtrType>* aList = nullptr)
+ : mWidth(&T::mWidth, "width", aOther.mWidth, advanced, aList)
+ , mHeight(&T::mHeight, "height", aOther.mHeight, advanced, aList)
+ , mFrameRate(&T::mFrameRate, "frameRate", aOther.mFrameRate, advanced, aList)
+ , mFacingMode(&T::mFacingMode, "facingMode", aOther.mFacingMode, advanced, aList)
+ , mMediaSource(&T::mMediaSource, "mediaSource", aOther.mMediaSource, aList)
+ , mBrowserWindow(&T::mBrowserWindow, "browserWindow",
+ aOther.mBrowserWindow.WasPassed() ?
+ aOther.mBrowserWindow.Value() : 0, aList)
+ , mScrollWithPage(&T::mScrollWithPage, "scrollWithPage",
+ aOther.mScrollWithPage.WasPassed() ?
+ aOther.mScrollWithPage.Value() : false, aList)
+ , mDeviceId(&T::mDeviceId, "deviceId", aOther.mDeviceId, advanced, aList)
+ , mViewportOffsetX(&T::mViewportOffsetX, "viewportOffsetX",
+ aOther.mViewportOffsetX, advanced, aList)
+ , mViewportOffsetY(&T::mViewportOffsetY, "viewportOffsetY",
+ aOther.mViewportOffsetY, advanced, aList)
+ , mViewportWidth(&T::mViewportWidth, "viewportWidth",
+ aOther.mViewportWidth, advanced, aList)
+ , mViewportHeight(&T::mViewportHeight, "viewportHeight",
+ aOther.mViewportHeight, advanced, aList)
+ , mEchoCancellation(&T::mEchoCancellation, "echoCancellation",
+ aOther.mEchoCancellation, advanced, aList)
+ , mMozNoiseSuppression(&T::mMozNoiseSuppression, "mozNoiseSuppression",
+ aOther.mMozNoiseSuppression,
+ advanced, aList)
+ , mMozAutoGainControl(&T::mMozAutoGainControl, "mozAutoGainControl",
+ aOther.mMozAutoGainControl, advanced, aList) {}
};
template<> bool NormalizedConstraintSet::Range<bool>::Merge(const Range& aOther);
template<> void NormalizedConstraintSet::Range<bool>::FinalizeMerge();
// Used instead of MediaTrackConstraints in lower-level code.
struct NormalizedConstraints : public NormalizedConstraintSet
{
- explicit NormalizedConstraints(const dom::MediaTrackConstraints& aOther);
+ explicit NormalizedConstraints(const dom::MediaTrackConstraints& aOther,
+ nsTArray<MemberPtrType>* aList = nullptr);
+
+ // Merge constructor
explicit NormalizedConstraints(
const nsTArray<const NormalizedConstraints*>& aOthers);
nsTArray<NormalizedConstraintSet> mAdvanced;
const char* mBadConstraint;
};
// Flattened version is used in low-level code with orthogonal constraints only.