Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(338)

Side by Side Diff: content/renderer/media/media_stream_constraints_util_sets.h

Issue 2728633002: Add utility set classes to support getUserMedia constraint proccessing. (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_CONSTRAINTS_UTIL_SETS_H_
6 #define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_CONSTRAINTS_UTIL_SETS_H_
7
8 #include <algorithm>
9 #include <limits>
10 #include <utility>
11 #include <vector>
12
13 #include "base/gtest_prod_util.h"
14 #include "base/logging.h"
15 #include "content/common/content_export.h"
16 #include "media/base/limits.h"
17
18 namespace blink {
19 struct WebMediaTrackConstraintSet;
20 }
21
22 namespace content {
23
24 // This class template represents a set of candidates suitable for a numeric
25 // range-based constraint.
26 template <typename T>
27 class NumericRangeSet {
28 public:
29 NumericRangeSet() : min_(0), max_(DefaultMax()) {}
30 NumericRangeSet(T min, T max) : min_(min), max_(max) {}
31 NumericRangeSet(const NumericRangeSet& other) = default;
32 NumericRangeSet& operator=(const NumericRangeSet& other) = default;
33 ~NumericRangeSet() = default;
34
35 T Min() const { return min_; }
36 T Max() const { return max_; }
37 bool IsEmpty() const { return max_ < min_; }
38
39 NumericRangeSet Intersection(const NumericRangeSet& other) const {
40 return NumericRangeSet(std::max(min_, other.min_),
41 std::min(max_, other.max_));
42 }
43
44 // Creates a NumericRangeSet based on the minimum and maximum values of
45 // |constraint|.
46 template <typename ConstraintType>
47 static auto FromConstraint(ConstraintType constraint)
48 -> NumericRangeSet<decltype(constraint.min())> {
49 return NumericRangeSet<decltype(constraint.min())>(
50 ConstraintHasMin(constraint) ? ConstraintMin(constraint) : 0,
51 ConstraintHasMax(constraint) ? ConstraintMax(constraint)
52 : DefaultMax());
53 }
54
55 private:
56 static inline T DefaultMax() {
57 return std::numeric_limits<T>::has_infinity
58 ? std::numeric_limits<T>::infinity()
59 : std::numeric_limits<T>::max();
60 }
61 T min_;
62 T max_;
63 };
64
65 // This class defines a set of discrete elements suitable for resolving
66 // constraints with a countable number of choices not suitable to be constrained
67 // by range such as strings, booleans and certain constraints of type long.
hta - Chromium 2017/03/03 11:02:36 Better language: "... not suitable to be constrain
Guido Urdaneta 2017/03/06 11:08:23 Done.
68 // The set of elements of an unconstrained set is application defined.
hta - Chromium 2017/03/03 11:02:36 I don't understand what this sentence tries to say
hbos_chromium 2017/03/03 16:01:42 The unconstrained set is a set that conceptually c
Guido Urdaneta 2017/03/06 11:08:23 Addressed following hbos' suggestion.
Guido Urdaneta 2017/03/06 11:08:23 Done.
69 template <typename T>
70 class DiscreteSet {
71 public:
72 // Creates an unconstrained set.
73 DiscreteSet() : is_unconstrained_(true) {}
hbos_chromium 2017/03/03 16:01:42 I would prefer a static function similar to EmptyS
Guido Urdaneta 2017/03/06 11:08:23 Done. Also renamed is_unconstrained to is_universa
74 // Creates a set containing the elements in |elements|.
75 // It is the responsibility of the caller to ensure that |elements| is not
76 // equivalent to the unconstrained set and that |elements| has no repeated
77 // values. Takes ownership of |elements|.
78 explicit DiscreteSet(std::vector<T> elements)
79 : is_unconstrained_(false), elements_(std::move(elements)) {}
80 // Creates an empty set;
81 static DiscreteSet EmptySet() { return DiscreteSet(std::vector<T>()); }
82
83 DiscreteSet(const DiscreteSet& other) = default;
hta - Chromium 2017/03/03 11:02:36 C++ query: Is there any code-generation effect fro
Guido Urdaneta 2017/03/06 11:08:23 This is intended. I want the class to be copyable
84 DiscreteSet& operator=(const DiscreteSet& other) = default;
85 DiscreteSet(DiscreteSet&& other) = default;
86 DiscreteSet& operator=(DiscreteSet&& other) = default;
87 ~DiscreteSet() = default;
88
89 bool Contains(const T& value) const {
90 return is_unconstrained_ ||
91 std::find(elements_.begin(), elements_.end(), value) !=
92 elements_.end();
93 }
94
95 bool IsEmpty() const { return !is_unconstrained_ && elements_.empty(); }
96
97 bool IsNonEmptyFinite() const { return !elements_.empty(); }
98
99 DiscreteSet Intersection(const DiscreteSet& other) const {
100 if (is_unconstrained_)
101 return other;
102 if (other.is_unconstrained_)
103 return *this;
104 if (IsEmpty() || other.IsEmpty())
105 return EmptySet();
106
107 // Both sets are finite and nonempty.
hta - Chromium 2017/03/03 11:02:36 s/finite/constrained/
Guido Urdaneta 2017/03/06 11:08:23 Done. Changed the wording to both sets have explic
108 std::vector<T> intersection;
109 for (const auto& entry : elements_) {
110 auto it =
111 std::find(other.elements_.begin(), other.elements_.end(), entry);
112 if (it != other.elements_.end()) {
113 intersection.push_back(entry);
114 }
115 }
116 return DiscreteSet(std::move(intersection));
hbos_chromium 2017/03/03 16:01:42 std::set would yield O(n log n) instead of O(n^2)
Guido Urdaneta 2017/03/06 11:08:23 Yes. For small sets vector is faster and makes it
117 }
118
119 // Returns a copy of the first element in the set. This is useful as a simple
120 // tie-breaker rule.
hbos_chromium 2017/03/03 16:01:42 Add a comment saying that this is not applicable t
Guido Urdaneta 2017/03/06 11:08:23 Done.
121 T FirstElement() const {
122 DCHECK(IsNonEmptyFinite());
123 return elements_[0];
124 }
125
126 bool is_unconstrained() const { return is_unconstrained_; }
127
128 private:
129 bool is_unconstrained_;
130 std::vector<T> elements_;
hta - Chromium 2017/03/03 11:02:36 Query: Would this work with std::set<>? In that c
hbos_chromium 2017/03/03 16:01:42 (In that case this could be represented by an Opti
Guido Urdaneta 2017/03/06 11:08:23 Acknowledged.
Guido Urdaneta 2017/03/06 11:08:23 This type is basically a wrapper over std::vector
131 };
132
133 // This class represents a set of (height, width) screen resolution candidates
134 // determined by width, height and aspect-ratio constraints.
135 class CONTENT_EXPORT ResolutionSet {
136 public:
137 static constexpr int kMinConstrainedDimension = 1;
138 static constexpr int kMaxConstrainedDimension =
139 media::limits::kMaxDimension - 1;
hta - Chromium 2017/03/03 11:02:36 kMaxDimension is already 32767 - I think you're us
Guido Urdaneta 2017/03/06 11:08:23 Got rid of all the "Constrained" constants and met
140 static constexpr int kMinConstrainedAspectRatio =
141 static_cast<double>(kMinConstrainedDimension) /
142 static_cast<double>(kMaxConstrainedDimension);
143 static constexpr int kMaxConstrainedAspectRatio =
144 static_cast<double>(kMaxConstrainedDimension) /
145 static_cast<double>(kMinConstrainedDimension);
hbos_chromium 2017/03/03 16:01:42 Doesn't it make more sense to use max and min (not
Guido Urdaneta 2017/03/06 11:08:23 I think you're right. The class now just supports
146
147 // Helper class that represents (height, width) points on a plane.
148 class Point {
hta - Chromium 2017/03/03 11:02:36 I'm not sure of the value of another point class.
hbos_chromium 2017/03/03 16:01:42 Point uses int. There is gfx::PointF and gfx::Vect
Guido Urdaneta 2017/03/06 11:08:22 I prefer to keep this class (at least for one more
Guido Urdaneta 2017/03/06 11:08:23 See reply to hbos.
149 public:
150 // Creates a (|height|, |width|) point. |height| and |width| must be finite.
151 Point(double height, double width);
152 Point(const Point& other);
153 Point& operator=(const Point& other);
154 ~Point();
155
156 // Accessors.
157 double height() const { return height_; }
158 double width() const { return width_; }
159 double AspectRatio() const { return width_ / height_; }
hbos_chromium 2017/03/03 16:01:42 Watch out for divide by zero?
Guido Urdaneta 2017/03/06 11:08:22 divide by zero is fine in most cases. NaN (0/0 or
160
161 // Exact equality/inequality operators.
162 bool operator==(const Point& other) const;
163 bool operator!=(const Point& other) const;
164
165 // Returns true if both coordinates of this point and |other| are
166 // approximately equal.
167 bool IsApproximatelyEqualTo(const Point& other) const;
168
169 // Vector-style addition and subtraction operators.
170 Point operator+(const Point& other) const;
171 Point operator-(const Point& other) const;
172
173 // Returns the dot product between |p1| and |p2|.
174 static double Dot(const Point& p1, const Point& p2);
175
176 // Returns the square Euclidean distance from |p1| to |p2|.
hta - Chromium 2017/03/03 11:02:36 Does it return the square of the distance or the d
hbos_chromium 2017/03/03 16:01:42 It's the square, so the function should be renamed
Guido Urdaneta 2017/03/06 11:08:22 Renamed.
Guido Urdaneta 2017/03/06 11:08:23 Square Euclidean is still a distance :) But rename
177 static double DistanceToPoint(const Point& p1, const Point& p2);
178
179 // Returns the point in the line segment determined by |s1| and |s2| that
180 // is closest to |p|.
181 static Point ClosestPointInSegment(const Point& p,
182 const Point& s1,
183 const Point& s2);
184
185 private:
186 double height_;
187 double width_;
hbos_chromium 2017/03/03 16:01:42 The point has no width and height, only coordinate
Guido Urdaneta 2017/03/06 11:08:23 I like height and width better to avoid confusion
hbos_chromium 2017/03/08 21:03:00 The way I see it is: Input to the algorithm is wid
188 };
189
190 ResolutionSet(); // Creates an unconstrained candidate set.
191 ResolutionSet(int min_height,
192 int max_height,
193 int min_width,
194 int max_width,
195 double min_aspect_ratio,
196 double max_aspect_ratio);
197 ResolutionSet(const ResolutionSet& other);
198 ResolutionSet& operator=(const ResolutionSet& other);
199 ~ResolutionSet();
200
201 // Getters.
202 int min_height() const { return min_height_; }
203 int max_height() const { return max_height_; }
204 int min_width() const { return min_width_; }
205 int max_width() const { return max_width_; }
206 double min_aspect_ratio() const { return min_aspect_ratio_; }
207 double max_aspect_ratio() const { return max_aspect_ratio_; }
208
209 // Returns true if this set is empty.
210 bool IsEmpty() const;
211
212 // These functions return true if a particular constraint causes the set to
213 // be empty.
214 bool IsHeightEmpty() const;
215 bool IsWidthEmpty() const;
216 bool IsAspectRatioEmpty() const;
217
218 // These functions return true if a particular variable is constrained.
219 // MinHeight and MinWidth are unconstrained if their value is less than
220 // kMinValidDimension.
221 // MaxHeight and MaxWidth are unconstrained if their value is greater than
222 // kMaxValidDimension.
223 // MinAspectRatio is unconstrained if its value is 0.0 or less.
224 // MaxAspectRatio is unconstrained if its value is positive infinity.
225 bool HasMinHeight() const;
226 bool HasMaxHeight() const;
227 bool HasMinWidth() const;
228 bool HasMaxWidth() const;
229 bool HasMinAspectRatio() const;
230 bool HasMaxAspectRatio() const;
231
232 // These functions return true if a particular variable is unconstrained on
233 // both ends.
234 bool IsHeightUnconstrained() const;
235 bool IsWidthUnconstrained() const;
236 bool IsAspectRatioUnconstrained() const;
237
238 // Returns true if the point (height, width) is included in this set.
239 bool ContainsPoint(int height, int width) const;
240 bool ContainsPoint(const Point& point) const;
241
242 // Returns a new set with the intersection of |*this| and |other|.
243 ResolutionSet Intersection(const ResolutionSet& other) const;
244
245 // Returns the closest point in this set to |point|. If |point| is included in
246 // this set, Point is returned. If this set is empty, behavior is undefined.
247 Point ClosestPointTo(const Point& point) const;
248
249 // Returns a point in this (nonempty) set closest to the ideal values for the
250 // height, width and aspectRatio constraints in |constraint_set|.
251 // Note that this function ignores all the other data in |constraint_set|.
252 // Only the ideal height, width and aspect ratio are used, and from now on
253 // referred to as |ideal_height|, |ideal_width| and |ideal_aspect_ratio|
254 // respectively.
255 //
256 // * If all three ideal values are given, |ideal_aspect_ratio| is ignored and
257 // the point closest to (|ideal_height|, |ideal_width|) is returned.
hbos_chromium 2017/03/03 16:01:42 It doesn't matter but it surprised/confused me at
Guido Urdaneta 2017/03/06 11:08:23 Because it is easier to think of aspectRatio as a
hbos_chromium 2017/03/08 21:03:00 Acknowledged. If this at any point is replaced by
258 // * If two ideal values are given, they are used to determine a single ideal
259 // point, which can be one of:
260 // - (|ideal_height|, |ideal_width|),
261 // - (|ideal_height|, |ideal_height|*|ideal_aspect_ratio|), or
262 // - (|ideal_width| / |ideal_aspect_ratio|, |ideal_width|).
263 // The point in the set closest to the ideal point is returned.
264 // * If a single ideal value is given, a point in the set closest to the line
265 // defined by the ideal value is returned. If there is more than one point
266 // closest to the ideal line, the following tie-breaker rules are used:
267 // - If |ideal_height| is provided, the point closest to
268 // (|ideal_height|, |ideal_height| * kDefaultAspectRatio).
269 // - If |ideal_width| is provided, the point closest to
270 // (|ideal_width| / kDefaultAspectRatio, |ideal_width|).
271 // - If |ideal_aspect_ratio| is provided, the point with largest area among
272 // the points closest to
273 // (kDefaultHeight, kDefaultHeight * aspect_ratio) and
274 // (kDefaultWidth / aspect_ratio, kDefaultWidth),
275 // where aspect_ratio is |ideal_aspect_ratio| if the ideal line intersects
276 // the set, and the closest aspect ratio to |ideal_aspect_ratio| among the
277 // points in the set if no point in the set has an aspect ratio equal to
278 // |ideal_aspect_ratio|.
279 // * If no ideal value is given, proceed as if only |ideal_aspect_ratio| was
280 // provided with a value of kDefaultAspectRatio.
281 //
282 // This is intended to support the implementation of the spec algorithm for
283 // selection of track settings, as defined in
284 // https://w3c.github.io/mediacapture-main/#dfn-selectsettings.
285 //
286 // The main difference between this algorithm and the spec is that when ideal
287 // values are provided, the spec mandates finding a point that minimizes the
288 // sum of custom relative distances for each provided ideal value, while this
289 // algorithm minimizes either the Euclidean distance (sum of square distances)
290 // on a height-width plane for the cases where two or three ideal values are
291 // provided, or the absolute distance for the case with one ideal value.
292 // Also, in the case with three ideal values, this algorithm ignores the
293 // distance to the ideal aspect ratio.
294 // In most cases the difference in the final result should be negligible.
295 // The reason to follow this approach is that optimization in the worst case
296 // is reduced to projection of a point on line segment, which is a simple
297 // operation that provides exact results. Using the distance function of the
298 // spec, which is not continuous, would require complex optimization methods
299 // that do not necessarily guarantee finding the real optimal value.
300 //
301 // This function has undefined behavior if this set is empty.
302 Point SelectClosestPointToIdeal(
303 const blink::WebMediaTrackConstraintSet& constraint_set) const;
304
305 // Utilities that return ResolutionCandidateSets constrained on a specific
hta - Chromium 2017/03/03 11:02:36 They return |ResolutionSet|s, not ResolutionCandid
Guido Urdaneta 2017/03/06 11:08:23 Indeed a leftover. Done.
306 // variable.
307 static ResolutionSet FromHeight(int min, int max);
308 static ResolutionSet FromExactHeight(int value);
309 static ResolutionSet FromWidth(int min, int max);
310 static ResolutionSet FromExactWidth(int value);
311 static ResolutionSet FromAspectRatio(double min, double max);
312 static ResolutionSet FromExactAspectRatio(double value);
313
314 // Returns a ResolutionCandidateSet initialized with |constraint_set|'s
315 // width, height and aspectRatio constraints.
316 static ResolutionSet FromConstraintSet(
317 const blink::WebMediaTrackConstraintSet& constraint_set);
318
319 private:
320 FRIEND_TEST_ALL_PREFIXES(MediaStreamConstraintsUtilSetsTest,
321 ResolutionVertices);
322
323 // Returns a list of the vertices defined by the constraints on a height-width
324 // Cartesian plane.
325 // If the list is empty, the set is empty.
326 // If the list contains a single point, the set contains a single point.
327 // If the list contains two points, the set is composed of points on a line
328 // segment.
329 // If the list contains three to six points, they are the vertices of a
330 // convex polygon containing all valid points in the set. Each pair of
331 // consecutive vertices (modulo the size of the list) corresponds to a side of
332 // the polygon, with the vertices given in counterclockwise order.
333 // The list cannot contain more than six points.
334 std::vector<Point> ComputeVertices() const;
335
336 // Adds |point| to |vertices| if |point| is included in this candidate set.
337 void TryAddVertex(std::vector<ResolutionSet::Point>* vertices,
338 const ResolutionSet::Point& point) const;
339
340 // Returns the vertices of the set that have the property accessed
341 // by |accessor| closest to |value|. The returned vector always has one or two
342 // elements. Behavior is undefined if the set is empty.
343 std::vector<Point> GetClosestVertices(double (Point::*accessor)() const,
344 double value) const;
345
346 // Implements SelectClosestPointToIdeal() for the case when only the ideal
347 // aspect ratio is provided.
348 Point SelectClosestPointToIdealAspectRatio(double ideal_aspect_ratio) const;
349
350 int min_height_;
351 int max_height_;
352 int min_width_;
353 int max_width_;
354 double min_aspect_ratio_;
355 double max_aspect_ratio_;
356 };
357
358 // Scalar multiplication for Points.
359 ResolutionSet::Point CONTENT_EXPORT operator*(double d,
360 const ResolutionSet::Point& p);
361
362 } // namespace content
363
364 #endif // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_CONSTRAINTS_UTIL_SETS_H_
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698