Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/webrtc/MediaTrackConstraints.h
Line
Count
Source (jump to first uncovered line)
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 <map>
11
#include <set>
12
#include <vector>
13
14
#include "mozilla/Attributes.h"
15
#include "mozilla/dom/MediaStreamTrackBinding.h"
16
#include "mozilla/dom/MediaTrackConstraintSetBinding.h"
17
#include "mozilla/dom/MediaTrackSupportedConstraintsBinding.h"
18
19
namespace mozilla {
20
21
class MediaDevice;
22
class MediaEngineSource;
23
24
template<class EnumValuesStrings, class Enum>
25
static const char* EnumToASCII(const EnumValuesStrings& aStrings, Enum aValue) {
26
  return aStrings[uint32_t(aValue)].value;
27
}
28
29
template<class EnumValuesStrings, class Enum>
30
static Enum StringToEnum(const EnumValuesStrings& aStrings,
31
                         const nsAString& aValue, Enum aDefaultValue) {
32
  for (size_t i = 0; aStrings[i].value; i++) {
33
    if (aValue.EqualsASCII(aStrings[i].value)) {
34
      return Enum(i);
35
    }
36
  }
37
  return aDefaultValue;
38
}
39
40
// Helper classes for orthogonal constraints without interdependencies.
41
// Instead of constraining values, constrain the constraints themselves.
42
class NormalizedConstraintSet
43
{
44
protected:
45
  class BaseRange
46
  {
47
  protected:
48
    typedef BaseRange NormalizedConstraintSet::* MemberPtrType;
49
50
    BaseRange(MemberPtrType aMemberPtr, const char* aName,
51
0
              nsTArray<MemberPtrType>* aList) : mName(aName) {
52
0
      if (aList) {
53
0
        aList->AppendElement(aMemberPtr);
54
0
      }
55
0
    }
56
    virtual ~BaseRange() {}
57
  public:
58
    virtual bool Merge(const BaseRange& aOther) = 0;
59
    virtual void FinalizeMerge() = 0;
60
61
    const char* mName;
62
  };
63
64
  typedef BaseRange NormalizedConstraintSet::* MemberPtrType;
65
66
public:
67
  template<class ValueType>
68
  class Range : public BaseRange
69
  {
70
  public:
71
    ValueType mMin, mMax;
72
    Maybe<ValueType> mIdeal;
73
74
    Range(MemberPtrType aMemberPtr, const char* aName, ValueType aMin,
75
          ValueType aMax, nsTArray<MemberPtrType>* aList)
76
      : BaseRange(aMemberPtr, aName, aList)
77
0
      , mMin(aMin), mMax(aMax), mMergeDenominator(0) {}
Unexecuted instantiation: mozilla::NormalizedConstraintSet::Range<bool>::Range(mozilla::NormalizedConstraintSet::BaseRange mozilla::NormalizedConstraintSet::*, char const*, bool, bool, nsTArray<mozilla::NormalizedConstraintSet::BaseRange mozilla::NormalizedConstraintSet::*>*)
Unexecuted instantiation: mozilla::NormalizedConstraintSet::Range<int>::Range(mozilla::NormalizedConstraintSet::BaseRange mozilla::NormalizedConstraintSet::*, char const*, int, int, nsTArray<mozilla::NormalizedConstraintSet::BaseRange mozilla::NormalizedConstraintSet::*>*)
Unexecuted instantiation: mozilla::NormalizedConstraintSet::Range<long>::Range(mozilla::NormalizedConstraintSet::BaseRange mozilla::NormalizedConstraintSet::*, char const*, long, long, nsTArray<mozilla::NormalizedConstraintSet::BaseRange mozilla::NormalizedConstraintSet::*>*)
Unexecuted instantiation: mozilla::NormalizedConstraintSet::Range<double>::Range(mozilla::NormalizedConstraintSet::BaseRange mozilla::NormalizedConstraintSet::*, char const*, double, double, nsTArray<mozilla::NormalizedConstraintSet::BaseRange mozilla::NormalizedConstraintSet::*>*)
78
    virtual ~Range() {};
79
80
    template<class ConstrainRange>
81
    void SetFrom(const ConstrainRange& aOther);
82
0
    ValueType Clamp(ValueType n) const { return std::max(mMin, std::min(n, mMax)); }
83
0
    ValueType Get(ValueType defaultValue) const {
84
0
      return Clamp(mIdeal.valueOr(defaultValue));
85
0
    }
86
0
    bool Intersects(const Range& aOther) const {
87
0
      return mMax >= aOther.mMin && mMin <= aOther.mMax;
88
0
    }
89
0
    void Intersect(const Range& aOther) {
90
0
      mMin = std::max(mMin, aOther.mMin);
91
0
      if (Intersects(aOther)) {
92
0
        mMax = std::min(mMax, aOther.mMax);
93
0
      } else {
94
0
        // If there is no intersection, we will down-scale or drop frame
95
0
        mMax = std::max(mMax, aOther.mMax);
96
0
      }
97
0
    }
98
    bool Merge(const Range& aOther) {
99
      if (strcmp(mName, "width") != 0 &&
100
          strcmp(mName, "height") != 0 &&
101
          strcmp(mName, "frameRate") != 0 &&
102
          !Intersects(aOther)) {
103
        return false;
104
      }
105
      Intersect(aOther);
106
107
      if (aOther.mIdeal.isSome()) {
108
        // Ideal values, as stored, may be outside their min max range, so use
109
        // clamped values in averaging, to avoid extreme outliers skewing results.
110
        if (mIdeal.isNothing()) {
111
          mIdeal.emplace(aOther.Get(0));
112
          mMergeDenominator = 1;
113
        } else {
114
          if (!mMergeDenominator) {
115
            *mIdeal = Get(0);
116
            mMergeDenominator = 1;
117
          }
118
          *mIdeal += aOther.Get(0);
119
          mMergeDenominator++;
120
        }
121
      }
122
      return true;
123
    }
124
    void FinalizeMerge() override
125
    {
126
      if (mMergeDenominator) {
127
        *mIdeal /= mMergeDenominator;
128
        mMergeDenominator = 0;
129
      }
130
    }
131
0
    void TakeHighestIdeal(const Range& aOther) {
132
0
      if (aOther.mIdeal.isSome()) {
133
0
        if (mIdeal.isNothing()) {
134
0
          mIdeal.emplace(aOther.Get(0));
135
0
        } else {
136
0
          *mIdeal = std::max(Get(0), aOther.Get(0));
137
0
        }
138
0
      }
139
0
    }
Unexecuted instantiation: mozilla::NormalizedConstraintSet::Range<int>::TakeHighestIdeal(mozilla::NormalizedConstraintSet::Range<int> const&)
Unexecuted instantiation: mozilla::NormalizedConstraintSet::Range<double>::TakeHighestIdeal(mozilla::NormalizedConstraintSet::Range<double> const&)
140
  private:
141
    bool Merge(const BaseRange& aOther) override {
142
      return Merge(static_cast<const Range&>(aOther));
143
    }
144
145
    uint32_t mMergeDenominator;
146
  };
147
148
  struct LongRange : public Range<int32_t>
149
  {
150
    typedef LongRange NormalizedConstraintSet::* LongPtrType;
151
152
    LongRange(LongPtrType aMemberPtr, const char* aName,
153
              const dom::OwningLongOrConstrainLongRange& aOther, bool advanced,
154
              nsTArray<MemberPtrType>* aList);
155
  };
156
157
  struct LongLongRange : public Range<int64_t>
158
  {
159
    typedef LongLongRange NormalizedConstraintSet::* LongLongPtrType;
160
161
    LongLongRange(LongLongPtrType aMemberPtr, const char* aName,
162
                  const long long& aOther,
163
                  nsTArray<MemberPtrType>* aList);
164
  };
165
166
  struct DoubleRange : public Range<double>
167
  {
168
    typedef DoubleRange NormalizedConstraintSet::* DoublePtrType;
169
170
    DoubleRange(DoublePtrType aMemberPtr,
171
                const char* aName,
172
                const dom::OwningDoubleOrConstrainDoubleRange& aOther,
173
                bool advanced,
174
                nsTArray<MemberPtrType>* aList);
175
  };
176
177
  struct BooleanRange : public Range<bool>
178
  {
179
    typedef BooleanRange NormalizedConstraintSet::* BooleanPtrType;
180
181
    BooleanRange(BooleanPtrType aMemberPtr, const char* aName,
182
                 const dom::OwningBooleanOrConstrainBooleanParameters& aOther,
183
                 bool advanced,
184
                 nsTArray<MemberPtrType>* aList);
185
186
    BooleanRange(BooleanPtrType aMemberPtr, const char* aName, const bool& aOther,
187
                 nsTArray<MemberPtrType>* aList)
188
0
      : Range<bool>((MemberPtrType)aMemberPtr, aName, false, true, aList) {
189
0
      mIdeal.emplace(aOther);
190
0
    }
191
  };
192
193
  struct StringRange : public BaseRange
194
  {
195
    typedef std::set<nsString> ValueType;
196
    ValueType mExact, mIdeal;
197
198
    typedef StringRange NormalizedConstraintSet::* StringPtrType;
199
200
    StringRange(StringPtrType aMemberPtr,  const char* aName,
201
        const dom::OwningStringOrStringSequenceOrConstrainDOMStringParameters& aOther,
202
        bool advanced,
203
        nsTArray<MemberPtrType>* aList);
204
205
    StringRange(StringPtrType aMemberPtr, const char* aName,
206
                const nsString& aOther, nsTArray<MemberPtrType>* aList)
207
0
      : BaseRange((MemberPtrType)aMemberPtr, aName, aList) {
208
0
      mIdeal.insert(aOther);
209
0
    }
210
211
    ~StringRange() {}
212
213
    void SetFrom(const dom::ConstrainDOMStringParameters& aOther);
214
    ValueType Clamp(const ValueType& n) const;
215
    ValueType Get(const ValueType& defaultValue) const {
216
      return Clamp(mIdeal.empty() ? defaultValue : mIdeal);
217
    }
218
    bool Intersects(const StringRange& aOther) const;
219
    void Intersect(const StringRange& aOther);
220
    bool Merge(const StringRange& aOther);
221
    void FinalizeMerge() override {}
222
  private:
223
    bool Merge(const BaseRange& aOther) override {
224
      return Merge(static_cast<const StringRange&>(aOther));
225
    }
226
  };
227
228
  // All new constraints should be added here whether they use flattening or not
229
  LongRange mWidth, mHeight;
230
  DoubleRange mFrameRate;
231
  StringRange mFacingMode;
232
  StringRange mMediaSource;
233
  LongLongRange mBrowserWindow;
234
  BooleanRange mScrollWithPage;
235
  StringRange mDeviceId;
236
  LongRange mViewportOffsetX, mViewportOffsetY, mViewportWidth, mViewportHeight;
237
  BooleanRange mEchoCancellation, mNoiseSuppression, mAutoGainControl;
238
  LongRange mChannelCount;
239
private:
240
  typedef NormalizedConstraintSet T;
241
public:
242
  NormalizedConstraintSet(const dom::MediaTrackConstraintSet& aOther,
243
                          bool advanced,
244
                          nsTArray<MemberPtrType>* aList = nullptr)
245
  : mWidth(&T::mWidth, "width", aOther.mWidth, advanced, aList)
246
  , mHeight(&T::mHeight, "height", aOther.mHeight, advanced, aList)
247
  , mFrameRate(&T::mFrameRate, "frameRate", aOther.mFrameRate, advanced, aList)
248
  , mFacingMode(&T::mFacingMode, "facingMode", aOther.mFacingMode, advanced, aList)
249
  , mMediaSource(&T::mMediaSource, "mediaSource", aOther.mMediaSource, aList)
250
  , mBrowserWindow(&T::mBrowserWindow, "browserWindow",
251
                   aOther.mBrowserWindow.WasPassed() ?
252
                   aOther.mBrowserWindow.Value() : 0, aList)
253
  , mScrollWithPage(&T::mScrollWithPage, "scrollWithPage",
254
                    aOther.mScrollWithPage.WasPassed() ?
255
                    aOther.mScrollWithPage.Value() : false, aList)
256
  , mDeviceId(&T::mDeviceId, "deviceId", aOther.mDeviceId, advanced, aList)
257
  , mViewportOffsetX(&T::mViewportOffsetX, "viewportOffsetX",
258
                     aOther.mViewportOffsetX, advanced, aList)
259
  , mViewportOffsetY(&T::mViewportOffsetY, "viewportOffsetY",
260
                     aOther.mViewportOffsetY, advanced, aList)
261
  , mViewportWidth(&T::mViewportWidth, "viewportWidth",
262
                   aOther.mViewportWidth, advanced, aList)
263
  , mViewportHeight(&T::mViewportHeight, "viewportHeight",
264
                    aOther.mViewportHeight, advanced, aList)
265
  , mEchoCancellation(&T::mEchoCancellation, "echoCancellation",
266
                      aOther.mEchoCancellation, advanced, aList)
267
  , mNoiseSuppression(&T::mNoiseSuppression, "noiseSuppression",
268
                      aOther.mNoiseSuppression,
269
                      advanced, aList)
270
  , mAutoGainControl(&T::mAutoGainControl, "autoGainControl",
271
                     aOther.mAutoGainControl, advanced, aList)
272
  , mChannelCount(&T::mChannelCount, "channelCount",
273
0
                  aOther.mChannelCount, advanced, aList) {}
274
};
275
276
template<> bool NormalizedConstraintSet::Range<bool>::Merge(const Range& aOther);
277
template<> void NormalizedConstraintSet::Range<bool>::FinalizeMerge();
278
279
// Used instead of MediaTrackConstraints in lower-level code.
280
struct NormalizedConstraints : public NormalizedConstraintSet
281
{
282
  explicit NormalizedConstraints(const dom::MediaTrackConstraints& aOther,
283
                        nsTArray<MemberPtrType>* aList = nullptr);
284
285
  // Merge constructor
286
  explicit NormalizedConstraints(
287
      const nsTArray<const NormalizedConstraints*>& aOthers);
288
289
  std::vector<NormalizedConstraintSet> mAdvanced;
290
  const char* mBadConstraint;
291
};
292
293
// Flattened version is used in low-level code with orthogonal constraints only.
294
struct FlattenedConstraints : public NormalizedConstraintSet
295
{
296
  explicit FlattenedConstraints(const NormalizedConstraints& aOther);
297
298
  explicit FlattenedConstraints(const dom::MediaTrackConstraints& aOther)
299
0
    : FlattenedConstraints(NormalizedConstraints(aOther)) {}
300
};
301
302
// A helper class for MediaEngineSources
303
class MediaConstraintsHelper
304
{
305
public:
306
  template<class ValueType, class NormalizedRange>
307
  static uint32_t FitnessDistance(ValueType aN, const NormalizedRange& aRange);
308
  template<class ValueType, class NormalizedRange>
309
  static uint32_t FeasibilityDistance(ValueType aN, const NormalizedRange& aRange);
310
  static uint32_t FitnessDistance(nsString aN,
311
      const NormalizedConstraintSet::StringRange& aConstraint);
312
protected:
313
314
  static bool
315
  SomeSettingsFit(const NormalizedConstraints &aConstraints,
316
                  const nsTArray<RefPtr<MediaDevice>>& aDevices);
317
318
public:
319
320
  static uint32_t
321
  GetMinimumFitnessDistance(const NormalizedConstraintSet &aConstraints,
322
                            const nsString& aDeviceId);
323
324
  // Apply constrains to a supplied list of devices (removes items from the list)
325
  static const char*
326
  SelectSettings(
327
      const NormalizedConstraints& aConstraints,
328
      nsTArray<RefPtr<MediaDevice>>& aDevices,
329
      bool aIsChrome);
330
331
  static const char*
332
  FindBadConstraint(const NormalizedConstraints& aConstraints,
333
                    const nsTArray<RefPtr<MediaDevice>>& aDevices);
334
335
  static const char*
336
  FindBadConstraint(const NormalizedConstraints& aConstraints,
337
                    const RefPtr<MediaEngineSource>& aMediaEngineSource,
338
                    const nsString& aDeviceId);
339
340
  // Warn on and convert use of deprecated constraints to new ones
341
  static void
342
  ConvertOldWithWarning(
343
      const dom::OwningBooleanOrConstrainBooleanParameters& old,
344
      dom::OwningBooleanOrConstrainBooleanParameters& to,
345
      const char* aMessageName,
346
      nsPIDOMWindowInner* aWindow);
347
};
348
349
} // namespace mozilla
350
351
#endif /* MEDIATRACKCONSTRAINTS_H_ */