| 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_video_device.h" | 5 #include "content/renderer/media/media_stream_constraints_util_video_device.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 basic_constraint_set, constrained_format.constrained_resolution(), | 182 basic_constraint_set, constrained_format.constrained_resolution(), |
| 183 constrained_format.constrained_frame_rate(), | 183 constrained_format.constrained_frame_rate(), |
| 184 capture_params.requested_format, expect_source_native_size); | 184 capture_params.requested_format, expect_source_native_size); |
| 185 | 185 |
| 186 return VideoCaptureSettings( | 186 return VideoCaptureSettings( |
| 187 candidate.device_id(), capture_params, candidate.noise_reduction(), | 187 candidate.device_id(), capture_params, candidate.noise_reduction(), |
| 188 track_adapter_settings, constrained_format.constrained_frame_rate().Min(), | 188 track_adapter_settings, constrained_format.constrained_frame_rate().Min(), |
| 189 constrained_format.constrained_frame_rate().Max()); | 189 constrained_format.constrained_frame_rate().Max()); |
| 190 } | 190 } |
| 191 | 191 |
| 192 // Generic distance function between two numeric values. Based on the fitness | |
| 193 // distance function described in | |
| 194 // https://w3c.github.io/mediacapture-main/#dfn-fitness-distance | |
| 195 double Distance(double value1, double value2) { | |
| 196 if (std::fabs(value1 - value2) <= blink::DoubleConstraint::kConstraintEpsilon) | |
| 197 return 0.0; | |
| 198 | |
| 199 return std::fabs(value1 - value2) / | |
| 200 std::max(std::fabs(value1), std::fabs(value2)); | |
| 201 } | |
| 202 | |
| 203 // Returns a pair with the minimum and maximum aspect ratios supported by the | 192 // Returns a pair with the minimum and maximum aspect ratios supported by the |
| 204 // candidate format |constrained_format|, subject to given width and height | 193 // candidate format |constrained_format|, subject to given width and height |
| 205 // constraints. | 194 // constraints. |
| 206 void GetSourceAspectRatioRange(const ConstrainedFormat& constrained_format, | 195 void GetSourceAspectRatioRange(const ConstrainedFormat& constrained_format, |
| 207 const blink::LongConstraint& height_constraint, | 196 const blink::LongConstraint& height_constraint, |
| 208 const blink::LongConstraint& width_constraint, | 197 const blink::LongConstraint& width_constraint, |
| 209 double* min_source_aspect_ratio, | 198 double* min_source_aspect_ratio, |
| 210 double* max_source_aspect_ratio) { | 199 double* max_source_aspect_ratio) { |
| 211 long min_height = constrained_format.MinHeight(); | 200 long min_height = constrained_format.MinHeight(); |
| 212 if (ConstraintHasMin(height_constraint)) | 201 if (ConstraintHasMin(height_constraint)) |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 277 (constraint_has_min && max_source_value < constraint_min) || | 266 (constraint_has_min && max_source_value < constraint_min) || |
| 278 (constraint_has_min && constraint_has_max && | 267 (constraint_has_min && constraint_has_max && |
| 279 constraint_min > constraint_max)) { | 268 constraint_min > constraint_max)) { |
| 280 if (failed_constraint_name) | 269 if (failed_constraint_name) |
| 281 *failed_constraint_name = constraint.GetName(); | 270 *failed_constraint_name = constraint.GetName(); |
| 282 return HUGE_VAL; | 271 return HUGE_VAL; |
| 283 } | 272 } |
| 284 | 273 |
| 285 // If the source value exceeds the maximum requested, penalize. | 274 // If the source value exceeds the maximum requested, penalize. |
| 286 if (constraint_has_max && native_source_value > constraint_max) | 275 if (constraint_has_max && native_source_value > constraint_max) |
| 287 return Distance(native_source_value, constraint_max); | 276 return NumericConstraintFitnessDistance(native_source_value, |
| 277 constraint_max); |
| 288 | 278 |
| 289 return 0.0; | 279 return 0.0; |
| 290 } | 280 } |
| 291 | 281 |
| 292 // Returns a custom distance function suitable for frame rate, given | 282 // Returns a custom distance function suitable for frame rate, given |
| 293 // a |constraint| and a candidate format |constrained_format|. | 283 // a |constraint| and a candidate format |constrained_format|. |
| 294 // A source can support track frame rates in the interval | 284 // A source can support track frame rates in the interval |
| 295 // [min_frame_rate, max_frame_rate], using frame-rate adjustments if | 285 // [min_frame_rate, max_frame_rate], using frame-rate adjustments if |
| 296 // necessary. If the candidate range and the constraint range are disjoint, | 286 // necessary. If the candidate range and the constraint range are disjoint, |
| 297 // return HUGE_VAL. | 287 // return HUGE_VAL. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 319 (constraint_has_min && constraint_has_max && | 309 (constraint_has_min && constraint_has_max && |
| 320 constraint_min > constraint_max)) { | 310 constraint_min > constraint_max)) { |
| 321 if (failed_constraint_name) | 311 if (failed_constraint_name) |
| 322 *failed_constraint_name = constraint.GetName(); | 312 *failed_constraint_name = constraint.GetName(); |
| 323 return HUGE_VAL; | 313 return HUGE_VAL; |
| 324 } | 314 } |
| 325 | 315 |
| 326 // Compute the cost using the native rate. | 316 // Compute the cost using the native rate. |
| 327 if (constraint_has_max && | 317 if (constraint_has_max && |
| 328 constrained_format.native_frame_rate() > constraint_max) | 318 constrained_format.native_frame_rate() > constraint_max) |
| 329 return Distance(constrained_format.native_frame_rate(), constraint_max); | 319 return NumericConstraintFitnessDistance( |
| 320 constrained_format.native_frame_rate(), constraint_max); |
| 330 | 321 |
| 331 return 0.0; | 322 return 0.0; |
| 332 } | 323 } |
| 333 | 324 |
| 334 // Returns a custom distance function suitable for aspect ratio, given | 325 // Returns a custom distance function suitable for aspect ratio, given |
| 335 // the values for the aspect_ratio, width and height constraints, and a | 326 // the values for the aspect_ratio, width and height constraints, and a |
| 336 // candidate format |constrained_format|. | 327 // candidate format |constrained_format|. |
| 337 // A source can support track resolutions that range from | 328 // A source can support track resolutions that range from |
| 338 // min_width x min_height to max_width x max_height | 329 // min_width x min_height to max_width x max_height |
| 339 // where | 330 // where |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 FormatSourceDistance(candidate.format(), constrained_format, | 484 FormatSourceDistance(candidate.format(), constrained_format, |
| 494 constraint_set, failed_constraint_name) + | 485 constraint_set, failed_constraint_name) + |
| 495 PowerLineFrequencyConstraintSourceDistance( | 486 PowerLineFrequencyConstraintSourceDistance( |
| 496 constraint_set.goog_power_line_frequency, | 487 constraint_set.goog_power_line_frequency, |
| 497 candidate.power_line_frequency(), failed_constraint_name) + | 488 candidate.power_line_frequency(), failed_constraint_name) + |
| 498 NoiseReductionConstraintSourceDistance( | 489 NoiseReductionConstraintSourceDistance( |
| 499 constraint_set.goog_noise_reduction, candidate.noise_reduction(), | 490 constraint_set.goog_noise_reduction, candidate.noise_reduction(), |
| 500 failed_constraint_name); | 491 failed_constraint_name); |
| 501 } | 492 } |
| 502 | 493 |
| 503 // Returns the fitness distance between |value| and |constraint|. | |
| 504 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. | |
| 505 double StringConstraintFitnessDistance( | |
| 506 const blink::WebString& value, | |
| 507 const blink::StringConstraint& constraint) { | |
| 508 if (!constraint.HasIdeal()) | |
| 509 return 0.0; | |
| 510 | |
| 511 for (auto& ideal_value : constraint.Ideal()) { | |
| 512 if (value == ideal_value) | |
| 513 return 0.0; | |
| 514 } | |
| 515 | |
| 516 return 1.0; | |
| 517 } | |
| 518 | |
| 519 // Returns the fitness distance between |value| and |constraint| for | 494 // Returns the fitness distance between |value| and |constraint| for |
| 520 // resolution constraints (i.e., width and height). | 495 // resolution constraints (i.e., width and height). |
| 521 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. | 496 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. |
| 522 double ResolutionConstraintFitnessDistance( | 497 double ResolutionConstraintFitnessDistance( |
| 523 long value, | 498 long value, |
| 524 const blink::LongConstraint& constraint) { | 499 const blink::LongConstraint& constraint) { |
| 525 if (!constraint.HasIdeal()) | 500 if (!constraint.HasIdeal()) |
| 526 return 0.0; | 501 return 0.0; |
| 527 | 502 |
| 528 // Source resolutions greater than ideal support the ideal value with | 503 // Source resolutions greater than ideal support the ideal value with |
| 529 // cropping. | 504 // cropping. |
| 530 if (value >= constraint.Ideal()) | 505 if (value >= constraint.Ideal()) |
| 531 return 0.0; | 506 return 0.0; |
| 532 | 507 |
| 533 return Distance(value, constraint.Ideal()); | 508 return NumericConstraintFitnessDistance(value, constraint.Ideal()); |
| 534 } | 509 } |
| 535 | 510 |
| 536 // Returns the fitness distance between |value| and |constraint| for | 511 // Returns the fitness distance between |value| and |constraint| for |
| 537 // resolution constraints (i.e., width and height), ignoring cropping. | 512 // resolution constraints (i.e., width and height), ignoring cropping. |
| 538 // This measures how well a native resolution supports the idea value. | 513 // This measures how well a native resolution supports the idea value. |
| 539 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. | 514 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. |
| 540 double ResolutionConstraintNativeFitnessDistance( | 515 double ResolutionConstraintNativeFitnessDistance( |
| 541 long value, | 516 long value, |
| 542 const blink::LongConstraint& constraint) { | 517 const blink::LongConstraint& constraint) { |
| 543 return constraint.HasIdeal() ? Distance(value, constraint.Ideal()) : 0.0; | 518 return constraint.HasIdeal() |
| 519 ? NumericConstraintFitnessDistance(value, constraint.Ideal()) |
| 520 : 0.0; |
| 544 } | 521 } |
| 545 | 522 |
| 546 // Returns the fitness distance between a source resolution settings | 523 // Returns the fitness distance between a source resolution settings |
| 547 // and the aspectRatio constraint, taking into account resolution restrictions | 524 // and the aspectRatio constraint, taking into account resolution restrictions |
| 548 // on the source imposed by the width and height constraints. | 525 // on the source imposed by the width and height constraints. |
| 549 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. | 526 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. |
| 550 double AspectRatioConstraintFitnessDistance( | 527 double AspectRatioConstraintFitnessDistance( |
| 551 const ConstrainedFormat& constrained_format, | 528 const ConstrainedFormat& constrained_format, |
| 552 const blink::LongConstraint& height_constraint, | 529 const blink::LongConstraint& height_constraint, |
| 553 const blink::LongConstraint& width_constraint, | 530 const blink::LongConstraint& width_constraint, |
| 554 const blink::DoubleConstraint& aspect_ratio_constraint) { | 531 const blink::DoubleConstraint& aspect_ratio_constraint) { |
| 555 if (!aspect_ratio_constraint.HasIdeal()) | 532 if (!aspect_ratio_constraint.HasIdeal()) |
| 556 return 0.0; | 533 return 0.0; |
| 557 | 534 |
| 558 double min_source_aspect_ratio; | 535 double min_source_aspect_ratio; |
| 559 double max_source_aspect_ratio; | 536 double max_source_aspect_ratio; |
| 560 GetSourceAspectRatioRange(constrained_format, height_constraint, | 537 GetSourceAspectRatioRange(constrained_format, height_constraint, |
| 561 width_constraint, &min_source_aspect_ratio, | 538 width_constraint, &min_source_aspect_ratio, |
| 562 &max_source_aspect_ratio); | 539 &max_source_aspect_ratio); |
| 563 | 540 |
| 564 // If the supported aspect ratio range does not include the ideal aspect | 541 // If the supported aspect ratio range does not include the ideal aspect |
| 565 // ratio, compute fitness using the spec formula. | 542 // ratio, compute fitness using the spec formula. |
| 566 if (max_source_aspect_ratio < | 543 if (max_source_aspect_ratio < |
| 567 aspect_ratio_constraint.Ideal() - | 544 aspect_ratio_constraint.Ideal() - |
| 568 blink::DoubleConstraint::kConstraintEpsilon) { | 545 blink::DoubleConstraint::kConstraintEpsilon) { |
| 569 return Distance(max_source_aspect_ratio, aspect_ratio_constraint.Ideal()); | 546 return NumericConstraintFitnessDistance(max_source_aspect_ratio, |
| 547 aspect_ratio_constraint.Ideal()); |
| 570 } | 548 } |
| 571 | 549 |
| 572 if (min_source_aspect_ratio > | 550 if (min_source_aspect_ratio > |
| 573 aspect_ratio_constraint.Ideal() + | 551 aspect_ratio_constraint.Ideal() + |
| 574 blink::DoubleConstraint::kConstraintEpsilon) { | 552 blink::DoubleConstraint::kConstraintEpsilon) { |
| 575 return Distance(min_source_aspect_ratio, aspect_ratio_constraint.Ideal()); | 553 return NumericConstraintFitnessDistance(min_source_aspect_ratio, |
| 554 aspect_ratio_constraint.Ideal()); |
| 576 } | 555 } |
| 577 | 556 |
| 578 // Otherwise, the ideal aspect ratio can be supported and the fitness is 0. | 557 // Otherwise, the ideal aspect ratio can be supported and the fitness is 0. |
| 579 return 0.0; | 558 return 0.0; |
| 580 } | 559 } |
| 581 | 560 |
| 582 // Returns the fitness distance between |value| and |constraint| for the | 561 // Returns the fitness distance between |value| and |constraint| for the |
| 583 // frameRate constraint. | 562 // frameRate constraint. |
| 584 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. | 563 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. |
| 585 double FrameRateConstraintFitnessDistance( | 564 double FrameRateConstraintFitnessDistance( |
| 586 double value, | 565 double value, |
| 587 const blink::DoubleConstraint& constraint) { | 566 const blink::DoubleConstraint& constraint) { |
| 588 if (!constraint.HasIdeal()) | 567 if (!constraint.HasIdeal()) |
| 589 return 0.0; | 568 return 0.0; |
| 590 | 569 |
| 591 // Source frame rates greater than ideal support the ideal value using | 570 // Source frame rates greater than ideal support the ideal value using |
| 592 // frame-rate adjustment. | 571 // frame-rate adjustment. |
| 593 if (value >= | 572 if (value >= |
| 594 constraint.Ideal() - blink::DoubleConstraint::kConstraintEpsilon) { | 573 constraint.Ideal() - blink::DoubleConstraint::kConstraintEpsilon) { |
| 595 return 0.0; | 574 return 0.0; |
| 596 } | 575 } |
| 597 | 576 |
| 598 return Distance(value, constraint.Ideal()); | 577 return NumericConstraintFitnessDistance(value, constraint.Ideal()); |
| 599 } | 578 } |
| 600 | 579 |
| 601 // Returns the fitness distance between |value| and |constraint| for the | 580 // Returns the fitness distance between |value| and |constraint| for the |
| 602 // frameRate constraint, ignoring frame-rate adjustment. | 581 // frameRate constraint, ignoring frame-rate adjustment. |
| 603 // It measures how well the native frame rate supports the ideal value. | 582 // It measures how well the native frame rate supports the ideal value. |
| 604 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. | 583 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. |
| 605 double FrameRateConstraintNativeFitnessDistance( | 584 double FrameRateConstraintNativeFitnessDistance( |
| 606 double value, | 585 double value, |
| 607 const blink::DoubleConstraint& constraint) { | 586 const blink::DoubleConstraint& constraint) { |
| 608 return constraint.HasIdeal() ? Distance(value, constraint.Ideal()) : 0.0; | 587 return constraint.HasIdeal() |
| 588 ? NumericConstraintFitnessDistance(value, constraint.Ideal()) |
| 589 : 0.0; |
| 609 } | 590 } |
| 610 | 591 |
| 611 // Returns the fitness distance between |value| and |constraint| for the | 592 // Returns the fitness distance between |value| and |constraint| for the |
| 612 // googPowerLineFrequency constraint. | 593 // googPowerLineFrequency constraint. |
| 613 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. | 594 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. |
| 614 double PowerLineFrequencyConstraintFitnessDistance( | 595 double PowerLineFrequencyConstraintFitnessDistance( |
| 615 long value, | 596 long value, |
| 616 const blink::LongConstraint& constraint) { | 597 const blink::LongConstraint& constraint) { |
| 617 if (!constraint.HasIdeal()) | 598 if (!constraint.HasIdeal()) |
| 618 return 0.0; | 599 return 0.0; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 728 // implementation choose a noise-reduction strategy. | 709 // implementation choose a noise-reduction strategy. |
| 729 double noise_reduction_distance = | 710 double noise_reduction_distance = |
| 730 candidate.noise_reduction() ? HUGE_VAL : 0.0; | 711 candidate.noise_reduction() ? HUGE_VAL : 0.0; |
| 731 distance_vector->push_back(noise_reduction_distance); | 712 distance_vector->push_back(noise_reduction_distance); |
| 732 | 713 |
| 733 // Prefer a resolution with area close to the default. | 714 // Prefer a resolution with area close to the default. |
| 734 int candidate_area = candidate.format().frame_size.GetArea(); | 715 int candidate_area = candidate.format().frame_size.GetArea(); |
| 735 double resolution_distance = | 716 double resolution_distance = |
| 736 candidate_area == kDefaultResolutionArea | 717 candidate_area == kDefaultResolutionArea |
| 737 ? 0.0 | 718 ? 0.0 |
| 738 : Distance(candidate_area, kDefaultResolutionArea); | 719 : NumericConstraintFitnessDistance(candidate_area, |
| 720 kDefaultResolutionArea); |
| 739 distance_vector->push_back(resolution_distance); | 721 distance_vector->push_back(resolution_distance); |
| 740 | 722 |
| 741 // Prefer a frame rate close to the default. | 723 // Prefer a frame rate close to the default. |
| 742 double frame_rate_distance = | 724 double frame_rate_distance = |
| 743 candidate.format().frame_rate == MediaStreamVideoSource::kDefaultFrameRate | 725 candidate.format().frame_rate == MediaStreamVideoSource::kDefaultFrameRate |
| 744 ? 0.0 | 726 ? 0.0 |
| 745 : Distance(candidate.format().frame_rate, | 727 : NumericConstraintFitnessDistance( |
| 746 MediaStreamVideoSource::kDefaultFrameRate); | 728 candidate.format().frame_rate, |
| 729 MediaStreamVideoSource::kDefaultFrameRate); |
| 747 distance_vector->push_back(frame_rate_distance); | 730 distance_vector->push_back(frame_rate_distance); |
| 748 } | 731 } |
| 749 | 732 |
| 750 } // namespace | 733 } // namespace |
| 751 | 734 |
| 752 blink::WebString GetVideoKindForFormat( | 735 blink::WebString GetVideoKindForFormat( |
| 753 const media::VideoCaptureFormat& format) { | 736 const media::VideoCaptureFormat& format) { |
| 754 return (format.pixel_format == media::PIXEL_FORMAT_Y16) | 737 return (format.pixel_format == media::PIXEL_FORMAT_Y16) |
| 755 ? blink::WebString::FromASCII(kVideoKindDepth) | 738 ? blink::WebString::FromASCII(kVideoKindDepth) |
| 756 : blink::WebString::FromASCII(kVideoKindColor); | 739 : blink::WebString::FromASCII(kVideoKindColor); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 878 } | 861 } |
| 879 } | 862 } |
| 880 | 863 |
| 881 if (!result.HasValue()) | 864 if (!result.HasValue()) |
| 882 return VideoCaptureSettings(failed_constraint_name); | 865 return VideoCaptureSettings(failed_constraint_name); |
| 883 | 866 |
| 884 return result; | 867 return result; |
| 885 } | 868 } |
| 886 | 869 |
| 887 } // namespace content | 870 } // namespace content |
| OLD | NEW |