| Index: content/renderer/media/media_stream_constraints_util_sets_unittest.cc
|
| diff --git a/content/renderer/media/media_stream_constraints_util_sets_unittest.cc b/content/renderer/media/media_stream_constraints_util_sets_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b76134d4a6091e85759d423a0d43274557f8c2ff
|
| --- /dev/null
|
| +++ b/content/renderer/media/media_stream_constraints_util_sets_unittest.cc
|
| @@ -0,0 +1,1281 @@
|
| +// 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 <string>
|
| +#include <vector>
|
| +
|
| +#include "content/renderer/media/media_stream_video_source.h"
|
| +#include "content/renderer/media/mock_constraint_factory.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace content {
|
| +
|
| +using Point = ResolutionSet::Point;
|
| +
|
| +namespace {
|
| +
|
| +// Defined as macro in order to get more informative line-number information
|
| +// when a test fails.
|
| +#define EXPECT_POINT_EQ(p1, p2) \
|
| + do { \
|
| + EXPECT_DOUBLE_EQ((p1).height(), (p2).height()); \
|
| + EXPECT_DOUBLE_EQ((p1).width(), (p2).width()); \
|
| + } while (0)
|
| +
|
| +// Checks if |point| is an element of |vertices| using
|
| +// Point::IsApproximatelyEqualTo() to test for equality.
|
| +void VerticesContain(const std::vector<Point>& vertices, const Point& point) {
|
| + bool result = false;
|
| + for (const auto& vertex : vertices) {
|
| + if (point.IsApproximatelyEqualTo(vertex)) {
|
| + result = true;
|
| + break;
|
| + }
|
| + }
|
| + EXPECT_TRUE(result);
|
| +}
|
| +
|
| +bool AreCounterclockwise(const std::vector<Point>& vertices) {
|
| + // Single point or segment are trivial cases.
|
| + if (vertices.size() <= 2)
|
| + return true;
|
| + else if (vertices.size() > 6) // Polygons of more than 6 sides are not valid.
|
| + return false;
|
| +
|
| + // The polygon defined by a resolution set is always convex and has at most 6
|
| + // sides. When producing a list of the vertices for such a polygon, it is
|
| + // important that they are returned in counterclockwise (or clockwise) order,
|
| + // to make sure that any consecutive pair of vertices (modulo the number of
|
| + // vertices) corresponds to a polygon side. Our implementation uses
|
| + // counterclockwise order.
|
| + // Compute orientation using the determinant of each diagonal in the
|
| + // polygon, using the first vertex as reference.
|
| + Point prev_diagonal = vertices[1] - vertices[0];
|
| + for (auto vertex = vertices.begin() + 2; vertex != vertices.end(); ++vertex) {
|
| + Point current_diagonal = *vertex - vertices[0];
|
| + // The determinant of the two diagonals returns the signed area of the
|
| + // parallelogram they generate. The area is positive if the diagonals are in
|
| + // counterclockwise order, zero if the diagonals have the same direction and
|
| + // negative if the diagonals are in clockwise order.
|
| + // See https://en.wikipedia.org/wiki/Determinant#2_.C3.97_2_matrices.
|
| + double det = prev_diagonal.height() * current_diagonal.width() -
|
| + current_diagonal.height() * prev_diagonal.width();
|
| + if (det <= 0)
|
| + return false;
|
| + prev_diagonal = current_diagonal;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +// Determines if |vertices| is valid according to the contract for
|
| +// ResolutionCandidateSet::ComputeVertices().
|
| +bool AreValidVertices(const ResolutionSet& set,
|
| + const std::vector<Point>& vertices) {
|
| + // Verify that every vertex is included in |set|.
|
| + for (const auto& vertex : vertices) {
|
| + if (!set.ContainsPoint(vertex))
|
| + return false;
|
| + }
|
| +
|
| + return AreCounterclockwise(vertices);
|
| +}
|
| +
|
| +// This function provides an alternative method for computing the projection
|
| +// of |point| on the line of segment |s1||s2| to be used to compare the results
|
| +// provided by Point::ClosestPointInSegment(). Since it relies on library
|
| +// functions, it has larger error in practice than
|
| +// Point::ClosestPointInSegment(), so results must be compared with
|
| +// Point::IsApproximatelyEqualTo().
|
| +// This function only computes projections. The result may be outside the
|
| +// segment |s1||s2|.
|
| +Point ProjectionOnSegmentLine(const Point& point,
|
| + const Point& s1,
|
| + const Point& s2) {
|
| + double segment_slope =
|
| + (s2.width() - s1.width()) / (s2.height() - s1.height());
|
| + double segment_angle = std::atan(segment_slope);
|
| + double norm = std::sqrt(Point::Dot(point, point));
|
| + double angle =
|
| + (point.height() == 0 && point.width() == 0)
|
| + ? 0.0
|
| + : std::atan(point.width() / point.height()) - segment_angle;
|
| + double projection_length = norm * std::cos(angle);
|
| + double projection_height = projection_length * std::cos(segment_angle);
|
| + double projection_width = projection_length * std::sin(segment_angle);
|
| + return Point(projection_height, projection_width);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +class MediaStreamConstraintsUtilSetsTest : public testing::Test {
|
| + protected:
|
| + using P = Point;
|
| + MockConstraintFactory factory_;
|
| +};
|
| +
|
| +// This test tests the test-harness function AreValidVertices.
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, VertexListValidity) {
|
| + EXPECT_TRUE(AreCounterclockwise({P(1, 1)}));
|
| + EXPECT_TRUE(AreCounterclockwise({P(1, 1)}));
|
| + EXPECT_TRUE(AreCounterclockwise({P(1, 0), P(0, 1)}));
|
| + EXPECT_TRUE(AreCounterclockwise({P(1, 1), P(0, 0), P(1, 0)}));
|
| +
|
| + // Not in counterclockwise order.
|
| + EXPECT_FALSE(AreCounterclockwise({P(1, 0), P(0, 0), P(1, 1)}));
|
| +
|
| + // Final vertex aligned with the previous two vertices.
|
| + EXPECT_FALSE(AreCounterclockwise({P(1, 0), P(1, 1), P(1, 1.5), P(1, 0.1)}));
|
| +
|
| + // Not in counterclockwise order.
|
| + EXPECT_FALSE(
|
| + AreCounterclockwise({P(1, 0), P(3, 0), P(2, 2), P(3.1, 1), P(0, 1)}));
|
| +
|
| + EXPECT_TRUE(AreCounterclockwise(
|
| + {P(1, 0), P(3, 0), P(3.1, 1), P(3, 2), P(1, 2), P(0.9, 1)}));
|
| +
|
| + // Not in counterclockwise order.
|
| + EXPECT_FALSE(AreCounterclockwise(
|
| + {P(1, 0), P(3, 0), P(3.1, 1), P(1, 2), P(3, 2), P(0.9, 1)}));
|
| +
|
| + // Counterclockwise, but more than 6 vertices.
|
| + EXPECT_FALSE(AreCounterclockwise(
|
| + {P(1, 0), P(3, 0), P(3.1, 1), P(3, 2), P(2, 2.1), P(1, 2), P(0.9, 1)}));
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, PointOperations) {
|
| + const Point kZero(0, 0);
|
| +
|
| + // Basic equality and inequality
|
| + EXPECT_EQ(P(0, 0), kZero);
|
| + EXPECT_EQ(P(50, 50), P(50, 50));
|
| + EXPECT_NE(kZero, P(50, 50));
|
| + EXPECT_NE(P(50, 50), P(100, 100));
|
| + EXPECT_NE(P(50, 50), P(100, 50));
|
| +
|
| + // Operations with zero.
|
| + EXPECT_EQ(kZero, kZero + kZero);
|
| + EXPECT_EQ(kZero, kZero - kZero);
|
| + EXPECT_EQ(kZero, 0.0 * kZero);
|
| + EXPECT_EQ(0.0, P::Dot(kZero, kZero));
|
| + EXPECT_EQ(0.0, P::SquareEuclideanDistance(kZero, kZero));
|
| + EXPECT_EQ(kZero, P::ClosestPointInSegment(kZero, kZero, kZero));
|
| +
|
| + // Operations with zero and nonzero values.
|
| + EXPECT_EQ(P(50, 50), kZero + P(50, 50));
|
| + EXPECT_EQ(P(50, 50) + kZero, kZero + P(50, 50));
|
| + EXPECT_EQ(P(50, 50), P(50, 50) - kZero);
|
| + EXPECT_EQ(kZero, P(50, 50) - P(50, 50));
|
| + EXPECT_EQ(kZero, 0.0 * P(50, 50));
|
| + EXPECT_EQ(0.0, P::Dot(kZero, P(50, 50)));
|
| + EXPECT_EQ(0.0, P::Dot(P(50, 50), kZero));
|
| + EXPECT_EQ(5000, P::SquareEuclideanDistance(kZero, P(50, 50)));
|
| + EXPECT_EQ(P::SquareEuclideanDistance(P(50, 50), kZero),
|
| + P::SquareEuclideanDistance(kZero, P(50, 50)));
|
| + EXPECT_EQ(kZero, P::ClosestPointInSegment(kZero, kZero, P(50, 50)));
|
| + EXPECT_EQ(kZero, P::ClosestPointInSegment(kZero, P(50, 50), kZero));
|
| + EXPECT_EQ(P(50, 50),
|
| + P::ClosestPointInSegment(P(50, 50), P(50, 50), P(50, 50)));
|
| +
|
| + // Operations with nonzero values.
|
| + // Additions.
|
| + EXPECT_EQ(P(100, 50), P(50, 50) + P(50, 0));
|
| + EXPECT_EQ(P(100, 50), P(50, 0) + P(50, 50));
|
| +
|
| + // Substractions.
|
| + EXPECT_EQ(P(50, 50), P(100, 100) - P(50, 50));
|
| + EXPECT_EQ(P(50, 50), P(100, 50) - P(50, 0));
|
| + EXPECT_EQ(P(50, 0), P(100, 50) - P(50, 50));
|
| +
|
| + // Scalar-vector products.
|
| + EXPECT_EQ(P(50, 50), 1.0 * P(50, 50));
|
| + EXPECT_EQ(P(75, 75), 1.5 * P(50, 50));
|
| + EXPECT_EQ(P(200, 100), 2.0 * P(100, 50));
|
| + EXPECT_EQ(2.0 * (P(100, 100) + P(100, 50)),
|
| + 2.0 * P(100, 100) + 2.0 * P(100, 50));
|
| +
|
| + // Dot products.
|
| + EXPECT_EQ(2 * 50 * 100, P::Dot(P(50, 50), P(100, 100)));
|
| + EXPECT_EQ(P::Dot(P(100, 100), P(50, 50)), P::Dot(P(50, 50), P(100, 100)));
|
| + EXPECT_EQ(0, P::Dot(P(100, 0), P(0, 100)));
|
| +
|
| + // Distances.
|
| + EXPECT_EQ(25, P::SquareEuclideanDistance(P(4, 0), P(0, 3)));
|
| + EXPECT_EQ(75 * 75, P::SquareEuclideanDistance(P(100, 0), P(25, 0)));
|
| + EXPECT_EQ(75 * 75, P::SquareEuclideanDistance(P(0, 100), P(0, 25)));
|
| + EXPECT_EQ(5 * 5 + 9 * 9, P::SquareEuclideanDistance(P(5, 1), P(10, 10)));
|
| +
|
| + // Closest point to segment from (10,0) to (50,0).
|
| + EXPECT_EQ(P(25, 0), P::ClosestPointInSegment(P(25, 25), P(10, 0), P(50, 0)));
|
| + EXPECT_EQ(P(50, 0),
|
| + P::ClosestPointInSegment(P(100, 100), P(10, 0), P(50, 0)));
|
| + EXPECT_EQ(P(10, 0), P::ClosestPointInSegment(P(0, 100), P(10, 0), P(50, 0)));
|
| +
|
| + // Closest point to segment from (0,10) to (0,50).
|
| + EXPECT_EQ(P(0, 25), P::ClosestPointInSegment(P(25, 25), P(0, 10), P(0, 50)));
|
| + EXPECT_EQ(P(0, 50),
|
| + P::ClosestPointInSegment(P(100, 100), P(0, 10), P(0, 50)));
|
| + EXPECT_EQ(P(0, 10), P::ClosestPointInSegment(P(100, 0), P(0, 10), P(0, 50)));
|
| +
|
| + // Closest point to segment from (0,10) to (10,0).
|
| + EXPECT_EQ(P(5, 5), P::ClosestPointInSegment(P(25, 25), P(0, 10), P(10, 0)));
|
| + EXPECT_EQ(P(5, 5), P::ClosestPointInSegment(P(100, 100), P(0, 10), P(10, 0)));
|
| + EXPECT_EQ(P(10, 0), P::ClosestPointInSegment(P(100, 0), P(0, 10), P(10, 0)));
|
| + EXPECT_EQ(P(0, 10), P::ClosestPointInSegment(P(0, 100), P(0, 10), P(10, 0)));
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionUnconstrained) {
|
| + ResolutionSet set;
|
| + EXPECT_TRUE(set.ContainsPoint(0, 0));
|
| + EXPECT_TRUE(set.ContainsPoint(1, 1));
|
| + EXPECT_TRUE(set.ContainsPoint(2000, 2000));
|
| + EXPECT_FALSE(set.IsHeightEmpty());
|
| + EXPECT_FALSE(set.IsWidthEmpty());
|
| + EXPECT_FALSE(set.IsAspectRatioEmpty());
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionConstrained) {
|
| + ResolutionSet set = ResolutionSet::FromHeight(10, 100);
|
| + EXPECT_FALSE(set.ContainsPoint(0, 0));
|
| + EXPECT_TRUE(set.ContainsPoint(10, 10));
|
| + EXPECT_TRUE(set.ContainsPoint(50, 50));
|
| + EXPECT_TRUE(set.ContainsPoint(100, 100));
|
| + EXPECT_FALSE(set.ContainsPoint(500, 500));
|
| + EXPECT_FALSE(set.IsHeightEmpty());
|
| + EXPECT_FALSE(set.IsWidthEmpty());
|
| + EXPECT_FALSE(set.IsAspectRatioEmpty());
|
| +
|
| + set = ResolutionSet::FromHeight(0, 100);
|
| + EXPECT_TRUE(set.ContainsPoint(0, 0));
|
| + EXPECT_TRUE(set.ContainsPoint(10, 10));
|
| + EXPECT_TRUE(set.ContainsPoint(50, 50));
|
| + EXPECT_TRUE(set.ContainsPoint(100, 100));
|
| + EXPECT_FALSE(set.ContainsPoint(500, 500));
|
| + EXPECT_FALSE(set.IsHeightEmpty());
|
| + EXPECT_FALSE(set.IsWidthEmpty());
|
| + EXPECT_FALSE(set.IsAspectRatioEmpty());
|
| +
|
| + set = ResolutionSet::FromHeight(100, ResolutionSet::kMaxDimension);
|
| + EXPECT_FALSE(set.ContainsPoint(0, 0));
|
| + EXPECT_FALSE(set.ContainsPoint(10, 10));
|
| + EXPECT_FALSE(set.ContainsPoint(50, 50));
|
| + EXPECT_TRUE(set.ContainsPoint(100, 100));
|
| + EXPECT_TRUE(set.ContainsPoint(500, 500));
|
| + EXPECT_FALSE(set.IsHeightEmpty());
|
| + EXPECT_FALSE(set.IsWidthEmpty());
|
| + EXPECT_FALSE(set.IsAspectRatioEmpty());
|
| +
|
| + set = ResolutionSet::FromWidth(10, 100);
|
| + EXPECT_FALSE(set.ContainsPoint(0, 0));
|
| + EXPECT_TRUE(set.ContainsPoint(10, 10));
|
| + EXPECT_TRUE(set.ContainsPoint(50, 50));
|
| + EXPECT_TRUE(set.ContainsPoint(100, 100));
|
| + EXPECT_FALSE(set.ContainsPoint(500, 500));
|
| + EXPECT_FALSE(set.IsHeightEmpty());
|
| + EXPECT_FALSE(set.IsWidthEmpty());
|
| + EXPECT_FALSE(set.IsAspectRatioEmpty());
|
| +
|
| + set = ResolutionSet::FromWidth(0, 100);
|
| + EXPECT_TRUE(set.ContainsPoint(0, 0));
|
| + EXPECT_TRUE(set.ContainsPoint(10, 10));
|
| + EXPECT_TRUE(set.ContainsPoint(50, 50));
|
| + EXPECT_TRUE(set.ContainsPoint(100, 100));
|
| + EXPECT_FALSE(set.ContainsPoint(500, 500));
|
| + EXPECT_FALSE(set.IsHeightEmpty());
|
| + EXPECT_FALSE(set.IsWidthEmpty());
|
| + EXPECT_FALSE(set.IsAspectRatioEmpty());
|
| +
|
| + set = ResolutionSet::FromWidth(100, ResolutionSet::kMaxDimension);
|
| + EXPECT_FALSE(set.ContainsPoint(0, 0));
|
| + EXPECT_FALSE(set.ContainsPoint(10, 10));
|
| + EXPECT_FALSE(set.ContainsPoint(50, 50));
|
| + EXPECT_TRUE(set.ContainsPoint(100, 100));
|
| + EXPECT_TRUE(set.ContainsPoint(500, 500));
|
| + EXPECT_FALSE(set.IsHeightEmpty());
|
| + EXPECT_FALSE(set.IsWidthEmpty());
|
| + EXPECT_FALSE(set.IsAspectRatioEmpty());
|
| +
|
| + set = ResolutionSet::FromAspectRatio(1.0, 2.0);
|
| + EXPECT_TRUE(set.ContainsPoint(0, 0));
|
| + EXPECT_TRUE(set.ContainsPoint(10, 10));
|
| + EXPECT_TRUE(set.ContainsPoint(10, 20));
|
| + EXPECT_TRUE(set.ContainsPoint(100, 100));
|
| + EXPECT_TRUE(set.ContainsPoint(2000, 4000));
|
| + EXPECT_FALSE(set.ContainsPoint(1, 50));
|
| + EXPECT_FALSE(set.ContainsPoint(50, 1));
|
| + EXPECT_FALSE(set.IsHeightEmpty());
|
| + EXPECT_FALSE(set.IsWidthEmpty());
|
| + EXPECT_FALSE(set.IsAspectRatioEmpty());
|
| +
|
| + set = ResolutionSet::FromAspectRatio(0.0, 2.0);
|
| + EXPECT_TRUE(set.ContainsPoint(0, 0));
|
| + EXPECT_TRUE(set.ContainsPoint(10, 10));
|
| + EXPECT_TRUE(set.ContainsPoint(10, 20));
|
| + EXPECT_TRUE(set.ContainsPoint(100, 100));
|
| + EXPECT_TRUE(set.ContainsPoint(2000, 4000));
|
| + EXPECT_FALSE(set.ContainsPoint(1, 50));
|
| + EXPECT_TRUE(set.ContainsPoint(50, 1));
|
| + EXPECT_FALSE(set.IsHeightEmpty());
|
| + EXPECT_FALSE(set.IsWidthEmpty());
|
| + EXPECT_FALSE(set.IsAspectRatioEmpty());
|
| +
|
| + set = ResolutionSet::FromAspectRatio(1.0, HUGE_VAL);
|
| + EXPECT_TRUE(set.ContainsPoint(0, 0));
|
| + EXPECT_TRUE(set.ContainsPoint(10, 10));
|
| + EXPECT_TRUE(set.ContainsPoint(10, 20));
|
| + EXPECT_TRUE(set.ContainsPoint(100, 100));
|
| + EXPECT_TRUE(set.ContainsPoint(2000, 4000));
|
| + EXPECT_TRUE(set.ContainsPoint(1, 50));
|
| + EXPECT_FALSE(set.ContainsPoint(50, 1));
|
| + EXPECT_FALSE(set.IsHeightEmpty());
|
| + EXPECT_FALSE(set.IsWidthEmpty());
|
| + EXPECT_FALSE(set.IsAspectRatioEmpty());
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionTrivialEmptiness) {
|
| + ResolutionSet set = ResolutionSet::FromHeight(100, 10);
|
| + EXPECT_TRUE(set.IsEmpty());
|
| + EXPECT_TRUE(set.IsHeightEmpty());
|
| + EXPECT_FALSE(set.IsWidthEmpty());
|
| + EXPECT_FALSE(set.IsAspectRatioEmpty());
|
| +
|
| + set = ResolutionSet::FromWidth(100, 10);
|
| + EXPECT_TRUE(set.IsEmpty());
|
| + EXPECT_FALSE(set.IsHeightEmpty());
|
| + EXPECT_TRUE(set.IsWidthEmpty());
|
| + EXPECT_FALSE(set.IsAspectRatioEmpty());
|
| +
|
| + set = ResolutionSet::FromAspectRatio(100.0, 10.0);
|
| + EXPECT_TRUE(set.IsEmpty());
|
| + EXPECT_FALSE(set.IsHeightEmpty());
|
| + EXPECT_FALSE(set.IsWidthEmpty());
|
| + EXPECT_TRUE(set.IsAspectRatioEmpty());
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionLineConstraintsEmptiness) {
|
| + ResolutionSet set(1, 1, 1, 1, 1, 1);
|
| + EXPECT_FALSE(set.IsEmpty());
|
| + EXPECT_FALSE(set.ContainsPoint(0, 0));
|
| + EXPECT_TRUE(set.ContainsPoint(1, 1));
|
| + EXPECT_FALSE(set.ContainsPoint(1, 0));
|
| + EXPECT_FALSE(set.ContainsPoint(0, 1));
|
| +
|
| + // Three lines that do not intersect in the same point is empty.
|
| + set = ResolutionSet(1, 1, 1, 1, 0.5, 0.5);
|
| + EXPECT_TRUE(set.IsEmpty());
|
| + EXPECT_TRUE(set.IsAspectRatioEmpty());
|
| + EXPECT_FALSE(set.ContainsPoint(0, 0));
|
| + EXPECT_FALSE(set.ContainsPoint(1, 1));
|
| + EXPECT_FALSE(set.ContainsPoint(1, 0));
|
| + EXPECT_FALSE(set.ContainsPoint(0, 1));
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionBoxEmptiness) {
|
| + int kMin = 100;
|
| + int kMax = 200;
|
| + // Max aspect ratio below box.
|
| + ResolutionSet set(kMin, kMax, kMin, kMax, 0.4, 0.4);
|
| + EXPECT_TRUE(set.IsEmpty());
|
| + EXPECT_TRUE(set.IsAspectRatioEmpty());
|
| +
|
| + // Min aspect ratio above box.
|
| + set = ResolutionSet(kMin, kMax, kMin, kMax, 3.0, HUGE_VAL);
|
| + EXPECT_TRUE(set.IsEmpty());
|
| + EXPECT_TRUE(set.IsAspectRatioEmpty());
|
| +
|
| + // Min aspect ratio crosses box.
|
| + set = ResolutionSet(kMin, kMax, kMin, kMax, 1.0, HUGE_VAL);
|
| + EXPECT_FALSE(set.IsEmpty());
|
| +
|
| + // Max aspect ratio crosses box.
|
| + set = ResolutionSet(kMin, kMax, kMin, kMax, 0.0, 1.0);
|
| + EXPECT_FALSE(set.IsEmpty());
|
| +
|
| + // Min and max aspect ratios cross box.
|
| + set = ResolutionSet(kMin, kMax, kMin, kMax, 0.9, 1.1);
|
| + EXPECT_FALSE(set.IsEmpty());
|
| +
|
| + // Min and max aspect ratios cover box.
|
| + set = ResolutionSet(kMin, kMax, kMin, kMax, 0.2, 100);
|
| + EXPECT_FALSE(set.IsEmpty());
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionPointIntersection) {
|
| + ResolutionSet set1(1, 2, 1, 2, 0.0, HUGE_VAL);
|
| + ResolutionSet set2 = ResolutionSet::FromExactAspectRatio(0.5);
|
| + auto intersection = set1.Intersection(set2);
|
| +
|
| + // The intersection should contain only the point (h=2, w=1)
|
| + EXPECT_TRUE(intersection.ContainsPoint(2, 1));
|
| +
|
| + // It should not contain any point in the vicinity of the included point
|
| + // (integer version).
|
| + EXPECT_FALSE(intersection.ContainsPoint(1, 0));
|
| + EXPECT_FALSE(intersection.ContainsPoint(2, 0));
|
| + EXPECT_FALSE(intersection.ContainsPoint(3, 0));
|
| + EXPECT_FALSE(intersection.ContainsPoint(1, 1));
|
| + EXPECT_FALSE(intersection.ContainsPoint(3, 1));
|
| + EXPECT_FALSE(intersection.ContainsPoint(1, 2));
|
| + EXPECT_FALSE(intersection.ContainsPoint(2, 2));
|
| + EXPECT_FALSE(intersection.ContainsPoint(3, 2));
|
| +
|
| + // It should not contain any point in the vicinity of the included point
|
| + // (floating-point version).
|
| + EXPECT_FALSE(intersection.ContainsPoint(P(2.0001, 1.0001)));
|
| + EXPECT_FALSE(intersection.ContainsPoint(P(2.0001, 1.0)));
|
| + EXPECT_FALSE(intersection.ContainsPoint(P(2.0001, 0.9999)));
|
| + EXPECT_FALSE(intersection.ContainsPoint(P(2.0, 1.0001)));
|
| + EXPECT_FALSE(intersection.ContainsPoint(P(2.0, 0.9999)));
|
| + EXPECT_FALSE(intersection.ContainsPoint(P(1.9999, 1.0001)));
|
| + EXPECT_FALSE(intersection.ContainsPoint(P(1.9999, 1.0)));
|
| + EXPECT_FALSE(intersection.ContainsPoint(P(1.9999, 0.9999)));
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionLineIntersection) {
|
| + ResolutionSet set1(1, 2, 1, 2, 0.0, HUGE_VAL);
|
| + ResolutionSet set2 = ResolutionSet::FromExactAspectRatio(1.0);
|
| +
|
| + // The intersection should contain (1,1) and (2,2)
|
| + auto intersection = set1.Intersection(set2);
|
| + EXPECT_TRUE(intersection.ContainsPoint(1, 1));
|
| + EXPECT_TRUE(intersection.ContainsPoint(2, 2));
|
| +
|
| + // It should not contain the other points in the bounding box.
|
| + EXPECT_FALSE(intersection.ContainsPoint(1, 2));
|
| + EXPECT_FALSE(intersection.ContainsPoint(2, 1));
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionBoxIntersection) {
|
| + const int kMin1 = 0;
|
| + const int kMax1 = 2;
|
| + ResolutionSet set1(kMin1, kMax1, kMin1, kMax1, 0.0, HUGE_VAL);
|
| +
|
| + const int kMin2 = 1;
|
| + const int kMax2 = 3;
|
| + ResolutionSet set2(kMin2, kMax2, kMin2, kMax2, 0.0, HUGE_VAL);
|
| +
|
| + auto intersection = set1.Intersection(set2);
|
| + for (int i = kMin1; i <= kMax2; ++i) {
|
| + for (int j = kMin1; j <= kMax2; ++j) {
|
| + if (i >= kMin2 && j >= kMin2 && i <= kMax1 && j <= kMax1)
|
| + EXPECT_TRUE(intersection.ContainsPoint(i, j));
|
| + else
|
| + EXPECT_FALSE(intersection.ContainsPoint(i, j));
|
| + }
|
| + }
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionPointSetClosestPoint) {
|
| + const int kHeight = 10;
|
| + const int kWidth = 10;
|
| + const double kAspectRatio = 1.0;
|
| + ResolutionSet set(kHeight, kHeight, kWidth, kWidth, kAspectRatio,
|
| + kAspectRatio);
|
| +
|
| + for (int height = 0; height < 100; height += 10) {
|
| + for (int width = 0; width < 100; width += 10) {
|
| + EXPECT_EQ(P(kHeight, kWidth), set.ClosestPointTo(P(height, width)));
|
| + }
|
| + }
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionLineSetClosestPoint) {
|
| + {
|
| + const int kHeight = 10;
|
| + auto set = ResolutionSet::FromExactHeight(kHeight);
|
| + for (int height = 0; height < 100; height += 10) {
|
| + for (int width = 0; width < 100; width += 10) {
|
| + EXPECT_EQ(P(kHeight, width), set.ClosestPointTo(P(height, width)));
|
| + }
|
| + }
|
| + const int kWidth = 10;
|
| + set = ResolutionSet::FromExactWidth(kWidth);
|
| + for (int height = 0; height < 100; height += 10) {
|
| + for (int width = 0; width < 100; width += 10) {
|
| + EXPECT_EQ(P(height, kWidth), set.ClosestPointTo(P(height, width)));
|
| + }
|
| + }
|
| + }
|
| +
|
| + {
|
| + const double kAspectRatios[] = {0.0, 0.1, 0.2, 0.5,
|
| + 1.0, 2.0, 5.0, HUGE_VAL};
|
| + for (double aspect_ratio : kAspectRatios) {
|
| + auto set = ResolutionSet::FromExactAspectRatio(aspect_ratio);
|
| + for (int height = 0; height < 100; height += 10) {
|
| + for (int width = 0; width < 100; width += 10) {
|
| + Point point(height, width);
|
| + Point expected =
|
| + ProjectionOnSegmentLine(point, P(0, 0), P(1, aspect_ratio));
|
| + Point actual = set.ClosestPointTo(point);
|
| + // This requires higher tolerance than ExpectPointEx due to the larger
|
| + // error of the alternative projection method.
|
| + EXPECT_TRUE(expected.IsApproximatelyEqualTo(actual));
|
| + }
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionGeneralSetClosestPoint) {
|
| + // This set contains the following vertices:
|
| + // (10, 10), (20, 10), (100, 50), (100, 100), (100/1.5, 100), (10, 15)
|
| + ResolutionSet set(10, 100, 10, 100, 0.5, 1.5);
|
| +
|
| + // Check that vertices are the closest points to themselves.
|
| + auto vertices = set.ComputeVertices();
|
| + for (auto& vertex : vertices)
|
| + EXPECT_EQ(vertex, set.ClosestPointTo(vertex));
|
| +
|
| + // Point inside the set.
|
| + EXPECT_EQ(P(11, 11), set.ClosestPointTo(P(11, 11)));
|
| +
|
| + // Close to horizontal segment (10, 10) (20, 10).
|
| + EXPECT_EQ(P(15, 10), set.ClosestPointTo(P(15, 9)));
|
| +
|
| + // Close to horizontal segment (100, 100) (100/1.5, 100).
|
| + EXPECT_EQ(P(99, 100), set.ClosestPointTo(P(99, 200)));
|
| +
|
| + // Close to vertical segment (10, 15) (10, 10).
|
| + EXPECT_EQ(P(10, 12.5), set.ClosestPointTo(P(2, 12.5)));
|
| +
|
| + // Close to vertical segment (100, 50) (100, 100).
|
| + EXPECT_EQ(P(100, 75), set.ClosestPointTo(P(120, 75)));
|
| +
|
| + // Close to oblique segment (20, 10) (100, 50)
|
| + {
|
| + Point point(70, 15);
|
| + Point expected = ProjectionOnSegmentLine(point, P(20, 10), P(100, 50));
|
| + Point actual = set.ClosestPointTo(point);
|
| + EXPECT_POINT_EQ(expected, actual);
|
| + }
|
| +
|
| + // Close to oblique segment (100/1.5, 100) (10, 15)
|
| + {
|
| + Point point(12, 70);
|
| + Point expected =
|
| + ProjectionOnSegmentLine(point, P(100 / 1.5, 100), P(10, 15));
|
| + Point actual = set.ClosestPointTo(point);
|
| + EXPECT_POINT_EQ(expected, actual);
|
| + }
|
| +
|
| + // Points close to vertices.
|
| + EXPECT_EQ(P(10, 10), set.ClosestPointTo(P(9, 9)));
|
| + EXPECT_EQ(P(20, 10), set.ClosestPointTo(P(20, 9)));
|
| + EXPECT_EQ(P(100, 50), set.ClosestPointTo(P(101, 50)));
|
| + EXPECT_EQ(P(100, 100), set.ClosestPointTo(P(101, 101)));
|
| + EXPECT_EQ(P(100 / 1.5, 100), set.ClosestPointTo(P(100 / 1.5, 101)));
|
| + EXPECT_EQ(P(10, 15), set.ClosestPointTo(P(9, 15)));
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionIdealIntersects) {
|
| + ResolutionSet set(100, 1000, 100, 1000, 0.5, 2.0);
|
| +
|
| + int kIdealHeight = 500;
|
| + int kIdealWidth = 1000;
|
| + double kIdealAspectRatio = 1.5;
|
| +
|
| + // Ideal height.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().height.setIdeal(kIdealHeight);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(
|
| + Point(kIdealHeight,
|
| + kIdealHeight * MediaStreamVideoSource::kDefaultAspectRatio),
|
| + point);
|
| + }
|
| +
|
| + // Ideal width.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().width.setIdeal(kIdealWidth);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(
|
| + Point(kIdealWidth / MediaStreamVideoSource::kDefaultAspectRatio,
|
| + kIdealWidth),
|
| + point);
|
| + }
|
| +
|
| + // Ideal aspect ratio.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_DOUBLE_EQ(MediaStreamVideoSource::kDefaultHeight, point.height());
|
| + EXPECT_DOUBLE_EQ(MediaStreamVideoSource::kDefaultHeight * kIdealAspectRatio,
|
| + point.width());
|
| + }
|
| +
|
| + // Ideal height and width.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().height.setIdeal(kIdealHeight);
|
| + factory_.basic().width.setIdeal(kIdealWidth);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(Point(kIdealHeight, kIdealWidth), point);
|
| + }
|
| +
|
| + // Ideal height and aspect-ratio.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().height.setIdeal(kIdealHeight);
|
| + factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(Point(kIdealHeight, kIdealHeight * kIdealAspectRatio),
|
| + point);
|
| + }
|
| +
|
| + // Ideal width and aspect-ratio.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().width.setIdeal(kIdealWidth);
|
| + factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(Point(kIdealWidth / kIdealAspectRatio, kIdealWidth), point);
|
| + }
|
| +
|
| + // Ideal height, width and aspect-ratio.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().height.setIdeal(kIdealHeight);
|
| + factory_.basic().width.setIdeal(kIdealWidth);
|
| + factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + // Ideal aspect ratio should be ignored.
|
| + EXPECT_POINT_EQ(Point(kIdealHeight, kIdealWidth), point);
|
| + }
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionIdealOutsideSinglePoint) {
|
| + // This set is a triangle with vertices (100,100), (1000,100) and (1000,1000).
|
| + ResolutionSet set(100, 1000, 100, 1000, 0.0, 1.0);
|
| +
|
| + int kIdealHeight = 50;
|
| + int kIdealWidth = 1100;
|
| + double kIdealAspectRatio = 0.09;
|
| + Point kVertex1(100, 100);
|
| + Point kVertex2(1000, 100);
|
| + Point kVertex3(1000, 1000);
|
| +
|
| + // Ideal height.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().height.setIdeal(kIdealHeight);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(kVertex1, point);
|
| + }
|
| +
|
| + // Ideal width.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().width.setIdeal(kIdealWidth);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(kVertex3, point);
|
| + }
|
| +
|
| + // Ideal aspect ratio.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(kVertex2, point);
|
| + }
|
| +
|
| + // Ideal height and width.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().height.setIdeal(kIdealHeight);
|
| + factory_.basic().width.setIdeal(kIdealWidth);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + Point expected = set.ClosestPointTo(Point(kIdealHeight, kIdealWidth));
|
| + EXPECT_POINT_EQ(expected, point);
|
| + }
|
| +
|
| + // Ideal height and aspect-ratio.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().height.setIdeal(kIdealHeight);
|
| + factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + Point expected = set.ClosestPointTo(
|
| + Point(kIdealHeight, kIdealHeight * kIdealAspectRatio));
|
| + EXPECT_POINT_EQ(expected, point);
|
| + }
|
| +
|
| + // Ideal width and aspect-ratio.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().width.setIdeal(kIdealWidth);
|
| + factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + Point expected =
|
| + set.ClosestPointTo(Point(kIdealWidth / kIdealAspectRatio, kIdealWidth));
|
| + EXPECT_POINT_EQ(expected, point);
|
| + }
|
| +
|
| + // Ideal height, width and aspect-ratio.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().height.setIdeal(kIdealHeight);
|
| + factory_.basic().width.setIdeal(kIdealWidth);
|
| + factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + // kIdealAspectRatio is ignored if all three ideals are given.
|
| + Point expected = set.ClosestPointTo(Point(kIdealHeight, kIdealWidth));
|
| + EXPECT_POINT_EQ(expected, point);
|
| + }
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest,
|
| + ResolutionIdealOutsideMultiplePoints) {
|
| + // This set is a triangle with vertices (100,100), (1000,100) and (1000,1000).
|
| + ResolutionSet set(100, 1000, 100, 1000, 0.0, 1.0);
|
| +
|
| + int kIdealHeight = 1100;
|
| + int kIdealWidth = 50;
|
| + double kIdealAspectRatio = 11.0;
|
| + Point kVertex1(100, 100);
|
| + Point kVertex2(1000, 100);
|
| + Point kVertex3(1000, 1000);
|
| +
|
| + // Ideal height.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().height.setIdeal(kIdealHeight);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + // Parallel to the side between kVertex2 and kVertex3. Point closest to
|
| + // default aspect ratio is kVertex3.
|
| + EXPECT_POINT_EQ(kVertex3, point);
|
| + }
|
| +
|
| + // Ideal width.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().width.setIdeal(kIdealWidth);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + // Parallel to the side between kVertex1 and kVertex2. Point closest to
|
| + // default aspect ratio is kVertex1.
|
| + EXPECT_POINT_EQ(kVertex1, point);
|
| + }
|
| +
|
| + // Ideal aspect ratio.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + // The side between kVertex1 and kVertex3 is closest. The points closest to
|
| + // default dimensions are (kDefaultHeight, kDefaultHeight * AR)
|
| + // and (kDefaultWidth / AR, kDefaultWidth). Since the aspect ratio of the
|
| + // polygon side is less than the default, the algorithm preserves the
|
| + // default width.
|
| + Point expected(
|
| + MediaStreamVideoSource::kDefaultWidth / kVertex1.AspectRatio(),
|
| + MediaStreamVideoSource::kDefaultWidth);
|
| + EXPECT_POINT_EQ(expected, point);
|
| + EXPECT_TRUE(set.ContainsPoint(expected));
|
| + }
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest,
|
| + ResolutionUnconstrainedExtremeIdeal) {
|
| + ResolutionSet set;
|
| +
|
| + // Ideal height.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().height.setIdeal(std::numeric_limits<long>::max());
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(
|
| + Point(ResolutionSet::kMaxDimension, ResolutionSet::kMaxDimension),
|
| + point);
|
| + factory_.basic().height.setIdeal(0);
|
| + point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(Point(0, 0), point);
|
| + }
|
| +
|
| + // Ideal width.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().width.setIdeal(std::numeric_limits<long>::max());
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(Point(ResolutionSet::kMaxDimension /
|
| + MediaStreamVideoSource::kDefaultAspectRatio,
|
| + ResolutionSet::kMaxDimension),
|
| + point);
|
| + factory_.basic().width.setIdeal(0);
|
| + point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(Point(0, 0), point);
|
| + }
|
| +
|
| + // Ideal Aspect Ratio.
|
| + {
|
| + factory_.Reset();
|
| + factory_.basic().aspectRatio.setIdeal(HUGE_VAL);
|
| + Point point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(Point(0, ResolutionSet::kMaxDimension), point);
|
| + factory_.basic().aspectRatio.setIdeal(0.0);
|
| + point = set.SelectClosestPointToIdeal(
|
| + factory_.CreateWebMediaConstraints().basic());
|
| + EXPECT_POINT_EQ(Point(ResolutionSet::kMaxDimension, 0), point);
|
| + }
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, ResolutionVertices) {
|
| + // Empty set.
|
| + {
|
| + ResolutionSet set(1000, 100, 1000, 100, 0.5, 1.5);
|
| + ASSERT_TRUE(set.IsEmpty());
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(0U, vertices.size());
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // Three lines that intersect at the same point.
|
| + {
|
| + ResolutionSet set(1, 1, 1, 1, 1, 1);
|
| + EXPECT_FALSE(set.IsEmpty());
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(1U, vertices.size());
|
| + VerticesContain(vertices, Point(1, 1));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // A line segment with the lower-left and upper-right corner of the box.
|
| + {
|
| + ResolutionSet set(0, 100, 0, 100, 1.0, 1.0);
|
| + EXPECT_FALSE(set.IsEmpty());
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(2U, vertices.size());
|
| + VerticesContain(vertices, Point(0, 0));
|
| + VerticesContain(vertices, Point(100, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(0, 100, 0, 100, 1.0, HUGE_VAL);
|
| + EXPECT_FALSE(set.IsEmpty());
|
| + vertices = set.ComputeVertices();
|
| + EXPECT_EQ(3U, vertices.size());
|
| + VerticesContain(vertices, Point(0, 0));
|
| + VerticesContain(vertices, Point(100, 100));
|
| + VerticesContain(vertices, Point(0, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(0, 100, 0, 100, 0, 1.0);
|
| + EXPECT_FALSE(set.IsEmpty());
|
| + vertices = set.ComputeVertices();
|
| + EXPECT_EQ(3U, vertices.size());
|
| + VerticesContain(vertices, Point(0, 0));
|
| + VerticesContain(vertices, Point(100, 100));
|
| + VerticesContain(vertices, Point(100, 0));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // A line segment that crosses the bottom and right sides of the box.
|
| + {
|
| + const double kAspectRatio = 50.0 / 75.0;
|
| + ResolutionSet set(50, 100, 50, 100, kAspectRatio, kAspectRatio);
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(2U, vertices.size());
|
| + VerticesContain(vertices, Point(50 / kAspectRatio, 50));
|
| + VerticesContain(vertices, Point(100, 100.0 * kAspectRatio));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(50, 100, 50, 100, kAspectRatio, HUGE_VAL);
|
| + vertices = set.ComputeVertices();
|
| + EXPECT_EQ(5U, vertices.size());
|
| + VerticesContain(vertices, Point(50 / kAspectRatio, 50));
|
| + VerticesContain(vertices, Point(100, 100.0 * kAspectRatio));
|
| + VerticesContain(vertices, Point(50, 50));
|
| + VerticesContain(vertices, Point(50, 100));
|
| + VerticesContain(vertices, Point(100, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(50, 100, 50, 100, 0.0, kAspectRatio);
|
| + vertices = set.ComputeVertices();
|
| + EXPECT_EQ(3U, vertices.size());
|
| + VerticesContain(vertices, Point(50 / kAspectRatio, 50));
|
| + VerticesContain(vertices, Point(100, 100.0 * kAspectRatio));
|
| + VerticesContain(vertices, Point(100, 50));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // A line segment that crosses the left and top sides of the box.
|
| + {
|
| + const double kAspectRatio = 75.0 / 50.0;
|
| + ResolutionSet set(50, 100, 50, 100, kAspectRatio, kAspectRatio);
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(2U, vertices.size());
|
| + VerticesContain(vertices, Point(50, 50 * kAspectRatio));
|
| + VerticesContain(vertices, Point(100 / kAspectRatio, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(50, 100, 50, 100, kAspectRatio, HUGE_VAL);
|
| + vertices = set.ComputeVertices();
|
| + EXPECT_EQ(3U, vertices.size());
|
| + VerticesContain(vertices, Point(50, 50 * kAspectRatio));
|
| + VerticesContain(vertices, Point(100 / kAspectRatio, 100));
|
| + VerticesContain(vertices, Point(50, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(50, 100, 50, 100, 0.0, kAspectRatio);
|
| + vertices = set.ComputeVertices();
|
| + EXPECT_EQ(5U, vertices.size());
|
| + VerticesContain(vertices, Point(50, 50 * kAspectRatio));
|
| + VerticesContain(vertices, Point(100 / kAspectRatio, 100));
|
| + VerticesContain(vertices, Point(50, 50));
|
| + VerticesContain(vertices, Point(100, 100));
|
| + VerticesContain(vertices, Point(100, 50));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // An aspect ratio constraint crosses the bottom and top sides of the box.
|
| + {
|
| + const double kAspectRatio = 75.0 / 50.0;
|
| + ResolutionSet set(0, 100, 50, 100, kAspectRatio, kAspectRatio);
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(2U, vertices.size());
|
| + VerticesContain(vertices, Point(50 / kAspectRatio, 50));
|
| + VerticesContain(vertices, Point(100 / kAspectRatio, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(0, 100, 50, 100, kAspectRatio, HUGE_VAL);
|
| + vertices = set.ComputeVertices();
|
| + EXPECT_EQ(4U, vertices.size());
|
| + VerticesContain(vertices, Point(50 / kAspectRatio, 50));
|
| + VerticesContain(vertices, Point(100 / kAspectRatio, 100));
|
| + VerticesContain(vertices, Point(0, 50));
|
| + VerticesContain(vertices, Point(0, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(0, 100, 50, 100, 0.0, kAspectRatio);
|
| + vertices = set.ComputeVertices();
|
| + EXPECT_EQ(4U, vertices.size());
|
| + VerticesContain(vertices, Point(50 / kAspectRatio, 50));
|
| + VerticesContain(vertices, Point(100 / kAspectRatio, 100));
|
| + VerticesContain(vertices, Point(100, 50));
|
| + VerticesContain(vertices, Point(100, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // An aspect-ratio constraint crosses the left and right sides of the box.
|
| + {
|
| + const double kAspectRatio = 75.0 / 50.0;
|
| + ResolutionSet set(50, 100, 0, 200, kAspectRatio, kAspectRatio);
|
| + auto vertices = set.ComputeVertices();
|
| + // This one fails if floating-point precision is too high.
|
| + EXPECT_EQ(2U, vertices.size());
|
| + VerticesContain(vertices, Point(50, 50 * kAspectRatio));
|
| + VerticesContain(vertices, Point(100, 100 * kAspectRatio));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(50, 100, 0, 200, kAspectRatio, HUGE_VAL);
|
| + vertices = set.ComputeVertices();
|
| + // This one fails if floating-point precision is too high.
|
| + EXPECT_EQ(4U, vertices.size());
|
| + VerticesContain(vertices, Point(50, 50 * kAspectRatio));
|
| + VerticesContain(vertices, Point(100, 100 * kAspectRatio));
|
| + VerticesContain(vertices, Point(50, 200));
|
| + VerticesContain(vertices, Point(100, 200));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(50, 100, 0, 200, 0.0, kAspectRatio);
|
| + vertices = set.ComputeVertices();
|
| + EXPECT_EQ(4U, vertices.size());
|
| + VerticesContain(vertices, Point(50, 50 * kAspectRatio));
|
| + VerticesContain(vertices, Point(100, 100 * kAspectRatio));
|
| + VerticesContain(vertices, Point(50, 0));
|
| + VerticesContain(vertices, Point(100, 0));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // Aspect-ratio lines touch the corners of the box.
|
| + {
|
| + ResolutionSet set(50, 100, 50, 100, 0.5, 2.0);
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(4U, vertices.size());
|
| + VerticesContain(vertices, Point(50, 50));
|
| + VerticesContain(vertices, Point(100, 50));
|
| + VerticesContain(vertices, Point(50, 100));
|
| + VerticesContain(vertices, Point(100, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // Hexagons.
|
| + {
|
| + ResolutionSet set(10, 100, 10, 100, 0.5, 1.5);
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(6U, vertices.size());
|
| + VerticesContain(vertices, Point(10, 10));
|
| + VerticesContain(vertices, Point(100, 100));
|
| + VerticesContain(vertices, Point(10, 10 * 1.5));
|
| + VerticesContain(vertices, Point(100 / 1.5, 100));
|
| + VerticesContain(vertices, Point(10 / 0.5, 10));
|
| + VerticesContain(vertices, Point(100, 100 * 0.5));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(50, 100, 50, 100, 50.0 / 75.0, 75.0 / 50.0);
|
| + vertices = set.ComputeVertices();
|
| + EXPECT_EQ(6U, vertices.size());
|
| + VerticesContain(vertices, Point(50, 50));
|
| + VerticesContain(vertices, Point(100, 100));
|
| + VerticesContain(vertices, Point(75, 50));
|
| + VerticesContain(vertices, Point(50, 75));
|
| + VerticesContain(vertices, Point(100, 100.0 * 50.0 / 75.0));
|
| + VerticesContain(vertices, Point(100 * 50.0 / 75.0, 100.0));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // Both aspect-ratio constraints cross the left and top sides of the box.
|
| + {
|
| + ResolutionSet set(10, 100, 10, 100, 1.5, 1.7);
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(4U, vertices.size());
|
| + VerticesContain(vertices, Point(10, 10 * 1.5));
|
| + VerticesContain(vertices, Point(10, 10 * 1.7));
|
| + VerticesContain(vertices, Point(100 / 1.5, 100));
|
| + VerticesContain(vertices, Point(100 / 1.7, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // Both aspect-ratio constraints cross the left and right sides of the box.
|
| + {
|
| + ResolutionSet set(10, 100, 10, ResolutionSet::kMaxDimension, 1.5, 1.7);
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(4U, vertices.size());
|
| + VerticesContain(vertices, Point(10, 10 * 1.5));
|
| + VerticesContain(vertices, Point(10, 10 * 1.7));
|
| + VerticesContain(vertices, Point(100, 100 * 1.5));
|
| + VerticesContain(vertices, Point(100, 100 * 1.7));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // Both aspect-ratio constraints cross the bottom and top sides of the box.
|
| + {
|
| + ResolutionSet set(10, 100, 50, 100, 2.0, 4.0);
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(4U, vertices.size());
|
| + VerticesContain(vertices, Point(50 / 2.0, 50));
|
| + VerticesContain(vertices, Point(100 / 2.0, 100));
|
| + VerticesContain(vertices, Point(50 / 4.0, 50));
|
| + VerticesContain(vertices, Point(100 / 4.0, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // Both aspect-ratio constraints cross the bottom and right sides of the box.
|
| + {
|
| + ResolutionSet set(10, 100, 50, 100, 0.7, 0.9);
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(4U, vertices.size());
|
| + VerticesContain(vertices, Point(50 / 0.7, 50));
|
| + VerticesContain(vertices, Point(50 / 0.9, 50));
|
| + VerticesContain(vertices, Point(100, 100 * 0.7));
|
| + VerticesContain(vertices, Point(100, 100 * 0.9));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // Pentagons.
|
| + {
|
| + ResolutionSet set(10, 100, 50, 100, 0.7, 4.0);
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(5U, vertices.size());
|
| + VerticesContain(vertices, Point(50 / 0.7, 50));
|
| + VerticesContain(vertices, Point(100, 100 * 0.7));
|
| + VerticesContain(vertices, Point(50 / 4.0, 50));
|
| + VerticesContain(vertices, Point(100 / 4.0, 100));
|
| + VerticesContain(vertices, Point(100, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(50, 100, 10, 100, 0.7, 1.5);
|
| + vertices = set.ComputeVertices();
|
| + EXPECT_EQ(5U, vertices.size());
|
| + VerticesContain(vertices, Point(50, 50 * 0.7));
|
| + VerticesContain(vertices, Point(100, 100 * 0.7));
|
| + VerticesContain(vertices, Point(50, 50 * 1.5));
|
| + VerticesContain(vertices, Point(100 / 1.5, 100));
|
| + VerticesContain(vertices, Point(100, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +
|
| + // Extreme aspect ratios, for completeness.
|
| + {
|
| + ResolutionSet set(0, 100, 0, ResolutionSet::kMaxDimension, 0.0, 0.0);
|
| + auto vertices = set.ComputeVertices();
|
| + EXPECT_EQ(2U, vertices.size());
|
| + VerticesContain(vertices, Point(0, 0));
|
| + VerticesContain(vertices, Point(100, 0));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| +
|
| + set = ResolutionSet(0, ResolutionSet::kMaxDimension, 0, 100, HUGE_VAL,
|
| + HUGE_VAL);
|
| + vertices = set.ComputeVertices();
|
| + EXPECT_EQ(2U, vertices.size());
|
| + VerticesContain(vertices, Point(0, 0));
|
| + VerticesContain(vertices, Point(0, 100));
|
| + EXPECT_TRUE(AreValidVertices(set, vertices));
|
| + }
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, NumericRangeSetDouble) {
|
| + using DoubleRangeSet = NumericRangeSet<double>;
|
| + // Set with maximum supported range.
|
| + DoubleRangeSet set;
|
| + EXPECT_EQ(0.0, set.Min());
|
| + EXPECT_EQ(HUGE_VAL, set.Max());
|
| + EXPECT_FALSE(set.IsEmpty());
|
| +
|
| + // Constrained set.
|
| + const double kMin = 1.0;
|
| + const double kMax = 10.0;
|
| + set = DoubleRangeSet(kMin, kMax);
|
| + EXPECT_EQ(kMin, set.Min());
|
| + EXPECT_EQ(kMax, set.Max());
|
| + EXPECT_FALSE(set.IsEmpty());
|
| +
|
| + // Empty set.
|
| + set = DoubleRangeSet(kMax, kMin);
|
| + EXPECT_TRUE(set.IsEmpty());
|
| +
|
| + // Intersection.
|
| + set = DoubleRangeSet(kMin, kMax);
|
| + const double kMin2 = 5.0;
|
| + const double kMax2 = 20.0;
|
| + auto intersection = set.Intersection(DoubleRangeSet(kMin2, kMax2));
|
| + EXPECT_EQ(kMin2, intersection.Min());
|
| + EXPECT_EQ(kMax, intersection.Max());
|
| + EXPECT_FALSE(intersection.IsEmpty());
|
| +
|
| + // Empty intersection.
|
| + intersection = set.Intersection(DoubleRangeSet(kMax + 1, HUGE_VAL));
|
| + EXPECT_TRUE(intersection.IsEmpty());
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, DiscreteSetString) {
|
| + // Universal set.
|
| + using StringSet = DiscreteSet<std::string>;
|
| + StringSet set = StringSet::UniversalSet();
|
| + EXPECT_TRUE(set.Contains("arbitrary"));
|
| + EXPECT_TRUE(set.Contains("strings"));
|
| + EXPECT_FALSE(set.IsEmpty());
|
| + EXPECT_TRUE(set.is_universal());
|
| + EXPECT_FALSE(set.HasExplicitElements());
|
| +
|
| + // Constrained set.
|
| + set = StringSet(std::vector<std::string>({"a", "b", "c"}));
|
| + EXPECT_TRUE(set.Contains("a"));
|
| + EXPECT_TRUE(set.Contains("b"));
|
| + EXPECT_TRUE(set.Contains("c"));
|
| + EXPECT_FALSE(set.Contains("d"));
|
| + EXPECT_FALSE(set.IsEmpty());
|
| + EXPECT_FALSE(set.is_universal());
|
| + EXPECT_TRUE(set.HasExplicitElements());
|
| + EXPECT_EQ(std::string("a"), set.FirstElement());
|
| +
|
| + // Empty set.
|
| + set = StringSet::EmptySet();
|
| + EXPECT_FALSE(set.Contains("a"));
|
| + EXPECT_FALSE(set.Contains("b"));
|
| + EXPECT_TRUE(set.IsEmpty());
|
| + EXPECT_FALSE(set.is_universal());
|
| + EXPECT_FALSE(set.HasExplicitElements());
|
| +
|
| + // Intersection.
|
| + set = StringSet(std::vector<std::string>({"a", "b", "c"}));
|
| + StringSet set2 = StringSet(std::vector<std::string>({"b", "c", "d"}));
|
| + auto intersection = set.Intersection(set2);
|
| + EXPECT_FALSE(intersection.Contains("a"));
|
| + EXPECT_TRUE(intersection.Contains("b"));
|
| + EXPECT_TRUE(intersection.Contains("c"));
|
| + EXPECT_FALSE(intersection.Contains("d"));
|
| + EXPECT_FALSE(intersection.IsEmpty());
|
| + EXPECT_FALSE(intersection.is_universal());
|
| + EXPECT_TRUE(intersection.HasExplicitElements());
|
| + EXPECT_EQ(std::string("b"), intersection.FirstElement());
|
| +
|
| + // Empty intersection.
|
| + set2 = StringSet(std::vector<std::string>({"d", "e", "f"}));
|
| + intersection = set.Intersection(set2);
|
| + EXPECT_FALSE(intersection.Contains("a"));
|
| + EXPECT_FALSE(intersection.Contains("b"));
|
| + EXPECT_FALSE(intersection.Contains("c"));
|
| + EXPECT_FALSE(intersection.Contains("d"));
|
| + EXPECT_TRUE(intersection.IsEmpty());
|
| + EXPECT_FALSE(intersection.is_universal());
|
| + EXPECT_FALSE(intersection.HasExplicitElements());
|
| +}
|
| +
|
| +TEST_F(MediaStreamConstraintsUtilSetsTest, DiscreteSetBool) {
|
| + using BoolSet = DiscreteSet<bool>;
|
| + // Universal set.
|
| + BoolSet set = BoolSet::UniversalSet();
|
| + EXPECT_TRUE(set.Contains(true));
|
| + EXPECT_TRUE(set.Contains(false));
|
| + EXPECT_FALSE(set.IsEmpty());
|
| + EXPECT_TRUE(set.is_universal());
|
| + EXPECT_FALSE(set.HasExplicitElements());
|
| +
|
| + // Constrained set.
|
| + set = BoolSet({true});
|
| + EXPECT_TRUE(set.Contains(true));
|
| + EXPECT_FALSE(set.Contains(false));
|
| + EXPECT_FALSE(set.IsEmpty());
|
| + EXPECT_FALSE(set.is_universal());
|
| + EXPECT_TRUE(set.HasExplicitElements());
|
| + EXPECT_TRUE(set.FirstElement());
|
| +
|
| + set = BoolSet({false});
|
| + EXPECT_FALSE(set.Contains(true));
|
| + EXPECT_TRUE(set.Contains(false));
|
| + EXPECT_FALSE(set.IsEmpty());
|
| + EXPECT_FALSE(set.is_universal());
|
| + EXPECT_TRUE(set.HasExplicitElements());
|
| + EXPECT_FALSE(set.FirstElement());
|
| +
|
| + // Empty set.
|
| + set = BoolSet::EmptySet();
|
| + EXPECT_FALSE(set.Contains(true));
|
| + EXPECT_FALSE(set.Contains(false));
|
| + EXPECT_TRUE(set.IsEmpty());
|
| + EXPECT_FALSE(set.is_universal());
|
| + EXPECT_FALSE(set.HasExplicitElements());
|
| +
|
| + // Intersection.
|
| + set = BoolSet::UniversalSet();
|
| + auto intersection = set.Intersection(BoolSet({true}));
|
| + EXPECT_TRUE(intersection.Contains(true));
|
| + EXPECT_FALSE(intersection.Contains(false));
|
| + intersection = set.Intersection(set);
|
| + EXPECT_TRUE(intersection.Contains(true));
|
| + EXPECT_TRUE(intersection.Contains(true));
|
| +
|
| + // Empty intersection.
|
| + set = BoolSet({true});
|
| + intersection = set.Intersection(BoolSet({false}));
|
| + EXPECT_TRUE(intersection.IsEmpty());
|
| +}
|
| +
|
| +} // namespace content
|
|
|