LCOV - code coverage report
Current view: top level - dom/media/webrtc - MediaTrackConstraints.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 153 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 101 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       3             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : // This file should not be included by other includes, as it contains code
       6             : 
       7             : #ifndef MEDIATRACKCONSTRAINTS_H_
       8             : #define MEDIATRACKCONSTRAINTS_H_
       9             : 
      10             : #include "mozilla/Attributes.h"
      11             : #include "mozilla/dom/MediaStreamTrackBinding.h"
      12             : #include "mozilla/dom/MediaTrackConstraintSetBinding.h"
      13             : #include "mozilla/dom/MediaTrackSupportedConstraintsBinding.h"
      14             : 
      15             : #include <map>
      16             : #include <set>
      17             : #include <vector>
      18             : 
      19             : namespace mozilla {
      20             : 
      21             : template<class EnumValuesStrings, class Enum>
      22           0 : static const char* EnumToASCII(const EnumValuesStrings& aStrings, Enum aValue) {
      23           0 :   return aStrings[uint32_t(aValue)].value;
      24             : }
      25             : 
      26             : template<class EnumValuesStrings, class Enum>
      27           0 : static Enum StringToEnum(const EnumValuesStrings& aStrings,
      28             :                          const nsAString& aValue, Enum aDefaultValue) {
      29           0 :   for (size_t i = 0; aStrings[i].value; i++) {
      30           0 :     if (aValue.EqualsASCII(aStrings[i].value)) {
      31           0 :       return Enum(i);
      32             :     }
      33             :   }
      34           0 :   return aDefaultValue;
      35             : }
      36             : 
      37             : // Helper classes for orthogonal constraints without interdependencies.
      38             : // Instead of constraining values, constrain the constraints themselves.
      39             : 
      40           0 : class NormalizedConstraintSet
      41             : {
      42             : protected:
      43           0 :   class BaseRange
      44             :   {
      45             :   protected:
      46             :     typedef BaseRange NormalizedConstraintSet::* MemberPtrType;
      47             : 
      48           0 :     BaseRange(MemberPtrType aMemberPtr, const char* aName,
      49           0 :               nsTArray<MemberPtrType>* aList) : mName(aName) {
      50           0 :       if (aList) {
      51           0 :         aList->AppendElement(aMemberPtr);
      52             :       }
      53           0 :     }
      54           0 :     virtual ~BaseRange() {}
      55             :   public:
      56             :     virtual bool Merge(const BaseRange& aOther) = 0;
      57             :     virtual void FinalizeMerge() = 0;
      58             : 
      59             :     const char* mName;
      60             :   };
      61             : 
      62             :   typedef BaseRange NormalizedConstraintSet::* MemberPtrType;
      63             : 
      64             : public:
      65             :   template<class ValueType>
      66           0 :   class Range : public BaseRange
      67             :   {
      68             :   public:
      69             :     ValueType mMin, mMax;
      70             :     Maybe<ValueType> mIdeal;
      71             : 
      72           0 :     Range(MemberPtrType aMemberPtr, const char* aName, ValueType aMin,
      73             :           ValueType aMax, nsTArray<MemberPtrType>* aList)
      74             :       : BaseRange(aMemberPtr, aName, aList)
      75           0 :       , mMin(aMin), mMax(aMax), mMergeDenominator(0) {}
      76           0 :     virtual ~Range() {};
      77             : 
      78             :     template<class ConstrainRange>
      79             :     void SetFrom(const ConstrainRange& aOther);
      80           0 :     ValueType Clamp(ValueType n) const { return std::max(mMin, std::min(n, mMax)); }
      81           0 :     ValueType Get(ValueType defaultValue) const {
      82           0 :       return Clamp(mIdeal.valueOr(defaultValue));
      83             :     }
      84           0 :     bool Intersects(const Range& aOther) const {
      85           0 :       return mMax >= aOther.mMin && mMin <= aOther.mMax;
      86             :     }
      87           0 :     void Intersect(const Range& aOther) {
      88           0 :       MOZ_ASSERT(Intersects(aOther));
      89           0 :       mMin = std::max(mMin, aOther.mMin);
      90           0 :       mMax = std::min(mMax, aOther.mMax);
      91           0 :     }
      92           0 :     bool Merge(const Range& aOther) {
      93           0 :       if (!Intersects(aOther)) {
      94           0 :         return false;
      95             :       }
      96           0 :       Intersect(aOther);
      97             : 
      98           0 :       if (aOther.mIdeal.isSome()) {
      99             :         // Ideal values, as stored, may be outside their min max range, so use
     100             :         // clamped values in averaging, to avoid extreme outliers skewing results.
     101           0 :         if (mIdeal.isNothing()) {
     102           0 :           mIdeal.emplace(aOther.Get(0));
     103           0 :           mMergeDenominator = 1;
     104             :         } else {
     105           0 :           if (!mMergeDenominator) {
     106           0 :             *mIdeal = Get(0);
     107           0 :             mMergeDenominator = 1;
     108             :           }
     109           0 :           *mIdeal += aOther.Get(0);
     110           0 :           mMergeDenominator++;
     111             :         }
     112             :       }
     113           0 :       return true;
     114             :     }
     115           0 :     void FinalizeMerge() override
     116             :     {
     117           0 :       if (mMergeDenominator) {
     118           0 :         *mIdeal /= mMergeDenominator;
     119           0 :         mMergeDenominator = 0;
     120             :       }
     121           0 :     }
     122           0 :     void TakeHighestIdeal(const Range& aOther) {
     123           0 :       if (aOther.mIdeal.isSome()) {
     124           0 :         if (mIdeal.isNothing()) {
     125           0 :           mIdeal.emplace(aOther.Get(0));
     126             :         } else {
     127           0 :           *mIdeal = std::max(Get(0), aOther.Get(0));
     128             :         }
     129             :       }
     130           0 :     }
     131             :   private:
     132           0 :     bool Merge(const BaseRange& aOther) override {
     133           0 :       return Merge(static_cast<const Range&>(aOther));
     134             :     }
     135             : 
     136             :     uint32_t mMergeDenominator;
     137             :   };
     138             : 
     139           0 :   struct LongRange : public Range<int32_t>
     140             :   {
     141             :     typedef LongRange NormalizedConstraintSet::* LongPtrType;
     142             : 
     143             :     LongRange(LongPtrType aMemberPtr, const char* aName,
     144             :               const dom::OwningLongOrConstrainLongRange& aOther, bool advanced,
     145             :               nsTArray<MemberPtrType>* aList);
     146             :   };
     147             : 
     148           0 :   struct LongLongRange : public Range<int64_t>
     149             :   {
     150             :     typedef LongLongRange NormalizedConstraintSet::* LongLongPtrType;
     151             : 
     152             :     LongLongRange(LongLongPtrType aMemberPtr, const char* aName,
     153             :                   const long long& aOther,
     154             :                   nsTArray<MemberPtrType>* aList);
     155             :   };
     156             : 
     157           0 :   struct DoubleRange : public Range<double>
     158             :   {
     159             :     typedef DoubleRange NormalizedConstraintSet::* DoublePtrType;
     160             : 
     161             :     DoubleRange(DoublePtrType aMemberPtr,
     162             :                 const char* aName,
     163             :                 const dom::OwningDoubleOrConstrainDoubleRange& aOther,
     164             :                 bool advanced,
     165             :                 nsTArray<MemberPtrType>* aList);
     166             :   };
     167             : 
     168           0 :   struct BooleanRange : public Range<bool>
     169             :   {
     170             :     typedef BooleanRange NormalizedConstraintSet::* BooleanPtrType;
     171             : 
     172             :     BooleanRange(BooleanPtrType aMemberPtr, const char* aName,
     173             :                  const dom::OwningBooleanOrConstrainBooleanParameters& aOther,
     174             :                  bool advanced,
     175             :                  nsTArray<MemberPtrType>* aList);
     176             : 
     177           0 :     BooleanRange(BooleanPtrType aMemberPtr, const char* aName, const bool& aOther,
     178             :                  nsTArray<MemberPtrType>* aList)
     179           0 :       : Range<bool>((MemberPtrType)aMemberPtr, aName, false, true, aList) {
     180           0 :       mIdeal.emplace(aOther);
     181           0 :     }
     182             :   };
     183             : 
     184           0 :   struct StringRange : public BaseRange
     185             :   {
     186             :     typedef std::set<nsString> ValueType;
     187             :     ValueType mExact, mIdeal;
     188             : 
     189             :     typedef StringRange NormalizedConstraintSet::* StringPtrType;
     190             : 
     191             :     StringRange(StringPtrType aMemberPtr,  const char* aName,
     192             :         const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters& aOther,
     193             :         bool advanced,
     194             :         nsTArray<MemberPtrType>* aList);
     195             : 
     196           0 :     StringRange(StringPtrType aMemberPtr, const char* aName,
     197             :                 const nsString& aOther, nsTArray<MemberPtrType>* aList)
     198           0 :       : BaseRange((MemberPtrType)aMemberPtr, aName, aList) {
     199           0 :       mIdeal.insert(aOther);
     200           0 :     }
     201             : 
     202           0 :     ~StringRange() {}
     203             : 
     204             :     void SetFrom(const dom::ConstrainDOMStringParameters& aOther);
     205             :     ValueType Clamp(const ValueType& n) const;
     206             :     ValueType Get(const ValueType& defaultValue) const {
     207             :       return Clamp(mIdeal.size() ? mIdeal : defaultValue);
     208             :     }
     209             :     bool Intersects(const StringRange& aOther) const;
     210             :     void Intersect(const StringRange& aOther);
     211             :     bool Merge(const StringRange& aOther);
     212           0 :     void FinalizeMerge() override {}
     213             :   private:
     214           0 :     bool Merge(const BaseRange& aOther) override {
     215           0 :       return Merge(static_cast<const StringRange&>(aOther));
     216             :     }
     217             :   };
     218             : 
     219             :   // All new constraints should be added here whether they use flattening or not
     220             :   LongRange mWidth, mHeight;
     221             :   DoubleRange mFrameRate;
     222             :   StringRange mFacingMode;
     223             :   StringRange mMediaSource;
     224             :   LongLongRange mBrowserWindow;
     225             :   BooleanRange mScrollWithPage;
     226             :   StringRange mDeviceId;
     227             :   LongRange mViewportOffsetX, mViewportOffsetY, mViewportWidth, mViewportHeight;
     228             :   BooleanRange mEchoCancellation, mNoiseSuppression, mAutoGainControl;
     229             :   LongRange mChannelCount;
     230             : private:
     231             :   typedef NormalizedConstraintSet T;
     232             : public:
     233           0 :   NormalizedConstraintSet(const dom::MediaTrackConstraintSet& aOther,
     234             :                           bool advanced,
     235             :                           nsTArray<MemberPtrType>* aList = nullptr)
     236           0 :   : mWidth(&T::mWidth, "width", aOther.mWidth, advanced, aList)
     237             :   , mHeight(&T::mHeight, "height", aOther.mHeight, advanced, aList)
     238             :   , mFrameRate(&T::mFrameRate, "frameRate", aOther.mFrameRate, advanced, aList)
     239             :   , mFacingMode(&T::mFacingMode, "facingMode", aOther.mFacingMode, advanced, aList)
     240             :   , mMediaSource(&T::mMediaSource, "mediaSource", aOther.mMediaSource, aList)
     241             :   , mBrowserWindow(&T::mBrowserWindow, "browserWindow",
     242           0 :                    aOther.mBrowserWindow.WasPassed() ?
     243           0 :                    aOther.mBrowserWindow.Value() : 0, aList)
     244             :   , mScrollWithPage(&T::mScrollWithPage, "scrollWithPage",
     245           0 :                     aOther.mScrollWithPage.WasPassed() ?
     246           0 :                     aOther.mScrollWithPage.Value() : false, aList)
     247             :   , mDeviceId(&T::mDeviceId, "deviceId", aOther.mDeviceId, advanced, aList)
     248             :   , mViewportOffsetX(&T::mViewportOffsetX, "viewportOffsetX",
     249             :                      aOther.mViewportOffsetX, advanced, aList)
     250             :   , mViewportOffsetY(&T::mViewportOffsetY, "viewportOffsetY",
     251             :                      aOther.mViewportOffsetY, advanced, aList)
     252             :   , mViewportWidth(&T::mViewportWidth, "viewportWidth",
     253             :                    aOther.mViewportWidth, advanced, aList)
     254             :   , mViewportHeight(&T::mViewportHeight, "viewportHeight",
     255             :                     aOther.mViewportHeight, advanced, aList)
     256             :   , mEchoCancellation(&T::mEchoCancellation, "echoCancellation",
     257             :                       aOther.mEchoCancellation, advanced, aList)
     258             :   , mNoiseSuppression(&T::mNoiseSuppression, "noiseSuppression",
     259             :                       aOther.mNoiseSuppression,
     260             :                       advanced, aList)
     261             :   , mAutoGainControl(&T::mAutoGainControl, "autoGainControl",
     262             :                      aOther.mAutoGainControl, advanced, aList)
     263             :   , mChannelCount(&T::mChannelCount, "channelCount",
     264           0 :                   aOther.mChannelCount, advanced, aList) {}
     265             : };
     266             : 
     267             : template<> bool NormalizedConstraintSet::Range<bool>::Merge(const Range& aOther);
     268             : template<> void NormalizedConstraintSet::Range<bool>::FinalizeMerge();
     269             : 
     270             : // Used instead of MediaTrackConstraints in lower-level code.
     271           0 : struct NormalizedConstraints : public NormalizedConstraintSet
     272             : {
     273             :   explicit NormalizedConstraints(const dom::MediaTrackConstraints& aOther,
     274             :                         nsTArray<MemberPtrType>* aList = nullptr);
     275             : 
     276             :   // Merge constructor
     277             :   explicit NormalizedConstraints(
     278             :       const nsTArray<const NormalizedConstraints*>& aOthers);
     279             : 
     280             :   std::vector<NormalizedConstraintSet> mAdvanced;
     281             :   const char* mBadConstraint;
     282             : };
     283             : 
     284             : // Flattened version is used in low-level code with orthogonal constraints only.
     285           0 : struct FlattenedConstraints : public NormalizedConstraintSet
     286             : {
     287             :   explicit FlattenedConstraints(const NormalizedConstraints& aOther);
     288             : 
     289           0 :   explicit FlattenedConstraints(const dom::MediaTrackConstraints& aOther)
     290           0 :     : FlattenedConstraints(NormalizedConstraints(aOther)) {}
     291             : };
     292             : 
     293             : // A helper class for MediaEngines
     294             : 
     295           0 : class MediaConstraintsHelper
     296             : {
     297             : protected:
     298             :   template<class ValueType, class NormalizedRange>
     299             :   static uint32_t FitnessDistance(ValueType aN, const NormalizedRange& aRange);
     300             :   static uint32_t FitnessDistance(nsString aN,
     301             :       const NormalizedConstraintSet::StringRange& aConstraint);
     302             : 
     303             :   static uint32_t
     304             :   GetMinimumFitnessDistance(const NormalizedConstraintSet &aConstraints,
     305             :                             const nsString& aDeviceId);
     306             : 
     307             :   template<class DeviceType>
     308             :   static bool
     309           0 :   SomeSettingsFit(const NormalizedConstraints &aConstraints,
     310             :                   nsTArray<RefPtr<DeviceType>>& aDevices)
     311             :   {
     312           0 :     nsTArray<const NormalizedConstraintSet*> sets;
     313           0 :     sets.AppendElement(&aConstraints);
     314             : 
     315           0 :     MOZ_ASSERT(aDevices.Length());
     316           0 :     for (auto& device : aDevices) {
     317           0 :       if (device->GetBestFitnessDistance(sets, false) != UINT32_MAX) {
     318           0 :         return true;
     319             :       }
     320             :     }
     321           0 :     return false;
     322             :   }
     323             : 
     324             : public:
     325             :   // Apply constrains to a supplied list of devices (removes items from the list)
     326             : 
     327             :   template<class DeviceType>
     328             :   static const char*
     329           0 :   SelectSettings(const NormalizedConstraints &aConstraints,
     330             :                  nsTArray<RefPtr<DeviceType>>& aDevices,
     331             :                  bool aIsChrome)
     332             :   {
     333           0 :     auto& c = aConstraints;
     334             : 
     335             :     // First apply top-level constraints.
     336             : 
     337             :     // Stack constraintSets that pass, starting with the required one, because the
     338             :     // whole stack must be re-satisfied each time a capability-set is ruled out
     339             :     // (this avoids storing state or pushing algorithm into the lower-level code).
     340           0 :     nsTArray<RefPtr<DeviceType>> unsatisfactory;
     341           0 :     nsTArray<const NormalizedConstraintSet*> aggregateConstraints;
     342           0 :     aggregateConstraints.AppendElement(&c);
     343             : 
     344           0 :     std::multimap<uint32_t, RefPtr<DeviceType>> ordered;
     345             : 
     346           0 :     for (uint32_t i = 0; i < aDevices.Length();) {
     347           0 :       uint32_t distance = aDevices[i]->GetBestFitnessDistance(aggregateConstraints,
     348           0 :                                                               aIsChrome);
     349           0 :       if (distance == UINT32_MAX) {
     350           0 :         unsatisfactory.AppendElement(aDevices[i]);
     351           0 :         aDevices.RemoveElementAt(i);
     352             :       } else {
     353           0 :         ordered.insert(std::pair<uint32_t, RefPtr<DeviceType>>(distance,
     354           0 :                                                                aDevices[i]));
     355           0 :         ++i;
     356             :       }
     357             :     }
     358           0 :     if (!aDevices.Length()) {
     359           0 :       return FindBadConstraint(c, unsatisfactory);
     360             :     }
     361             : 
     362             :     // Order devices by shortest distance
     363           0 :     for (auto& ordinal : ordered) {
     364           0 :       aDevices.RemoveElement(ordinal.second);
     365           0 :       aDevices.AppendElement(ordinal.second);
     366             :     }
     367             : 
     368             :     // Then apply advanced constraints.
     369             : 
     370           0 :     for (int i = 0; i < int(c.mAdvanced.size()); i++) {
     371           0 :       aggregateConstraints.AppendElement(&c.mAdvanced[i]);
     372           0 :       nsTArray<RefPtr<DeviceType>> rejects;
     373           0 :       for (uint32_t j = 0; j < aDevices.Length();) {
     374           0 :         if (aDevices[j]->GetBestFitnessDistance(aggregateConstraints,
     375           0 :                                                 aIsChrome) == UINT32_MAX) {
     376           0 :           rejects.AppendElement(aDevices[j]);
     377           0 :           aDevices.RemoveElementAt(j);
     378             :         } else {
     379           0 :           ++j;
     380             :         }
     381             :       }
     382           0 :       if (!aDevices.Length()) {
     383           0 :         aDevices.AppendElements(Move(rejects));
     384           0 :         aggregateConstraints.RemoveElementAt(aggregateConstraints.Length() - 1);
     385             :       }
     386             :     }
     387           0 :     return nullptr;
     388             :   }
     389             : 
     390             :   template<class DeviceType>
     391             :   static const char*
     392           0 :   FindBadConstraint(const NormalizedConstraints& aConstraints,
     393             :                     nsTArray<RefPtr<DeviceType>>& aDevices)
     394             :   {
     395             :     // The spec says to report a constraint that satisfies NONE
     396             :     // of the sources. Unfortunately, this is a bit laborious to find out, and
     397             :     // requires updating as new constraints are added!
     398           0 :     auto& c = aConstraints;
     399           0 :     dom::MediaTrackConstraints empty;
     400             : 
     401           0 :     if (!aDevices.Length() ||
     402           0 :         !SomeSettingsFit(NormalizedConstraints(empty), aDevices)) {
     403           0 :       return "";
     404             :     }
     405             :     {
     406           0 :       NormalizedConstraints fresh(empty);
     407           0 :       fresh.mDeviceId = c.mDeviceId;
     408           0 :       if (!SomeSettingsFit(fresh, aDevices)) {
     409           0 :         return "deviceId";
     410             :       }
     411             :     }
     412             :     {
     413           0 :       NormalizedConstraints fresh(empty);
     414           0 :       fresh.mWidth = c.mWidth;
     415           0 :       if (!SomeSettingsFit(fresh, aDevices)) {
     416           0 :         return "width";
     417             :       }
     418             :     }
     419             :     {
     420           0 :       NormalizedConstraints fresh(empty);
     421           0 :       fresh.mHeight = c.mHeight;
     422           0 :       if (!SomeSettingsFit(fresh, aDevices)) {
     423           0 :         return "height";
     424             :       }
     425             :     }
     426             :     {
     427           0 :       NormalizedConstraints fresh(empty);
     428           0 :       fresh.mFrameRate = c.mFrameRate;
     429           0 :       if (!SomeSettingsFit(fresh, aDevices)) {
     430           0 :         return "frameRate";
     431             :       }
     432             :     }
     433             :     {
     434           0 :       NormalizedConstraints fresh(empty);
     435           0 :       fresh.mFacingMode = c.mFacingMode;
     436           0 :       if (!SomeSettingsFit(fresh, aDevices)) {
     437           0 :         return "facingMode";
     438             :       }
     439             :     }
     440           0 :     return "";
     441             :   }
     442             : 
     443             :   template<class MediaEngineSourceType>
     444             :   static const char*
     445             :   FindBadConstraint(const NormalizedConstraints& aConstraints,
     446             :                     const MediaEngineSourceType& aMediaEngineSource,
     447             :                     const nsString& aDeviceId);
     448             : 
     449             :   // Warn on and convert use of deprecated constraints to new ones
     450             : 
     451             :   static void
     452             :   ConvertOldWithWarning(
     453             :       const dom::OwningBooleanOrConstrainBooleanParameters& old,
     454             :       dom::OwningBooleanOrConstrainBooleanParameters& to,
     455             :       const char* aMessageName,
     456             :       nsPIDOMWindowInner* aWindow);
     457             : };
     458             : 
     459             : } // namespace mozilla
     460             : 
     461             : #endif /* MEDIATRACKCONSTRAINTS_H_ */

Generated by: LCOV version 1.13