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

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

Powered by Google App Engine
This is Rietveld 408576698