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> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "content/renderer/media/media_stream_constraints_util.h" | 13 #include "content/renderer/media/media_stream_constraints_util.h" |
| 14 #include "content/renderer/media/media_stream_constraints_util_sets.h" |
14 #include "content/renderer/media/media_stream_video_source.h" | 15 #include "content/renderer/media/media_stream_video_source.h" |
15 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" | 16 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" |
16 #include "third_party/WebKit/public/platform/WebString.h" | 17 #include "third_party/WebKit/public/platform/WebString.h" |
17 | 18 |
18 namespace content { | 19 namespace content { |
19 | 20 |
20 namespace { | 21 namespace { |
21 | 22 |
22 // Number of default settings to be used as final tie-breaking criteria for | 23 // Number of default settings to be used as final tie-breaking criteria for |
23 // settings that are equally good at satisfying constraints: | 24 // settings that are equally good at satisfying constraints: |
(...skipping 19 matching lines...) Expand all Loading... |
43 return blink::WebString::fromASCII("environment"); | 44 return blink::WebString::fromASCII("environment"); |
44 case ::mojom::FacingMode::LEFT: | 45 case ::mojom::FacingMode::LEFT: |
45 return blink::WebString::fromASCII("left"); | 46 return blink::WebString::fromASCII("left"); |
46 case ::mojom::FacingMode::RIGHT: | 47 case ::mojom::FacingMode::RIGHT: |
47 return blink::WebString::fromASCII("right"); | 48 return blink::WebString::fromASCII("right"); |
48 default: | 49 default: |
49 return blink::WebString::fromASCII(""); | 50 return blink::WebString::fromASCII(""); |
50 } | 51 } |
51 } | 52 } |
52 | 53 |
53 struct VideoDeviceCaptureSourceSettings { | 54 struct Candidate { |
54 public: | 55 public: |
55 VideoDeviceCaptureSourceSettings( | 56 Candidate(const std::string& device_id, |
56 const std::string& device_id, | 57 const media::VideoCaptureFormat& format, |
57 const media::VideoCaptureFormat& format, | 58 ::mojom::FacingMode facing_mode, |
58 ::mojom::FacingMode facing_mode, | 59 media::PowerLineFrequency power_line_frequency, |
59 media::PowerLineFrequency power_line_frequency, | 60 const base::Optional<bool>& noise_reduction) |
60 const rtc::Optional<bool>& noise_reduction) | |
61 : device_id_(device_id), | 61 : device_id_(device_id), |
62 format_(format), | 62 format_(format), |
63 facing_mode_(facing_mode), | 63 facing_mode_(facing_mode), |
64 power_line_frequency_(power_line_frequency), | 64 power_line_frequency_(power_line_frequency), |
65 noise_reduction_(noise_reduction) {} | 65 noise_reduction_(noise_reduction) {} |
66 | 66 |
67 VideoDeviceCaptureSourceSettings( | |
68 const VideoDeviceCaptureSourceSettings& other) = default; | |
69 VideoDeviceCaptureSourceSettings& operator=( | |
70 const VideoDeviceCaptureSourceSettings& other) = default; | |
71 VideoDeviceCaptureSourceSettings(VideoDeviceCaptureSourceSettings&& other) = | |
72 default; | |
73 VideoDeviceCaptureSourceSettings& operator=( | |
74 VideoDeviceCaptureSourceSettings&& other) = default; | |
75 ~VideoDeviceCaptureSourceSettings() = default; | |
76 | |
77 // These accessor-like methods transform types to what Blink constraint | 67 // These accessor-like methods transform types to what Blink constraint |
78 // classes expect. | 68 // classes expect. |
79 blink::WebString GetFacingMode() const { return ToWebString(facing_mode_); } | 69 blink::WebString GetFacingMode() const { return ToWebString(facing_mode_); } |
80 long GetPowerLineFrequency() const { | 70 long GetPowerLineFrequency() const { |
81 return static_cast<long>(power_line_frequency_); | 71 return static_cast<long>(power_line_frequency_); |
82 } | 72 } |
83 blink::WebString GetDeviceId() const { | 73 blink::WebString GetDeviceId() const { |
84 return blink::WebString::fromASCII(device_id_.data()); | 74 return blink::WebString::fromASCII(device_id_.data()); |
85 } | 75 } |
86 blink::WebString GetVideoKind() const { | 76 blink::WebString GetVideoKind() const { |
87 return GetVideoKindForFormat(format_); | 77 return GetVideoKindForFormat(format_); |
88 } | 78 } |
89 | 79 |
90 // Accessors. | 80 // Accessors. |
91 const media::VideoCaptureFormat& format() const { return format_; } | 81 const media::VideoCaptureFormat& format() const { return format_; } |
92 const std::string& device_id() const { return device_id_; } | 82 const std::string& device_id() const { return device_id_; } |
93 ::mojom::FacingMode facing_mode() const { return facing_mode_; } | 83 ::mojom::FacingMode facing_mode() const { return facing_mode_; } |
94 media::PowerLineFrequency power_line_frequency() const { | 84 media::PowerLineFrequency power_line_frequency() const { |
95 return power_line_frequency_; | 85 return power_line_frequency_; |
96 } | 86 } |
97 const rtc::Optional<bool>& noise_reduction() const { | 87 const base::Optional<bool>& noise_reduction() const { |
98 return noise_reduction_; | 88 return noise_reduction_; |
99 } | 89 } |
100 | 90 |
101 private: | 91 private: |
102 std::string device_id_; | 92 std::string device_id_; |
103 media::VideoCaptureFormat format_; | 93 media::VideoCaptureFormat format_; |
104 ::mojom::FacingMode facing_mode_; | 94 ::mojom::FacingMode facing_mode_; |
105 media::PowerLineFrequency power_line_frequency_; | 95 media::PowerLineFrequency power_line_frequency_; |
106 rtc::Optional<bool> noise_reduction_; | 96 base::Optional<bool> noise_reduction_; |
107 }; | 97 }; |
108 | 98 |
109 // The ConstrainedFormat class keeps track of the effect of constraint sets on | 99 // The ConstrainedFormat class keeps track of the effect of constraint sets on |
110 // the range of values supported by a video-capture format while iterating over | 100 // the range of values supported by a video-capture format while iterating over |
111 // the constraint sets. | 101 // the constraint sets. |
112 // For example, suppose a device supports a width of 1024. Then, in principle, | 102 // For example, suppose a device supports a width of 1024. Then, in principle, |
113 // it can support any width below 1024 using cropping. | 103 // it can support any width below 1024 using cropping. |
114 // Suppose the first advanced constraint set requests a maximum width of 640, | 104 // Suppose the first advanced constraint set requests a maximum width of 640, |
115 // and the second advanced constraint set requests a minimum of 800. | 105 // and the second advanced constraint set requests a minimum of 800. |
116 // Separately, the camera supports both advanced sets. However, if the first | 106 // Separately, the camera supports both advanced sets. However, if the first |
117 // set is supported, the second set can no longer be supported because width can | 107 // set is supported, the second set can no longer be supported because width can |
118 // no longer exceed 640. The ConstrainedFormat class keeps track of this. | 108 // no longer exceed 640. The ConstrainedFormat class keeps track of this. |
119 class ConstrainedFormat { | 109 class ConstrainedFormat { |
120 public: | 110 public: |
121 explicit ConstrainedFormat(const media::VideoCaptureFormat& format) | 111 explicit ConstrainedFormat(const media::VideoCaptureFormat& format) |
122 : native_height_(format.frame_size.height()), | 112 : native_height_(format.frame_size.height()), |
123 min_height_(1), | |
124 max_height_(format.frame_size.height()), | |
125 native_width_(format.frame_size.width()), | 113 native_width_(format.frame_size.width()), |
126 min_width_(1), | |
127 max_width_(format.frame_size.width()), | |
128 native_frame_rate_(format.frame_rate), | 114 native_frame_rate_(format.frame_rate), |
129 min_frame_rate_(1), | 115 constrained_resolution_(1, |
130 max_frame_rate_(format.frame_rate) {} | 116 format.frame_size.height(), |
| 117 1, |
| 118 format.frame_size.width(), |
| 119 0.0, |
| 120 HUGE_VAL), |
| 121 constrained_frame_rate_(1, format.frame_rate) {} |
131 | 122 |
132 long native_height() const { return native_height_; } | 123 long native_height() const { return native_height_; } |
133 long min_height() const { return min_height_; } | |
134 long max_height() const { return max_height_; } | |
135 long native_width() const { return native_width_; } | 124 long native_width() const { return native_width_; } |
136 long min_width() const { return min_width_; } | 125 double native_frame_rate() const { return native_frame_rate_; } |
137 long max_width() const { return max_width_; } | 126 const ResolutionSet& constrained_resolution() const { |
138 long native_frame_rate() const { return native_frame_rate_; } | 127 return constrained_resolution_; |
139 long min_frame_rate() const { return min_frame_rate_; } | 128 } |
140 long max_frame_rate() const { return max_frame_rate_; } | 129 const NumericRangeSet<double>& constrained_frame_rate() const { |
| 130 return constrained_frame_rate_; |
| 131 } |
141 | 132 |
142 void ApplyConstraintSet( | 133 long MinHeight() const { return constrained_resolution_.min_height(); } |
| 134 long MaxHeight() const { return constrained_resolution_.max_height(); } |
| 135 long MinWidth() const { return constrained_resolution_.min_width(); } |
| 136 long MaxWidth() const { return constrained_resolution_.max_width(); } |
| 137 double MinAspectRatio() const { |
| 138 return constrained_resolution_.min_aspect_ratio(); |
| 139 } |
| 140 double MaxAspectRatio() const { |
| 141 return constrained_resolution_.max_aspect_ratio(); |
| 142 } |
| 143 double MinFrameRate() const { return constrained_frame_rate_.Min(); } |
| 144 double MaxFrameRate() const { return constrained_frame_rate_.Max(); } |
| 145 |
| 146 // Returns true if the application of |constraint_set| is successful and |
| 147 // results in a nonempty set. Returns true otherwise. |
| 148 bool ApplyConstraintSet( |
143 const blink::WebMediaTrackConstraintSet& constraint_set) { | 149 const blink::WebMediaTrackConstraintSet& constraint_set) { |
144 if (ConstraintHasMin(constraint_set.width)) | 150 constrained_resolution_ = constrained_resolution_.Intersection( |
145 min_width_ = std::max(min_width_, ConstraintMin(constraint_set.width)); | 151 ResolutionSet::FromConstraintSet(constraint_set)); |
146 if (ConstraintHasMax(constraint_set.width)) | 152 constrained_frame_rate_ = constrained_frame_rate_.Intersection( |
147 max_width_ = std::min(max_width_, ConstraintMax(constraint_set.width)); | 153 NumericRangeSet<double>::FromConstraint(constraint_set.frameRate)); |
148 | 154 DCHECK(!constrained_resolution_.IsEmpty()); |
149 if (ConstraintHasMin(constraint_set.height)) | 155 DCHECK(!constrained_frame_rate_.IsEmpty()); |
150 min_height_ = std::max(min_height_, ConstraintMin(constraint_set.height)); | 156 return true; |
151 if (ConstraintHasMax(constraint_set.height)) | |
152 max_height_ = std::min(max_height_, ConstraintMax(constraint_set.height)); | |
153 | |
154 if (ConstraintHasMin(constraint_set.frameRate)) | |
155 min_frame_rate_ = | |
156 std::max(min_frame_rate_, ConstraintMin(constraint_set.frameRate)); | |
157 if (ConstraintHasMax(constraint_set.frameRate)) | |
158 max_frame_rate_ = | |
159 std::min(max_frame_rate_, ConstraintMax(constraint_set.frameRate)); | |
160 } | 157 } |
161 | 158 |
162 private: | 159 private: |
163 // Using long for compatibility with Blink constraint classes. | 160 // Using long for compatibility with Blink constraint classes. |
164 long native_height_; | 161 long native_height_; |
165 long min_height_; | |
166 long max_height_; | |
167 long native_width_; | 162 long native_width_; |
168 long min_width_; | |
169 long max_width_; | |
170 double native_frame_rate_; | 163 double native_frame_rate_; |
171 double min_frame_rate_; | 164 ResolutionSet constrained_resolution_; |
172 double max_frame_rate_; | 165 NumericRangeSet<double> constrained_frame_rate_; |
173 }; | 166 }; |
174 | 167 |
175 VideoDeviceCaptureSourceSelectionResult ResultFromSettings( | 168 VideoCaptureSettings ComputeVideoDeviceCaptureSettings( |
176 const VideoDeviceCaptureSourceSettings& settings) { | 169 const Candidate& candidate, |
| 170 const ConstrainedFormat& constrained_format, |
| 171 const blink::WebMediaTrackConstraintSet& basic_constraint_set) { |
177 media::VideoCaptureParams capture_params; | 172 media::VideoCaptureParams capture_params; |
178 capture_params.requested_format = settings.format(); | 173 capture_params.requested_format = candidate.format(); |
179 capture_params.power_line_frequency = settings.power_line_frequency(); | 174 capture_params.power_line_frequency = candidate.power_line_frequency(); |
| 175 auto track_adapter_settings = SelectVideoTrackAdapterSettings( |
| 176 basic_constraint_set, constrained_format.constrained_resolution(), |
| 177 constrained_format.constrained_frame_rate(), |
| 178 capture_params.requested_format); |
180 | 179 |
181 return VideoDeviceCaptureSourceSelectionResult( | 180 return VideoCaptureSettings( |
182 settings.device_id(), settings.facing_mode(), capture_params, | 181 candidate.device_id(), capture_params, candidate.noise_reduction(), |
183 settings.noise_reduction()); | 182 track_adapter_settings, |
| 183 constrained_format.constrained_frame_rate().Min()); |
184 } | 184 } |
185 | 185 |
186 // Generic distance function between two numeric values. Based on the fitness | 186 // Generic distance function between two numeric values. Based on the fitness |
187 // distance function described in | 187 // distance function described in |
188 // https://w3c.github.io/mediacapture-main/#dfn-fitness-distance | 188 // https://w3c.github.io/mediacapture-main/#dfn-fitness-distance |
189 double Distance(double value1, double value2) { | 189 double Distance(double value1, double value2) { |
190 if (std::fabs(value1 - value2) <= blink::DoubleConstraint::kConstraintEpsilon) | 190 if (std::fabs(value1 - value2) <= blink::DoubleConstraint::kConstraintEpsilon) |
191 return 0.0; | 191 return 0.0; |
192 | 192 |
193 return std::fabs(value1 - value2) / | 193 return std::fabs(value1 - value2) / |
194 std::max(std::fabs(value1), std::fabs(value2)); | 194 std::max(std::fabs(value1), std::fabs(value2)); |
195 } | 195 } |
196 | 196 |
197 // Returns a pair with the minimum and maximum aspect ratios supported by the | 197 // Returns a pair with the minimum and maximum aspect ratios supported by the |
198 // candidate format |constrained_format|, subject to given width and height | 198 // candidate format |constrained_format|, subject to given width and height |
199 // constraints. | 199 // constraints. |
200 void GetSourceAspectRatioRange(const ConstrainedFormat& constrained_format, | 200 void GetSourceAspectRatioRange(const ConstrainedFormat& constrained_format, |
201 const blink::LongConstraint& height_constraint, | 201 const blink::LongConstraint& height_constraint, |
202 const blink::LongConstraint& width_constraint, | 202 const blink::LongConstraint& width_constraint, |
203 double* min_source_aspect_ratio, | 203 double* min_source_aspect_ratio, |
204 double* max_source_aspect_ratio) { | 204 double* max_source_aspect_ratio) { |
205 long min_height = constrained_format.min_height(); | 205 long min_height = constrained_format.MinHeight(); |
206 if (ConstraintHasMin(height_constraint)) | 206 if (ConstraintHasMin(height_constraint)) |
207 min_height = std::max(min_height, ConstraintMin(height_constraint)); | 207 min_height = std::max(min_height, ConstraintMin(height_constraint)); |
208 | 208 |
209 long max_height = constrained_format.max_height(); | 209 long max_height = constrained_format.MaxHeight(); |
210 if (ConstraintHasMax(height_constraint)) | 210 if (ConstraintHasMax(height_constraint)) |
211 max_height = std::min(max_height, ConstraintMax(height_constraint)); | 211 max_height = std::min(max_height, ConstraintMax(height_constraint)); |
212 | 212 |
213 long min_width = constrained_format.min_width(); | 213 long min_width = constrained_format.MinWidth(); |
214 if (ConstraintHasMin(width_constraint)) | 214 if (ConstraintHasMin(width_constraint)) |
215 min_width = std::max(min_width, ConstraintMin(width_constraint)); | 215 min_width = std::max(min_width, ConstraintMin(width_constraint)); |
216 | 216 |
217 long max_width = constrained_format.max_width(); | 217 long max_width = constrained_format.MaxWidth(); |
218 if (ConstraintHasMax(width_constraint)) | 218 if (ConstraintHasMax(width_constraint)) |
219 max_width = std::min(max_width, ConstraintMax(width_constraint)); | 219 max_width = std::min(max_width, ConstraintMax(width_constraint)); |
220 | 220 |
221 *min_source_aspect_ratio = | 221 *min_source_aspect_ratio = std::max( |
| 222 constrained_format.MinAspectRatio(), |
222 std::max(static_cast<double>(min_width) / static_cast<double>(max_height), | 223 std::max(static_cast<double>(min_width) / static_cast<double>(max_height), |
223 kMinSourceAspectRatio); | 224 kMinSourceAspectRatio)); |
224 *max_source_aspect_ratio = | 225 *max_source_aspect_ratio = std::min( |
| 226 constrained_format.MaxAspectRatio(), |
225 std::max(static_cast<double>(max_width) / static_cast<double>(min_height), | 227 std::max(static_cast<double>(max_width) / static_cast<double>(min_height), |
226 kMinSourceAspectRatio); | 228 kMinSourceAspectRatio)); |
227 } | 229 } |
228 | 230 |
229 // Returns a custom distance between a string and a string constraint. | 231 // Returns a custom distance between a string and a string constraint. |
230 // Returns 0 if |value| satisfies |constraint|. HUGE_VAL otherwise. | 232 // Returns 0 if |value| satisfies |constraint|. HUGE_VAL otherwise. |
231 double StringConstraintSourceDistance(const blink::WebString& value, | 233 double StringConstraintSourceDistance(const blink::WebString& value, |
232 const blink::StringConstraint& constraint, | 234 const blink::StringConstraint& constraint, |
233 const char** failed_constraint_name) { | 235 const char** failed_constraint_name) { |
234 if (constraint.matches(value)) | 236 if (constraint.matches(value)) |
235 return 0.0; | 237 return 0.0; |
236 | 238 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
294 double FrameRateConstraintSourceDistance( | 296 double FrameRateConstraintSourceDistance( |
295 const ConstrainedFormat& constrained_format, | 297 const ConstrainedFormat& constrained_format, |
296 const blink::DoubleConstraint& constraint, | 298 const blink::DoubleConstraint& constraint, |
297 const char** failed_constraint_name) { | 299 const char** failed_constraint_name) { |
298 bool constraint_has_min = ConstraintHasMin(constraint); | 300 bool constraint_has_min = ConstraintHasMin(constraint); |
299 double constraint_min = constraint_has_min ? ConstraintMin(constraint) : -1.0; | 301 double constraint_min = constraint_has_min ? ConstraintMin(constraint) : -1.0; |
300 bool constraint_has_max = ConstraintHasMax(constraint); | 302 bool constraint_has_max = ConstraintHasMax(constraint); |
301 double constraint_max = constraint_has_max ? ConstraintMax(constraint) : -1.0; | 303 double constraint_max = constraint_has_max ? ConstraintMax(constraint) : -1.0; |
302 | 304 |
303 if ((constraint_has_max && | 305 if ((constraint_has_max && |
304 constrained_format.min_frame_rate() > | 306 constrained_format.MinFrameRate() > |
305 constraint_max + blink::DoubleConstraint::kConstraintEpsilon) || | 307 constraint_max + blink::DoubleConstraint::kConstraintEpsilon) || |
306 (constraint_has_min && | 308 (constraint_has_min && |
307 constrained_format.max_frame_rate() < | 309 constrained_format.MaxFrameRate() < |
308 constraint_min - blink::DoubleConstraint::kConstraintEpsilon)) { | 310 constraint_min - blink::DoubleConstraint::kConstraintEpsilon)) { |
309 if (failed_constraint_name) | 311 if (failed_constraint_name) |
310 *failed_constraint_name = constraint.name(); | 312 *failed_constraint_name = constraint.name(); |
311 return HUGE_VAL; | 313 return HUGE_VAL; |
312 } | 314 } |
313 | 315 |
314 // Compute the cost using the native rate. | 316 // Compute the cost using the native rate. |
315 if (constraint_has_max && | 317 if (constraint_has_max && |
316 constrained_format.native_frame_rate() > constraint_max) | 318 constrained_format.native_frame_rate() > constraint_max) |
317 return Distance(constrained_format.native_frame_rate(), constraint_max); | 319 return Distance(constrained_format.native_frame_rate(), constraint_max); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 | 396 |
395 return 0.0; | 397 return 0.0; |
396 } | 398 } |
397 | 399 |
398 // Returns a custom distance function suitable for the googNoiseReduction | 400 // Returns a custom distance function suitable for the googNoiseReduction |
399 // constraint, given a |constraint| and a candidate value |value|. | 401 // constraint, given a |constraint| and a candidate value |value|. |
400 // The distance is HUGE_VAL if |candidate_value| cannot satisfy |constraint|. | 402 // The distance is HUGE_VAL if |candidate_value| cannot satisfy |constraint|. |
401 // Otherwise, the distance is zero. | 403 // Otherwise, the distance is zero. |
402 double NoiseReductionConstraintSourceDistance( | 404 double NoiseReductionConstraintSourceDistance( |
403 const blink::BooleanConstraint& constraint, | 405 const blink::BooleanConstraint& constraint, |
404 const rtc::Optional<bool>& value, | 406 const base::Optional<bool>& value, |
405 const char** failed_constraint_name) { | 407 const char** failed_constraint_name) { |
406 if (!constraint.hasExact()) | 408 if (!constraint.hasExact()) |
407 return 0.0; | 409 return 0.0; |
408 | 410 |
409 if (value && *value == constraint.exact()) | 411 if (value && *value == constraint.exact()) |
410 return 0.0; | 412 return 0.0; |
411 | 413 |
412 if (failed_constraint_name) | 414 if (failed_constraint_name) |
413 *failed_constraint_name = constraint.name(); | 415 *failed_constraint_name = constraint.name(); |
414 return HUGE_VAL; | 416 return HUGE_VAL; |
(...skipping 20 matching lines...) Expand all Loading... |
435 // |constraint_set| cannot be satisfied together with previous constraint sets, | 437 // |constraint_set| cannot be satisfied together with previous constraint sets, |
436 // but will not influence the numeric value returned if it is not infinite. | 438 // but will not influence the numeric value returned if it is not infinite. |
437 // Formats with lower distance satisfy |constraint_set| with lower resource | 439 // Formats with lower distance satisfy |constraint_set| with lower resource |
438 // usage. | 440 // usage. |
439 double FormatSourceDistance( | 441 double FormatSourceDistance( |
440 const media::VideoCaptureFormat& format, | 442 const media::VideoCaptureFormat& format, |
441 const ConstrainedFormat& constrained_format, | 443 const ConstrainedFormat& constrained_format, |
442 const blink::WebMediaTrackConstraintSet& constraint_set, | 444 const blink::WebMediaTrackConstraintSet& constraint_set, |
443 const char** failed_constraint_name) { | 445 const char** failed_constraint_name) { |
444 return ResolutionConstraintSourceDistance( | 446 return ResolutionConstraintSourceDistance( |
445 constrained_format.native_height(), | 447 constrained_format.native_height(), constrained_format.MinHeight(), |
446 constrained_format.min_height(), constrained_format.max_height(), | 448 constrained_format.MaxHeight(), constraint_set.height, |
447 constraint_set.height, failed_constraint_name) + | 449 failed_constraint_name) + |
448 ResolutionConstraintSourceDistance( | 450 ResolutionConstraintSourceDistance( |
449 constrained_format.native_width(), constrained_format.min_width(), | 451 constrained_format.native_width(), constrained_format.MinWidth(), |
450 constrained_format.max_width(), constraint_set.width, | 452 constrained_format.MaxWidth(), constraint_set.width, |
451 failed_constraint_name) + | 453 failed_constraint_name) + |
452 AspectRatioConstraintSourceDistance( | 454 AspectRatioConstraintSourceDistance( |
453 constrained_format, constraint_set.height, constraint_set.width, | 455 constrained_format, constraint_set.height, constraint_set.width, |
454 constraint_set.aspectRatio, failed_constraint_name) + | 456 constraint_set.aspectRatio, failed_constraint_name) + |
455 FrameRateConstraintSourceDistance(constrained_format, | 457 FrameRateConstraintSourceDistance(constrained_format, |
456 constraint_set.frameRate, | 458 constraint_set.frameRate, |
457 failed_constraint_name) + | 459 failed_constraint_name) + |
458 StringConstraintSourceDistance(GetVideoKindForFormat(format), | 460 StringConstraintSourceDistance(GetVideoKindForFormat(format), |
459 constraint_set.videoKind, | 461 constraint_set.videoKind, |
460 failed_constraint_name); | 462 failed_constraint_name); |
461 } | 463 } |
462 | 464 |
463 // Returns a custom distance between |constraint_set| and |candidate|, given | 465 // Returns a custom distance between |constraint_set| and |candidate|, given |
464 // that the configuration is already constrained by |constrained_format|. | 466 // that the configuration is already constrained by |constrained_format|. |
465 // |constrained_format| may cause the distance to be infinite if | 467 // |constrained_format| may cause the distance to be infinite if |
466 // |constraint_set| cannot be satisfied together with previous constraint sets, | 468 // |constraint_set| cannot be satisfied together with previous constraint sets, |
467 // but will not influence the numeric value returned if it is not infinite. | 469 // but will not influence the numeric value returned if it is not infinite. |
468 // Candidates with lower distance satisfy |constraint_set| with lower resource | 470 // Candidates with lower distance satisfy |constraint_set| with lower resource |
469 // usage. | 471 // usage. |
470 double CandidateSourceDistance( | 472 double CandidateSourceDistance( |
471 const VideoDeviceCaptureSourceSettings& candidate, | 473 const Candidate& candidate, |
472 const ConstrainedFormat& constrained_format, | 474 const ConstrainedFormat& constrained_format, |
473 const blink::WebMediaTrackConstraintSet& constraint_set, | 475 const blink::WebMediaTrackConstraintSet& constraint_set, |
474 const char** failed_constraint_name) { | 476 const char** failed_constraint_name) { |
475 return DeviceSourceDistance(candidate.device_id(), candidate.facing_mode(), | 477 return DeviceSourceDistance(candidate.device_id(), candidate.facing_mode(), |
476 constraint_set, failed_constraint_name) + | 478 constraint_set, failed_constraint_name) + |
477 FormatSourceDistance(candidate.format(), constrained_format, | 479 FormatSourceDistance(candidate.format(), constrained_format, |
478 constraint_set, failed_constraint_name) + | 480 constraint_set, failed_constraint_name) + |
479 PowerLineFrequencyConstraintSourceDistance( | 481 PowerLineFrequencyConstraintSourceDistance( |
480 constraint_set.googPowerLineFrequency, | 482 constraint_set.googPowerLineFrequency, |
481 candidate.power_line_frequency(), failed_constraint_name) + | 483 candidate.power_line_frequency(), failed_constraint_name) + |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 if (value == constraint.ideal()) | 608 if (value == constraint.ideal()) |
607 return 0.0; | 609 return 0.0; |
608 | 610 |
609 return 1.0; | 611 return 1.0; |
610 } | 612 } |
611 | 613 |
612 // Returns the fitness distance between |value| and |constraint| for the | 614 // Returns the fitness distance between |value| and |constraint| for the |
613 // googNoiseReduction constraint. | 615 // googNoiseReduction constraint. |
614 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. | 616 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. |
615 double NoiseReductionConstraintFitnessDistance( | 617 double NoiseReductionConstraintFitnessDistance( |
616 const rtc::Optional<bool>& value, | 618 const base::Optional<bool>& value, |
617 const blink::BooleanConstraint& constraint) { | 619 const blink::BooleanConstraint& constraint) { |
618 if (!constraint.hasIdeal()) | 620 if (!constraint.hasIdeal()) |
619 return 0.0; | 621 return 0.0; |
620 | 622 |
621 if (value && value == constraint.ideal()) | 623 if (value && value == constraint.ideal()) |
622 return 0.0; | 624 return 0.0; |
623 | 625 |
624 return 1.0; | 626 return 1.0; |
625 } | 627 } |
626 | 628 |
627 // Returns the fitness distance between |constraint_set| and |candidate| given | 629 // Returns the fitness distance between |constraint_set| and |candidate| given |
628 // that the configuration is already constrained by |constrained_format|. | 630 // that the configuration is already constrained by |constrained_format|. |
629 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. | 631 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. |
630 double CandidateFitnessDistance( | 632 double CandidateFitnessDistance( |
631 const VideoDeviceCaptureSourceSettings& candidate, | 633 const Candidate& candidate, |
632 const ConstrainedFormat& constrained_format, | 634 const ConstrainedFormat& constrained_format, |
633 const blink::WebMediaTrackConstraintSet& constraint_set) { | 635 const blink::WebMediaTrackConstraintSet& constraint_set) { |
634 DCHECK(std::isfinite(CandidateSourceDistance(candidate, constrained_format, | 636 DCHECK(std::isfinite(CandidateSourceDistance(candidate, constrained_format, |
635 constraint_set, nullptr))); | 637 constraint_set, nullptr))); |
636 double fitness = 0.0; | 638 double fitness = 0.0; |
637 fitness += AspectRatioConstraintFitnessDistance( | 639 fitness += AspectRatioConstraintFitnessDistance( |
638 constrained_format, constraint_set.height, constraint_set.width, | 640 constrained_format, constraint_set.height, constraint_set.width, |
639 constraint_set.aspectRatio); | 641 constraint_set.aspectRatio); |
640 fitness += StringConstraintFitnessDistance(candidate.GetDeviceId(), | 642 fitness += StringConstraintFitnessDistance(candidate.GetDeviceId(), |
641 constraint_set.deviceId); | 643 constraint_set.deviceId); |
642 fitness += StringConstraintFitnessDistance(candidate.GetFacingMode(), | 644 fitness += StringConstraintFitnessDistance(candidate.GetFacingMode(), |
643 constraint_set.facingMode); | 645 constraint_set.facingMode); |
644 fitness += StringConstraintFitnessDistance(candidate.GetVideoKind(), | 646 fitness += StringConstraintFitnessDistance(candidate.GetVideoKind(), |
645 constraint_set.videoKind); | 647 constraint_set.videoKind); |
646 fitness += PowerLineFrequencyConstraintFitnessDistance( | 648 fitness += PowerLineFrequencyConstraintFitnessDistance( |
647 candidate.GetPowerLineFrequency(), constraint_set.googPowerLineFrequency); | 649 candidate.GetPowerLineFrequency(), constraint_set.googPowerLineFrequency); |
648 fitness += NoiseReductionConstraintFitnessDistance( | 650 fitness += NoiseReductionConstraintFitnessDistance( |
649 candidate.noise_reduction(), constraint_set.googNoiseReduction); | 651 candidate.noise_reduction(), constraint_set.googNoiseReduction); |
650 // No need to pass minimum value to compute fitness for range-based | 652 // No need to pass minimum value to compute fitness for range-based |
651 // constraints because all candidates start out with the same minimum and are | 653 // constraints because all candidates start out with the same minimum and are |
652 // subject to the same constraints. | 654 // subject to the same constraints. |
653 fitness += ResolutionConstraintFitnessDistance( | 655 fitness += ResolutionConstraintFitnessDistance(constrained_format.MaxHeight(), |
654 constrained_format.max_height(), constraint_set.height); | 656 constraint_set.height); |
655 fitness += ResolutionConstraintFitnessDistance(constrained_format.max_width(), | 657 fitness += ResolutionConstraintFitnessDistance(constrained_format.MaxWidth(), |
656 constraint_set.width); | 658 constraint_set.width); |
657 fitness += FrameRateConstraintFitnessDistance( | 659 fitness += FrameRateConstraintFitnessDistance( |
658 constrained_format.max_frame_rate(), constraint_set.frameRate); | 660 constrained_format.MaxFrameRate(), constraint_set.frameRate); |
659 | 661 |
660 return fitness; | 662 return fitness; |
661 } | 663 } |
662 | 664 |
663 // Returns the native fitness distance between a candidate format and a | 665 // Returns the native fitness distance between a candidate format and a |
664 // constraint set. The returned value is the sum of the fitness distances for | 666 // constraint set. The returned value is the sum of the fitness distances for |
665 // the native values of settings that support a range of values (i.e., width, | 667 // the native values of settings that support a range of values (i.e., width, |
666 // height and frame rate). | 668 // height and frame rate). |
667 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. | 669 // Based on https://w3c.github.io/mediacapture-main/#dfn-fitness-distance. |
668 double CandidateNativeFitnessDistance( | 670 double CandidateNativeFitnessDistance( |
(...skipping 11 matching lines...) Expand all Loading... |
680 } | 682 } |
681 | 683 |
682 using DistanceVector = std::vector<double>; | 684 using DistanceVector = std::vector<double>; |
683 | 685 |
684 // This function appends additional entries to |distance_vector| based on | 686 // This function appends additional entries to |distance_vector| based on |
685 // custom distance metrics between |candidate| and some default settings. | 687 // custom distance metrics between |candidate| and some default settings. |
686 // These entries are to be used as the final tie breaker for candidates that | 688 // These entries are to be used as the final tie breaker for candidates that |
687 // are equally good according to the spec and the custom distance functions | 689 // are equally good according to the spec and the custom distance functions |
688 // between candidates and constraints. | 690 // between candidates and constraints. |
689 void AppendDistanceFromDefault( | 691 void AppendDistanceFromDefault( |
690 const VideoDeviceCaptureSourceSettings& candidate, | 692 const Candidate& candidate, |
691 const VideoDeviceCaptureCapabilities& capabilities, | 693 const VideoDeviceCaptureCapabilities& capabilities, |
692 DistanceVector* distance_vector) { | 694 DistanceVector* distance_vector) { |
693 // Favor IDs that appear first in the enumeration. | 695 // Favor IDs that appear first in the enumeration. |
694 for (size_t i = 0; i < capabilities.device_capabilities.size(); ++i) { | 696 for (size_t i = 0; i < capabilities.device_capabilities.size(); ++i) { |
695 if (candidate.device_id() == | 697 if (candidate.device_id() == |
696 capabilities.device_capabilities[i]->device_id) { | 698 capabilities.device_capabilities[i]->device_id) { |
697 distance_vector->push_back(i); | 699 distance_vector->push_back(i); |
698 break; | 700 break; |
699 } | 701 } |
700 } | 702 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 : blink::WebString::fromASCII(kVideoKindColor); | 741 : blink::WebString::fromASCII(kVideoKindColor); |
740 } | 742 } |
741 | 743 |
742 VideoDeviceCaptureCapabilities::VideoDeviceCaptureCapabilities() = default; | 744 VideoDeviceCaptureCapabilities::VideoDeviceCaptureCapabilities() = default; |
743 VideoDeviceCaptureCapabilities::VideoDeviceCaptureCapabilities( | 745 VideoDeviceCaptureCapabilities::VideoDeviceCaptureCapabilities( |
744 VideoDeviceCaptureCapabilities&& other) = default; | 746 VideoDeviceCaptureCapabilities&& other) = default; |
745 VideoDeviceCaptureCapabilities::~VideoDeviceCaptureCapabilities() = default; | 747 VideoDeviceCaptureCapabilities::~VideoDeviceCaptureCapabilities() = default; |
746 VideoDeviceCaptureCapabilities& VideoDeviceCaptureCapabilities::operator=( | 748 VideoDeviceCaptureCapabilities& VideoDeviceCaptureCapabilities::operator=( |
747 VideoDeviceCaptureCapabilities&& other) = default; | 749 VideoDeviceCaptureCapabilities&& other) = default; |
748 | 750 |
749 VideoDeviceCaptureSourceSelectionResult:: | 751 VideoCaptureSettings SelectSettingsVideoDeviceCapture( |
750 VideoDeviceCaptureSourceSelectionResult() | |
751 : VideoDeviceCaptureSourceSelectionResult("") {} | |
752 | |
753 VideoDeviceCaptureSourceSelectionResult:: | |
754 VideoDeviceCaptureSourceSelectionResult(const char* failed_constraint_name) | |
755 : failed_constraint_name_(failed_constraint_name) {} | |
756 | |
757 VideoDeviceCaptureSourceSelectionResult:: | |
758 VideoDeviceCaptureSourceSelectionResult( | |
759 const std::string& device_id, | |
760 ::mojom::FacingMode facing_mode, | |
761 media::VideoCaptureParams capture_params, | |
762 rtc::Optional<bool> noise_reduction) | |
763 : failed_constraint_name_(nullptr), | |
764 device_id_(device_id), | |
765 facing_mode_(facing_mode), | |
766 capture_params_(capture_params), | |
767 noise_reduction_(noise_reduction) {} | |
768 | |
769 VideoDeviceCaptureSourceSelectionResult:: | |
770 VideoDeviceCaptureSourceSelectionResult( | |
771 const VideoDeviceCaptureSourceSelectionResult& other) = default; | |
772 VideoDeviceCaptureSourceSelectionResult:: | |
773 VideoDeviceCaptureSourceSelectionResult( | |
774 VideoDeviceCaptureSourceSelectionResult&& other) = default; | |
775 VideoDeviceCaptureSourceSelectionResult:: | |
776 ~VideoDeviceCaptureSourceSelectionResult() = default; | |
777 VideoDeviceCaptureSourceSelectionResult& | |
778 VideoDeviceCaptureSourceSelectionResult::operator=( | |
779 const VideoDeviceCaptureSourceSelectionResult& other) = default; | |
780 VideoDeviceCaptureSourceSelectionResult& | |
781 VideoDeviceCaptureSourceSelectionResult::operator=( | |
782 VideoDeviceCaptureSourceSelectionResult&& other) = default; | |
783 | |
784 VideoDeviceCaptureSourceSelectionResult SelectVideoDeviceCaptureSourceSettings( | |
785 const VideoDeviceCaptureCapabilities& capabilities, | 752 const VideoDeviceCaptureCapabilities& capabilities, |
786 const blink::WebMediaConstraints& constraints) { | 753 const blink::WebMediaConstraints& constraints) { |
787 // This function works only if infinity is defined for the double type. | 754 // This function works only if infinity is defined for the double type. |
788 DCHECK(std::numeric_limits<double>::has_infinity); | 755 DCHECK(std::numeric_limits<double>::has_infinity); |
789 | 756 |
790 // A distance vector contains: | 757 // A distance vector contains: |
791 // a) For each advanced constraint set, a 0/1 value indicating if the | 758 // a) For each advanced constraint set, a 0/1 value indicating if the |
792 // candidate satisfies the corresponding constraint set. | 759 // candidate satisfies the corresponding constraint set. |
793 // b) Fitness distance for the candidate based on support for the ideal values | 760 // b) Fitness distance for the candidate based on support for the ideal values |
794 // of the basic constraint set. | 761 // of the basic constraint set. |
795 // c) A custom distance value based on how "well" a candidate satisfies each | 762 // c) A custom distance value based on how "well" a candidate satisfies each |
796 // constraint set, including basic and advanced sets. | 763 // constraint set, including basic and advanced sets. |
797 // d) Native fitness distance for the candidate based on support for the | 764 // d) Native fitness distance for the candidate based on support for the |
798 // ideal values of the basic constraint set using native values for | 765 // ideal values of the basic constraint set using native values for |
799 // settings that can support a range of values. | 766 // settings that can support a range of values. |
800 // e) A custom distance value based on how close the candidate is to default | 767 // e) A custom distance value based on how close the candidate is to default |
801 // settings. | 768 // settings. |
802 // Parts (a) and (b) are according to spec. Parts (c) to (e) are | 769 // Parts (a) and (b) are according to spec. Parts (c) to (e) are |
803 // implementation specific and used to break ties. | 770 // implementation specific and used to break ties. |
804 DistanceVector best_distance(2 * constraints.advanced().size() + 3 + | 771 DistanceVector best_distance(2 * constraints.advanced().size() + 3 + |
805 kNumDefaultDistanceEntries); | 772 kNumDefaultDistanceEntries); |
806 std::fill(best_distance.begin(), best_distance.end(), HUGE_VAL); | 773 std::fill(best_distance.begin(), best_distance.end(), HUGE_VAL); |
807 VideoDeviceCaptureSourceSelectionResult result; | 774 VideoCaptureSettings result; |
808 const char* failed_constraint_name = result.failed_constraint_name(); | 775 const char* failed_constraint_name = result.failed_constraint_name(); |
809 | 776 |
810 for (auto& device : capabilities.device_capabilities) { | 777 for (auto& device : capabilities.device_capabilities) { |
811 double basic_device_distance = | 778 double basic_device_distance = |
812 DeviceSourceDistance(device->device_id, device->facing_mode, | 779 DeviceSourceDistance(device->device_id, device->facing_mode, |
813 constraints.basic(), &failed_constraint_name); | 780 constraints.basic(), &failed_constraint_name); |
814 if (!std::isfinite(basic_device_distance)) | 781 if (!std::isfinite(basic_device_distance)) |
815 continue; | 782 continue; |
816 | 783 |
817 for (auto& format : device->formats) { | 784 for (auto& format : device->formats) { |
818 ConstrainedFormat constrained_format(format); | 785 ConstrainedFormat constrained_format(format); |
819 double basic_format_distance = | 786 double basic_format_distance = |
820 FormatSourceDistance(format, constrained_format, constraints.basic(), | 787 FormatSourceDistance(format, constrained_format, constraints.basic(), |
821 &failed_constraint_name); | 788 &failed_constraint_name); |
822 if (!std::isfinite(basic_format_distance)) | 789 if (!std::isfinite(basic_format_distance)) |
823 continue; | 790 continue; |
824 constrained_format.ApplyConstraintSet(constraints.basic()); | 791 constrained_format.ApplyConstraintSet(constraints.basic()); |
| 792 DCHECK(!constrained_format.constrained_resolution().IsEmpty()); |
| 793 DCHECK(!constrained_format.constrained_frame_rate().IsEmpty()); |
825 | 794 |
826 for (auto& power_line_frequency : capabilities.power_line_capabilities) { | 795 for (auto& power_line_frequency : capabilities.power_line_capabilities) { |
827 double basic_power_line_frequency_distance = | 796 double basic_power_line_frequency_distance = |
828 PowerLineFrequencyConstraintSourceDistance( | 797 PowerLineFrequencyConstraintSourceDistance( |
829 constraints.basic().googPowerLineFrequency, | 798 constraints.basic().googPowerLineFrequency, |
830 power_line_frequency, &failed_constraint_name); | 799 power_line_frequency, &failed_constraint_name); |
831 if (!std::isfinite(basic_power_line_frequency_distance)) | 800 if (!std::isfinite(basic_power_line_frequency_distance)) |
832 continue; | 801 continue; |
833 | 802 |
834 for (auto& noise_reduction : | 803 for (auto& noise_reduction : |
835 capabilities.noise_reduction_capabilities) { | 804 capabilities.noise_reduction_capabilities) { |
836 double basic_noise_reduction_distance = | 805 double basic_noise_reduction_distance = |
837 NoiseReductionConstraintSourceDistance( | 806 NoiseReductionConstraintSourceDistance( |
838 constraints.basic().googNoiseReduction, noise_reduction, | 807 constraints.basic().googNoiseReduction, noise_reduction, |
839 &failed_constraint_name); | 808 &failed_constraint_name); |
840 if (!std::isfinite(basic_noise_reduction_distance)) | 809 if (!std::isfinite(basic_noise_reduction_distance)) |
841 continue; | 810 continue; |
842 | 811 |
843 // The candidate satisfies the basic constraint set. | 812 // The candidate satisfies the basic constraint set. |
844 double candidate_basic_custom_distance = | 813 double candidate_basic_custom_distance = |
845 basic_device_distance + basic_format_distance + | 814 basic_device_distance + basic_format_distance + |
846 basic_power_line_frequency_distance + | 815 basic_power_line_frequency_distance + |
847 basic_noise_reduction_distance; | 816 basic_noise_reduction_distance; |
848 DCHECK(std::isfinite(candidate_basic_custom_distance)); | 817 DCHECK(std::isfinite(candidate_basic_custom_distance)); |
849 | 818 |
850 // Temporary vector to save custom distances for advanced constraints. | 819 // Temporary vector to save custom distances for advanced constraints. |
851 // Custom distances must be added to the candidate distance vector | 820 // Custom distances must be added to the candidate distance vector |
852 // after all the spec-mandated values. | 821 // after all the spec-mandated values. |
853 DistanceVector advanced_custom_distance_vector; | 822 DistanceVector advanced_custom_distance_vector; |
854 VideoDeviceCaptureSourceSettings candidate( | 823 Candidate candidate(device->device_id, format, device->facing_mode, |
855 device->device_id, format, device->facing_mode, | 824 power_line_frequency, noise_reduction); |
856 power_line_frequency, noise_reduction); | |
857 DistanceVector candidate_distance_vector; | 825 DistanceVector candidate_distance_vector; |
858 // First criteria for valid candidates is satisfaction of advanced | 826 // First criteria for valid candidates is satisfaction of advanced |
859 // constraint sets. | 827 // constraint sets. |
860 for (const auto& advanced_set : constraints.advanced()) { | 828 for (const auto& advanced_set : constraints.advanced()) { |
861 double custom_distance = CandidateSourceDistance( | 829 double custom_distance = CandidateSourceDistance( |
862 candidate, constrained_format, advanced_set, nullptr); | 830 candidate, constrained_format, advanced_set, nullptr); |
863 advanced_custom_distance_vector.push_back(custom_distance); | 831 advanced_custom_distance_vector.push_back(custom_distance); |
864 double spec_distance = std::isfinite(custom_distance) ? 0 : 1; | 832 double spec_distance = std::isfinite(custom_distance) ? 0 : 1; |
865 candidate_distance_vector.push_back(spec_distance); | 833 candidate_distance_vector.push_back(spec_distance); |
866 if (std::isfinite(custom_distance)) | 834 if (std::isfinite(custom_distance)) |
(...skipping 14 matching lines...) Expand all Loading... |
881 candidate_distance_vector.push_back(CandidateNativeFitnessDistance( | 849 candidate_distance_vector.push_back(CandidateNativeFitnessDistance( |
882 constrained_format, constraints.basic())); | 850 constrained_format, constraints.basic())); |
883 | 851 |
884 // Final criteria are custom distances to default settings. | 852 // Final criteria are custom distances to default settings. |
885 AppendDistanceFromDefault(candidate, capabilities, | 853 AppendDistanceFromDefault(candidate, capabilities, |
886 &candidate_distance_vector); | 854 &candidate_distance_vector); |
887 | 855 |
888 DCHECK_EQ(best_distance.size(), candidate_distance_vector.size()); | 856 DCHECK_EQ(best_distance.size(), candidate_distance_vector.size()); |
889 if (candidate_distance_vector < best_distance) { | 857 if (candidate_distance_vector < best_distance) { |
890 best_distance = candidate_distance_vector; | 858 best_distance = candidate_distance_vector; |
891 result = ResultFromSettings(candidate); | 859 result = ComputeVideoDeviceCaptureSettings( |
| 860 candidate, constrained_format, constraints.basic()); |
892 } | 861 } |
893 } | 862 } |
894 } | 863 } |
895 } | 864 } |
896 } | 865 } |
897 | 866 |
898 if (!result.HasValue()) | 867 if (!result.HasValue()) |
899 return VideoDeviceCaptureSourceSelectionResult(failed_constraint_name); | 868 return VideoCaptureSettings(failed_constraint_name); |
900 | 869 |
901 return result; | 870 return result; |
902 } | 871 } |
903 | 872 |
904 } // namespace content | 873 } // namespace content |
OLD | NEW |