1 /*
2 * Copyright (c) 2010 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "media/base/video_adapter.h"
12
13 #include <limits>
14 #include <memory>
15 #include <string>
16 #include <utility>
17
18 #include "api/video/resolution.h"
19 #include "api/video/video_frame.h"
20 #include "api/video/video_source_interface.h"
21 #include "media/base/fake_frame_source.h"
22 #include "rtc_base/arraysize.h"
23 #include "rtc_base/time_utils.h"
24 #include "test/field_trial.h"
25 #include "test/gmock.h"
26 #include "test/gtest.h"
27
28 namespace cricket {
29 namespace {
30 const int kWidth = 1280;
31 const int kHeight = 720;
32 const int kDefaultFps = 30;
33
34 using ::testing::_;
35 using ::testing::Eq;
36 using ::testing::Pair;
37 using webrtc::Resolution;
38
BuildSinkWants(absl::optional<int> target_pixel_count,int max_pixel_count,int max_framerate_fps,int sink_alignment=1)39 rtc::VideoSinkWants BuildSinkWants(absl::optional<int> target_pixel_count,
40 int max_pixel_count,
41 int max_framerate_fps,
42 int sink_alignment = 1) {
43 rtc::VideoSinkWants wants;
44 wants.target_pixel_count = target_pixel_count;
45 wants.max_pixel_count = max_pixel_count;
46 wants.max_framerate_fps = max_framerate_fps;
47 wants.resolution_alignment = sink_alignment;
48 wants.is_active = true;
49 wants.aggregates.emplace(rtc::VideoSinkWants::Aggregates());
50 wants.aggregates->any_active_without_requested_resolution = false;
51 return wants;
52 }
53
BuildSinkWants(absl::optional<webrtc::Resolution> requested_resolution,bool any_active_without_requested_resolution)54 rtc::VideoSinkWants BuildSinkWants(
55 absl::optional<webrtc::Resolution> requested_resolution,
56 bool any_active_without_requested_resolution) {
57 rtc::VideoSinkWants wants;
58 wants.max_framerate_fps = kDefaultFps;
59 wants.resolution_alignment = 1;
60 wants.is_active = true;
61 if (requested_resolution) {
62 wants.target_pixel_count = requested_resolution->PixelCount();
63 wants.max_pixel_count = requested_resolution->PixelCount();
64 wants.requested_resolution.emplace(rtc::VideoSinkWants::FrameSize(
65 requested_resolution->width, requested_resolution->height));
66 } else {
67 wants.target_pixel_count = kWidth * kHeight;
68 wants.max_pixel_count = kWidth * kHeight;
69 }
70 wants.aggregates.emplace(rtc::VideoSinkWants::Aggregates());
71 wants.aggregates->any_active_without_requested_resolution =
72 any_active_without_requested_resolution;
73 return wants;
74 }
75
76 } // namespace
77
78 class VideoAdapterTest : public ::testing::Test,
79 public ::testing::WithParamInterface<bool> {
80 public:
VideoAdapterTest()81 VideoAdapterTest() : VideoAdapterTest("", 1) {}
VideoAdapterTest(const std::string & field_trials,int source_resolution_alignment)82 explicit VideoAdapterTest(const std::string& field_trials,
83 int source_resolution_alignment)
84 : override_field_trials_(field_trials),
85 frame_source_(std::make_unique<FakeFrameSource>(
86 kWidth,
87 kHeight,
88 VideoFormat::FpsToInterval(kDefaultFps) /
89 rtc::kNumNanosecsPerMicrosec)),
90 adapter_(source_resolution_alignment),
91 adapter_wrapper_(std::make_unique<VideoAdapterWrapper>(&adapter_)),
92 use_new_format_request_(GetParam()) {}
93
94 protected:
95 // Wrap a VideoAdapter and collect stats.
96 class VideoAdapterWrapper {
97 public:
98 struct Stats {
99 int captured_frames = 0;
100 int dropped_frames = 0;
101 bool last_adapt_was_no_op = false;
102
103 int cropped_width = 0;
104 int cropped_height = 0;
105 int out_width = 0;
106 int out_height = 0;
107 };
108
VideoAdapterWrapper(VideoAdapter * adapter)109 explicit VideoAdapterWrapper(VideoAdapter* adapter)
110 : video_adapter_(adapter) {}
111
AdaptFrame(const webrtc::VideoFrame & frame)112 void AdaptFrame(const webrtc::VideoFrame& frame) {
113 const int in_width = frame.width();
114 const int in_height = frame.height();
115 int cropped_width;
116 int cropped_height;
117 int out_width;
118 int out_height;
119 if (video_adapter_->AdaptFrameResolution(
120 in_width, in_height,
121 frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec,
122 &cropped_width, &cropped_height, &out_width, &out_height)) {
123 stats_.cropped_width = cropped_width;
124 stats_.cropped_height = cropped_height;
125 stats_.out_width = out_width;
126 stats_.out_height = out_height;
127 stats_.last_adapt_was_no_op =
128 (in_width == cropped_width && in_height == cropped_height &&
129 in_width == out_width && in_height == out_height);
130 } else {
131 ++stats_.dropped_frames;
132 }
133 ++stats_.captured_frames;
134 }
135
GetStats() const136 Stats GetStats() const { return stats_; }
137
138 private:
139 VideoAdapter* video_adapter_;
140 Stats stats_;
141 };
142
VerifyAdaptedResolution(const VideoAdapterWrapper::Stats & stats,int cropped_width,int cropped_height,int out_width,int out_height)143 void VerifyAdaptedResolution(const VideoAdapterWrapper::Stats& stats,
144 int cropped_width,
145 int cropped_height,
146 int out_width,
147 int out_height) {
148 EXPECT_EQ(cropped_width, stats.cropped_width);
149 EXPECT_EQ(cropped_height, stats.cropped_height);
150 EXPECT_EQ(out_width, stats.out_width);
151 EXPECT_EQ(out_height, stats.out_height);
152 }
153
OnOutputFormatRequest(int width,int height,const absl::optional<int> & fps)154 void OnOutputFormatRequest(int width,
155 int height,
156 const absl::optional<int>& fps) {
157 if (use_new_format_request_) {
158 absl::optional<std::pair<int, int>> target_aspect_ratio =
159 std::make_pair(width, height);
160 absl::optional<int> max_pixel_count = width * height;
161 absl::optional<int> max_fps = fps;
162 adapter_.OnOutputFormatRequest(target_aspect_ratio, max_pixel_count,
163 max_fps);
164 return;
165 }
166 adapter_.OnOutputFormatRequest(
167 VideoFormat(width, height, fps ? VideoFormat::FpsToInterval(*fps) : 0,
168 cricket::FOURCC_I420));
169 }
170
171 // Return pair of <out resolution, cropping>
AdaptFrameResolution(webrtc::Resolution res)172 std::pair<webrtc::Resolution, webrtc::Resolution> AdaptFrameResolution(
173 webrtc::Resolution res) {
174 webrtc::Resolution out;
175 webrtc::Resolution cropped;
176 timestamp_ns_ += 1000000000;
177 EXPECT_TRUE(adapter_.AdaptFrameResolution(
178 res.width, res.height, timestamp_ns_, &cropped.width, &cropped.height,
179 &out.width, &out.height));
180 return std::make_pair(out, cropped);
181 }
182
183 webrtc::test::ScopedFieldTrials override_field_trials_;
184 const std::unique_ptr<FakeFrameSource> frame_source_;
185 VideoAdapter adapter_;
186 int64_t timestamp_ns_ = 0;
187 int cropped_width_;
188 int cropped_height_;
189 int out_width_;
190 int out_height_;
191 const std::unique_ptr<VideoAdapterWrapper> adapter_wrapper_;
192 const bool use_new_format_request_;
193 };
194
195 INSTANTIATE_TEST_SUITE_P(OnOutputFormatRequests,
196 VideoAdapterTest,
197 ::testing::Values(true, false));
198
199 // Do not adapt the frame rate or the resolution. Expect no frame drop, no
200 // cropping, and no resolution change.
TEST_P(VideoAdapterTest,AdaptNothing)201 TEST_P(VideoAdapterTest, AdaptNothing) {
202 for (int i = 0; i < 10; ++i)
203 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
204
205 // Verify no frame drop and no resolution change.
206 VideoAdapterWrapper::Stats stats = adapter_wrapper_->GetStats();
207 EXPECT_GE(stats.captured_frames, 10);
208 EXPECT_EQ(0, stats.dropped_frames);
209 VerifyAdaptedResolution(stats, kWidth, kHeight, kWidth, kHeight);
210 EXPECT_TRUE(stats.last_adapt_was_no_op);
211 }
212
TEST_P(VideoAdapterTest,AdaptZeroInterval)213 TEST_P(VideoAdapterTest, AdaptZeroInterval) {
214 OnOutputFormatRequest(kWidth, kHeight, absl::nullopt);
215 for (int i = 0; i < 40; ++i)
216 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
217
218 // Verify no crash and that frames aren't dropped.
219 VideoAdapterWrapper::Stats stats = adapter_wrapper_->GetStats();
220 EXPECT_GE(stats.captured_frames, 40);
221 EXPECT_EQ(0, stats.dropped_frames);
222 VerifyAdaptedResolution(stats, kWidth, kHeight, kWidth, kHeight);
223 }
224
225 // Adapt the frame rate to be half of the capture rate at the beginning. Expect
226 // the number of dropped frames to be half of the number the captured frames.
TEST_P(VideoAdapterTest,AdaptFramerateToHalf)227 TEST_P(VideoAdapterTest, AdaptFramerateToHalf) {
228 OnOutputFormatRequest(kWidth, kHeight, kDefaultFps / 2);
229
230 // Capture 10 frames and verify that every other frame is dropped. The first
231 // frame should not be dropped.
232 for (int i = 0; i < 10; ++i)
233 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
234 EXPECT_GE(adapter_wrapper_->GetStats().captured_frames, 10);
235 EXPECT_EQ(5, adapter_wrapper_->GetStats().dropped_frames);
236 }
237
238 // Adapt the frame rate to be two thirds of the capture rate at the beginning.
239 // Expect the number of dropped frames to be one thirds of the number the
240 // captured frames.
TEST_P(VideoAdapterTest,AdaptFramerateToTwoThirds)241 TEST_P(VideoAdapterTest, AdaptFramerateToTwoThirds) {
242 OnOutputFormatRequest(kWidth, kHeight, kDefaultFps * 2 / 3);
243
244 // Capture 10 frames and verify that every third frame is dropped. The first
245 // frame should not be dropped.
246 for (int i = 0; i < 10; ++i)
247 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
248 EXPECT_GE(adapter_wrapper_->GetStats().captured_frames, 10);
249 EXPECT_EQ(3, adapter_wrapper_->GetStats().dropped_frames);
250 }
251
252 // Request frame rate twice as high as captured frame rate. Expect no frame
253 // drop.
TEST_P(VideoAdapterTest,AdaptFramerateHighLimit)254 TEST_P(VideoAdapterTest, AdaptFramerateHighLimit) {
255 OnOutputFormatRequest(kWidth, kHeight, kDefaultFps * 2);
256
257 for (int i = 0; i < 10; ++i)
258 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
259
260 // Verify no frame drop.
261 EXPECT_EQ(0, adapter_wrapper_->GetStats().dropped_frames);
262 }
263
264 // Adapt the frame rate to be half of the capture rate. No resolution limit set.
265 // Expect the number of dropped frames to be half of the number the captured
266 // frames.
TEST_P(VideoAdapterTest,AdaptFramerateToHalfWithNoPixelLimit)267 TEST_P(VideoAdapterTest, AdaptFramerateToHalfWithNoPixelLimit) {
268 adapter_.OnOutputFormatRequest(absl::nullopt, absl::nullopt, kDefaultFps / 2);
269
270 // Capture 10 frames and verify that every other frame is dropped. The first
271 // frame should not be dropped.
272 int expected_dropped_frames = 0;
273 for (int i = 0; i < 10; ++i) {
274 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
275 EXPECT_GE(adapter_wrapper_->GetStats().captured_frames, i + 1);
276 if (i % 2 == 1)
277 ++expected_dropped_frames;
278 EXPECT_EQ(expected_dropped_frames,
279 adapter_wrapper_->GetStats().dropped_frames);
280 VerifyAdaptedResolution(adapter_wrapper_->GetStats(), kWidth, kHeight,
281 kWidth, kHeight);
282 }
283 }
284
285 // Adapt the frame rate to be half of the capture rate after capturing no less
286 // than 10 frames. Expect no frame dropped before adaptation and frame dropped
287 // after adaptation.
TEST_P(VideoAdapterTest,AdaptFramerateOntheFly)288 TEST_P(VideoAdapterTest, AdaptFramerateOntheFly) {
289 OnOutputFormatRequest(kWidth, kHeight, kDefaultFps);
290 for (int i = 0; i < 10; ++i)
291 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
292
293 // Verify no frame drop before adaptation.
294 EXPECT_EQ(0, adapter_wrapper_->GetStats().dropped_frames);
295
296 // Adapt the frame rate.
297 OnOutputFormatRequest(kWidth, kHeight, kDefaultFps / 2);
298 for (int i = 0; i < 20; ++i)
299 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
300
301 // Verify frame drop after adaptation.
302 EXPECT_GT(adapter_wrapper_->GetStats().dropped_frames, 0);
303 }
304
305 // Do not adapt the frame rate or the resolution. Expect no frame drop, no
306 // cropping, and no resolution change.
TEST_P(VideoAdapterTest,AdaptFramerateRequestMax)307 TEST_P(VideoAdapterTest, AdaptFramerateRequestMax) {
308 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt,
309 std::numeric_limits<int>::max(),
310 std::numeric_limits<int>::max()));
311
312 for (int i = 0; i < 10; ++i)
313 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
314
315 // Verify no frame drop and no resolution change.
316 VideoAdapterWrapper::Stats stats = adapter_wrapper_->GetStats();
317 EXPECT_GE(stats.captured_frames, 10);
318 EXPECT_EQ(0, stats.dropped_frames);
319 VerifyAdaptedResolution(stats, kWidth, kHeight, kWidth, kHeight);
320 EXPECT_TRUE(stats.last_adapt_was_no_op);
321 }
322
TEST_P(VideoAdapterTest,AdaptFramerateRequestZero)323 TEST_P(VideoAdapterTest, AdaptFramerateRequestZero) {
324 adapter_.OnSinkWants(
325 BuildSinkWants(absl::nullopt, std::numeric_limits<int>::max(), 0));
326 for (int i = 0; i < 10; ++i)
327 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
328
329 // Verify no crash and that frames aren't dropped.
330 VideoAdapterWrapper::Stats stats = adapter_wrapper_->GetStats();
331 EXPECT_GE(stats.captured_frames, 10);
332 EXPECT_EQ(10, stats.dropped_frames);
333 }
334
335 // Adapt the frame rate to be half of the capture rate at the beginning. Expect
336 // the number of dropped frames to be half of the number the captured frames.
TEST_P(VideoAdapterTest,AdaptFramerateRequestHalf)337 TEST_P(VideoAdapterTest, AdaptFramerateRequestHalf) {
338 adapter_.OnSinkWants(BuildSinkWants(
339 absl::nullopt, std::numeric_limits<int>::max(), kDefaultFps / 2));
340 for (int i = 0; i < 10; ++i)
341 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
342
343 // Verify no crash and that frames aren't dropped.
344 VideoAdapterWrapper::Stats stats = adapter_wrapper_->GetStats();
345 EXPECT_GE(stats.captured_frames, 10);
346 EXPECT_EQ(5, stats.dropped_frames);
347 VerifyAdaptedResolution(stats, kWidth, kHeight, kWidth, kHeight);
348 }
349
350 // Set a very high output pixel resolution. Expect no cropping or resolution
351 // change.
TEST_P(VideoAdapterTest,AdaptFrameResolutionHighLimit)352 TEST_P(VideoAdapterTest, AdaptFrameResolutionHighLimit) {
353 OnOutputFormatRequest(kWidth * 10, kHeight * 10, kDefaultFps);
354 EXPECT_TRUE(adapter_.AdaptFrameResolution(kWidth, kHeight, 0, &cropped_width_,
355 &cropped_height_, &out_width_,
356 &out_height_));
357 EXPECT_EQ(kWidth, cropped_width_);
358 EXPECT_EQ(kHeight, cropped_height_);
359 EXPECT_EQ(kWidth, out_width_);
360 EXPECT_EQ(kHeight, out_height_);
361 }
362
363 // Adapt the frame resolution to be the same as capture resolution. Expect no
364 // cropping or resolution change.
TEST_P(VideoAdapterTest,AdaptFrameResolutionIdentical)365 TEST_P(VideoAdapterTest, AdaptFrameResolutionIdentical) {
366 OnOutputFormatRequest(kWidth, kHeight, kDefaultFps);
367 EXPECT_TRUE(adapter_.AdaptFrameResolution(kWidth, kHeight, 0, &cropped_width_,
368 &cropped_height_, &out_width_,
369 &out_height_));
370 EXPECT_EQ(kWidth, cropped_width_);
371 EXPECT_EQ(kHeight, cropped_height_);
372 EXPECT_EQ(kWidth, out_width_);
373 EXPECT_EQ(kHeight, out_height_);
374 }
375
376 // Adapt the frame resolution to be a quarter of the capture resolution. Expect
377 // no cropping, but a resolution change.
TEST_P(VideoAdapterTest,AdaptFrameResolutionQuarter)378 TEST_P(VideoAdapterTest, AdaptFrameResolutionQuarter) {
379 OnOutputFormatRequest(kWidth / 2, kHeight / 2, kDefaultFps);
380 EXPECT_TRUE(adapter_.AdaptFrameResolution(kWidth, kHeight, 0, &cropped_width_,
381 &cropped_height_, &out_width_,
382 &out_height_));
383 EXPECT_EQ(kWidth, cropped_width_);
384 EXPECT_EQ(kHeight, cropped_height_);
385 EXPECT_EQ(kWidth / 2, out_width_);
386 EXPECT_EQ(kHeight / 2, out_height_);
387 }
388
389 // Adapt the pixel resolution to 0. Expect frame drop.
TEST_P(VideoAdapterTest,AdaptFrameResolutionDrop)390 TEST_P(VideoAdapterTest, AdaptFrameResolutionDrop) {
391 OnOutputFormatRequest(kWidth * 0, kHeight * 0, kDefaultFps);
392 EXPECT_FALSE(adapter_.AdaptFrameResolution(kWidth, kHeight, 0,
393 &cropped_width_, &cropped_height_,
394 &out_width_, &out_height_));
395 }
396
397 // Adapt the frame resolution to be a quarter of the capture resolution at the
398 // beginning. Expect no cropping but a resolution change.
TEST_P(VideoAdapterTest,AdaptResolution)399 TEST_P(VideoAdapterTest, AdaptResolution) {
400 OnOutputFormatRequest(kWidth / 2, kHeight / 2, kDefaultFps);
401 for (int i = 0; i < 10; ++i)
402 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
403
404 // Verify no frame drop, no cropping, and resolution change.
405 VideoAdapterWrapper::Stats stats = adapter_wrapper_->GetStats();
406 EXPECT_EQ(0, stats.dropped_frames);
407 VerifyAdaptedResolution(stats, kWidth, kHeight, kWidth / 2, kHeight / 2);
408 }
409
410 // Adapt the frame resolution to be a quarter of the capture resolution after
411 // capturing no less than 10 frames. Expect no resolution change before
412 // adaptation and resolution change after adaptation.
TEST_P(VideoAdapterTest,AdaptResolutionOnTheFly)413 TEST_P(VideoAdapterTest, AdaptResolutionOnTheFly) {
414 OnOutputFormatRequest(kWidth, kHeight, kDefaultFps);
415 for (int i = 0; i < 10; ++i)
416 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
417
418 // Verify no resolution change before adaptation.
419 VerifyAdaptedResolution(adapter_wrapper_->GetStats(), kWidth, kHeight, kWidth,
420 kHeight);
421
422 // Adapt the frame resolution.
423 OnOutputFormatRequest(kWidth / 2, kHeight / 2, kDefaultFps);
424 for (int i = 0; i < 10; ++i)
425 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
426
427 // Verify resolution change after adaptation.
428 VerifyAdaptedResolution(adapter_wrapper_->GetStats(), kWidth, kHeight,
429 kWidth / 2, kHeight / 2);
430 }
431
432 // Drop all frames for resolution 0x0.
TEST_P(VideoAdapterTest,DropAllFrames)433 TEST_P(VideoAdapterTest, DropAllFrames) {
434 OnOutputFormatRequest(kWidth * 0, kHeight * 0, kDefaultFps);
435 for (int i = 0; i < 10; ++i)
436 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
437
438 // Verify all frames are dropped.
439 VideoAdapterWrapper::Stats stats = adapter_wrapper_->GetStats();
440 EXPECT_GE(stats.captured_frames, 10);
441 EXPECT_EQ(stats.captured_frames, stats.dropped_frames);
442 }
443
TEST_P(VideoAdapterTest,TestOnOutputFormatRequest)444 TEST_P(VideoAdapterTest, TestOnOutputFormatRequest) {
445 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0, &cropped_width_,
446 &cropped_height_, &out_width_,
447 &out_height_));
448 EXPECT_EQ(640, cropped_width_);
449 EXPECT_EQ(400, cropped_height_);
450 EXPECT_EQ(640, out_width_);
451 EXPECT_EQ(400, out_height_);
452
453 // Format request 640x400.
454 OnOutputFormatRequest(640, 400, absl::nullopt);
455 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0, &cropped_width_,
456 &cropped_height_, &out_width_,
457 &out_height_));
458 EXPECT_EQ(640, cropped_width_);
459 EXPECT_EQ(400, cropped_height_);
460 EXPECT_EQ(640, out_width_);
461 EXPECT_EQ(400, out_height_);
462
463 // Request 1280x720, higher than input, but aspect 16:9. Expect cropping but
464 // no scaling.
465 OnOutputFormatRequest(1280, 720, absl::nullopt);
466 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0, &cropped_width_,
467 &cropped_height_, &out_width_,
468 &out_height_));
469 EXPECT_EQ(640, cropped_width_);
470 EXPECT_EQ(360, cropped_height_);
471 EXPECT_EQ(640, out_width_);
472 EXPECT_EQ(360, out_height_);
473
474 // Request 0x0.
475 OnOutputFormatRequest(0, 0, absl::nullopt);
476 EXPECT_FALSE(adapter_.AdaptFrameResolution(640, 400, 0, &cropped_width_,
477 &cropped_height_, &out_width_,
478 &out_height_));
479
480 // Request 320x200. Expect scaling, but no cropping.
481 OnOutputFormatRequest(320, 200, absl::nullopt);
482 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0, &cropped_width_,
483 &cropped_height_, &out_width_,
484 &out_height_));
485 EXPECT_EQ(640, cropped_width_);
486 EXPECT_EQ(400, cropped_height_);
487 EXPECT_EQ(320, out_width_);
488 EXPECT_EQ(200, out_height_);
489
490 // Request resolution close to 2/3 scale. Expect adapt down. Scaling to 2/3
491 // is not optimized and not allowed, therefore 1/2 scaling will be used
492 // instead.
493 OnOutputFormatRequest(424, 265, absl::nullopt);
494 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0, &cropped_width_,
495 &cropped_height_, &out_width_,
496 &out_height_));
497 EXPECT_EQ(640, cropped_width_);
498 EXPECT_EQ(400, cropped_height_);
499 EXPECT_EQ(320, out_width_);
500 EXPECT_EQ(200, out_height_);
501
502 // Request resolution of 3 / 8. Expect adapt down.
503 OnOutputFormatRequest(640 * 3 / 8, 400 * 3 / 8, absl::nullopt);
504 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0, &cropped_width_,
505 &cropped_height_, &out_width_,
506 &out_height_));
507 EXPECT_EQ(640, cropped_width_);
508 EXPECT_EQ(400, cropped_height_);
509 EXPECT_EQ(640 * 3 / 8, out_width_);
510 EXPECT_EQ(400 * 3 / 8, out_height_);
511
512 // Switch back up. Expect adapt.
513 OnOutputFormatRequest(320, 200, absl::nullopt);
514 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0, &cropped_width_,
515 &cropped_height_, &out_width_,
516 &out_height_));
517 EXPECT_EQ(640, cropped_width_);
518 EXPECT_EQ(400, cropped_height_);
519 EXPECT_EQ(320, out_width_);
520 EXPECT_EQ(200, out_height_);
521
522 // Format request 480x300.
523 OnOutputFormatRequest(480, 300, absl::nullopt);
524 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0, &cropped_width_,
525 &cropped_height_, &out_width_,
526 &out_height_));
527 EXPECT_EQ(640, cropped_width_);
528 EXPECT_EQ(400, cropped_height_);
529 EXPECT_EQ(480, out_width_);
530 EXPECT_EQ(300, out_height_);
531 }
532
TEST_P(VideoAdapterTest,TestViewRequestPlusCameraSwitch)533 TEST_P(VideoAdapterTest, TestViewRequestPlusCameraSwitch) {
534 // Start at HD.
535 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
536 &cropped_height_, &out_width_,
537 &out_height_));
538 EXPECT_EQ(1280, cropped_width_);
539 EXPECT_EQ(720, cropped_height_);
540 EXPECT_EQ(1280, out_width_);
541 EXPECT_EQ(720, out_height_);
542
543 // Format request for VGA.
544 OnOutputFormatRequest(640, 360, absl::nullopt);
545 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
546 &cropped_height_, &out_width_,
547 &out_height_));
548 EXPECT_EQ(1280, cropped_width_);
549 EXPECT_EQ(720, cropped_height_);
550 EXPECT_EQ(640, out_width_);
551 EXPECT_EQ(360, out_height_);
552
553 // Now, the camera reopens at VGA.
554 // Both the frame and the output format should be 640x360.
555 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0, &cropped_width_,
556 &cropped_height_, &out_width_,
557 &out_height_));
558 EXPECT_EQ(640, cropped_width_);
559 EXPECT_EQ(360, cropped_height_);
560 EXPECT_EQ(640, out_width_);
561 EXPECT_EQ(360, out_height_);
562
563 // And another view request comes in for 640x360, which should have no
564 // real impact.
565 OnOutputFormatRequest(640, 360, absl::nullopt);
566 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0, &cropped_width_,
567 &cropped_height_, &out_width_,
568 &out_height_));
569 EXPECT_EQ(640, cropped_width_);
570 EXPECT_EQ(360, cropped_height_);
571 EXPECT_EQ(640, out_width_);
572 EXPECT_EQ(360, out_height_);
573 }
574
TEST_P(VideoAdapterTest,TestVgaWidth)575 TEST_P(VideoAdapterTest, TestVgaWidth) {
576 // Requested output format is 640x360.
577 OnOutputFormatRequest(640, 360, absl::nullopt);
578
579 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0, &cropped_width_,
580 &cropped_height_, &out_width_,
581 &out_height_));
582 // Expect cropping.
583 EXPECT_EQ(640, cropped_width_);
584 EXPECT_EQ(360, cropped_height_);
585 EXPECT_EQ(640, out_width_);
586 EXPECT_EQ(360, out_height_);
587
588 // But if frames come in at 640x360, we shouldn't adapt them down.
589 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0, &cropped_width_,
590 &cropped_height_, &out_width_,
591 &out_height_));
592 EXPECT_EQ(640, cropped_width_);
593 EXPECT_EQ(360, cropped_height_);
594 EXPECT_EQ(640, out_width_);
595 EXPECT_EQ(360, out_height_);
596
597 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0, &cropped_width_,
598 &cropped_height_, &out_width_,
599 &out_height_));
600 EXPECT_EQ(640, cropped_width_);
601 EXPECT_EQ(360, cropped_height_);
602 EXPECT_EQ(640, out_width_);
603 EXPECT_EQ(360, out_height_);
604 }
605
TEST_P(VideoAdapterTest,TestOnResolutionRequestInSmallSteps)606 TEST_P(VideoAdapterTest, TestOnResolutionRequestInSmallSteps) {
607 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
608 &cropped_height_, &out_width_,
609 &out_height_));
610 EXPECT_EQ(1280, cropped_width_);
611 EXPECT_EQ(720, cropped_height_);
612 EXPECT_EQ(1280, out_width_);
613 EXPECT_EQ(720, out_height_);
614
615 // Adapt down one step.
616 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt, 1280 * 720 - 1,
617 std::numeric_limits<int>::max()));
618 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
619 &cropped_height_, &out_width_,
620 &out_height_));
621 EXPECT_EQ(1280, cropped_width_);
622 EXPECT_EQ(720, cropped_height_);
623 EXPECT_EQ(960, out_width_);
624 EXPECT_EQ(540, out_height_);
625
626 // Adapt down one step more.
627 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt, 960 * 540 - 1,
628 std::numeric_limits<int>::max()));
629 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
630 &cropped_height_, &out_width_,
631 &out_height_));
632 EXPECT_EQ(1280, cropped_width_);
633 EXPECT_EQ(720, cropped_height_);
634 EXPECT_EQ(640, out_width_);
635 EXPECT_EQ(360, out_height_);
636
637 // Adapt down one step more.
638 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt, 640 * 360 - 1,
639 std::numeric_limits<int>::max()));
640 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
641 &cropped_height_, &out_width_,
642 &out_height_));
643 EXPECT_EQ(1280, cropped_width_);
644 EXPECT_EQ(720, cropped_height_);
645 EXPECT_EQ(480, out_width_);
646 EXPECT_EQ(270, out_height_);
647
648 // Adapt up one step.
649 adapter_.OnSinkWants(
650 BuildSinkWants(640 * 360, 960 * 540, std::numeric_limits<int>::max()));
651 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
652 &cropped_height_, &out_width_,
653 &out_height_));
654 EXPECT_EQ(1280, cropped_width_);
655 EXPECT_EQ(720, cropped_height_);
656 EXPECT_EQ(640, out_width_);
657 EXPECT_EQ(360, out_height_);
658
659 // Adapt up one step more.
660 adapter_.OnSinkWants(
661 BuildSinkWants(960 * 540, 1280 * 720, std::numeric_limits<int>::max()));
662 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
663 &cropped_height_, &out_width_,
664 &out_height_));
665 EXPECT_EQ(1280, cropped_width_);
666 EXPECT_EQ(720, cropped_height_);
667 EXPECT_EQ(960, out_width_);
668 EXPECT_EQ(540, out_height_);
669
670 // Adapt up one step more.
671 adapter_.OnSinkWants(
672 BuildSinkWants(1280 * 720, 1920 * 1080, std::numeric_limits<int>::max()));
673 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
674 &cropped_height_, &out_width_,
675 &out_height_));
676 EXPECT_EQ(1280, cropped_width_);
677 EXPECT_EQ(720, cropped_height_);
678 EXPECT_EQ(1280, out_width_);
679 EXPECT_EQ(720, out_height_);
680 }
681
TEST_P(VideoAdapterTest,TestOnResolutionRequestMaxZero)682 TEST_P(VideoAdapterTest, TestOnResolutionRequestMaxZero) {
683 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
684 &cropped_height_, &out_width_,
685 &out_height_));
686 EXPECT_EQ(1280, cropped_width_);
687 EXPECT_EQ(720, cropped_height_);
688 EXPECT_EQ(1280, out_width_);
689 EXPECT_EQ(720, out_height_);
690
691 adapter_.OnSinkWants(
692 BuildSinkWants(absl::nullopt, 0, std::numeric_limits<int>::max()));
693 EXPECT_FALSE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
694 &cropped_height_, &out_width_,
695 &out_height_));
696 }
697
TEST_P(VideoAdapterTest,TestOnResolutionRequestInLargeSteps)698 TEST_P(VideoAdapterTest, TestOnResolutionRequestInLargeSteps) {
699 // Large step down.
700 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt, 640 * 360 - 1,
701 std::numeric_limits<int>::max()));
702 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
703 &cropped_height_, &out_width_,
704 &out_height_));
705 EXPECT_EQ(1280, cropped_width_);
706 EXPECT_EQ(720, cropped_height_);
707 EXPECT_EQ(480, out_width_);
708 EXPECT_EQ(270, out_height_);
709
710 // Large step up.
711 adapter_.OnSinkWants(
712 BuildSinkWants(1280 * 720, 1920 * 1080, std::numeric_limits<int>::max()));
713 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
714 &cropped_height_, &out_width_,
715 &out_height_));
716 EXPECT_EQ(1280, cropped_width_);
717 EXPECT_EQ(720, cropped_height_);
718 EXPECT_EQ(1280, out_width_);
719 EXPECT_EQ(720, out_height_);
720 }
721
TEST_P(VideoAdapterTest,TestOnOutputFormatRequestCapsMaxResolution)722 TEST_P(VideoAdapterTest, TestOnOutputFormatRequestCapsMaxResolution) {
723 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt, 640 * 360 - 1,
724 std::numeric_limits<int>::max()));
725 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
726 &cropped_height_, &out_width_,
727 &out_height_));
728 EXPECT_EQ(1280, cropped_width_);
729 EXPECT_EQ(720, cropped_height_);
730 EXPECT_EQ(480, out_width_);
731 EXPECT_EQ(270, out_height_);
732
733 OnOutputFormatRequest(640, 360, absl::nullopt);
734 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
735 &cropped_height_, &out_width_,
736 &out_height_));
737 EXPECT_EQ(1280, cropped_width_);
738 EXPECT_EQ(720, cropped_height_);
739 EXPECT_EQ(480, out_width_);
740 EXPECT_EQ(270, out_height_);
741
742 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt, 960 * 720,
743 std::numeric_limits<int>::max()));
744 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
745 &cropped_height_, &out_width_,
746 &out_height_));
747 EXPECT_EQ(1280, cropped_width_);
748 EXPECT_EQ(720, cropped_height_);
749 EXPECT_EQ(640, out_width_);
750 EXPECT_EQ(360, out_height_);
751 }
752
TEST_P(VideoAdapterTest,TestOnResolutionRequestReset)753 TEST_P(VideoAdapterTest, TestOnResolutionRequestReset) {
754 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
755 &cropped_height_, &out_width_,
756 &out_height_));
757 EXPECT_EQ(1280, cropped_width_);
758 EXPECT_EQ(720, cropped_height_);
759 EXPECT_EQ(1280, out_width_);
760 EXPECT_EQ(720, out_height_);
761
762 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt, 640 * 360 - 1,
763 std::numeric_limits<int>::max()));
764 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
765 &cropped_height_, &out_width_,
766 &out_height_));
767 EXPECT_EQ(1280, cropped_width_);
768 EXPECT_EQ(720, cropped_height_);
769 EXPECT_EQ(480, out_width_);
770 EXPECT_EQ(270, out_height_);
771
772 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt,
773 std::numeric_limits<int>::max(),
774 std::numeric_limits<int>::max()));
775 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
776 &cropped_height_, &out_width_,
777 &out_height_));
778 EXPECT_EQ(1280, cropped_width_);
779 EXPECT_EQ(720, cropped_height_);
780 EXPECT_EQ(1280, out_width_);
781 EXPECT_EQ(720, out_height_);
782 }
783
TEST_P(VideoAdapterTest,TestOnOutputFormatRequestResolutionReset)784 TEST_P(VideoAdapterTest, TestOnOutputFormatRequestResolutionReset) {
785 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
786 &cropped_height_, &out_width_,
787 &out_height_));
788 EXPECT_EQ(1280, cropped_width_);
789 EXPECT_EQ(720, cropped_height_);
790 EXPECT_EQ(1280, out_width_);
791 EXPECT_EQ(720, out_height_);
792
793 adapter_.OnOutputFormatRequest(absl::nullopt, 640 * 360 - 1, absl::nullopt);
794 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
795 &cropped_height_, &out_width_,
796 &out_height_));
797 EXPECT_EQ(1280, cropped_width_);
798 EXPECT_EQ(720, cropped_height_);
799 EXPECT_EQ(480, out_width_);
800 EXPECT_EQ(270, out_height_);
801
802 adapter_.OnOutputFormatRequest(absl::nullopt, absl::nullopt, absl::nullopt);
803 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0, &cropped_width_,
804 &cropped_height_, &out_width_,
805 &out_height_));
806 EXPECT_EQ(1280, cropped_width_);
807 EXPECT_EQ(720, cropped_height_);
808 EXPECT_EQ(1280, out_width_);
809 EXPECT_EQ(720, out_height_);
810 }
811
TEST_P(VideoAdapterTest,TestOnOutputFormatRequestFpsReset)812 TEST_P(VideoAdapterTest, TestOnOutputFormatRequestFpsReset) {
813 OnOutputFormatRequest(kWidth, kHeight, kDefaultFps / 2);
814 for (int i = 0; i < 10; ++i)
815 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
816
817 // Verify frame drop.
818 const int dropped_frames = adapter_wrapper_->GetStats().dropped_frames;
819 EXPECT_GT(dropped_frames, 0);
820
821 // Reset frame rate.
822 OnOutputFormatRequest(kWidth, kHeight, absl::nullopt);
823 for (int i = 0; i < 20; ++i)
824 adapter_wrapper_->AdaptFrame(frame_source_->GetFrame());
825
826 // Verify no frame drop after reset.
827 EXPECT_EQ(dropped_frames, adapter_wrapper_->GetStats().dropped_frames);
828 }
829
TEST_P(VideoAdapterTest,RequestAspectRatio)830 TEST_P(VideoAdapterTest, RequestAspectRatio) {
831 // Request aspect ratio 320/180 (16:9), smaller than input, but no resolution
832 // limit. Expect cropping but no scaling.
833 adapter_.OnOutputFormatRequest(std::make_pair(320, 180), absl::nullopt,
834 absl::nullopt);
835 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0, &cropped_width_,
836 &cropped_height_, &out_width_,
837 &out_height_));
838 EXPECT_EQ(640, cropped_width_);
839 EXPECT_EQ(360, cropped_height_);
840 EXPECT_EQ(640, out_width_);
841 EXPECT_EQ(360, out_height_);
842 }
843
TEST_P(VideoAdapterTest,RequestAspectRatioWithDifferentOrientation)844 TEST_P(VideoAdapterTest, RequestAspectRatioWithDifferentOrientation) {
845 // Request 720x1280, higher than input, but aspect 16:9. Orientation should
846 // not matter, expect cropping but no scaling.
847 OnOutputFormatRequest(720, 1280, absl::nullopt);
848 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0, &cropped_width_,
849 &cropped_height_, &out_width_,
850 &out_height_));
851 EXPECT_EQ(640, cropped_width_);
852 EXPECT_EQ(360, cropped_height_);
853 EXPECT_EQ(640, out_width_);
854 EXPECT_EQ(360, out_height_);
855 }
856
TEST_P(VideoAdapterTest,InvalidAspectRatioIgnored)857 TEST_P(VideoAdapterTest, InvalidAspectRatioIgnored) {
858 // Request aspect ratio 320/0. Expect no cropping.
859 adapter_.OnOutputFormatRequest(std::make_pair(320, 0), absl::nullopt,
860 absl::nullopt);
861 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0, &cropped_width_,
862 &cropped_height_, &out_width_,
863 &out_height_));
864 EXPECT_EQ(640, cropped_width_);
865 EXPECT_EQ(400, cropped_height_);
866 EXPECT_EQ(640, out_width_);
867 EXPECT_EQ(400, out_height_);
868 }
869
TEST_P(VideoAdapterTest,TestCroppingWithResolutionRequest)870 TEST_P(VideoAdapterTest, TestCroppingWithResolutionRequest) {
871 // Ask for 640x360 (16:9 aspect).
872 OnOutputFormatRequest(640, 360, absl::nullopt);
873 // Send 640x480 (4:3 aspect).
874 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0, &cropped_width_,
875 &cropped_height_, &out_width_,
876 &out_height_));
877 // Expect cropping to 16:9 format and no scaling.
878 EXPECT_EQ(640, cropped_width_);
879 EXPECT_EQ(360, cropped_height_);
880 EXPECT_EQ(640, out_width_);
881 EXPECT_EQ(360, out_height_);
882
883 // Adapt down one step.
884 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt, 640 * 360 - 1,
885 std::numeric_limits<int>::max()));
886 // Expect cropping to 16:9 format and 3/4 scaling.
887 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0, &cropped_width_,
888 &cropped_height_, &out_width_,
889 &out_height_));
890 EXPECT_EQ(640, cropped_width_);
891 EXPECT_EQ(360, cropped_height_);
892 EXPECT_EQ(480, out_width_);
893 EXPECT_EQ(270, out_height_);
894
895 // Adapt down one step more.
896 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt, 480 * 270 - 1,
897 std::numeric_limits<int>::max()));
898 // Expect cropping to 16:9 format and 1/2 scaling.
899 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0, &cropped_width_,
900 &cropped_height_, &out_width_,
901 &out_height_));
902 EXPECT_EQ(640, cropped_width_);
903 EXPECT_EQ(360, cropped_height_);
904 EXPECT_EQ(320, out_width_);
905 EXPECT_EQ(180, out_height_);
906
907 // Adapt up one step.
908 adapter_.OnSinkWants(
909 BuildSinkWants(480 * 270, 640 * 360, std::numeric_limits<int>::max()));
910 // Expect cropping to 16:9 format and 3/4 scaling.
911 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0, &cropped_width_,
912 &cropped_height_, &out_width_,
913 &out_height_));
914 EXPECT_EQ(640, cropped_width_);
915 EXPECT_EQ(360, cropped_height_);
916 EXPECT_EQ(480, out_width_);
917 EXPECT_EQ(270, out_height_);
918
919 // Adapt up one step more.
920 adapter_.OnSinkWants(
921 BuildSinkWants(640 * 360, 960 * 540, std::numeric_limits<int>::max()));
922 // Expect cropping to 16:9 format and no scaling.
923 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0, &cropped_width_,
924 &cropped_height_, &out_width_,
925 &out_height_));
926 EXPECT_EQ(640, cropped_width_);
927 EXPECT_EQ(360, cropped_height_);
928 EXPECT_EQ(640, out_width_);
929 EXPECT_EQ(360, out_height_);
930
931 // Try to adapt up one step more.
932 adapter_.OnSinkWants(
933 BuildSinkWants(960 * 540, 1280 * 720, std::numeric_limits<int>::max()));
934 // Expect cropping to 16:9 format and no scaling.
935 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0, &cropped_width_,
936 &cropped_height_, &out_width_,
937 &out_height_));
938 EXPECT_EQ(640, cropped_width_);
939 EXPECT_EQ(360, cropped_height_);
940 EXPECT_EQ(640, out_width_);
941 EXPECT_EQ(360, out_height_);
942 }
943
TEST_P(VideoAdapterTest,TestCroppingOddResolution)944 TEST_P(VideoAdapterTest, TestCroppingOddResolution) {
945 // Ask for 640x360 (16:9 aspect), with 3/16 scaling.
946 OnOutputFormatRequest(640, 360, absl::nullopt);
947 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt,
948 640 * 360 * 3 / 16 * 3 / 16,
949 std::numeric_limits<int>::max()));
950
951 // Send 640x480 (4:3 aspect).
952 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0, &cropped_width_,
953 &cropped_height_, &out_width_,
954 &out_height_));
955
956 // Instead of getting the exact aspect ratio with cropped resolution 640x360,
957 // the resolution should be adjusted to get a perfect scale factor instead.
958 EXPECT_EQ(640, cropped_width_);
959 EXPECT_EQ(368, cropped_height_);
960 EXPECT_EQ(120, out_width_);
961 EXPECT_EQ(69, out_height_);
962 }
963
TEST_P(VideoAdapterTest,TestAdaptToVerySmallResolution)964 TEST_P(VideoAdapterTest, TestAdaptToVerySmallResolution) {
965 // Ask for 1920x1080 (16:9 aspect), with 1/16 scaling.
966 const int w = 1920;
967 const int h = 1080;
968 OnOutputFormatRequest(w, h, absl::nullopt);
969 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt, w * h * 1 / 16 * 1 / 16,
970 std::numeric_limits<int>::max()));
971
972 // Send 1920x1080 (16:9 aspect).
973 EXPECT_TRUE(adapter_.AdaptFrameResolution(
974 w, h, 0, &cropped_width_, &cropped_height_, &out_width_, &out_height_));
975
976 // Instead of getting the exact aspect ratio with cropped resolution 1920x1080
977 // the resolution should be adjusted to get a perfect scale factor instead.
978 EXPECT_EQ(1920, cropped_width_);
979 EXPECT_EQ(1072, cropped_height_);
980 EXPECT_EQ(120, out_width_);
981 EXPECT_EQ(67, out_height_);
982
983 // Adapt back up one step to 3/32.
984 adapter_.OnSinkWants(BuildSinkWants(w * h * 3 / 32 * 3 / 32,
985 w * h * 1 / 8 * 1 / 8,
986 std::numeric_limits<int>::max()));
987
988 // Send 1920x1080 (16:9 aspect).
989 EXPECT_TRUE(adapter_.AdaptFrameResolution(
990 w, h, 0, &cropped_width_, &cropped_height_, &out_width_, &out_height_));
991
992 EXPECT_EQ(160, out_width_);
993 EXPECT_EQ(90, out_height_);
994 }
995
TEST_P(VideoAdapterTest,AdaptFrameResolutionDropWithResolutionRequest)996 TEST_P(VideoAdapterTest, AdaptFrameResolutionDropWithResolutionRequest) {
997 OnOutputFormatRequest(0, 0, kDefaultFps);
998 EXPECT_FALSE(adapter_.AdaptFrameResolution(kWidth, kHeight, 0,
999 &cropped_width_, &cropped_height_,
1000 &out_width_, &out_height_));
1001
1002 adapter_.OnSinkWants(BuildSinkWants(960 * 540,
1003 std::numeric_limits<int>::max(),
1004 std::numeric_limits<int>::max()));
1005
1006 // Still expect all frames to be dropped
1007 EXPECT_FALSE(adapter_.AdaptFrameResolution(kWidth, kHeight, 0,
1008 &cropped_width_, &cropped_height_,
1009 &out_width_, &out_height_));
1010
1011 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt, 640 * 480 - 1,
1012 std::numeric_limits<int>::max()));
1013
1014 // Still expect all frames to be dropped
1015 EXPECT_FALSE(adapter_.AdaptFrameResolution(kWidth, kHeight, 0,
1016 &cropped_width_, &cropped_height_,
1017 &out_width_, &out_height_));
1018 }
1019
1020 // Test that we will adapt to max given a target pixel count close to max.
TEST_P(VideoAdapterTest,TestAdaptToMax)1021 TEST_P(VideoAdapterTest, TestAdaptToMax) {
1022 OnOutputFormatRequest(640, 360, kDefaultFps);
1023 adapter_.OnSinkWants(BuildSinkWants(640 * 360 - 1 /* target */,
1024 std::numeric_limits<int>::max(),
1025 std::numeric_limits<int>::max()));
1026
1027 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0, &cropped_width_,
1028 &cropped_height_, &out_width_,
1029 &out_height_));
1030 EXPECT_EQ(640, out_width_);
1031 EXPECT_EQ(360, out_height_);
1032 }
1033
1034 // Test adjusting to 16:9 in landscape, and 9:16 in portrait.
TEST(VideoAdapterTestMultipleOrientation,TestNormal)1035 TEST(VideoAdapterTestMultipleOrientation, TestNormal) {
1036 VideoAdapter video_adapter;
1037 video_adapter.OnOutputFormatRequest(std::make_pair(640, 360), 640 * 360,
1038 std::make_pair(360, 640), 360 * 640, 30);
1039
1040 int cropped_width;
1041 int cropped_height;
1042 int out_width;
1043 int out_height;
1044 EXPECT_TRUE(video_adapter.AdaptFrameResolution(
1045 /* in_width= */ 640, /* in_height= */ 480, /* in_timestamp_ns= */ 0,
1046 &cropped_width, &cropped_height, &out_width, &out_height));
1047 EXPECT_EQ(640, cropped_width);
1048 EXPECT_EQ(360, cropped_height);
1049 EXPECT_EQ(640, out_width);
1050 EXPECT_EQ(360, out_height);
1051
1052 EXPECT_TRUE(video_adapter.AdaptFrameResolution(
1053 /* in_width= */ 480, /* in_height= */ 640,
1054 /* in_timestamp_ns= */ rtc::kNumNanosecsPerSec / 30, &cropped_width,
1055 &cropped_height, &out_width, &out_height));
1056 EXPECT_EQ(360, cropped_width);
1057 EXPECT_EQ(640, cropped_height);
1058 EXPECT_EQ(360, out_width);
1059 EXPECT_EQ(640, out_height);
1060 }
1061
1062 // Force output to be 9:16, even for landscape input.
TEST(VideoAdapterTestMultipleOrientation,TestForcePortrait)1063 TEST(VideoAdapterTestMultipleOrientation, TestForcePortrait) {
1064 VideoAdapter video_adapter;
1065 video_adapter.OnOutputFormatRequest(std::make_pair(360, 640), 640 * 360,
1066 std::make_pair(360, 640), 360 * 640, 30);
1067
1068 int cropped_width;
1069 int cropped_height;
1070 int out_width;
1071 int out_height;
1072 EXPECT_TRUE(video_adapter.AdaptFrameResolution(
1073 /* in_width= */ 640, /* in_height= */ 480, /* in_timestamp_ns= */ 0,
1074 &cropped_width, &cropped_height, &out_width, &out_height));
1075 EXPECT_EQ(270, cropped_width);
1076 EXPECT_EQ(480, cropped_height);
1077 EXPECT_EQ(270, out_width);
1078 EXPECT_EQ(480, out_height);
1079
1080 EXPECT_TRUE(video_adapter.AdaptFrameResolution(
1081 /* in_width= */ 480, /* in_height= */ 640,
1082 /* in_timestamp_ns= */ rtc::kNumNanosecsPerSec / 30, &cropped_width,
1083 &cropped_height, &out_width, &out_height));
1084 EXPECT_EQ(360, cropped_width);
1085 EXPECT_EQ(640, cropped_height);
1086 EXPECT_EQ(360, out_width);
1087 EXPECT_EQ(640, out_height);
1088 }
1089
TEST_P(VideoAdapterTest,AdaptResolutionInStepsFirst3_4)1090 TEST_P(VideoAdapterTest, AdaptResolutionInStepsFirst3_4) {
1091 const int kWidth = 1280;
1092 const int kHeight = 720;
1093 OnOutputFormatRequest(kWidth, kHeight, absl::nullopt); // 16:9 aspect.
1094
1095 // Scale factors: 3/4, 2/3, 3/4, 2/3, ...
1096 // Scale : 3/4, 1/2, 3/8, 1/4, 3/16, 1/8.
1097 const int kExpectedWidths[] = {960, 640, 480, 320, 240, 160};
1098 const int kExpectedHeights[] = {540, 360, 270, 180, 135, 90};
1099
1100 int request_width = kWidth;
1101 int request_height = kHeight;
1102
1103 for (size_t i = 0; i < arraysize(kExpectedWidths); ++i) {
1104 // Adapt down one step.
1105 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt,
1106 request_width * request_height - 1,
1107 std::numeric_limits<int>::max()));
1108 EXPECT_TRUE(adapter_.AdaptFrameResolution(kWidth, kHeight, 0,
1109 &cropped_width_, &cropped_height_,
1110 &out_width_, &out_height_));
1111 EXPECT_EQ(kExpectedWidths[i], out_width_);
1112 EXPECT_EQ(kExpectedHeights[i], out_height_);
1113 request_width = out_width_;
1114 request_height = out_height_;
1115 }
1116 }
1117
TEST_P(VideoAdapterTest,AdaptResolutionInStepsFirst2_3)1118 TEST_P(VideoAdapterTest, AdaptResolutionInStepsFirst2_3) {
1119 const int kWidth = 1920;
1120 const int kHeight = 1080;
1121 OnOutputFormatRequest(kWidth, kHeight, absl::nullopt); // 16:9 aspect.
1122
1123 // Scale factors: 2/3, 3/4, 2/3, 3/4, ...
1124 // Scale: 2/3, 1/2, 1/3, 1/4, 1/6, 1/8, 1/12.
1125 const int kExpectedWidths[] = {1280, 960, 640, 480, 320, 240, 160};
1126 const int kExpectedHeights[] = {720, 540, 360, 270, 180, 135, 90};
1127
1128 int request_width = kWidth;
1129 int request_height = kHeight;
1130
1131 for (size_t i = 0; i < arraysize(kExpectedWidths); ++i) {
1132 // Adapt down one step.
1133 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt,
1134 request_width * request_height - 1,
1135 std::numeric_limits<int>::max()));
1136 EXPECT_TRUE(adapter_.AdaptFrameResolution(kWidth, kHeight, 0,
1137 &cropped_width_, &cropped_height_,
1138 &out_width_, &out_height_));
1139 EXPECT_EQ(kExpectedWidths[i], out_width_);
1140 EXPECT_EQ(kExpectedHeights[i], out_height_);
1141 request_width = out_width_;
1142 request_height = out_height_;
1143 }
1144 }
1145
TEST_P(VideoAdapterTest,AdaptResolutionInStepsFirst2x2_3)1146 TEST_P(VideoAdapterTest, AdaptResolutionInStepsFirst2x2_3) {
1147 const int kWidth = 1440;
1148 const int kHeight = 1080;
1149 OnOutputFormatRequest(kWidth, kHeight, absl::nullopt); // 4:3 aspect.
1150
1151 // Scale factors: 2/3, 2/3, 3/4, 2/3, 3/4, ...
1152 // Scale : 2/3, 4/9, 1/3, 2/9, 1/6, 1/9, 1/12, 1/18, 1/24, 1/36.
1153 const int kExpectedWidths[] = {960, 640, 480, 320, 240, 160, 120, 80, 60, 40};
1154 const int kExpectedHeights[] = {720, 480, 360, 240, 180, 120, 90, 60, 45, 30};
1155
1156 int request_width = kWidth;
1157 int request_height = kHeight;
1158
1159 for (size_t i = 0; i < arraysize(kExpectedWidths); ++i) {
1160 // Adapt down one step.
1161 adapter_.OnSinkWants(BuildSinkWants(absl::nullopt,
1162 request_width * request_height - 1,
1163 std::numeric_limits<int>::max()));
1164 EXPECT_TRUE(adapter_.AdaptFrameResolution(kWidth, kHeight, 0,
1165 &cropped_width_, &cropped_height_,
1166 &out_width_, &out_height_));
1167 EXPECT_EQ(kExpectedWidths[i], out_width_);
1168 EXPECT_EQ(kExpectedHeights[i], out_height_);
1169 request_width = out_width_;
1170 request_height = out_height_;
1171 }
1172 }
1173
TEST_P(VideoAdapterTest,AdaptResolutionWithSinkAlignment)1174 TEST_P(VideoAdapterTest, AdaptResolutionWithSinkAlignment) {
1175 constexpr int kSourceWidth = 1280;
1176 constexpr int kSourceHeight = 720;
1177 constexpr int kSourceFramerate = 30;
1178 constexpr int kRequestedWidth = 480;
1179 constexpr int kRequestedHeight = 270;
1180 constexpr int kRequestedFramerate = 30;
1181
1182 OnOutputFormatRequest(kRequestedWidth, kRequestedHeight, kRequestedFramerate);
1183
1184 int frame_num = 1;
1185 for (const int sink_alignment : {2, 3, 4, 5}) {
1186 adapter_.OnSinkWants(
1187 BuildSinkWants(absl::nullopt, std::numeric_limits<int>::max(),
1188 std::numeric_limits<int>::max(), sink_alignment));
1189 EXPECT_TRUE(adapter_.AdaptFrameResolution(
1190 kSourceWidth, kSourceHeight,
1191 frame_num * rtc::kNumNanosecsPerSec / kSourceFramerate, &cropped_width_,
1192 &cropped_height_, &out_width_, &out_height_));
1193 EXPECT_EQ(out_width_ % sink_alignment, 0);
1194 EXPECT_EQ(out_height_ % sink_alignment, 0);
1195
1196 ++frame_num;
1197 }
1198 }
1199
1200 // Verify the cases the OnOutputFormatRequest is ignored and
1201 // requested_resolution is used instead.
TEST_P(VideoAdapterTest,UseRequestedResolutionInsteadOfOnOutputFormatRequest)1202 TEST_P(VideoAdapterTest, UseRequestedResolutionInsteadOfOnOutputFormatRequest) {
1203 {
1204 // Both new and old API active => Use OnOutputFormatRequest
1205 OnOutputFormatRequest(640, 360, kDefaultFps);
1206 adapter_.OnSinkWants(
1207 BuildSinkWants(Resolution{.width = 960, .height = 540},
1208 /* any_active_without_requested_resolution= */ true));
1209
1210 EXPECT_THAT(
1211 AdaptFrameResolution(/* input frame */ {.width = 1280, .height = 720})
1212 .first,
1213 Eq(Resolution{.width = 640, .height = 360}));
1214 }
1215 {
1216 // New API active, old API inactive, ignore OnOutputFormatRequest and use
1217 // requested_resolution.
1218 OnOutputFormatRequest(640, 360, kDefaultFps);
1219 adapter_.OnSinkWants(
1220 BuildSinkWants(Resolution{.width = 960, .height = 540},
1221 /* any_active_without_requested_resolution= */ false));
1222
1223 EXPECT_THAT(
1224 AdaptFrameResolution(/* input frame */ {.width = 1280, .height = 720})
1225 .first,
1226 Eq(Resolution{.width = 960, .height = 540}));
1227 }
1228
1229 {
1230 // New API inactive, old API inactive, use OnOutputFormatRequest.
1231 OnOutputFormatRequest(640, 360, kDefaultFps);
1232 adapter_.OnSinkWants(
1233 BuildSinkWants(absl::nullopt,
1234 /* any_active_without_requested_resolution= */ false));
1235
1236 EXPECT_THAT(
1237 AdaptFrameResolution(/* input frame */ {.width = 1280, .height = 720})
1238 .first,
1239 Eq(Resolution{.width = 640, .height = 360}));
1240 }
1241
1242 {
1243 // New API active, old API inactive, remember OnOutputFormatRequest.
1244 OnOutputFormatRequest(640, 360, kDefaultFps);
1245 adapter_.OnSinkWants(
1246 BuildSinkWants(Resolution{.width = 960, .height = 540},
1247 /* any_active_without_requested_resolution= */ false));
1248
1249 EXPECT_THAT(
1250 AdaptFrameResolution(/* input frame */ {.width = 1280, .height = 720})
1251 .first,
1252 Eq(Resolution{.width = 960, .height = 540}));
1253
1254 // This is ignored since there is not any active NOT using
1255 // requested_resolution.
1256 OnOutputFormatRequest(320, 180, kDefaultFps);
1257
1258 EXPECT_THAT(
1259 AdaptFrameResolution(/* input frame */ {.width = 1280, .height = 720})
1260 .first,
1261 Eq(Resolution{.width = 960, .height = 540}));
1262
1263 // Disable new API => fallback to last OnOutputFormatRequest.
1264 adapter_.OnSinkWants(
1265 BuildSinkWants(absl::nullopt,
1266 /* any_active_without_requested_resolution= */ false));
1267
1268 EXPECT_THAT(
1269 AdaptFrameResolution(/* input frame */ {.width = 1280, .height = 720})
1270 .first,
1271 Eq(Resolution{.width = 320, .height = 180}));
1272 }
1273 }
1274
1275 class VideoAdapterWithSourceAlignmentTest : public VideoAdapterTest {
1276 protected:
1277 static constexpr int kSourceResolutionAlignment = 7;
1278
VideoAdapterWithSourceAlignmentTest()1279 VideoAdapterWithSourceAlignmentTest()
1280 : VideoAdapterTest(/*field_trials=*/"", kSourceResolutionAlignment) {}
1281 };
1282
TEST_P(VideoAdapterWithSourceAlignmentTest,AdaptResolution)1283 TEST_P(VideoAdapterWithSourceAlignmentTest, AdaptResolution) {
1284 constexpr int kSourceWidth = 1280;
1285 constexpr int kSourceHeight = 720;
1286 constexpr int kRequestedWidth = 480;
1287 constexpr int kRequestedHeight = 270;
1288 constexpr int kRequestedFramerate = 30;
1289
1290 OnOutputFormatRequest(kRequestedWidth, kRequestedHeight, kRequestedFramerate);
1291
1292 EXPECT_TRUE(adapter_.AdaptFrameResolution(
1293 kSourceWidth, kSourceHeight, /*in_timestamp_ns=*/0, &cropped_width_,
1294 &cropped_height_, &out_width_, &out_height_));
1295 EXPECT_EQ(out_width_ % kSourceResolutionAlignment, 0);
1296 EXPECT_EQ(out_height_ % kSourceResolutionAlignment, 0);
1297 }
1298
TEST_P(VideoAdapterWithSourceAlignmentTest,AdaptResolutionWithSinkAlignment)1299 TEST_P(VideoAdapterWithSourceAlignmentTest, AdaptResolutionWithSinkAlignment) {
1300 constexpr int kSourceWidth = 1280;
1301 constexpr int kSourceHeight = 720;
1302 // 7 and 8 neither divide 480 nor 270.
1303 constexpr int kRequestedWidth = 480;
1304 constexpr int kRequestedHeight = 270;
1305 constexpr int kRequestedFramerate = 30;
1306 constexpr int kSinkResolutionAlignment = 8;
1307
1308 OnOutputFormatRequest(kRequestedWidth, kRequestedHeight, kRequestedFramerate);
1309
1310 adapter_.OnSinkWants(BuildSinkWants(
1311 absl::nullopt, std::numeric_limits<int>::max(),
1312 std::numeric_limits<int>::max(), kSinkResolutionAlignment));
1313 EXPECT_TRUE(adapter_.AdaptFrameResolution(
1314 kSourceWidth, kSourceHeight, /*in_timestamp_ns=*/0, &cropped_width_,
1315 &cropped_height_, &out_width_, &out_height_));
1316 EXPECT_EQ(out_width_ % kSourceResolutionAlignment, 0);
1317 EXPECT_EQ(out_height_ % kSourceResolutionAlignment, 0);
1318 EXPECT_EQ(out_width_ % kSinkResolutionAlignment, 0);
1319 EXPECT_EQ(out_height_ % kSinkResolutionAlignment, 0);
1320 }
1321
1322 INSTANTIATE_TEST_SUITE_P(OnOutputFormatRequests,
1323 VideoAdapterWithSourceAlignmentTest,
1324 ::testing::Values(true, false));
1325
1326 } // namespace cricket
1327