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 |