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

Unified Diff: content/renderer/media/media_stream_constraints_util_sets.cc

Issue 2728633002: Add utility set classes to support getUserMedia constraint proccessing. (Closed)
Patch Set: Created 3 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: content/renderer/media/media_stream_constraints_util_sets.cc
diff --git a/content/renderer/media/media_stream_constraints_util_sets.cc b/content/renderer/media/media_stream_constraints_util_sets.cc
new file mode 100644
index 0000000000000000000000000000000000000000..022240160a523395d6f2d3fafaa4d2b6b684970a
--- /dev/null
+++ b/content/renderer/media/media_stream_constraints_util_sets.cc
@@ -0,0 +1,572 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/media_stream_constraints_util_sets.h"
+
+#include <cmath>
+
+#include "content/renderer/media/media_stream_constraints_util.h"
+#include "content/renderer/media/media_stream_video_source.h"
+#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
+
+namespace content {
+
+using Point = ResolutionSet::Point;
+
+namespace {
+
+constexpr double kTolerance = 1e-5;
+
+constexpr int kDefaultHeight = MediaStreamVideoSource::kDefaultHeight;
+constexpr int kDefaultWidth = MediaStreamVideoSource::kDefaultWidth;
+constexpr double kDefaultAspectRatio =
+ MediaStreamVideoSource::kDefaultAspectRatio;
+
+// Not perfect, but good enough for this application.
+bool AreApproximatelyEqual(double d1, double d2) {
+ if (std::fabs((d1 - d2)) <= kTolerance)
+ return true;
+
+ return d1 == d2 ||
hbos_chromium 2017/03/03 16:01:42 Isn't any value minus itself 0.0 even with finite
Guido Urdaneta 2017/03/06 11:08:22 No, it isn't in floating point. Inf-Inf is NaN. An
hbos_chromium 2017/03/08 21:03:00 Acknowledged.
+ (std::fabs((d1 - d2) / d1) <= kTolerance &&
+ std::fabs((d1 - d2) / d2) <= kTolerance);
hta - Chromium 2017/03/03 11:02:36 I'm trying to imagine a realistic case where you w
Guido Urdaneta 2017/03/06 11:08:22 d1=Inf, d2=Inf.
Guido Urdaneta 2017/03/06 15:08:21 The relative comparisons are for large values.
+}
+
+bool IsLess(double d1, double d2) {
+ return d1 < d2 && !AreApproximatelyEqual(d1, d2);
+}
+
+bool IsLessOrEqual(double d1, double d2) {
+ return d1 < d2 || AreApproximatelyEqual(d1, d2);
+}
+
+bool IsGreater(double d1, double d2) {
+ return d1 > d2 && !AreApproximatelyEqual(d1, d2);
+}
+
+bool IsGreaterOrEqual(double d1, double d2) {
+ return d1 > d2 || AreApproximatelyEqual(d1, d2);
+}
+
+int DimensionFromConstraintValue(long dimension) {
hta - Chromium 2017/03/03 11:02:36 Why return value int when argument is long? Consis
Guido Urdaneta 2017/03/06 11:08:22 This is intended to transform values coming from b
+ if (dimension > ResolutionSet::kMaxConstrainedDimension) {
+ return ResolutionSet::kMaxConstrainedDimension + 1;
+ } else if (dimension < ResolutionSet::kMinConstrainedDimension) {
+ return 0;
+ }
+
+ return static_cast<int>(dimension);
+}
+
+int MinDimensionFromConstraint(const blink::LongConstraint& constraint) {
+ if (!ConstraintHasMin(constraint))
+ return 0;
+
+ return DimensionFromConstraintValue(ConstraintMin(constraint));
+}
+
+int MaxDimensionFromConstraint(const blink::LongConstraint& constraint) {
+ if (!ConstraintHasMax(constraint))
+ return ResolutionSet::kMaxConstrainedDimension + 1;
+
+ return DimensionFromConstraintValue(ConstraintMax(constraint));
+}
+
+double AspectRatioFromConstraintValue(double aspect_ratio) {
+ return aspect_ratio < ResolutionSet::kMinConstrainedAspectRatio
+ ? 0.0
hta - Chromium 2017/03/03 11:02:36 Why 0.0 and not ResolutionSet::kMinConstrainedAspe
Guido Urdaneta 2017/03/06 11:08:22 The question became obsolete now that the concept
+ : aspect_ratio;
+}
+
+double MinAspectRatioFromConstraint(const blink::DoubleConstraint& constraint) {
+ if (!ConstraintHasMin(constraint))
+ return 0.0;
+
+ return AspectRatioFromConstraintValue(ConstraintMin(constraint));
+}
+
+double MaxAspectRatioFromConstraint(const blink::DoubleConstraint& constraint) {
+ if (!ConstraintHasMax(constraint))
+ return HUGE_VAL;
+
+ return AspectRatioFromConstraintValue(ConstraintMax(constraint));
+}
+
+// Utility to transform |dimension| to a value in the supported range.
+// Useful for ideal values.
+int ToValidConstrainedDimension(long dimension) {
hta - Chromium 2017/03/03 11:02:35 When you have these functions that change the valu
Guido Urdaneta 2017/03/06 11:08:22 Acknowledged. I removed the would-be Clamp functio
+ if (dimension > ResolutionSet::kMaxConstrainedDimension)
+ return ResolutionSet::kMaxConstrainedDimension;
+ else if (dimension < ResolutionSet::kMinConstrainedDimension)
+ return ResolutionSet::kMinConstrainedDimension;
+
+ return dimension;
+}
+
+// Utility to transform |aspect_ratio| to a value in the supported range.
+// Useful for ideal values.
+double ToValidConstrainedAspectRatio(double aspect_ratio) {
+ if (aspect_ratio > ResolutionSet::kMaxConstrainedAspectRatio)
+ return ResolutionSet::kMaxConstrainedAspectRatio;
+ else if (aspect_ratio < ResolutionSet::kMinConstrainedAspectRatio)
+ return ResolutionSet::kMinConstrainedAspectRatio;
+
+ return aspect_ratio;
+}
+
+// Returns the point in the segment determined by |vertices| closest to
+// |point|.
+// |vertices| must have 1 or 2 elements. Otherwise, behavior is undefined.
+Point GetClosestPoint(const std::vector<Point> vertices, const Point& point) {
hbos_chromium 2017/03/03 16:01:41 1-2 vertices: is this to avoid having to check if
Guido Urdaneta 2017/03/06 11:08:22 Done. Also expanded the documentation a bit.
+ DCHECK(!vertices.empty());
+ // If only a single vertex closest to |point|, return that vertex.
+ if (vertices.size() == 1U)
+ return vertices[0];
+
+ DCHECK_EQ(vertices.size(), 2U);
+ // If a polygon side is closest to the ideal height, return the
+ // point with aspect ratio closest to the default.
+ return Point::ClosestPointInSegment(point, vertices[0], vertices[1]);
+}
+
+Point SelectPointWithLargestArea(const Point& p1, const Point& p2) {
+ return p1.width() * p1.height() > p2.width() * p2.height() ? p1 : p2;
+}
+
+} // namespace
+
+Point::Point(double height, double width) : height_(height), width_(width) {}
+Point::Point(const Point& other) = default;
+Point& Point::operator=(const Point& other) = default;
+Point::~Point() = default;
+
+bool Point::operator==(const Point& other) const {
+ return height_ == other.height_ && width_ == other.width_;
+}
+
+bool Point::operator!=(const Point& other) const {
+ return !(*this == other);
+}
+
+bool Point::IsApproximatelyEqualTo(const Point& other) const {
+ return AreApproximatelyEqual(height_, other.height_) &&
+ AreApproximatelyEqual(width_, other.width_);
+}
+
+Point Point::operator+(const Point& other) const {
+ return Point(height_ + other.height_, width_ + other.width_);
+}
+
+Point Point::operator-(const Point& other) const {
+ return Point(height_ - other.height_, width_ - other.width_);
+}
+
+Point operator*(double d, const Point& p) {
+ return Point(d * p.height(), d * p.width());
+}
+
+// Returns the dot product between |p1| and |p2|.
+// static
+double Point::Dot(const Point& p1, const Point& p2) {
+ return p1.height_ * p2.height_ + p1.width_ * p2.width_;
+}
+
+// static
+double Point::DistanceToPoint(const Point& p1, const Point& p2) {
+ Point diff = p1 - p2;
+ return Dot(diff, diff);
+}
+
+// static
+Point Point::ClosestPointInSegment(const Point& p,
+ const Point& s1,
+ const Point& s2) {
+ // If |s1| and |s2| are the same, it is not really a segment. The closest
+ // point to |p| is |s1|=|s2|.
+ if (s1 == s2)
+ return s1;
+
+ // Translate coordinates to a system where the origin is |s1|.
+ Point p_trans = p - s1;
+ Point s2_trans = s2 - s1;
+
+ // On this system, we are interested in the projection of |p_trans| on
+ // |s2_trans|. The projection is m * |s2_trans|, where
+ // m = Dot(|s2_trans|, |p_trans|) / Dot(|s2_trans|, |s2_trans|).
+ // If 0 <= m <= 1, the projection falls within the segment, and the closest
+ // point is the projection itself.
+ // If m < 0, the closest point is S1.
+ // If m > 1, the closest point is S2.
+ double m = Dot(s2_trans, p_trans) / Dot(s2_trans, s2_trans);
+ if (m < 0)
+ return s1;
+ else if (m > 1)
+ return s2;
+
+ // Return the projection in the original coordinate system.
+ return s1 + m * s2_trans;
+}
+
+ResolutionSet::ResolutionSet(int min_height,
+ int max_height,
+ int min_width,
+ int max_width,
+ double min_aspect_ratio,
+ double max_aspect_ratio)
+ : min_height_(min_height),
+ max_height_(max_height),
+ min_width_(min_width),
+ max_width_(max_width),
+ min_aspect_ratio_(min_aspect_ratio),
+ max_aspect_ratio_(max_aspect_ratio) {
+ DCHECK_GE(min_height_, 0);
+ DCHECK_GE(max_height_, 0);
+ DCHECK_LE(max_height_, kMaxConstrainedDimension + 1);
+ DCHECK_GE(min_width_, 0);
+ DCHECK_GE(max_width_, 0);
+ DCHECK_LE(max_width_, kMaxConstrainedDimension + 1);
hbos_chromium 2017/03/03 16:01:42 Here and elsewhere I would prefer kMaxDimension.
Guido Urdaneta 2017/03/06 11:08:22 Done. Question: Do you refer to a kMaxDimension in
hbos_chromium 2017/03/08 21:03:00 This is good.
+ DCHECK_GE(min_aspect_ratio_, 0.0);
+ DCHECK_GE(max_aspect_ratio_, 0.0);
+}
+
+ResolutionSet::ResolutionSet()
+ : ResolutionSet(0,
+ kMaxConstrainedDimension + 1,
+ 0,
+ kMaxConstrainedDimension + 1,
+ 0.0,
+ HUGE_VAL) {}
+
+ResolutionSet::ResolutionSet(const ResolutionSet& other) = default;
+ResolutionSet::~ResolutionSet() = default;
+ResolutionSet& ResolutionSet::operator=(const ResolutionSet& other) = default;
+
+bool ResolutionSet::IsHeightEmpty() const {
+ return min_height_ > max_height_ || min_height_ > kMaxConstrainedDimension ||
+ max_height_ <= 0;
+}
+
+bool ResolutionSet::IsWidthEmpty() const {
+ return min_width_ > max_width_ || min_width_ > kMaxConstrainedDimension ||
+ max_width_ <= 0;
+}
+
+bool ResolutionSet::IsAspectRatioEmpty() const {
+ double max_resolution_aspect_ratio =
+ static_cast<double>(max_width_) / static_cast<double>(min_height_);
+ double min_resolution_aspect_ratio =
+ static_cast<double>(min_width_) / static_cast<double>(max_height_);
+
+ return IsGreater(min_aspect_ratio_, max_aspect_ratio_) ||
+ IsLess(max_resolution_aspect_ratio, min_aspect_ratio_) ||
+ IsGreater(min_resolution_aspect_ratio, max_aspect_ratio_) ||
+ !std::isfinite(min_aspect_ratio_) || max_aspect_ratio_ <= 0.0;
+}
+
+bool ResolutionSet::IsEmpty() const {
+ return IsHeightEmpty() || IsWidthEmpty() || IsAspectRatioEmpty();
+}
+
+// These functions return true if a particular variable is constrained.
+bool ResolutionSet::HasMinHeight() const {
+ return min_height_ >= kMinConstrainedDimension;
+}
+
+bool ResolutionSet::HasMaxHeight() const {
+ return max_height_ <= kMaxConstrainedDimension;
+}
+
+bool ResolutionSet::HasMinWidth() const {
+ return min_width_ >= kMinConstrainedDimension;
+}
+
+bool ResolutionSet::HasMaxWidth() const {
+ return max_width_ <= kMaxConstrainedDimension;
+}
+
+bool ResolutionSet::HasMinAspectRatio() const {
+ return min_aspect_ratio_ > 0.0;
+}
+
+bool ResolutionSet::HasMaxAspectRatio() const {
+ return std::isfinite(max_aspect_ratio_);
+}
+
+bool ResolutionSet::IsHeightUnconstrained() const {
+ return !HasMinHeight() && !HasMaxHeight();
+}
+
+bool ResolutionSet::IsWidthUnconstrained() const {
+ return !HasMinWidth() && !HasMaxWidth();
+}
+
+bool ResolutionSet::IsAspectRatioUnconstrained() const {
+ return !HasMinAspectRatio() && !HasMaxAspectRatio();
+}
+
+bool ResolutionSet::ContainsPoint(int height, int width) const {
+ return ContainsPoint(Point(height, width));
+}
+
+bool ResolutionSet::ContainsPoint(const Point& point) const {
+ double ratio = point.width() / point.height();
hbos_chromium 2017/03/03 16:01:42 Watch out for divide by zero!
Guido Urdaneta 2017/03/06 11:08:22 Inf aspect ratio is fine. NaN (0/0) or (Inf/Inf) i
hbos_chromium 2017/03/08 21:03:00 Acknowledged.
+ // (0.0, 0.0) is always included in the aspect-ratio range.
hbos_chromium 2017/03/03 16:01:42 Why? If min resolution is > (0,0) then it isn't co
Guido Urdaneta 2017/03/06 11:08:22 In that case (0,0) would be part of the set of poi
hbos_chromium 2017/03/08 21:03:00 Acknowledged.
+ return point.height() >= min_height_ && point.height() <= max_height_ &&
+ point.width() >= min_width_ && point.width() <= max_width_ &&
+ ((IsGreaterOrEqual(ratio, min_aspect_ratio_) &&
+ IsLessOrEqual(ratio, max_aspect_ratio_)) ||
+ (point.width() == 0.0 && point.height() == 0.0));
hbos_chromium 2017/03/03 16:01:42 (Good that the comparators take precision errors i
Guido Urdaneta 2017/03/06 11:08:22 Acknowledged.
+}
+
+ResolutionSet ResolutionSet::Intersection(const ResolutionSet& other) const {
+ return ResolutionSet(std::max(min_height_, other.min_height_),
+ std::min(max_height_, other.max_height_),
+ std::max(min_width_, other.min_width_),
+ std::min(max_width_, other.max_width_),
+ std::max(min_aspect_ratio_, other.min_aspect_ratio_),
+ std::min(max_aspect_ratio_, other.max_aspect_ratio_));
hbos_chromium 2017/03/03 16:01:41 I think this is incorrect if there is an offset be
Guido Urdaneta 2017/03/06 11:08:22 The case you are showing is impossible here. All a
hbos_chromium 2017/03/08 21:03:00 Acknowledged.
+}
+
+Point ResolutionSet::ClosestPointTo(const Point& point) const {
+ DCHECK(std::numeric_limits<double>::has_infinity);
+
+ if (ContainsPoint(point))
+ return point;
+
+ auto vertices = ComputeVertices();
+ DCHECK_GE(vertices.size(), 1U);
+ Point best_candidate(0, 0);
+ double best_distance = HUGE_VAL;
+ for (size_t i = 0; i < vertices.size(); ++i) {
+ Point candidate = Point::ClosestPointInSegment(
+ point, vertices[i], vertices[(i + 1) % vertices.size()]);
+ double distance = Point::DistanceToPoint(point, candidate);
+ if (distance < best_distance) {
+ best_candidate = candidate;
+ best_distance = distance;
+ }
+ }
+
+ DCHECK(std::isfinite(best_distance));
+ return best_candidate;
+}
+
+std::vector<Point> ResolutionSet::GetClosestVertices(double (Point::*accessor)()
+ const,
+ double value) const {
+ DCHECK(!IsEmpty());
+ std::vector<Point> vertices = ComputeVertices();
+ std::vector<Point> closest_vertices;
+ double best_diff = HUGE_VAL;
+ for (const auto& vertex : vertices) {
+ double diff = std::fabs((vertex.*accessor)() - value);
+ if (diff <= best_diff) {
+ if (diff < best_diff) {
+ best_diff = diff;
+ closest_vertices.clear();
+ }
+ closest_vertices.push_back(vertex);
+ }
+ }
+ DCHECK(!closest_vertices.empty());
+ DCHECK_LE(closest_vertices.size(), 2U);
+ return closest_vertices;
+}
+
+Point ResolutionSet::SelectClosestPointToIdealAspectRatio(
+ double ideal_aspect_ratio) const {
+ ResolutionSet intersection =
+ Intersection(ResolutionSet::FromExactAspectRatio(ideal_aspect_ratio));
+ if (!intersection.IsEmpty()) {
+ Point default_height_point(kDefaultHeight,
+ kDefaultHeight * ideal_aspect_ratio);
+ Point default_width_point(kDefaultWidth / ideal_aspect_ratio,
+ kDefaultWidth);
+ return SelectPointWithLargestArea(
+ intersection.ClosestPointTo(default_height_point),
+ intersection.ClosestPointTo(default_width_point));
+ }
+ std::vector<Point> closest_vertices =
+ GetClosestVertices(&Point::AspectRatio, ideal_aspect_ratio);
+ double actual_aspect_ratio = closest_vertices[0].AspectRatio();
+ Point default_height_point(kDefaultHeight,
+ kDefaultHeight * actual_aspect_ratio);
+ Point default_width_point(kDefaultWidth / actual_aspect_ratio, kDefaultWidth);
+ return SelectPointWithLargestArea(
+ GetClosestPoint(closest_vertices, default_height_point),
+ GetClosestPoint(closest_vertices, default_width_point));
+}
+
+Point ResolutionSet::SelectClosestPointToIdeal(
+ const blink::WebMediaTrackConstraintSet& constraint_set) const {
+ DCHECK(!IsEmpty());
+ int num_ideals = 0;
+ if (constraint_set.height.hasIdeal())
+ ++num_ideals;
+ if (constraint_set.width.hasIdeal())
+ ++num_ideals;
+ if (constraint_set.aspectRatio.hasIdeal())
+ ++num_ideals;
+
+ switch (num_ideals) {
+ case 0:
+ return SelectClosestPointToIdealAspectRatio(kDefaultAspectRatio);
+
+ case 1:
+ // This case requires a point closest to a line.
+ // In all variants, if the ideal line intersects the polygon, select the
+ // point in the intersection that is closest to preserving the default
+ // aspect ratio or a default dimension.
+ // If the ideal line is outside the polygon, there is either a single
+ // vertex or a polygon side closest to the ideal line. If a single vertex,
+ // select that vertex. If a polygon side, select the point on that side
+ // that is closest to preserving the default aspect ratio or a default
+ // dimension.
+ if (constraint_set.height.hasIdeal()) {
+ int ideal_height =
+ ToValidConstrainedDimension(constraint_set.height.ideal());
+ ResolutionSet ideal_line = ResolutionSet::FromExactHeight(ideal_height);
+ ResolutionSet intersection = Intersection(ideal_line);
+ if (!intersection.IsEmpty()) {
+ return intersection.ClosestPointTo(
+ Point(ideal_height, ideal_height * kDefaultAspectRatio));
+ }
+ std::vector<Point> closest_vertices =
+ GetClosestVertices(&Point::height, ideal_height);
+ Point ideal_point(closest_vertices[0].height(),
+ closest_vertices[0].height() * kDefaultAspectRatio);
+ return GetClosestPoint(closest_vertices, ideal_point);
+ } else if (constraint_set.width.hasIdeal()) {
+ int ideal_width =
+ ToValidConstrainedDimension(constraint_set.width.ideal());
+ ResolutionSet ideal_line = ResolutionSet::FromExactWidth(ideal_width);
+ ResolutionSet intersection = Intersection(ideal_line);
+ if (!intersection.IsEmpty()) {
+ return intersection.ClosestPointTo(
+ Point(ideal_width / kDefaultAspectRatio, ideal_width));
+ }
+ std::vector<Point> closest_vertices =
+ GetClosestVertices(&Point::width, ideal_width);
+ Point ideal_point(closest_vertices[0].width() / kDefaultAspectRatio,
+ closest_vertices[0].width());
+ return GetClosestPoint(closest_vertices, ideal_point);
+ } else {
+ DCHECK(constraint_set.aspectRatio.hasIdeal());
+ double ideal_aspect_ratio =
+ ToValidConstrainedAspectRatio(constraint_set.aspectRatio.ideal());
+ return SelectClosestPointToIdealAspectRatio(ideal_aspect_ratio);
+ }
+ NOTREACHED();
+
+ default:
hta - Chromium 2017/03/03 11:02:36 This is the case that will handle 2 and 3 ideal va
Guido Urdaneta 2017/03/06 11:08:22 Done.
+ double ideal_height;
+ double ideal_width;
+ if (constraint_set.height.hasIdeal()) {
+ ideal_height =
+ ToValidConstrainedDimension(constraint_set.height.ideal());
+ ideal_width =
+ constraint_set.width.hasIdeal()
+ ? ToValidConstrainedDimension(constraint_set.width.ideal())
+ : ideal_height *
+ ToValidConstrainedAspectRatio(
+ constraint_set.aspectRatio.ideal());
+ } else {
+ DCHECK(constraint_set.width.hasIdeal());
+ DCHECK(constraint_set.aspectRatio.hasIdeal());
+ ideal_width = ToValidConstrainedDimension(constraint_set.width.ideal());
+ ideal_height =
+ ideal_width /
+ ToValidConstrainedAspectRatio(constraint_set.aspectRatio.ideal());
+ }
+ return ClosestPointTo(Point(ideal_height, ideal_width));
+ }
+ NOTREACHED();
+}
+
+// static
+ResolutionSet ResolutionSet::FromHeight(int min, int max) {
+ return ResolutionSet(min, max, 0, kMaxConstrainedDimension + 1, 0.0,
+ HUGE_VAL);
+}
+
+// static
+ResolutionSet ResolutionSet::FromExactHeight(int value) {
+ return ResolutionSet(value, value, 0, kMaxConstrainedDimension + 1, 0.0,
+ HUGE_VAL);
+}
+
+// static
+ResolutionSet ResolutionSet::FromWidth(int min, int max) {
+ return ResolutionSet(0, kMaxConstrainedDimension + 1, min, max, 0.0,
+ HUGE_VAL);
+}
+
+// static
+ResolutionSet ResolutionSet::FromExactWidth(int value) {
+ return ResolutionSet(0, kMaxConstrainedDimension + 1, value, value, 0.0,
+ HUGE_VAL);
+}
+
+// static
+ResolutionSet ResolutionSet::FromAspectRatio(double min, double max) {
+ return ResolutionSet(0, kMaxConstrainedDimension + 1, 0,
+ kMaxConstrainedDimension + 1, min, max);
+}
+
+// static
+ResolutionSet ResolutionSet::FromExactAspectRatio(double value) {
+ return ResolutionSet(0, kMaxConstrainedDimension + 1, 0,
+ kMaxConstrainedDimension + 1, value, value);
+}
+
+std::vector<Point> ResolutionSet::ComputeVertices() const {
+ std::vector<Point> vertices;
+ // Add vertices in counterclockwise order
+ // Start with min_height, min_width and continue along min_width.
+ TryAddVertex(&vertices, Point(min_height_, min_width_));
+ TryAddVertex(&vertices, Point(min_width_ / max_aspect_ratio_, min_width_));
+ TryAddVertex(&vertices, Point(min_width_ / min_aspect_ratio_, min_width_));
+ TryAddVertex(&vertices, Point(max_height_, min_width_));
+ // Continue along max_height.
+ TryAddVertex(&vertices, Point(max_height_, max_height_ * min_aspect_ratio_));
+ TryAddVertex(&vertices, Point(max_height_, max_height_ * max_aspect_ratio_));
+ TryAddVertex(&vertices, Point(max_height_, max_width_));
+ // Continue along max_width.
+ TryAddVertex(&vertices, Point(max_width_ / min_aspect_ratio_, max_width_));
+ TryAddVertex(&vertices, Point(max_width_ / max_aspect_ratio_, max_width_));
+ TryAddVertex(&vertices, Point(min_height_, max_width_));
+ // Finish along min_height.
+ TryAddVertex(&vertices, Point(min_height_, min_height_ * max_aspect_ratio_));
+ TryAddVertex(&vertices, Point(min_height_, min_height_ * min_aspect_ratio_));
+
+ DCHECK_LE(vertices.size(), 6U);
+ return vertices;
+}
+
+void ResolutionSet::TryAddVertex(std::vector<Point>* vertices,
+ const Point& point) const {
+ if (!ContainsPoint(point))
+ return;
+
+ // Add the point to the |vertices| if not already added.
+ // This is to prevent duplicates in case an aspect ratio intersects a width
+ // or height right on a vertex.
+ if (vertices->empty() ||
+ (*(vertices->end() - 1) != point && *vertices->begin() != point)) {
+ vertices->push_back(point);
+ }
+}
+
+ResolutionSet ResolutionSet::FromConstraintSet(
+ const blink::WebMediaTrackConstraintSet& constraint_set) {
+ return ResolutionSet(
+ MinDimensionFromConstraint(constraint_set.height),
+ MaxDimensionFromConstraint(constraint_set.height),
+ MinDimensionFromConstraint(constraint_set.width),
+ MaxDimensionFromConstraint(constraint_set.width),
+ MinAspectRatioFromConstraint(constraint_set.aspectRatio),
+ MaxAspectRatioFromConstraint(constraint_set.aspectRatio));
+}
+
+} // namespace content

Powered by Google App Engine
This is Rietveld 408576698