diff --git a/dom/media/webrtc/MediaTrackConstraints.cpp b/dom/media/webrtc/MediaTrackConstraints.cpp index 7d8361caf103..f634e9dd5ae9 100644 --- a/dom/media/webrtc/MediaTrackConstraints.cpp +++ b/dom/media/webrtc/MediaTrackConstraints.cpp @@ -76,8 +76,14 @@ NormalizedConstraintSet::Range::FinalizeMerge() } NormalizedConstraintSet::LongRange::LongRange( - const dom::OwningLongOrConstrainLongRange& aOther, bool advanced) -: Range(1 + INT32_MIN, INT32_MAX) // +1 avoids Windows compiler bug + LongPtrType aMemberPtr, + const char* aName, + const dom::OwningLongOrConstrainLongRange& aOther, + bool advanced, + nsTArray* aList) +: Range((MemberPtrType)aMemberPtr, aName, + 1 + INT32_MIN, INT32_MAX, // +1 avoids Windows compiler bug + aList) { if (aOther.IsLong()) { if (advanced) { @@ -90,10 +96,26 @@ NormalizedConstraintSet::LongRange::LongRange( } } +NormalizedConstraintSet::LongLongRange::LongLongRange( + LongLongPtrType aMemberPtr, + const char* aName, + const long long& aOther, + nsTArray* aList) +: Range((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(-std::numeric_limits::infinity(), - std::numeric_limits::infinity()) + DoublePtrType aMemberPtr, + const char* aName, + const dom::OwningDoubleOrConstrainDoubleRange& aOther, bool advanced, + nsTArray* aList) +: Range((MemberPtrType)aMemberPtr, aName, + -std::numeric_limits::infinity(), + std::numeric_limits::infinity(), aList) { if (aOther.IsDouble()) { if (advanced) { @@ -107,8 +129,12 @@ NormalizedConstraintSet::DoubleRange::DoubleRange( } NormalizedConstraintSet::BooleanRange::BooleanRange( - const dom::OwningBooleanOrConstrainBooleanParameters& aOther, bool advanced) -: Range(false, true) + BooleanPtrType aMemberPtr, + const char* aName, + const dom::OwningBooleanOrConstrainBooleanParameters& aOther, + bool advanced, + nsTArray* aList) +: Range((MemberPtrType)aMemberPtr, aName, false, true, aList) { if (aOther.IsBoolean()) { if (advanced) { @@ -129,8 +155,12 @@ NormalizedConstraintSet::BooleanRange::BooleanRange( } NormalizedConstraintSet::StringRange::StringRange( + StringPtrType aMemberPtr, + const char* aName, const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters& aOther, - bool advanced) + bool advanced, + nsTArray* aList) + : BaseRange((MemberPtrType)aMemberPtr, aName, aList) { if (aOther.IsString()) { if (advanced) { @@ -240,8 +270,11 @@ NormalizedConstraintSet::StringRange::Merge(const StringRange& aOther) return true; } -NormalizedConstraints::NormalizedConstraints(const dom::MediaTrackConstraints& aOther) -: NormalizedConstraintSet(aOther, false), mBadConstraint(nullptr) +NormalizedConstraints::NormalizedConstraints( + const dom::MediaTrackConstraints& aOther, + nsTArray* aList) + : NormalizedConstraintSet(aOther, false, aList) + , mBadConstraint(nullptr) { if (aOther.mAdvanced.WasPassed()) { for (auto& entry : aOther.mAdvanced.Value()) { @@ -257,79 +290,32 @@ NormalizedConstraints::NormalizedConstraints( : NormalizedConstraintSet(*aOthers[0]) , mBadConstraint(nullptr) { + // Create a list of member pointers. + nsTArray 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) diff --git a/dom/media/webrtc/MediaTrackConstraints.h b/dom/media/webrtc/MediaTrackConstraints.h index 5977c607b602..ff7ac7cf33e7 100644 --- a/dom/media/webrtc/MediaTrackConstraints.h +++ b/dom/media/webrtc/MediaTrackConstraints.h @@ -36,17 +36,43 @@ static Enum StringToEnum(const EnumValuesStrings& aStrings, // 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* 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 Range + class Range : public BaseRange { public: ValueType mMin, mMax; Maybe mIdeal; - Range(ValueType aMin, ValueType aMax) - : mMin(aMin), mMax(aMax), mMergeDenominator(0) {} + Range(MemberPtrType aMemberPtr, const char* aName, ValueType aMin, + ValueType aMax, nsTArray* aList) + : BaseRange(aMemberPtr, aName, aList) + , mMin(aMin), mMax(aMax), mMergeDenominator(0) {} + virtual ~Range() {}; template void SetFrom(const ConstrainRange& aOther); @@ -79,7 +105,7 @@ struct NormalizedConstraintSet } return true; } - void FinalizeMerge() + void FinalizeMerge() override { if (mMergeDenominator) { *mIdeal /= mMergeDenominator; @@ -87,34 +113,77 @@ struct NormalizedConstraintSet } } private: + bool Merge(const BaseRange& aOther) override { + return Merge(static_cast(aOther)); + } + uint32_t mMergeDenominator; }; struct LongRange : public Range { - LongRange(const dom::OwningLongOrConstrainLongRange& aOther, bool advanced); + typedef LongRange NormalizedConstraintSet::* LongPtrType; + + LongRange(LongPtrType aMemberPtr, const char* aName, + const dom::OwningLongOrConstrainLongRange& aOther, bool advanced, + nsTArray* aList); + }; + + struct LongLongRange : public Range + { + typedef LongLongRange NormalizedConstraintSet::* LongLongPtrType; + + LongLongRange(LongLongPtrType aMemberPtr, const char* aName, + const long long& aOther, + nsTArray* aList); }; struct DoubleRange : public Range { - DoubleRange(const dom::OwningDoubleOrConstrainDoubleRange& aOther, - bool advanced); + typedef DoubleRange NormalizedConstraintSet::* DoublePtrType; + + DoubleRange(DoublePtrType aMemberPtr, + const char* aName, + const dom::OwningDoubleOrConstrainDoubleRange& aOther, + bool advanced, + nsTArray* aList); }; struct BooleanRange : public Range { - BooleanRange(const dom::OwningBooleanOrConstrainBooleanParameters& aOther, - bool advanced); + typedef BooleanRange NormalizedConstraintSet::* BooleanPtrType; + + BooleanRange(BooleanPtrType aMemberPtr, const char* aName, + const dom::OwningBooleanOrConstrainBooleanParameters& aOther, + bool advanced, + nsTArray* aList); + + BooleanRange(BooleanPtrType aMemberPtr, const char* aName, const bool& aOther, + nsTArray* aList) + : Range((MemberPtrType)aMemberPtr, aName, false, true, aList) { + mIdeal.emplace(aOther); + } }; - struct StringRange + struct StringRange : public BaseRange { typedef std::set ValueType; ValueType mExact, mIdeal; - StringRange( + typedef StringRange NormalizedConstraintSet::* StringPtrType; + + StringRange(StringPtrType aMemberPtr, const char* aName, const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters& aOther, - bool advanced); + bool advanced, + nsTArray* aList); + + StringRange(StringPtrType aMemberPtr, const char* aName, + const nsString& aOther, nsTArray* aList) + : BaseRange((MemberPtrType)aMemberPtr, aName, aList) { + mIdeal.insert(aOther); + } + + ~StringRange() {} void SetFrom(const dom::ConstrainDOMStringParameters& aOther); ValueType Clamp(const ValueType& n) const; @@ -124,39 +193,56 @@ struct NormalizedConstraintSet 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(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* 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::Merge(const Range& aOther); @@ -165,7 +251,10 @@ template<> void NormalizedConstraintSet::Range::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* aList = nullptr); + + // Merge constructor explicit NormalizedConstraints( const nsTArray& aOthers);