/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_ */ |