OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/media/media_stream_constraints_util_sets.h" | 5 #include "content/renderer/media/media_stream_constraints_util_sets.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "content/renderer/media/media_stream_constraints_util.h" | 9 #include "content/renderer/media/media_stream_constraints_util.h" |
10 #include "content/renderer/media/media_stream_video_source.h" | |
11 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" | 10 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" |
12 | 11 |
13 namespace content { | 12 namespace content { |
14 | 13 |
15 using Point = ResolutionSet::Point; | 14 using Point = ResolutionSet::Point; |
16 | 15 |
17 namespace { | 16 namespace { |
18 | 17 |
19 constexpr double kTolerance = 1e-5; | 18 constexpr double kTolerance = 1e-5; |
20 | 19 |
21 constexpr int kDefaultHeight = MediaStreamVideoSource::kDefaultHeight; | |
22 constexpr int kDefaultWidth = MediaStreamVideoSource::kDefaultWidth; | |
23 constexpr double kDefaultAspectRatio = | |
24 MediaStreamVideoSource::kDefaultAspectRatio; | |
25 | |
26 // Not perfect, but good enough for this application. | 20 // Not perfect, but good enough for this application. |
27 bool AreApproximatelyEqual(double d1, double d2) { | 21 bool AreApproximatelyEqual(double d1, double d2) { |
28 if (std::fabs((d1 - d2)) <= kTolerance) | 22 if (std::fabs((d1 - d2)) <= kTolerance) |
29 return true; | 23 return true; |
30 | 24 |
31 return d1 == d2 || (std::fabs((d1 - d2) / d1) <= kTolerance && | 25 return d1 == d2 || (std::fabs((d1 - d2) / d1) <= kTolerance && |
32 std::fabs((d1 - d2) / d2) <= kTolerance); | 26 std::fabs((d1 - d2) / d2) <= kTolerance); |
33 } | 27 } |
34 | 28 |
35 bool IsLess(double d1, double d2) { | 29 bool IsLess(double d1, double d2) { |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 ResolutionSet ResolutionSet::Intersection(const ResolutionSet& other) const { | 261 ResolutionSet ResolutionSet::Intersection(const ResolutionSet& other) const { |
268 return ResolutionSet(std::max(min_height_, other.min_height_), | 262 return ResolutionSet(std::max(min_height_, other.min_height_), |
269 std::min(max_height_, other.max_height_), | 263 std::min(max_height_, other.max_height_), |
270 std::max(min_width_, other.min_width_), | 264 std::max(min_width_, other.min_width_), |
271 std::min(max_width_, other.max_width_), | 265 std::min(max_width_, other.max_width_), |
272 std::max(min_aspect_ratio_, other.min_aspect_ratio_), | 266 std::max(min_aspect_ratio_, other.min_aspect_ratio_), |
273 std::min(max_aspect_ratio_, other.max_aspect_ratio_)); | 267 std::min(max_aspect_ratio_, other.max_aspect_ratio_)); |
274 } | 268 } |
275 | 269 |
276 Point ResolutionSet::SelectClosestPointToIdeal( | 270 Point ResolutionSet::SelectClosestPointToIdeal( |
277 const blink::WebMediaTrackConstraintSet& constraint_set) const { | 271 const blink::WebMediaTrackConstraintSet& constraint_set, |
| 272 int default_height, |
| 273 int default_width) const { |
| 274 DCHECK_GE(default_height, 1); |
| 275 DCHECK_GE(default_width, 1); |
| 276 double default_aspect_ratio = |
| 277 static_cast<double>(default_width) / static_cast<double>(default_height); |
| 278 |
278 DCHECK(!IsEmpty()); | 279 DCHECK(!IsEmpty()); |
279 int num_ideals = 0; | 280 int num_ideals = 0; |
280 if (constraint_set.height.hasIdeal()) | 281 if (constraint_set.height.hasIdeal()) |
281 ++num_ideals; | 282 ++num_ideals; |
282 if (constraint_set.width.hasIdeal()) | 283 if (constraint_set.width.hasIdeal()) |
283 ++num_ideals; | 284 ++num_ideals; |
284 if (constraint_set.aspectRatio.hasIdeal()) | 285 if (constraint_set.aspectRatio.hasIdeal()) |
285 ++num_ideals; | 286 ++num_ideals; |
286 | 287 |
287 switch (num_ideals) { | 288 switch (num_ideals) { |
288 case 0: | 289 case 0: |
289 return SelectClosestPointToIdealAspectRatio(kDefaultAspectRatio); | 290 return SelectClosestPointToIdealAspectRatio( |
| 291 default_aspect_ratio, default_height, default_width); |
290 | 292 |
291 case 1: | 293 case 1: |
292 // This case requires a point closest to a line. | 294 // This case requires a point closest to a line. |
293 // In all variants, if the ideal line intersects the polygon, select the | 295 // In all variants, if the ideal line intersects the polygon, select the |
294 // point in the intersection that is closest to preserving the default | 296 // point in the intersection that is closest to preserving the default |
295 // aspect ratio or a default dimension. | 297 // aspect ratio or a default dimension. |
296 // If the ideal line is outside the polygon, there is either a single | 298 // If the ideal line is outside the polygon, there is either a single |
297 // vertex or a polygon side closest to the ideal line. If a single vertex, | 299 // vertex or a polygon side closest to the ideal line. If a single vertex, |
298 // select that vertex. If a polygon side, select the point on that side | 300 // select that vertex. If a polygon side, select the point on that side |
299 // that is closest to preserving the default aspect ratio or a default | 301 // that is closest to preserving the default aspect ratio or a default |
300 // dimension. | 302 // dimension. |
301 if (constraint_set.height.hasIdeal()) { | 303 if (constraint_set.height.hasIdeal()) { |
302 int ideal_height = ToValidDimension(constraint_set.height.ideal()); | 304 int ideal_height = ToValidDimension(constraint_set.height.ideal()); |
303 ResolutionSet ideal_line = ResolutionSet::FromExactHeight(ideal_height); | 305 ResolutionSet ideal_line = ResolutionSet::FromExactHeight(ideal_height); |
304 ResolutionSet intersection = Intersection(ideal_line); | 306 ResolutionSet intersection = Intersection(ideal_line); |
305 if (!intersection.IsEmpty()) { | 307 if (!intersection.IsEmpty()) { |
306 return intersection.ClosestPointTo( | 308 return intersection.ClosestPointTo( |
307 Point(ideal_height, ideal_height * kDefaultAspectRatio)); | 309 Point(ideal_height, ideal_height * default_aspect_ratio)); |
308 } | 310 } |
309 std::vector<Point> closest_vertices = | 311 std::vector<Point> closest_vertices = |
310 GetClosestVertices(&Point::height, ideal_height); | 312 GetClosestVertices(&Point::height, ideal_height); |
311 Point ideal_point(closest_vertices[0].height(), | 313 Point ideal_point(closest_vertices[0].height(), |
312 closest_vertices[0].height() * kDefaultAspectRatio); | 314 closest_vertices[0].height() * default_aspect_ratio); |
313 return GetClosestPointToVertexOrSide(closest_vertices, ideal_point); | 315 return GetClosestPointToVertexOrSide(closest_vertices, ideal_point); |
314 } else if (constraint_set.width.hasIdeal()) { | 316 } else if (constraint_set.width.hasIdeal()) { |
315 int ideal_width = ToValidDimension(constraint_set.width.ideal()); | 317 int ideal_width = ToValidDimension(constraint_set.width.ideal()); |
316 ResolutionSet ideal_line = ResolutionSet::FromExactWidth(ideal_width); | 318 ResolutionSet ideal_line = ResolutionSet::FromExactWidth(ideal_width); |
317 ResolutionSet intersection = Intersection(ideal_line); | 319 ResolutionSet intersection = Intersection(ideal_line); |
318 if (!intersection.IsEmpty()) { | 320 if (!intersection.IsEmpty()) { |
319 return intersection.ClosestPointTo( | 321 return intersection.ClosestPointTo( |
320 Point(ideal_width / kDefaultAspectRatio, ideal_width)); | 322 Point(ideal_width / default_aspect_ratio, ideal_width)); |
321 } | 323 } |
322 std::vector<Point> closest_vertices = | 324 std::vector<Point> closest_vertices = |
323 GetClosestVertices(&Point::width, ideal_width); | 325 GetClosestVertices(&Point::width, ideal_width); |
324 Point ideal_point(closest_vertices[0].width() / kDefaultAspectRatio, | 326 Point ideal_point(closest_vertices[0].width() / default_aspect_ratio, |
325 closest_vertices[0].width()); | 327 closest_vertices[0].width()); |
326 return GetClosestPointToVertexOrSide(closest_vertices, ideal_point); | 328 return GetClosestPointToVertexOrSide(closest_vertices, ideal_point); |
327 } else { | 329 } else { |
328 DCHECK(constraint_set.aspectRatio.hasIdeal()); | 330 DCHECK(constraint_set.aspectRatio.hasIdeal()); |
329 double ideal_aspect_ratio = | 331 double ideal_aspect_ratio = |
330 ToValidAspectRatio(constraint_set.aspectRatio.ideal()); | 332 ToValidAspectRatio(constraint_set.aspectRatio.ideal()); |
331 return SelectClosestPointToIdealAspectRatio(ideal_aspect_ratio); | 333 return SelectClosestPointToIdealAspectRatio( |
| 334 ideal_aspect_ratio, default_height, default_width); |
332 } | 335 } |
333 | 336 |
334 case 2: | 337 case 2: |
335 case 3: | 338 case 3: |
336 double ideal_height; | 339 double ideal_height; |
337 double ideal_width; | 340 double ideal_width; |
338 if (constraint_set.height.hasIdeal()) { | 341 if (constraint_set.height.hasIdeal()) { |
339 ideal_height = ToValidDimension(constraint_set.height.ideal()); | 342 ideal_height = ToValidDimension(constraint_set.height.ideal()); |
340 ideal_width = | 343 ideal_width = |
341 constraint_set.width.hasIdeal() | 344 constraint_set.width.hasIdeal() |
(...skipping 10 matching lines...) Expand all Loading... |
352 return ClosestPointTo(Point(ideal_height, ideal_width)); | 355 return ClosestPointTo(Point(ideal_height, ideal_width)); |
353 | 356 |
354 default: | 357 default: |
355 NOTREACHED(); | 358 NOTREACHED(); |
356 } | 359 } |
357 NOTREACHED(); | 360 NOTREACHED(); |
358 return Point(-1, -1); | 361 return Point(-1, -1); |
359 } | 362 } |
360 | 363 |
361 Point ResolutionSet::SelectClosestPointToIdealAspectRatio( | 364 Point ResolutionSet::SelectClosestPointToIdealAspectRatio( |
362 double ideal_aspect_ratio) const { | 365 double ideal_aspect_ratio, |
| 366 int default_height, |
| 367 int default_width) const { |
363 ResolutionSet intersection = | 368 ResolutionSet intersection = |
364 Intersection(ResolutionSet::FromExactAspectRatio(ideal_aspect_ratio)); | 369 Intersection(ResolutionSet::FromExactAspectRatio(ideal_aspect_ratio)); |
365 if (!intersection.IsEmpty()) { | 370 if (!intersection.IsEmpty()) { |
366 Point default_height_point(kDefaultHeight, | 371 Point default_height_point(default_height, |
367 kDefaultHeight * ideal_aspect_ratio); | 372 default_height * ideal_aspect_ratio); |
368 Point default_width_point(kDefaultWidth / ideal_aspect_ratio, | 373 Point default_width_point(default_width / ideal_aspect_ratio, |
369 kDefaultWidth); | 374 default_width); |
370 return SelectPointWithLargestArea( | 375 return SelectPointWithLargestArea( |
371 intersection.ClosestPointTo(default_height_point), | 376 intersection.ClosestPointTo(default_height_point), |
372 intersection.ClosestPointTo(default_width_point)); | 377 intersection.ClosestPointTo(default_width_point)); |
373 } | 378 } |
374 std::vector<Point> closest_vertices = | 379 std::vector<Point> closest_vertices = |
375 GetClosestVertices(&Point::AspectRatio, ideal_aspect_ratio); | 380 GetClosestVertices(&Point::AspectRatio, ideal_aspect_ratio); |
376 double actual_aspect_ratio = closest_vertices[0].AspectRatio(); | 381 double actual_aspect_ratio = closest_vertices[0].AspectRatio(); |
377 Point default_height_point(kDefaultHeight, | 382 Point default_height_point(default_height, |
378 kDefaultHeight * actual_aspect_ratio); | 383 default_height * actual_aspect_ratio); |
379 Point default_width_point(kDefaultWidth / actual_aspect_ratio, kDefaultWidth); | 384 Point default_width_point(default_width / actual_aspect_ratio, default_width); |
380 return SelectPointWithLargestArea( | 385 return SelectPointWithLargestArea( |
381 GetClosestPointToVertexOrSide(closest_vertices, default_height_point), | 386 GetClosestPointToVertexOrSide(closest_vertices, default_height_point), |
382 GetClosestPointToVertexOrSide(closest_vertices, default_width_point)); | 387 GetClosestPointToVertexOrSide(closest_vertices, default_width_point)); |
383 } | 388 } |
384 | 389 |
385 Point ResolutionSet::ClosestPointTo(const Point& point) const { | 390 Point ResolutionSet::ClosestPointTo(const Point& point) const { |
386 DCHECK(std::numeric_limits<double>::has_infinity); | 391 DCHECK(std::numeric_limits<double>::has_infinity); |
| 392 DCHECK(std::isfinite(point.height())); |
| 393 DCHECK(std::isfinite(point.width())); |
387 | 394 |
388 if (ContainsPoint(point)) | 395 if (ContainsPoint(point)) |
389 return point; | 396 return point; |
390 | 397 |
391 auto vertices = ComputeVertices(); | 398 auto vertices = ComputeVertices(); |
392 DCHECK_GE(vertices.size(), 1U); | 399 DCHECK_GE(vertices.size(), 1U); |
393 Point best_candidate(0, 0); | 400 Point best_candidate(0, 0); |
394 double best_distance = HUGE_VAL; | 401 double best_distance = HUGE_VAL; |
395 for (size_t i = 0; i < vertices.size(); ++i) { | 402 for (size_t i = 0; i < vertices.size(); ++i) { |
396 Point candidate = Point::ClosestPointInSegment( | 403 Point candidate = Point::ClosestPointInSegment( |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 return ResolutionSet( | 527 return ResolutionSet( |
521 MinDimensionFromConstraint(constraint_set.height), | 528 MinDimensionFromConstraint(constraint_set.height), |
522 MaxDimensionFromConstraint(constraint_set.height), | 529 MaxDimensionFromConstraint(constraint_set.height), |
523 MinDimensionFromConstraint(constraint_set.width), | 530 MinDimensionFromConstraint(constraint_set.width), |
524 MaxDimensionFromConstraint(constraint_set.width), | 531 MaxDimensionFromConstraint(constraint_set.width), |
525 MinAspectRatioFromConstraint(constraint_set.aspectRatio), | 532 MinAspectRatioFromConstraint(constraint_set.aspectRatio), |
526 MaxAspectRatioFromConstraint(constraint_set.aspectRatio)); | 533 MaxAspectRatioFromConstraint(constraint_set.aspectRatio)); |
527 } | 534 } |
528 | 535 |
529 } // namespace content | 536 } // namespace content |
OLD | NEW |