OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/renderer/media/media_stream_constraints_util_video_source.h" | |
6 | |
7 #include <algorithm> | |
8 #include <utility> | |
9 | |
10 #include "base/optional.h" | |
11 #include "content/renderer/media/media_stream_video_source.h" | |
12 #include "content/renderer/media/mock_constraint_factory.h" | |
13 #include "testing/gtest/include/gtest/gtest.h" | |
14 #include "third_party/WebKit/public/platform/WebMediaConstraints.h" | |
15 | |
16 namespace content { | |
17 | |
18 namespace { | |
19 | |
20 const char kDeviceID1[] = "fake_device_1"; | |
21 const char kDeviceID2[] = "fake_device_2"; | |
22 const char kDeviceID3[] = "fake_device_3"; | |
23 const char kDeviceID4[] = "fake_device_4"; | |
24 } | |
25 | |
26 class MediaStreamConstraintsUtilVideoSourceTest : public testing::Test { | |
27 public: | |
28 void SetUp() override { | |
29 // Default device. It is default because it is the first in the enumeration. | |
30 ::mojom::VideoInputDeviceCapabilitiesPtr device = | |
31 ::mojom::VideoInputDeviceCapabilities::New(); | |
32 device->device_id = kDeviceID1; | |
33 device->facing_mode = ::mojom::FacingMode::NONE; | |
34 device->formats = { | |
35 media::VideoCaptureFormat(gfx::Size(200, 200), 40.0f, | |
36 media::PIXEL_FORMAT_I420), | |
37 // This entry is is the closest to defaults. | |
38 media::VideoCaptureFormat(gfx::Size(500, 500), 40.0f, | |
39 media::PIXEL_FORMAT_I420), | |
40 media::VideoCaptureFormat(gfx::Size(1000, 1000), 20.0f, | |
41 media::PIXEL_FORMAT_I420), | |
42 }; | |
43 capabilities_.device_capabilities.push_back(std::move(device)); | |
44 | |
45 // A low-resolution device. | |
46 device = ::mojom::VideoInputDeviceCapabilities::New(); | |
47 device->device_id = kDeviceID2; | |
48 device->facing_mode = ::mojom::FacingMode::ENVIRONMENT; | |
49 device->formats = { | |
50 media::VideoCaptureFormat(gfx::Size(40, 30), 20.0f, | |
51 media::PIXEL_FORMAT_I420), | |
52 media::VideoCaptureFormat(gfx::Size(320, 240), 30.0f, | |
53 media::PIXEL_FORMAT_I420), | |
54 // This format has defaults for all settings | |
55 media::VideoCaptureFormat( | |
56 gfx::Size(MediaStreamVideoSource::kDefaultWidth, | |
57 MediaStreamVideoSource::kDefaultHeight), | |
58 MediaStreamVideoSource::kDefaultFrameRate, | |
59 media::PIXEL_FORMAT_I420), | |
60 media::VideoCaptureFormat(gfx::Size(800, 600), 20.0f, | |
61 media::PIXEL_FORMAT_I420), | |
62 }; | |
63 capabilities_.device_capabilities.push_back(std::move(device)); | |
64 | |
65 // A high-resolution device. | |
66 device = ::mojom::VideoInputDeviceCapabilities::New(); | |
67 device->device_id = kDeviceID3; | |
68 device->facing_mode = ::mojom::FacingMode::USER; | |
69 device->formats = { | |
70 media::VideoCaptureFormat(gfx::Size(320, 240), 10.0f, | |
71 media::PIXEL_FORMAT_I420), | |
72 media::VideoCaptureFormat(gfx::Size(640, 480), 10.0f, | |
73 media::PIXEL_FORMAT_I420), | |
74 // This format has defaults for all settings | |
75 media::VideoCaptureFormat( | |
76 gfx::Size(MediaStreamVideoSource::kDefaultWidth, | |
77 MediaStreamVideoSource::kDefaultHeight), | |
78 MediaStreamVideoSource::kDefaultFrameRate, | |
79 media::PIXEL_FORMAT_I420), | |
80 media::VideoCaptureFormat(gfx::Size(1280, 720), 60.0f, | |
81 media::PIXEL_FORMAT_I420), | |
82 media::VideoCaptureFormat(gfx::Size(1920, 1080), 60.0f, | |
83 media::PIXEL_FORMAT_I420), | |
84 media::VideoCaptureFormat(gfx::Size(2304, 1536), 10.0f, | |
85 media::PIXEL_FORMAT_I420), | |
86 }; | |
87 capabilities_.device_capabilities.push_back(std::move(device)); | |
88 | |
89 // A depth capture device. | |
90 device = ::mojom::VideoInputDeviceCapabilities::New(); | |
91 device->device_id = kDeviceID4; | |
92 device->facing_mode = ::mojom::FacingMode::ENVIRONMENT; | |
93 device->formats = {media::VideoCaptureFormat(gfx::Size(640, 480), 30.0f, | |
94 media::PIXEL_FORMAT_Y16)}; | |
95 capabilities_.device_capabilities.push_back(std::move(device)); | |
96 | |
97 capabilities_.power_line_capabilities = { | |
98 media::PowerLineFrequency::FREQUENCY_DEFAULT, | |
99 media::PowerLineFrequency::FREQUENCY_50HZ, | |
100 media::PowerLineFrequency::FREQUENCY_60HZ, | |
101 }; | |
102 | |
103 default_device_ = capabilities_.device_capabilities[0].get(); | |
104 low_res_device_ = capabilities_.device_capabilities[1].get(); | |
105 high_res_device_ = capabilities_.device_capabilities[2].get(); | |
106 default_closest_format_ = &default_device_->formats[1]; | |
107 low_res_closest_format_ = &low_res_device_->formats[2]; | |
108 high_res_closest_format_ = &high_res_device_->formats[2]; | |
109 high_res_highest_format_ = &high_res_device_->formats[5]; | |
110 } | |
111 | |
112 protected: | |
113 VideoCaptureSourceSelectionResult SelectSettings() { | |
114 blink::WebMediaConstraints constraints = | |
115 constraint_factory_.CreateWebMediaConstraints(); | |
116 return SelectVideoCaptureSourceSettings(capabilities_, constraints); | |
117 } | |
118 | |
119 VideoCaptureCapabilities capabilities_; | |
120 const mojom::VideoInputDeviceCapabilities* default_device_; | |
121 const mojom::VideoInputDeviceCapabilities* low_res_device_; | |
122 const mojom::VideoInputDeviceCapabilities* high_res_device_; | |
123 // Closest formats to the default settings. | |
124 const media::VideoCaptureFormat* default_closest_format_; | |
125 const media::VideoCaptureFormat* low_res_closest_format_; | |
126 const media::VideoCaptureFormat* high_res_closest_format_; | |
127 const media::VideoCaptureFormat* high_res_highest_format_; | |
128 | |
129 MockConstraintFactory constraint_factory_; | |
130 }; | |
131 | |
132 // The Unconstrained test checks the default selection criteria. | |
133 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, Unconstrained) { | |
134 constraint_factory_.Reset(); | |
135 auto result = SelectSettings(); | |
136 EXPECT_TRUE(result.has_value()); | |
137 // Should select the default device with closest-to-default settings. | |
138 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
139 EXPECT_EQ(default_device_->facing_mode, result.settings.facing_mode()); | |
140 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
141 } | |
142 | |
143 // The "Overconstrained" tests verify that failure of any single required | |
144 // constraint results in failure to select a candidate. | |
145 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, OverconstrainedOnDeviceID) { | |
146 constraint_factory_.Reset(); | |
147 constraint_factory_.basic().deviceId.setExact( | |
148 blink::WebString::fromASCII("NONEXISTING")); | |
149 auto result = SelectSettings(); | |
150 EXPECT_FALSE(result.has_value()); | |
151 EXPECT_EQ(constraint_factory_.basic().deviceId.name(), | |
152 result.failed_constraint_name); | |
153 } | |
154 | |
155 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, OverconstrainedOnFacingMode) { | |
156 constraint_factory_.Reset(); | |
157 // No device in |capabilities_| has facing mode equal to LEFT. | |
158 constraint_factory_.basic().facingMode.setExact( | |
159 blink::WebString::fromASCII("left")); | |
160 auto result = SelectSettings(); | |
161 EXPECT_FALSE(result.has_value()); | |
162 EXPECT_EQ(constraint_factory_.basic().facingMode.name(), | |
163 result.failed_constraint_name); | |
164 } | |
165 | |
166 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, OverconstrainedOnVideoKind) { | |
167 constraint_factory_.Reset(); | |
168 // No device in |capabilities_| has video kind infrared. | |
169 constraint_factory_.basic().videoKind.setExact( | |
170 blink::WebString::fromASCII("infrared")); | |
171 auto result = SelectSettings(); | |
172 EXPECT_FALSE(result.has_value()); | |
173 EXPECT_EQ(constraint_factory_.basic().videoKind.name(), | |
174 result.failed_constraint_name); | |
175 } | |
176 | |
177 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, OverconstrainedOnHeight) { | |
178 constraint_factory_.Reset(); | |
179 constraint_factory_.basic().height.setExact(123467890); | |
180 auto result = SelectSettings(); | |
181 EXPECT_FALSE(result.has_value()); | |
182 EXPECT_EQ(constraint_factory_.basic().height.name(), | |
183 result.failed_constraint_name); | |
184 | |
185 constraint_factory_.Reset(); | |
186 constraint_factory_.basic().height.setMin(123467890); | |
187 result = SelectSettings(); | |
188 EXPECT_FALSE(result.has_value()); | |
189 EXPECT_EQ(constraint_factory_.basic().height.name(), | |
190 result.failed_constraint_name); | |
191 | |
192 constraint_factory_.Reset(); | |
193 constraint_factory_.basic().height.setMax(0); | |
194 result = SelectSettings(); | |
195 EXPECT_FALSE(result.has_value()); | |
196 EXPECT_EQ(constraint_factory_.basic().height.name(), | |
197 result.failed_constraint_name); | |
198 } | |
199 | |
200 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, OverconstrainedOnWidth) { | |
201 constraint_factory_.Reset(); | |
202 constraint_factory_.basic().width.setExact(123467890); | |
203 auto result = SelectSettings(); | |
204 EXPECT_FALSE(result.has_value()); | |
205 EXPECT_EQ(constraint_factory_.basic().width.name(), | |
206 result.failed_constraint_name); | |
207 | |
208 constraint_factory_.Reset(); | |
209 constraint_factory_.basic().width.setMin(123467890); | |
210 result = SelectSettings(); | |
211 EXPECT_FALSE(result.has_value()); | |
212 EXPECT_EQ(constraint_factory_.basic().width.name(), | |
213 result.failed_constraint_name); | |
214 | |
215 constraint_factory_.Reset(); | |
216 constraint_factory_.basic().width.setMax(0); | |
217 result = SelectSettings(); | |
218 EXPECT_FALSE(result.has_value()); | |
219 EXPECT_EQ(constraint_factory_.basic().width.name(), | |
220 result.failed_constraint_name); | |
221 } | |
222 | |
223 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, | |
224 OverconstrainedOnAspectRatio) { | |
225 constraint_factory_.Reset(); | |
226 constraint_factory_.basic().aspectRatio.setExact(123467890.0); | |
227 auto result = SelectSettings(); | |
228 EXPECT_FALSE(result.has_value()); | |
229 EXPECT_EQ(constraint_factory_.basic().aspectRatio.name(), | |
230 result.failed_constraint_name); | |
231 | |
232 constraint_factory_.Reset(); | |
233 constraint_factory_.basic().aspectRatio.setMin(123467890.0); | |
234 result = SelectSettings(); | |
235 EXPECT_FALSE(result.has_value()); | |
236 EXPECT_EQ(constraint_factory_.basic().aspectRatio.name(), | |
237 result.failed_constraint_name); | |
238 | |
239 constraint_factory_.Reset(); | |
240 // This value is lower than the minimum supported by sources. | |
241 double kLowAspectRatio = 0.01; | |
242 constraint_factory_.basic().aspectRatio.setMax(kLowAspectRatio); | |
243 result = SelectSettings(); | |
244 EXPECT_FALSE(result.has_value()); | |
245 EXPECT_EQ(constraint_factory_.basic().aspectRatio.name(), | |
246 result.failed_constraint_name); | |
247 } | |
248 | |
249 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, OverconstrainedOnFrameRate) { | |
250 constraint_factory_.Reset(); | |
251 constraint_factory_.basic().frameRate.setExact(123467890.0); | |
252 auto result = SelectSettings(); | |
253 EXPECT_FALSE(result.has_value()); | |
254 EXPECT_EQ(constraint_factory_.basic().frameRate.name(), | |
255 result.failed_constraint_name); | |
256 | |
257 constraint_factory_.Reset(); | |
258 constraint_factory_.basic().frameRate.setMin(123467890.0); | |
259 result = SelectSettings(); | |
260 EXPECT_FALSE(result.has_value()); | |
261 EXPECT_EQ(constraint_factory_.basic().frameRate.name(), | |
262 result.failed_constraint_name); | |
263 | |
264 constraint_factory_.Reset(); | |
265 constraint_factory_.basic().frameRate.setMax(0.0); | |
266 result = SelectSettings(); | |
267 EXPECT_FALSE(result.has_value()); | |
268 EXPECT_EQ(constraint_factory_.basic().frameRate.name(), | |
269 result.failed_constraint_name); | |
270 } | |
271 | |
272 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, | |
273 OverconstrainedOnPowerLineFrequency) { | |
274 constraint_factory_.Reset(); | |
275 constraint_factory_.basic().googPowerLineFrequency.setExact(123467890); | |
276 auto result = SelectSettings(); | |
277 EXPECT_FALSE(result.has_value()); | |
278 EXPECT_EQ(constraint_factory_.basic().googPowerLineFrequency.name(), | |
279 result.failed_constraint_name); | |
280 | |
281 constraint_factory_.Reset(); | |
282 constraint_factory_.basic().googPowerLineFrequency.setMin(123467890); | |
283 result = SelectSettings(); | |
284 EXPECT_FALSE(result.has_value()); | |
285 EXPECT_EQ(constraint_factory_.basic().googPowerLineFrequency.name(), | |
286 result.failed_constraint_name); | |
287 | |
288 constraint_factory_.Reset(); | |
289 constraint_factory_.basic().googPowerLineFrequency.setMax(-1); | |
290 result = SelectSettings(); | |
291 EXPECT_FALSE(result.has_value()); | |
292 EXPECT_EQ(constraint_factory_.basic().googPowerLineFrequency.name(), | |
293 result.failed_constraint_name); | |
294 } | |
295 | |
296 // The "Mandatory" and "Ideal" tests check that various selection criteria work | |
297 // for each individual constraint in the basic constraint set. | |
298 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryDeviceID) { | |
299 constraint_factory_.Reset(); | |
300 constraint_factory_.basic().deviceId.setExact( | |
301 blink::WebString::fromASCII(default_device_->device_id)); | |
302 auto result = SelectSettings(); | |
303 EXPECT_TRUE(result.has_value()); | |
304 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
305 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
306 EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT, | |
307 result.settings.power_line_frequency()); | |
308 | |
309 constraint_factory_.basic().deviceId.setExact( | |
310 blink::WebString::fromASCII(low_res_device_->device_id)); | |
311 result = SelectSettings(); | |
312 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
313 EXPECT_EQ(*low_res_closest_format_, result.settings.format()); | |
314 EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT, | |
315 result.settings.power_line_frequency()); | |
316 | |
317 constraint_factory_.basic().deviceId.setExact( | |
318 blink::WebString::fromASCII(high_res_device_->device_id)); | |
319 result = SelectSettings(); | |
320 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
321 EXPECT_EQ(*high_res_closest_format_, result.settings.format()); | |
322 EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT, | |
323 result.settings.power_line_frequency()); | |
324 } | |
325 | |
326 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryFacingMode) { | |
327 constraint_factory_.Reset(); | |
328 constraint_factory_.basic().facingMode.setExact( | |
329 blink::WebString::fromASCII("environment")); | |
330 auto result = SelectSettings(); | |
331 EXPECT_TRUE(result.has_value()); | |
332 EXPECT_EQ(::mojom::FacingMode::ENVIRONMENT, result.settings.facing_mode()); | |
333 // Only the low-res device supports environment facing mode. Should select | |
334 // default settings for everything else. | |
335 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
336 EXPECT_EQ(*low_res_closest_format_, result.settings.format()); | |
337 EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT, | |
338 result.settings.power_line_frequency()); | |
339 | |
340 constraint_factory_.basic().facingMode.setExact( | |
341 blink::WebString::fromASCII("user")); | |
342 result = SelectSettings(); | |
343 EXPECT_TRUE(result.has_value()); | |
344 EXPECT_EQ(::mojom::FacingMode::USER, result.settings.facing_mode()); | |
345 // Only the high-res device supports user facing mode. Should select default | |
346 // settings for everything else. | |
347 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
348 EXPECT_EQ(*high_res_closest_format_, result.settings.format()); | |
349 EXPECT_EQ(media::PowerLineFrequency::FREQUENCY_DEFAULT, | |
350 result.settings.power_line_frequency()); | |
351 } | |
352 | |
353 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryVideoKind) { | |
354 constraint_factory_.Reset(); | |
355 constraint_factory_.basic().videoKind.setExact( | |
356 blink::WebString::fromASCII("depth")); | |
357 auto result = SelectSettings(); | |
358 EXPECT_TRUE(result.has_value()); | |
359 EXPECT_EQ(kDeviceID4, result.settings.device_id()); | |
360 EXPECT_EQ(media::PIXEL_FORMAT_Y16, result.settings.format().pixel_format); | |
361 | |
362 constraint_factory_.basic().videoKind.setExact( | |
363 blink::WebString::fromASCII("color")); | |
364 result = SelectSettings(); | |
365 EXPECT_TRUE(result.has_value()); | |
366 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
367 } | |
368 | |
369 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryPowerLineFrequency) { | |
370 constraint_factory_.Reset(); | |
371 const media::PowerLineFrequency kPowerLineFrequencies[] = { | |
372 media::PowerLineFrequency::FREQUENCY_50HZ, | |
373 media::PowerLineFrequency::FREQUENCY_60HZ}; | |
374 for (auto power_line_frequency : kPowerLineFrequencies) { | |
375 constraint_factory_.basic().googPowerLineFrequency.setExact( | |
376 static_cast<long>(power_line_frequency)); | |
377 auto result = SelectSettings(); | |
378 EXPECT_TRUE(result.has_value()); | |
379 EXPECT_EQ(power_line_frequency, result.settings.power_line_frequency()); | |
380 // The default device and settings closest to the default should be | |
381 // selected. | |
382 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
383 EXPECT_EQ(default_device_->facing_mode, result.settings.facing_mode()); | |
384 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
385 } | |
386 } | |
387 | |
388 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryExactHeight) { | |
389 constraint_factory_.Reset(); | |
390 const int kHeight = MediaStreamVideoSource::kDefaultHeight; | |
391 constraint_factory_.basic().height.setExact(kHeight); | |
392 auto result = SelectSettings(); | |
393 EXPECT_TRUE(result.has_value()); | |
394 // All devices in |capabilities_| support the requested height. The algorithm | |
395 // should prefer the first device that supports the requested height natively, | |
396 // which is the low-res device. | |
397 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
398 EXPECT_EQ(kHeight, result.settings.GetHeight()); | |
399 | |
400 const int kLargeHeight = 1500; | |
401 constraint_factory_.basic().height.setExact(kLargeHeight); | |
402 result = SelectSettings(); | |
403 EXPECT_TRUE(result.has_value()); | |
404 // Only the high-res device at the highest resolution supports the requested | |
405 // height, even if not natively. | |
406 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
407 EXPECT_EQ(*high_res_highest_format_, result.settings.format()); | |
408 } | |
409 | |
410 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMinHeight) { | |
411 constraint_factory_.Reset(); | |
412 const int kHeight = MediaStreamVideoSource::kDefaultHeight; | |
413 constraint_factory_.basic().height.setMin(kHeight); | |
414 auto result = SelectSettings(); | |
415 EXPECT_TRUE(result.has_value()); | |
416 // All devices in |capabilities_| support the requested height range. The | |
417 // algorithm should prefer the default device. | |
418 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
419 EXPECT_LE(kHeight, result.settings.GetHeight()); | |
420 | |
421 const int kLargeHeight = 1500; | |
422 constraint_factory_.basic().height.setMin(kLargeHeight); | |
423 result = SelectSettings(); | |
424 EXPECT_TRUE(result.has_value()); | |
425 // Only the high-res device at the highest resolution supports the requested | |
426 // height range. | |
427 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
428 EXPECT_EQ(*high_res_highest_format_, result.settings.format()); | |
429 } | |
430 | |
431 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMaxHeight) { | |
432 constraint_factory_.Reset(); | |
433 const int kLowHeight = 20; | |
434 constraint_factory_.basic().height.setMax(kLowHeight); | |
435 auto result = SelectSettings(); | |
436 EXPECT_TRUE(result.has_value()); | |
437 // All devices in |capabilities_| support the requested height range. The | |
438 // algorithm should prefer the settings that natively exceed the requested | |
439 // maximum by the lowest amount. In this case it is the low-res device. | |
440 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
441 EXPECT_EQ(low_res_device_->formats[0], result.settings.format()); | |
442 } | |
443 | |
444 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryHeightRange) { | |
445 constraint_factory_.Reset(); | |
446 { | |
447 const int kMinHeight = 480; | |
448 const int kMaxHeight = 720; | |
449 constraint_factory_.basic().height.setMin(kMinHeight); | |
450 constraint_factory_.basic().height.setMax(kMaxHeight); | |
451 auto result = SelectSettings(); | |
452 EXPECT_TRUE(result.has_value()); | |
453 EXPECT_GE(result.settings.GetHeight(), kMinHeight); | |
454 EXPECT_LE(result.settings.GetHeight(), kMaxHeight); | |
455 // All devices in |capabilities_| support the constraint range. The | |
456 // algorithm should prefer the default device since it has at least one | |
457 // native format (the closest-to-default format) included in the requested | |
458 // range. | |
459 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
460 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
461 } | |
462 | |
463 { | |
464 const int kMinHeight = 550; | |
465 const int kMaxHeight = 650; | |
466 constraint_factory_.basic().height.setMin(kMinHeight); | |
467 constraint_factory_.basic().height.setMax(kMaxHeight); | |
468 auto result = SelectSettings(); | |
469 EXPECT_TRUE(result.has_value()); | |
470 EXPECT_GE(result.settings.GetHeight(), kMinHeight); | |
471 EXPECT_LE(result.settings.GetHeight(), kMaxHeight); | |
472 // In this case, the algorithm should prefer the low-res device since it is | |
473 // the first device with a native format (800x600) included in the requested | |
474 // range. | |
475 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
476 EXPECT_EQ(800, result.settings.GetWidth()); | |
477 EXPECT_EQ(600, result.settings.GetHeight()); | |
478 } | |
479 | |
480 { | |
481 const int kMinHeight = 700; | |
482 const int kMaxHeight = 800; | |
483 constraint_factory_.basic().height.setMin(kMinHeight); | |
484 constraint_factory_.basic().height.setMax(kMaxHeight); | |
485 auto result = SelectSettings(); | |
486 EXPECT_TRUE(result.has_value()); | |
487 EXPECT_GE(result.settings.GetHeight(), kMinHeight); | |
488 EXPECT_LE(result.settings.GetHeight(), kMaxHeight); | |
489 // In this case, the algorithm should prefer the high-res device since it is | |
490 // the only device with a native format (1280x720) included in the requested | |
491 // range. | |
492 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
493 EXPECT_EQ(1280, result.settings.GetWidth()); | |
494 EXPECT_EQ(720, result.settings.GetHeight()); | |
495 } | |
496 } | |
497 | |
498 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, IdealHeight) { | |
499 constraint_factory_.Reset(); | |
500 { | |
501 const int kIdealHeight = 480; | |
502 constraint_factory_.basic().height.setIdeal(kIdealHeight); | |
503 auto result = SelectSettings(); | |
504 EXPECT_TRUE(result.has_value()); | |
505 // The algorithm should select the first device that supports the ideal | |
506 // height natively. | |
507 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
508 EXPECT_EQ(kIdealHeight, result.settings.GetHeight()); | |
509 } | |
510 | |
511 { | |
512 const int kIdealHeight = 481; | |
513 constraint_factory_.basic().height.setIdeal(kIdealHeight); | |
514 auto result = SelectSettings(); | |
515 EXPECT_TRUE(result.has_value()); | |
516 // In this case, the default device is selected because it can satisfy the | |
517 // ideal at a lower cost than the other devices (500 vs 600 or 720). | |
518 // Note that a native resolution of 480 is further from the ideal than | |
519 // 500 cropped to 480. | |
520 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
521 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
522 } | |
523 | |
524 { | |
525 const int kIdealHeight = 1079; | |
526 constraint_factory_.basic().height.setIdeal(kIdealHeight); | |
527 auto result = SelectSettings(); | |
528 EXPECT_TRUE(result.has_value()); | |
529 // In this case, the high-res device has two configurations that satisfy | |
530 // the ideal value (1920x1080 and 2304x1536). Select the one with shortest | |
531 // native distance to the ideal value (1920x1080). | |
532 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
533 EXPECT_EQ(1920, result.settings.GetWidth()); | |
534 EXPECT_EQ(1080, result.settings.GetHeight()); | |
535 } | |
536 | |
537 { | |
538 const int kIdealHeight = 1200; | |
539 constraint_factory_.basic().height.setIdeal(kIdealHeight); | |
540 auto result = SelectSettings(); | |
541 EXPECT_TRUE(result.has_value()); | |
542 // The algorithm must the select the only device that can satisfy the ideal, | |
543 // which is the high-res device at the highest resolution. | |
544 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
545 EXPECT_EQ(*high_res_highest_format_, result.settings.format()); | |
546 } | |
547 } | |
548 | |
549 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryExactWidth) { | |
550 constraint_factory_.Reset(); | |
551 const int kWidth = 640; | |
552 constraint_factory_.basic().width.setExact(kWidth); | |
553 auto result = SelectSettings(); | |
554 EXPECT_TRUE(result.has_value()); | |
555 // All devices in |capabilities_| support the requested width. The algorithm | |
556 // should prefer the first device that supports the requested width natively, | |
557 // which is the low-res device. | |
558 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
559 EXPECT_EQ(kWidth, result.settings.GetWidth()); | |
560 | |
561 const int kLargeWidth = 2000; | |
562 constraint_factory_.basic().width.setExact(kLargeWidth); | |
563 result = SelectSettings(); | |
564 EXPECT_TRUE(result.has_value()); | |
565 EXPECT_LE(kLargeWidth, result.settings.GetWidth()); | |
566 // Only the high-res device at the highest resolution supports the requested | |
567 // width, even if not natively. | |
568 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
569 EXPECT_EQ(*high_res_highest_format_, result.settings.format()); | |
570 } | |
571 | |
572 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMinWidth) { | |
573 constraint_factory_.Reset(); | |
574 const int kWidth = 640; | |
575 constraint_factory_.basic().width.setMin(kWidth); | |
576 auto result = SelectSettings(); | |
577 EXPECT_TRUE(result.has_value()); | |
578 // All devices in |capabilities_| support the requested width range. The | |
579 // algorithm should prefer the default device at 1000x1000, which is the | |
580 // first configuration that satisfies the minimum width. | |
581 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
582 EXPECT_LE(kWidth, result.settings.GetWidth()); | |
583 EXPECT_EQ(1000, result.settings.GetWidth()); | |
584 EXPECT_EQ(1000, result.settings.GetHeight()); | |
585 | |
586 const int kLargeWidth = 2000; | |
587 constraint_factory_.basic().width.setMin(kLargeWidth); | |
588 result = SelectSettings(); | |
589 EXPECT_TRUE(result.has_value()); | |
590 // Only the high-res device at the highest resolution supports the requested | |
591 // minimum width. | |
592 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
593 EXPECT_LE(kLargeWidth, result.settings.GetWidth()); | |
594 EXPECT_EQ(*high_res_highest_format_, result.settings.format()); | |
595 } | |
596 | |
597 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMaxWidth) { | |
598 constraint_factory_.Reset(); | |
599 const int kLowWidth = 30; | |
600 constraint_factory_.basic().width.setMax(kLowWidth); | |
601 auto result = SelectSettings(); | |
602 EXPECT_TRUE(result.has_value()); | |
603 // All devices in |capabilities_| support the requested width range. The | |
604 // algorithm should prefer the settings that natively exceed the requested | |
605 // maximum by the lowest amount. In this case it is the low-res device at its | |
606 // lowest resolution. | |
607 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
608 EXPECT_EQ(low_res_device_->formats[0], result.settings.format()); | |
609 } | |
610 | |
611 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryWidthRange) { | |
612 constraint_factory_.Reset(); | |
613 { | |
614 const int kMinWidth = 640; | |
615 const int kMaxWidth = 1280; | |
616 constraint_factory_.basic().width.setMin(kMinWidth); | |
617 constraint_factory_.basic().width.setMax(kMaxWidth); | |
618 auto result = SelectSettings(); | |
619 EXPECT_TRUE(result.has_value()); | |
620 EXPECT_GE(result.settings.GetWidth(), kMinWidth); | |
621 EXPECT_LE(result.settings.GetWidth(), kMaxWidth); | |
622 // All devices in |capabilities_| support the constraint range. The | |
623 // algorithm should prefer the default device since it has at least one | |
624 // native format (1000x1000) included in the requested range. | |
625 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
626 EXPECT_EQ(1000, result.settings.GetWidth()); | |
627 EXPECT_EQ(1000, result.settings.GetHeight()); | |
628 } | |
629 | |
630 { | |
631 const int kMinWidth = 750; | |
632 const int kMaxWidth = 850; | |
633 constraint_factory_.basic().width.setMin(kMinWidth); | |
634 constraint_factory_.basic().width.setMax(kMaxWidth); | |
635 auto result = SelectSettings(); | |
636 EXPECT_TRUE(result.has_value()); | |
637 EXPECT_GE(result.settings.GetWidth(), kMinWidth); | |
638 EXPECT_LE(result.settings.GetWidth(), kMaxWidth); | |
639 // In this case, the algorithm should prefer the low-res device since it is | |
640 // the first device with a native format (800x600) included in the requested | |
641 // range. | |
642 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
643 EXPECT_EQ(800, result.settings.GetWidth()); | |
644 EXPECT_EQ(600, result.settings.GetHeight()); | |
645 } | |
646 | |
647 { | |
648 const int kMinWidth = 1900; | |
649 const int kMaxWidth = 2000; | |
650 constraint_factory_.basic().width.setMin(kMinWidth); | |
651 constraint_factory_.basic().width.setMax(kMaxWidth); | |
652 auto result = SelectSettings(); | |
653 EXPECT_TRUE(result.has_value()); | |
654 EXPECT_GE(result.settings.GetWidth(), kMinWidth); | |
655 EXPECT_LE(result.settings.GetWidth(), kMaxWidth); | |
656 // In this case, the algorithm should prefer the high-res device since it is | |
657 // the only device with a native format (1920x1080) included in the | |
658 // requested range. | |
659 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
660 EXPECT_EQ(1920, result.settings.GetWidth()); | |
661 EXPECT_EQ(1080, result.settings.GetHeight()); | |
662 } | |
663 } | |
664 | |
665 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, IdealWidth) { | |
666 constraint_factory_.Reset(); | |
667 { | |
668 const int kIdealWidth = 320; | |
669 constraint_factory_.basic().width.setIdeal(kIdealWidth); | |
670 auto result = SelectSettings(); | |
671 EXPECT_TRUE(result.has_value()); | |
672 // The algorithm should select the first device that supports the ideal | |
673 // width natively, which is the low-res device at 320x240. | |
674 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
675 EXPECT_EQ(kIdealWidth, result.settings.GetWidth()); | |
676 } | |
677 | |
678 { | |
679 const int kIdealWidth = 321; | |
680 constraint_factory_.basic().width.setIdeal(kIdealWidth); | |
681 auto result = SelectSettings(); | |
682 EXPECT_TRUE(result.has_value()); | |
683 // In this case, the default device is selected because it can satisfy the | |
684 // ideal at a lower cost than the other devices (500 vs 640). | |
685 // Note that a native resolution of 320 is further from the ideal value of | |
686 // 321 than 500 cropped to 321. | |
687 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
688 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
689 } | |
690 | |
691 { | |
692 const int kIdealWidth = 2000; | |
693 constraint_factory_.basic().width.setIdeal(kIdealWidth); | |
694 auto result = SelectSettings(); | |
695 EXPECT_TRUE(result.has_value()); | |
696 // The algorithm must the select the only device that can satisfy the ideal. | |
697 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
698 EXPECT_EQ(*high_res_highest_format_, result.settings.format()); | |
699 } | |
700 | |
701 { | |
702 const int kIdealWidth = 3000; | |
703 constraint_factory_.basic().width.setIdeal(kIdealWidth); | |
704 auto result = SelectSettings(); | |
705 EXPECT_TRUE(result.has_value()); | |
706 // The algorithm must the select the device and setting with less distance | |
707 // to the ideal. | |
708 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
709 EXPECT_EQ(*high_res_highest_format_, result.settings.format()); | |
710 } | |
711 } | |
712 | |
713 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryExactFrameRate) { | |
714 constraint_factory_.Reset(); | |
715 const double kFrameRate = MediaStreamVideoSource::kDefaultFrameRate; | |
716 constraint_factory_.basic().frameRate.setExact(kFrameRate); | |
717 auto result = SelectSettings(); | |
718 EXPECT_TRUE(result.has_value()); | |
719 // All devices in |capabilities_| support the requested frame rate. The | |
720 // algorithm should prefer the first device that supports the requested frame | |
721 // rate natively, which is the low-res device at 640x480x30Hz. | |
722 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
723 EXPECT_EQ(kFrameRate, result.settings.GetFrameRate()); | |
724 EXPECT_EQ(640, result.settings.GetWidth()); | |
725 EXPECT_EQ(480, result.settings.GetHeight()); | |
726 | |
727 const double kLargeFrameRate = 50; | |
728 constraint_factory_.basic().frameRate.setExact(kLargeFrameRate); | |
729 result = SelectSettings(); | |
730 EXPECT_TRUE(result.has_value()); | |
731 // Only the high-res device supports the requested frame rate, even if not | |
732 // natively. The least expensive configuration that supports the requested | |
733 // frame rate is 1280x720x60Hz. | |
734 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
735 EXPECT_EQ(60.0, result.settings.GetFrameRate()); | |
736 EXPECT_EQ(1280, result.settings.GetWidth()); | |
737 EXPECT_EQ(720, result.settings.GetHeight()); | |
738 } | |
739 | |
740 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMinFrameRate) { | |
741 constraint_factory_.Reset(); | |
742 const double kFrameRate = MediaStreamVideoSource::kDefaultFrameRate; | |
743 constraint_factory_.basic().frameRate.setMin(kFrameRate); | |
744 auto result = SelectSettings(); | |
745 EXPECT_TRUE(result.has_value()); | |
746 // All devices in |capabilities_| support the requested frame-rate range. The | |
747 // algorithm should prefer the default device. | |
748 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
749 // The format closest to the default satisfies the constraint. | |
750 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
751 | |
752 const double kLargeFrameRate = 50; | |
753 constraint_factory_.basic().frameRate.setMin(kLargeFrameRate); | |
754 result = SelectSettings(); | |
755 EXPECT_TRUE(result.has_value()); | |
756 // Only the high-res device supports the requested frame-rate range. | |
757 // The least expensive configuration is 1280x720x60Hz. | |
758 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
759 EXPECT_LE(kLargeFrameRate, result.settings.GetFrameRate()); | |
760 EXPECT_EQ(1280, result.settings.GetWidth()); | |
761 EXPECT_EQ(720, result.settings.GetHeight()); | |
762 } | |
763 | |
764 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMaxFrameRate) { | |
765 constraint_factory_.Reset(); | |
766 const double kLowFrameRate = 10; | |
767 constraint_factory_.basic().frameRate.setMax(kLowFrameRate); | |
768 auto result = SelectSettings(); | |
769 EXPECT_TRUE(result.has_value()); | |
770 // All devices in |capabilities_| support the requested frame-rate range. The | |
771 // algorithm should prefer the settings that natively exceed the requested | |
772 // maximum by the lowest amount. In this case it is the high-res device with | |
773 // default resolution . | |
774 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
775 EXPECT_EQ(kLowFrameRate, result.settings.GetFrameRate()); | |
776 EXPECT_EQ(MediaStreamVideoSource::kDefaultHeight, | |
777 result.settings.GetHeight()); | |
778 EXPECT_EQ(MediaStreamVideoSource::kDefaultWidth, result.settings.GetWidth()); | |
779 } | |
780 | |
781 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryFrameRateRange) { | |
782 constraint_factory_.Reset(); | |
783 { | |
784 const double kMinFrameRate = 10; | |
785 const double kMaxFrameRate = 40; | |
786 constraint_factory_.basic().frameRate.setMin(kMinFrameRate); | |
787 constraint_factory_.basic().frameRate.setMax(kMaxFrameRate); | |
788 auto result = SelectSettings(); | |
789 EXPECT_TRUE(result.has_value()); | |
790 EXPECT_LE(kMinFrameRate, result.settings.GetFrameRate()); | |
791 EXPECT_GE(kMaxFrameRate, result.settings.GetFrameRate()); | |
792 // All devices in |capabilities_| support the constraint range. The | |
793 // algorithm should prefer the default device since its closest-to-default | |
794 // format has a frame rate included in the requested range. | |
795 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
796 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
797 } | |
798 | |
799 { | |
800 const double kMinFrameRate = 25; | |
801 const double kMaxFrameRate = 35; | |
802 constraint_factory_.basic().frameRate.setMin(kMinFrameRate); | |
803 constraint_factory_.basic().frameRate.setMax(kMaxFrameRate); | |
804 auto result = SelectSettings(); | |
805 EXPECT_TRUE(result.has_value()); | |
806 EXPECT_GE(result.settings.GetFrameRate(), kMinFrameRate); | |
807 EXPECT_LE(result.settings.GetFrameRate(), kMaxFrameRate); | |
808 // In this case, the algorithm should prefer the low-res device since it is | |
809 // the first device with a native frame rate included in the requested | |
810 // range. The default resolution should be preferred as secondary criterion. | |
811 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
812 EXPECT_EQ(*low_res_closest_format_, result.settings.format()); | |
813 } | |
814 | |
815 { | |
816 const double kMinFrameRate = 50; | |
817 const double kMaxFrameRate = 70; | |
818 constraint_factory_.basic().frameRate.setMin(kMinFrameRate); | |
819 constraint_factory_.basic().frameRate.setMax(kMaxFrameRate); | |
820 auto result = SelectSettings(); | |
821 EXPECT_TRUE(result.has_value()); | |
822 EXPECT_GE(result.settings.GetFrameRate(), kMinFrameRate); | |
823 EXPECT_LE(result.settings.GetFrameRate(), kMaxFrameRate); | |
824 // In this case, the algorithm should prefer the high-res device since it is | |
825 // the only device with a native format included in the requested range. | |
826 // The 1280x720 resolution should be selected due to closeness to default | |
827 // settings, which is the second tie-breaker criterion that applies. | |
828 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
829 EXPECT_EQ(1280, result.settings.GetWidth()); | |
830 EXPECT_EQ(720, result.settings.GetHeight()); | |
831 } | |
832 } | |
833 | |
834 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, IdealFrameRate) { | |
835 constraint_factory_.Reset(); | |
836 { | |
837 const double kIdealFrameRate = MediaStreamVideoSource::kDefaultFrameRate; | |
838 constraint_factory_.basic().frameRate.setIdeal(kIdealFrameRate); | |
839 auto result = SelectSettings(); | |
840 EXPECT_TRUE(result.has_value()); | |
841 // The algorithm should select the first configuration that supports the | |
842 // ideal frame rate natively, which is the low-res device. Default | |
843 // resolution should be selected as secondary criterion. | |
844 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
845 EXPECT_EQ(*low_res_closest_format_, result.settings.format()); | |
846 } | |
847 | |
848 { | |
849 const double kIdealFrameRate = 31; | |
850 constraint_factory_.basic().frameRate.setIdeal(kIdealFrameRate); | |
851 auto result = SelectSettings(); | |
852 EXPECT_TRUE(result.has_value()); | |
853 // In this case, the default device is selected because it can satisfy the | |
854 // ideal at a lower cost than the other devices (40 vs 60). | |
855 // Note that a native frame rate of 30 is further from the ideal than | |
856 // 31 adjusted to 30. | |
857 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
858 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
859 } | |
860 | |
861 { | |
862 const double kIdealFrameRate = 55; | |
863 constraint_factory_.basic().frameRate.setIdeal(kIdealFrameRate); | |
864 auto result = SelectSettings(); | |
865 EXPECT_TRUE(result.has_value()); | |
866 // The high-res device format 1280x720x60.0 must be selected because its | |
867 // frame rate can satisfy the ideal frame rate and has resolution closest | |
868 // to the default. | |
869 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
870 EXPECT_EQ(1280, result.settings.GetWidth()); | |
871 EXPECT_EQ(720, result.settings.GetHeight()); | |
872 EXPECT_EQ(60, result.settings.GetFrameRate()); | |
873 } | |
874 | |
875 { | |
876 const double kIdealFrameRate = 100; | |
877 constraint_factory_.basic().frameRate.setIdeal(kIdealFrameRate); | |
878 auto result = SelectSettings(); | |
879 EXPECT_TRUE(result.has_value()); | |
880 // The algorithm must select settings with frame rate closest to the ideal. | |
881 // The high-res device format 1280x720x60.0 must be selected because its | |
882 // frame rate it closest to the ideal value and it has resolution closest to | |
883 // the default. | |
884 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
885 EXPECT_EQ(1280, result.settings.GetWidth()); | |
886 EXPECT_EQ(720, result.settings.GetHeight()); | |
887 EXPECT_EQ(60, result.settings.GetFrameRate()); | |
888 } | |
889 } | |
890 | |
891 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryExactAspectRatio) { | |
892 constraint_factory_.Reset(); | |
893 const double kAspectRatio = 4.0 / 3.0; | |
894 constraint_factory_.basic().aspectRatio.setExact(kAspectRatio); | |
895 auto result = SelectSettings(); | |
896 EXPECT_TRUE(result.has_value()); | |
897 double min_width = 1.0; | |
898 double max_width = result.settings.GetWidth(); | |
899 double min_height = 1.0; | |
900 double max_height = result.settings.GetHeight(); | |
901 double min_aspect_ratio = min_width / max_height; | |
902 double max_aspect_ratio = max_width / min_height; | |
903 // The requested aspect ratio must be within the supported range. | |
904 EXPECT_GE(kAspectRatio, min_aspect_ratio); | |
905 EXPECT_LE(kAspectRatio, max_aspect_ratio); | |
906 // All devices in |capabilities_| support the requested aspect ratio. | |
907 // The algorithm should prefer the first device that supports the requested | |
908 // aspect ratio. | |
909 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
910 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
911 | |
912 const long kMinWidth = 500; | |
913 const long kMaxWidth = 1000; | |
914 const long kMaxHeight = 500; | |
915 constraint_factory_.basic().height.setMax(kMaxHeight); | |
916 constraint_factory_.basic().width.setMin(kMinWidth); | |
917 constraint_factory_.basic().width.setMax(kMaxWidth); | |
918 constraint_factory_.basic().aspectRatio.setExact(kAspectRatio); | |
919 result = SelectSettings(); | |
920 EXPECT_TRUE(result.has_value()); | |
921 min_width = std::max(1L, kMinWidth); | |
922 max_width = std::min(result.settings.GetWidth(), kMaxWidth); | |
923 min_height = 1.0; | |
924 max_height = std::min(result.settings.GetHeight(), kMaxHeight); | |
925 min_aspect_ratio = min_width / max_height; | |
926 max_aspect_ratio = max_width / min_height; | |
927 // The requested aspect ratio must be within the supported range. | |
928 EXPECT_GE(kAspectRatio, min_aspect_ratio); | |
929 EXPECT_LE(kAspectRatio, max_aspect_ratio); | |
930 // The default device can support the requested aspect ratio with the default | |
931 // settings (500x500) using cropping. | |
932 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
933 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
934 | |
935 const long kMinHeight = 480; | |
936 constraint_factory_.basic().height.setMin(kMinHeight); | |
937 constraint_factory_.basic().height.setMax(kMaxHeight); | |
938 constraint_factory_.basic().width.setMin(kMinWidth); | |
939 constraint_factory_.basic().width.setMax(kMaxWidth); | |
940 constraint_factory_.basic().aspectRatio.setExact(kAspectRatio); | |
941 result = SelectSettings(); | |
942 EXPECT_TRUE(result.has_value()); | |
943 min_width = std::max(1L, kMinWidth); | |
944 max_width = std::min(result.settings.GetWidth(), kMaxWidth); | |
945 min_height = std::max(1L, kMinHeight); | |
946 max_height = std::min(result.settings.GetHeight(), kMaxHeight); | |
947 min_aspect_ratio = min_width / max_height; | |
948 max_aspect_ratio = max_width / min_height; | |
949 // The requested aspect ratio must be within the supported range. | |
950 EXPECT_GE(kAspectRatio, min_aspect_ratio); | |
951 EXPECT_LE(kAspectRatio, max_aspect_ratio); | |
952 // Given resolution constraints, the default device with closest-to-default | |
953 // settings cannot satisfy the required aspect ratio. | |
954 // The first device that can do it is the low-res device with a native | |
955 // resolution of 640x480. Higher resolutions for the default device are more | |
956 // penalized by the constraints than the default native resolution of the | |
957 // low-res device. | |
958 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
959 EXPECT_EQ(*low_res_closest_format_, result.settings.format()); | |
960 } | |
961 | |
962 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMinAspectRatio) { | |
963 constraint_factory_.Reset(); | |
964 const double kAspectRatio = 4.0 / 3.0; | |
965 constraint_factory_.basic().aspectRatio.setMin(kAspectRatio); | |
966 auto result = SelectSettings(); | |
967 EXPECT_TRUE(result.has_value()); | |
968 double max_width = result.settings.GetWidth(); | |
969 double min_height = 1.0; | |
970 double max_aspect_ratio = max_width / min_height; | |
971 // Minimum constraint aspect ratio must be less than or equal to the maximum | |
972 // supported by the source. | |
973 EXPECT_LE(kAspectRatio, max_aspect_ratio); | |
974 // All devices in |capabilities_| support the requested aspect-ratio range. | |
975 // The algorithm should prefer the first device that supports the requested | |
976 // aspect-ratio range, which in this case is the default device. | |
977 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
978 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
979 | |
980 const long kMinWidth = 500; | |
981 const long kMaxWidth = 1000; | |
982 const long kMinHeight = 480; | |
983 const long kMaxHeight = 500; | |
984 constraint_factory_.basic().width.setMin(kMinWidth); | |
985 constraint_factory_.basic().width.setMax(kMaxWidth); | |
986 constraint_factory_.basic().height.setMin(kMinHeight); | |
987 constraint_factory_.basic().height.setMax(kMaxHeight); | |
988 constraint_factory_.basic().aspectRatio.setMin(kAspectRatio); | |
989 result = SelectSettings(); | |
990 EXPECT_TRUE(result.has_value()); | |
991 max_width = std::min(result.settings.GetWidth(), kMaxWidth); | |
992 min_height = std::max(1L, kMinHeight); | |
993 max_aspect_ratio = max_width / min_height; | |
994 // Minimum constraint aspect ratio must be less than or equal to the minimum | |
995 // supported by the source. | |
996 EXPECT_LE(kAspectRatio, max_aspect_ratio); | |
997 // Given resolution constraints, the default device with closest-to-default | |
998 // settings cannot satisfy the required minimum aspect ratio (maximum would | |
999 // be 500/480). The first device that can is the low-res device with a native | |
1000 // resolution of 640x480. | |
1001 // Higher resolutions for the default device are more penalized by the | |
1002 // constraints than the default native resolution of the low-res device. | |
1003 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
1004 EXPECT_EQ(*low_res_closest_format_, result.settings.format()); | |
1005 } | |
1006 | |
1007 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryMaxAspectRatio) { | |
1008 constraint_factory_.Reset(); | |
1009 const double kAspectRatio = 0.5; | |
1010 constraint_factory_.basic().aspectRatio.setMax(kAspectRatio); | |
1011 auto result = SelectSettings(); | |
1012 EXPECT_TRUE(result.has_value()); | |
1013 double min_width = 1.0; | |
1014 double max_height = result.settings.GetHeight(); | |
1015 double min_aspect_ratio = min_width / max_height; | |
1016 // Minimum constraint aspect ratio must be less than or equal to the maximum | |
1017 // supported by the source. | |
1018 EXPECT_GE(kAspectRatio, min_aspect_ratio); | |
1019 // All devices in |capabilities_| support the requested aspect-ratio range. | |
1020 // The algorithm should prefer the first device that supports the requested | |
1021 // aspect-ratio range, which in this case is the default device. | |
1022 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
1023 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
1024 | |
1025 const long kExactWidth = 360; | |
1026 const long kMinHeight = 360; | |
1027 const long kMaxHeight = 720; | |
1028 constraint_factory_.basic().width.setExact(kExactWidth); | |
1029 constraint_factory_.basic().height.setMin(kMinHeight); | |
1030 constraint_factory_.basic().height.setMax(kMaxHeight); | |
1031 constraint_factory_.basic().aspectRatio.setMax(kAspectRatio); | |
1032 result = SelectSettings(); | |
1033 EXPECT_TRUE(result.has_value()); | |
1034 min_width = std::max(1L, kExactWidth); | |
1035 max_height = std::min(result.settings.GetHeight(), kMaxHeight); | |
1036 min_aspect_ratio = min_width / max_height; | |
1037 // Minimum constraint aspect ratio must be less than or equal to the minimum | |
1038 // supported by the source. | |
1039 EXPECT_GE(kAspectRatio, min_aspect_ratio); | |
1040 // Given resolution constraints, the default device with closest-to-default | |
1041 // settings cannot satisfy the required maximum aspect ratio (maximum would | |
1042 // be 360/500). | |
1043 // The high-res device with a native resolution of 1280x720 can support | |
1044 // 360x720 with cropping with less penalty than the default device at | |
1045 // 1000x1000. | |
1046 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
1047 EXPECT_EQ(1280, result.settings.GetWidth()); | |
1048 EXPECT_EQ(720, result.settings.GetHeight()); | |
1049 } | |
1050 | |
1051 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, MandatoryAspectRatioRange) { | |
1052 constraint_factory_.Reset(); | |
1053 { | |
1054 const double kMinAspectRatio = 0.5; | |
1055 const double kMaxAspectRatio = 1.0; | |
1056 | |
1057 constraint_factory_.basic().aspectRatio.setMin(kMinAspectRatio); | |
1058 constraint_factory_.basic().aspectRatio.setMax(kMaxAspectRatio); | |
1059 auto result = SelectSettings(); | |
1060 EXPECT_TRUE(result.has_value()); | |
1061 double min_width = 1.0; | |
1062 double max_width = result.settings.GetWidth(); | |
1063 double min_height = 1.0; | |
1064 double max_height = result.settings.GetHeight(); | |
1065 double min_aspect_ratio = min_width / max_height; | |
1066 double max_aspect_ratio = max_width / min_height; | |
1067 // Constraint aspect-ratio range must have nonempty intersection with | |
1068 // supported range. | |
1069 EXPECT_LE(kMinAspectRatio, max_aspect_ratio); | |
1070 EXPECT_GE(kMaxAspectRatio, min_aspect_ratio); | |
1071 // All devices in |capabilities_| support the requested aspect-ratio range. | |
1072 // The algorithm should prefer the first device that supports the requested | |
1073 // aspect-ratio range, which in this case is the default device. | |
1074 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
1075 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
1076 } | |
1077 | |
1078 { | |
1079 const double kMinAspectRatio = 3.0; | |
1080 const double kMaxAspectRatio = 4.0; | |
1081 | |
1082 const long kExactHeight = 600; | |
1083 constraint_factory_.Reset(); | |
1084 constraint_factory_.basic().height.setMin(kExactHeight); | |
1085 constraint_factory_.basic().aspectRatio.setMin(kMinAspectRatio); | |
1086 constraint_factory_.basic().aspectRatio.setMax(kMaxAspectRatio); | |
1087 auto result = SelectSettings(); | |
1088 EXPECT_TRUE(result.has_value()); | |
1089 double min_width = 1.0; | |
1090 double max_width = result.settings.GetWidth(); | |
1091 double min_height = 1.0; | |
1092 double max_height = result.settings.GetHeight(); | |
1093 double min_aspect_ratio = min_width / max_height; | |
1094 double max_aspect_ratio = max_width / min_height; | |
1095 // Constraint aspect-ratio range must have nonempty intersection with | |
1096 // supported range. | |
1097 EXPECT_LE(kMinAspectRatio, max_aspect_ratio); | |
1098 EXPECT_GE(kMaxAspectRatio, min_aspect_ratio); | |
1099 // The only device that supports the resolution and aspect ratio constraint | |
1100 // is the high-res device. The 1920x1080 is the least expensive format. | |
1101 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
1102 EXPECT_EQ(1920, result.settings.GetWidth()); | |
1103 EXPECT_EQ(1080, result.settings.GetHeight()); | |
1104 } | |
1105 } | |
1106 | |
1107 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, IdealAspectRatio) { | |
1108 constraint_factory_.Reset(); | |
1109 { | |
1110 const double kIdealAspectRatio = 0.5; | |
1111 constraint_factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio); | |
1112 auto result = SelectSettings(); | |
1113 EXPECT_TRUE(result.has_value()); | |
1114 double min_width = 1.0; | |
1115 double max_width = result.settings.GetWidth(); | |
1116 double min_height = 1.0; | |
1117 double max_height = result.settings.GetHeight(); | |
1118 double min_aspect_ratio = min_width / max_height; | |
1119 double max_aspect_ratio = max_width / min_height; | |
1120 // All devices in |capabilities_| support the ideal aspect-ratio. | |
1121 // The algorithm should prefer the default device with closest-to-default | |
1122 // settings. | |
1123 EXPECT_LE(kIdealAspectRatio, max_aspect_ratio); | |
1124 EXPECT_GE(kIdealAspectRatio, min_aspect_ratio); | |
1125 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
1126 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
1127 } | |
1128 | |
1129 { | |
1130 const double kIdealAspectRatio = 1500.0; | |
1131 constraint_factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio); | |
1132 auto result = SelectSettings(); | |
1133 EXPECT_TRUE(result.has_value()); | |
1134 // The only device that supports the ideal aspect ratio is the high-res | |
1135 // device. The least expensive way to support it with the 1920x1080 format | |
1136 // cropped to 1500x1. | |
1137 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
1138 EXPECT_EQ(1920, result.settings.GetWidth()); | |
1139 EXPECT_EQ(1080, result.settings.GetHeight()); | |
1140 } | |
1141 | |
1142 { | |
1143 const double kIdealAspectRatio = 2000.0; | |
1144 constraint_factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio); | |
1145 auto result = SelectSettings(); | |
1146 EXPECT_TRUE(result.has_value()); | |
1147 // The only device that supports the ideal aspect ratio is the high-res | |
1148 // device with its highest resolution, cropped to 2000x1. | |
1149 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
1150 EXPECT_EQ(*high_res_highest_format_, result.settings.format()); | |
1151 } | |
1152 | |
1153 { | |
1154 const double kIdealAspectRatio = 4000.0; | |
1155 constraint_factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio); | |
1156 auto result = SelectSettings(); | |
1157 EXPECT_TRUE(result.has_value()); | |
1158 // The configuration closest to the ideal aspect ratio is is the high-res | |
1159 // device with its highest resolution, cropped to 2304x1. | |
1160 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
1161 EXPECT_EQ(*high_res_highest_format_, result.settings.format()); | |
1162 } | |
1163 | |
1164 { | |
1165 const double kIdealAspectRatio = 2.0; | |
1166 constraint_factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio); | |
1167 constraint_factory_.basic().height.setExact(400); | |
1168 auto result = SelectSettings(); | |
1169 EXPECT_TRUE(result.has_value()); | |
1170 // The first device to support the ideal aspect ratio and the resolution | |
1171 // constraint is the low-res device. The 800x600 format cropped to 800x400 | |
1172 // is the lest expensive way to achieve it. | |
1173 EXPECT_EQ(low_res_device_->device_id, result.settings.device_id()); | |
1174 EXPECT_EQ(800, result.settings.GetWidth()); | |
1175 EXPECT_EQ(600, result.settings.GetHeight()); | |
1176 } | |
1177 | |
1178 { | |
1179 const double kIdealAspectRatio = 3.0; | |
1180 constraint_factory_.basic().aspectRatio.setIdeal(kIdealAspectRatio); | |
1181 constraint_factory_.basic().height.setExact(400); | |
1182 auto result = SelectSettings(); | |
1183 EXPECT_TRUE(result.has_value()); | |
1184 // The only device that supports the ideal aspect ratio and the resolution | |
1185 // constraint is the high-res device. The 1280x720 cropped to 1200x400 is | |
1186 // the lest expensive way to achieve it. | |
1187 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
1188 EXPECT_EQ(1280, result.settings.GetWidth()); | |
1189 EXPECT_EQ(720, result.settings.GetHeight()); | |
1190 } | |
1191 } | |
1192 | |
1193 // The "Advanced" tests check selection criteria involving advanced constraint | |
1194 // sets. | |
1195 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, AdvancedExactResolution) { | |
1196 { | |
1197 constraint_factory_.Reset(); | |
1198 blink::WebMediaTrackConstraintSet& advanced1 = | |
1199 constraint_factory_.AddAdvanced(); | |
1200 advanced1.width.setExact(4000); | |
1201 advanced1.height.setExact(4000); | |
1202 blink::WebMediaTrackConstraintSet& advanced2 = | |
1203 constraint_factory_.AddAdvanced(); | |
1204 advanced2.width.setExact(3000); | |
1205 advanced2.height.setExact(3000); | |
1206 auto result = SelectSettings(); | |
1207 // No device supports the advanced constraint sets. | |
1208 // Tie-breaker rule that applies is closeness to default settings. | |
1209 EXPECT_EQ(default_device_->device_id, result.settings.device_id()); | |
1210 EXPECT_EQ(*default_closest_format_, result.settings.format()); | |
1211 | |
1212 blink::WebMediaTrackConstraintSet& advanced3 = | |
1213 constraint_factory_.AddAdvanced(); | |
1214 advanced3.width.setExact(1920); | |
1215 advanced3.height.setExact(1080); | |
1216 result = SelectSettings(); | |
1217 EXPECT_TRUE(result.has_value()); | |
1218 // The high-res device natively supports the third advanced constraint set | |
1219 // and should be selected. | |
1220 // First tie-breaker rule that applies is support for advanced constraints | |
1221 // that appear first. Second tie-breaker rule is custom distance to advanced | |
1222 // constraint sets that appear first. | |
1223 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
1224 EXPECT_EQ(1920, result.settings.GetWidth()); | |
1225 EXPECT_EQ(1080, result.settings.GetHeight()); | |
1226 | |
1227 blink::WebMediaTrackConstraintSet& advanced4 = | |
1228 constraint_factory_.AddAdvanced(); | |
1229 advanced4.width.setExact(640); | |
1230 advanced4.height.setExact(480); | |
1231 result = SelectSettings(); | |
1232 EXPECT_TRUE(result.has_value()); | |
1233 // First tie-breaker rule that applies is support for advanced constraints | |
1234 // that appear first, which leaves out configurations that only support the | |
1235 // fourth advanced constraint set in favor of configurations that support | |
1236 // the third set. | |
1237 // Second tie-breaker rule is custom distance to advanced constraint sets | |
1238 // that appear first. | |
1239 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
1240 EXPECT_EQ(1920, result.settings.GetWidth()); | |
1241 EXPECT_EQ(1080, result.settings.GetHeight()); | |
1242 | |
1243 constraint_factory_.basic().width.setIdeal(800); | |
1244 constraint_factory_.basic().height.setIdeal(600); | |
1245 result = SelectSettings(); | |
1246 EXPECT_TRUE(result.has_value()); | |
1247 // The ideal value is supported by the same configuration, so nothing | |
1248 // changes. | |
1249 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
1250 EXPECT_EQ(1920, result.settings.GetWidth()); | |
1251 EXPECT_EQ(1080, result.settings.GetHeight()); | |
1252 | |
1253 constraint_factory_.basic().width.setIdeal(2000); | |
1254 constraint_factory_.basic().height.setIdeal(1500); | |
1255 result = SelectSettings(); | |
1256 EXPECT_TRUE(result.has_value()); | |
1257 // The closest configuration to the ideal resolution is the high-res device | |
1258 // at the highest resolution. | |
1259 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
1260 EXPECT_EQ(*high_res_highest_format_, result.settings.format()); | |
1261 } | |
1262 } | |
1263 | |
1264 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, | |
1265 AdvancedResolutionAndFrameRate) { | |
1266 { | |
1267 constraint_factory_.Reset(); | |
1268 blink::WebMediaTrackConstraintSet& advanced1 = | |
1269 constraint_factory_.AddAdvanced(); | |
1270 advanced1.width.setExact(1920); | |
1271 advanced1.height.setExact(1080); | |
1272 blink::WebMediaTrackConstraintSet& advanced2 = | |
1273 constraint_factory_.AddAdvanced(); | |
1274 advanced2.frameRate.setExact(60.0); | |
1275 blink::WebMediaTrackConstraintSet& advanced3 = | |
1276 constraint_factory_.AddAdvanced(); | |
1277 advanced3.width.setExact(2304); | |
1278 advanced3.height.setExact(1536); | |
1279 auto result = SelectSettings(); | |
1280 EXPECT_TRUE(result.has_value()); | |
1281 // The high-res device is the only one that satisfies the first advanced | |
1282 // set. 2304x1536x10.0 satisfies sets 1 and 3, while 1920x1080x60.0 | |
1283 // satisfies sets 1, and 2. The latter must be selected, regardless of | |
1284 // any other criteria. | |
1285 EXPECT_EQ(high_res_device_->device_id, result.settings.device_id()); | |
1286 EXPECT_EQ(1920, result.settings.GetWidth()); | |
1287 EXPECT_EQ(1080, result.settings.GetHeight()); | |
1288 EXPECT_EQ(60.0, result.settings.GetFrameRate()); | |
1289 } | |
1290 } | |
1291 | |
1292 // The "NoDevices" tests verify that the algorithm returns the expected result | |
1293 // when there are no candidates to choose from. | |
1294 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, NoDevicesNoConstraints) { | |
1295 constraint_factory_.Reset(); | |
1296 VideoCaptureCapabilities capabilities; | |
1297 auto result = SelectVideoCaptureSourceSettings( | |
1298 capabilities, constraint_factory_.CreateWebMediaConstraints()); | |
1299 EXPECT_FALSE(result.has_value()); | |
1300 EXPECT_TRUE(std::string(result.failed_constraint_name).empty()); | |
1301 } | |
1302 | |
1303 TEST_F(MediaStreamConstraintsUtilVideoSourceTest, NoDevicesWithConstraints) { | |
1304 constraint_factory_.Reset(); | |
1305 constraint_factory_.basic().height.setExact(100); | |
1306 VideoCaptureCapabilities capabilities; | |
1307 auto result = SelectVideoCaptureSourceSettings( | |
1308 capabilities, constraint_factory_.CreateWebMediaConstraints()); | |
1309 EXPECT_FALSE(result.has_value()); | |
1310 EXPECT_TRUE(std::string(result.failed_constraint_name).empty()); | |
1311 } | |
1312 | |
1313 } // namespace content | |
OLD | NEW |