Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(33)

Side by Side Diff: content/renderer/media/media_stream_constraints_util_video_source_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698