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

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

Issue 2707203006: Minor refactoring of support classes for video-device constraints. (Closed)
Patch Set: hbos comment + fix in accessor 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 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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698