blob: d3a66c189d14125f7a03a180ca2c01eae6ea683b [file] [log] [blame]
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2010 The WebRTC project authors. All Rights Reserved.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * 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.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00009 */
10
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000011#include <limits.h> // For INT_MAX
kwiberg686a8ef2016-02-26 03:00:35 -080012
kwibergbfefb032016-05-01 14:53:46 -070013#include <memory>
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000014#include <string>
15#include <vector>
16
kjellandera96e2d72016-02-04 23:52:28 -080017#include "webrtc/media/base/fakevideocapturer.h"
18#include "webrtc/media/base/mediachannel.h"
19#include "webrtc/media/base/testutils.h"
20#include "webrtc/media/base/videoadapter.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020021#include "webrtc/rtc_base/gunit.h"
22#include "webrtc/rtc_base/logging.h"
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000023
24namespace cricket {
sprangc5d62e22017-04-02 23:53:04 -070025namespace {
26const int kDefaultFps = 30;
27} // namespace
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000028
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000029class VideoAdapterTest : public testing::Test {
30 public:
31 virtual void SetUp() {
Magnus Jedvert01840572015-04-10 11:18:39 +020032 capturer_.reset(new FakeVideoCapturer);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000033 capture_format_ = capturer_->GetSupportedFormats()->at(0);
sprangc5d62e22017-04-02 23:53:04 -070034 capture_format_.interval = VideoFormat::FpsToInterval(kDefaultFps);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000035
Per766ad3b2016-04-05 15:23:49 +020036 listener_.reset(new VideoCapturerListener(&adapter_));
nissef5297a02016-09-30 01:34:27 -070037 capturer_->AddOrUpdateSink(listener_.get(), rtc::VideoSinkWants());
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000038 }
39
pbos@webrtc.org75c3ec12014-08-27 18:16:13 +000040 virtual void TearDown() {
41 // Explicitly disconnect the VideoCapturer before to avoid data races
42 // (frames delivered to VideoCapturerListener while it's being destructed).
nissef5297a02016-09-30 01:34:27 -070043 capturer_->RemoveSink(listener_.get());
pbos@webrtc.org75c3ec12014-08-27 18:16:13 +000044 }
45
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000046 protected:
nissef5297a02016-09-30 01:34:27 -070047 class VideoCapturerListener
nisseacd935b2016-11-11 03:55:13 -080048 : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000049 public:
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000050 struct Stats {
51 int captured_frames;
52 int dropped_frames;
53 bool last_adapt_was_no_op;
54
magjed709f73c2016-05-13 10:26:00 -070055 int cropped_width;
56 int cropped_height;
57 int out_width;
58 int out_height;
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000059 };
60
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000061 explicit VideoCapturerListener(VideoAdapter* adapter)
62 : video_adapter_(adapter),
sprang84a37592017-02-10 07:04:27 -080063 cropped_width_(0),
64 cropped_height_(0),
65 out_width_(0),
66 out_height_(0),
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000067 captured_frames_(0),
68 dropped_frames_(0),
sprang84a37592017-02-10 07:04:27 -080069 last_adapt_was_no_op_(false) {}
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000070
nisseacd935b2016-11-11 03:55:13 -080071 void OnFrame(const webrtc::VideoFrame& frame) {
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000072 rtc::CritScope lock(&crit_);
nissef5297a02016-09-30 01:34:27 -070073 const int in_width = frame.width();
74 const int in_height = frame.height();
magjed709f73c2016-05-13 10:26:00 -070075 int cropped_width;
76 int cropped_height;
77 int out_width;
78 int out_height;
nissef5297a02016-09-30 01:34:27 -070079 if (video_adapter_->AdaptFrameResolution(
80 in_width, in_height,
81 frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec,
82 &cropped_width, &cropped_height, &out_width, &out_height)) {
magjed709f73c2016-05-13 10:26:00 -070083 cropped_width_ = cropped_width;
84 cropped_height_ = cropped_height;
85 out_width_ = out_width;
86 out_height_ = out_height;
87 last_adapt_was_no_op_ =
88 (in_width == cropped_width && in_height == cropped_height &&
89 in_width == out_width && in_height == out_height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000090 } else {
91 ++dropped_frames_;
92 }
93 ++captured_frames_;
94 }
95
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000096 Stats GetStats() {
97 rtc::CritScope lock(&crit_);
98 Stats stats;
99 stats.captured_frames = captured_frames_;
100 stats.dropped_frames = dropped_frames_;
101 stats.last_adapt_was_no_op = last_adapt_was_no_op_;
magjed709f73c2016-05-13 10:26:00 -0700102 stats.cropped_width = cropped_width_;
103 stats.cropped_height = cropped_height_;
104 stats.out_width = out_width_;
105 stats.out_height = out_height_;
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000106 return stats;
107 }
108
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000109 private:
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000110 rtc::CriticalSection crit_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000111 VideoAdapter* video_adapter_;
magjed709f73c2016-05-13 10:26:00 -0700112 int cropped_width_;
113 int cropped_height_;
114 int out_width_;
115 int out_height_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000116 int captured_frames_;
117 int dropped_frames_;
118 bool last_adapt_was_no_op_;
119 };
120
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000121
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000122 void VerifyAdaptedResolution(const VideoCapturerListener::Stats& stats,
magjed709f73c2016-05-13 10:26:00 -0700123 int cropped_width,
124 int cropped_height,
125 int out_width,
126 int out_height) {
127 EXPECT_EQ(cropped_width, stats.cropped_width);
128 EXPECT_EQ(cropped_height, stats.cropped_height);
129 EXPECT_EQ(out_width, stats.out_width);
130 EXPECT_EQ(out_height, stats.out_height);
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000131 }
132
kwiberg686a8ef2016-02-26 03:00:35 -0800133 std::unique_ptr<FakeVideoCapturer> capturer_;
Per766ad3b2016-04-05 15:23:49 +0200134 VideoAdapter adapter_;
magjed709f73c2016-05-13 10:26:00 -0700135 int cropped_width_;
136 int cropped_height_;
137 int out_width_;
138 int out_height_;
kwiberg686a8ef2016-02-26 03:00:35 -0800139 std::unique_ptr<VideoCapturerListener> listener_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000140 VideoFormat capture_format_;
141};
142
magjed709f73c2016-05-13 10:26:00 -0700143// Do not adapt the frame rate or the resolution. Expect no frame drop, no
144// cropping, and no resolution change.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000145TEST_F(VideoAdapterTest, AdaptNothing) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000146 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200147 for (int i = 0; i < 10; ++i)
148 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000149
150 // Verify no frame drop and no resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000151 VideoCapturerListener::Stats stats = listener_->GetStats();
152 EXPECT_GE(stats.captured_frames, 10);
153 EXPECT_EQ(0, stats.dropped_frames);
magjed709f73c2016-05-13 10:26:00 -0700154 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
155 capture_format_.width, capture_format_.height);
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000156 EXPECT_TRUE(stats.last_adapt_was_no_op);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000157}
158
159TEST_F(VideoAdapterTest, AdaptZeroInterval) {
160 VideoFormat format = capturer_->GetSupportedFormats()->at(0);
161 format.interval = 0;
Per766ad3b2016-04-05 15:23:49 +0200162 adapter_.OnOutputFormatRequest(format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000163 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200164 for (int i = 0; i < 10; ++i)
165 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000166
167 // Verify no crash and that frames aren't dropped.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000168 VideoCapturerListener::Stats stats = listener_->GetStats();
169 EXPECT_GE(stats.captured_frames, 10);
170 EXPECT_EQ(0, stats.dropped_frames);
magjed709f73c2016-05-13 10:26:00 -0700171 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
172 capture_format_.width, capture_format_.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000173}
174
175// Adapt the frame rate to be half of the capture rate at the beginning. Expect
176// the number of dropped frames to be half of the number the captured frames.
magjed604abe02016-05-19 06:05:40 -0700177TEST_F(VideoAdapterTest, AdaptFramerateToHalf) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000178 VideoFormat request_format = capture_format_;
179 request_format.interval *= 2;
Per766ad3b2016-04-05 15:23:49 +0200180 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000181 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
magjed604abe02016-05-19 06:05:40 -0700182
183 // Capture 10 frames and verify that every other frame is dropped. The first
184 // frame should not be dropped.
185 capturer_->CaptureFrame();
186 EXPECT_GE(listener_->GetStats().captured_frames, 1);
187 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
188
189 capturer_->CaptureFrame();
190 EXPECT_GE(listener_->GetStats().captured_frames, 2);
nissef5297a02016-09-30 01:34:27 -0700191 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700192
193 capturer_->CaptureFrame();
194 EXPECT_GE(listener_->GetStats().captured_frames, 3);
195 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
196
197 capturer_->CaptureFrame();
198 EXPECT_GE(listener_->GetStats().captured_frames, 4);
nissef5297a02016-09-30 01:34:27 -0700199 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700200
201 capturer_->CaptureFrame();
202 EXPECT_GE(listener_->GetStats().captured_frames, 5);
203 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
204
205 capturer_->CaptureFrame();
206 EXPECT_GE(listener_->GetStats().captured_frames, 6);
nissef5297a02016-09-30 01:34:27 -0700207 EXPECT_EQ(3, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700208
209 capturer_->CaptureFrame();
210 EXPECT_GE(listener_->GetStats().captured_frames, 7);
211 EXPECT_EQ(3, listener_->GetStats().dropped_frames);
212
213 capturer_->CaptureFrame();
214 EXPECT_GE(listener_->GetStats().captured_frames, 8);
nissef5297a02016-09-30 01:34:27 -0700215 EXPECT_EQ(4, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700216
217 capturer_->CaptureFrame();
218 EXPECT_GE(listener_->GetStats().captured_frames, 9);
219 EXPECT_EQ(4, listener_->GetStats().dropped_frames);
220
221 capturer_->CaptureFrame();
222 EXPECT_GE(listener_->GetStats().captured_frames, 10);
nissef5297a02016-09-30 01:34:27 -0700223 EXPECT_EQ(5, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700224}
225
226// Adapt the frame rate to be two thirds of the capture rate at the beginning.
227// Expect the number of dropped frames to be one thirds of the number the
228// captured frames.
229TEST_F(VideoAdapterTest, AdaptFramerateToTwoThirds) {
230 VideoFormat request_format = capture_format_;
231 request_format.interval = request_format.interval * 3 / 2;
232 adapter_.OnOutputFormatRequest(request_format);
233 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
234
235 // Capture 10 frames and verify that every third frame is dropped. The first
236 // frame should not be dropped.
237 capturer_->CaptureFrame();
238 EXPECT_GE(listener_->GetStats().captured_frames, 1);
239 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
240
241 capturer_->CaptureFrame();
242 EXPECT_GE(listener_->GetStats().captured_frames, 2);
243 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
244
245 capturer_->CaptureFrame();
246 EXPECT_GE(listener_->GetStats().captured_frames, 3);
247 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
248
249 capturer_->CaptureFrame();
250 EXPECT_GE(listener_->GetStats().captured_frames, 4);
251 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
252
253 capturer_->CaptureFrame();
254 EXPECT_GE(listener_->GetStats().captured_frames, 5);
255 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
256
257 capturer_->CaptureFrame();
258 EXPECT_GE(listener_->GetStats().captured_frames, 6);
259 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
260
261 capturer_->CaptureFrame();
262 EXPECT_GE(listener_->GetStats().captured_frames, 7);
263 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
264
265 capturer_->CaptureFrame();
266 EXPECT_GE(listener_->GetStats().captured_frames, 8);
267 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
268
269 capturer_->CaptureFrame();
270 EXPECT_GE(listener_->GetStats().captured_frames, 9);
271 EXPECT_EQ(3, listener_->GetStats().dropped_frames);
272
273 capturer_->CaptureFrame();
274 EXPECT_GE(listener_->GetStats().captured_frames, 10);
275 EXPECT_EQ(3, listener_->GetStats().dropped_frames);
276}
277
278// Request frame rate twice as high as captured frame rate. Expect no frame
279// drop.
280TEST_F(VideoAdapterTest, AdaptFramerateHighLimit) {
281 VideoFormat request_format = capture_format_;
282 request_format.interval /= 2;
283 adapter_.OnOutputFormatRequest(request_format);
284 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200285 for (int i = 0; i < 10; ++i)
286 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000287
magjed604abe02016-05-19 06:05:40 -0700288 // Verify no frame drop.
289 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000290}
291
magjed604abe02016-05-19 06:05:40 -0700292// After the first timestamp, add a big offset to the timestamps. Expect that
293// the adapter is conservative and resets to the new offset and does not drop
294// any frame.
295TEST_F(VideoAdapterTest, AdaptFramerateTimestampOffset) {
sprangc5d62e22017-04-02 23:53:04 -0700296 const int64_t capture_interval = VideoFormat::FpsToInterval(kDefaultFps);
magjed604abe02016-05-19 06:05:40 -0700297 adapter_.OnOutputFormatRequest(
298 VideoFormat(640, 480, capture_interval, cricket::FOURCC_ANY));
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000299
magjed604abe02016-05-19 06:05:40 -0700300 const int64_t first_timestamp = 0;
301 adapter_.AdaptFrameResolution(640, 480, first_timestamp,
302 &cropped_width_, &cropped_height_,
303 &out_width_, &out_height_);
304 EXPECT_GT(out_width_, 0);
305 EXPECT_GT(out_height_, 0);
306
307 const int64_t big_offset = -987654321LL * 1000;
308 const int64_t second_timestamp = big_offset;
309 adapter_.AdaptFrameResolution(640, 480, second_timestamp,
310 &cropped_width_, &cropped_height_,
311 &out_width_, &out_height_);
312 EXPECT_GT(out_width_, 0);
313 EXPECT_GT(out_height_, 0);
314
315 const int64_t third_timestamp = big_offset + capture_interval;
316 adapter_.AdaptFrameResolution(640, 480, third_timestamp,
317 &cropped_width_, &cropped_height_,
318 &out_width_, &out_height_);
319 EXPECT_GT(out_width_, 0);
320 EXPECT_GT(out_height_, 0);
321}
322
323// Request 30 fps and send 30 fps with jitter. Expect that no frame is dropped.
324TEST_F(VideoAdapterTest, AdaptFramerateTimestampJitter) {
sprangc5d62e22017-04-02 23:53:04 -0700325 const int64_t capture_interval = VideoFormat::FpsToInterval(kDefaultFps);
magjed604abe02016-05-19 06:05:40 -0700326 adapter_.OnOutputFormatRequest(
327 VideoFormat(640, 480, capture_interval, cricket::FOURCC_ANY));
328
329 adapter_.AdaptFrameResolution(640, 480, capture_interval * 0 / 10,
330 &cropped_width_, &cropped_height_,
331 &out_width_, &out_height_);
332 EXPECT_GT(out_width_, 0);
333 EXPECT_GT(out_height_, 0);
334
335 adapter_.AdaptFrameResolution(640, 480, capture_interval * 10 / 10 - 1,
336 &cropped_width_, &cropped_height_,
337 &out_width_, &out_height_);
338 EXPECT_GT(out_width_, 0);
339 EXPECT_GT(out_height_, 0);
340
341 adapter_.AdaptFrameResolution(640, 480, capture_interval * 25 / 10,
342 &cropped_width_, &cropped_height_,
343 &out_width_, &out_height_);
344 EXPECT_GT(out_width_, 0);
345 EXPECT_GT(out_height_, 0);
346
347 adapter_.AdaptFrameResolution(640, 480, capture_interval * 30 / 10,
348 &cropped_width_, &cropped_height_,
349 &out_width_, &out_height_);
350 EXPECT_GT(out_width_, 0);
351 EXPECT_GT(out_height_, 0);
352
353 adapter_.AdaptFrameResolution(640, 480, capture_interval * 35 / 10,
354 &cropped_width_, &cropped_height_,
355 &out_width_, &out_height_);
356 EXPECT_GT(out_width_, 0);
357 EXPECT_GT(out_height_, 0);
358
359 adapter_.AdaptFrameResolution(640, 480, capture_interval * 50 / 10,
360 &cropped_width_, &cropped_height_,
361 &out_width_, &out_height_);
362 EXPECT_GT(out_width_, 0);
363 EXPECT_GT(out_height_, 0);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000364}
365
366// Adapt the frame rate to be half of the capture rate after capturing no less
367// than 10 frames. Expect no frame dropped before adaptation and frame dropped
368// after adaptation.
369TEST_F(VideoAdapterTest, AdaptFramerateOntheFly) {
370 VideoFormat request_format = capture_format_;
Per766ad3b2016-04-05 15:23:49 +0200371 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000372 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200373 for (int i = 0; i < 10; ++i)
374 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000375
376 // Verify no frame drop before adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000377 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000378
379 // Adapat the frame rate.
380 request_format.interval *= 2;
Per766ad3b2016-04-05 15:23:49 +0200381 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000382
Magnus Jedvert01840572015-04-10 11:18:39 +0200383 for (int i = 0; i < 20; ++i)
384 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000385
386 // Verify frame drop after adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000387 EXPECT_GT(listener_->GetStats().dropped_frames, 0);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000388}
389
sprangc5d62e22017-04-02 23:53:04 -0700390// Do not adapt the frame rate or the resolution. Expect no frame drop, no
391// cropping, and no resolution change.
392TEST_F(VideoAdapterTest, OnFramerateRequestMax) {
393 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(),
394 std::numeric_limits<int>::max(),
395 std::numeric_limits<int>::max());
396
397 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
398 for (int i = 0; i < 10; ++i)
399 capturer_->CaptureFrame();
400
401 // Verify no frame drop and no resolution change.
402 VideoCapturerListener::Stats stats = listener_->GetStats();
403 EXPECT_GE(stats.captured_frames, 10);
404 EXPECT_EQ(0, stats.dropped_frames);
405 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
406 capture_format_.width, capture_format_.height);
407 EXPECT_TRUE(stats.last_adapt_was_no_op);
408}
409
410TEST_F(VideoAdapterTest, OnFramerateRequestZero) {
411 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(),
412 std::numeric_limits<int>::max(), 0);
413 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
414 for (int i = 0; i < 10; ++i)
415 capturer_->CaptureFrame();
416
417 // Verify no crash and that frames aren't dropped.
418 VideoCapturerListener::Stats stats = listener_->GetStats();
419 EXPECT_GE(stats.captured_frames, 10);
420 EXPECT_EQ(10, stats.dropped_frames);
421}
422
423// Adapt the frame rate to be half of the capture rate at the beginning. Expect
424// the number of dropped frames to be half of the number the captured frames.
425TEST_F(VideoAdapterTest, OnFramerateRequestHalf) {
426 adapter_.OnResolutionFramerateRequest(
427 rtc::Optional<int>(), std::numeric_limits<int>::max(), kDefaultFps / 2);
428 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
429 for (int i = 0; i < 10; ++i)
430 capturer_->CaptureFrame();
431
432 // Verify no crash and that frames aren't dropped.
433 VideoCapturerListener::Stats stats = listener_->GetStats();
434 EXPECT_GE(stats.captured_frames, 10);
435 EXPECT_EQ(5, stats.dropped_frames);
436 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
437 capture_format_.width, capture_format_.height);
438}
439
magjed709f73c2016-05-13 10:26:00 -0700440// Set a very high output pixel resolution. Expect no cropping or resolution
441// change.
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000442TEST_F(VideoAdapterTest, AdaptFrameResolutionHighLimit) {
Per766ad3b2016-04-05 15:23:49 +0200443 VideoFormat output_format = capture_format_;
magjed709f73c2016-05-13 10:26:00 -0700444 output_format.width *= 10;
445 output_format.height *= 10;
Per766ad3b2016-04-05 15:23:49 +0200446 adapter_.OnOutputFormatRequest(output_format);
nisse47ac4622016-05-25 08:47:01 -0700447 EXPECT_TRUE(adapter_.AdaptFrameResolution(
448 capture_format_.width, capture_format_.height, 0,
449 &cropped_width_, &cropped_height_,
450 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700451 EXPECT_EQ(capture_format_.width, cropped_width_);
452 EXPECT_EQ(capture_format_.height, cropped_height_);
453 EXPECT_EQ(capture_format_.width, out_width_);
454 EXPECT_EQ(capture_format_.height, out_height_);
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000455}
456
457// Adapt the frame resolution to be the same as capture resolution. Expect no
magjed709f73c2016-05-13 10:26:00 -0700458// cropping or resolution change.
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000459TEST_F(VideoAdapterTest, AdaptFrameResolutionIdentical) {
Per766ad3b2016-04-05 15:23:49 +0200460 adapter_.OnOutputFormatRequest(capture_format_);
nisse47ac4622016-05-25 08:47:01 -0700461 EXPECT_TRUE(adapter_.AdaptFrameResolution(
462 capture_format_.width, capture_format_.height, 0,
463 &cropped_width_, &cropped_height_,
464 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700465 EXPECT_EQ(capture_format_.width, cropped_width_);
466 EXPECT_EQ(capture_format_.height, cropped_height_);
467 EXPECT_EQ(capture_format_.width, out_width_);
468 EXPECT_EQ(capture_format_.height, out_height_);
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000469}
470
471// Adapt the frame resolution to be a quarter of the capture resolution. Expect
magjed709f73c2016-05-13 10:26:00 -0700472// no cropping, but a resolution change.
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000473TEST_F(VideoAdapterTest, AdaptFrameResolutionQuarter) {
474 VideoFormat request_format = capture_format_;
475 request_format.width /= 2;
476 request_format.height /= 2;
Per766ad3b2016-04-05 15:23:49 +0200477 adapter_.OnOutputFormatRequest(request_format);
nisse47ac4622016-05-25 08:47:01 -0700478 EXPECT_TRUE(adapter_.AdaptFrameResolution(
479 capture_format_.width, capture_format_.height, 0,
480 &cropped_width_, &cropped_height_,
481 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700482 EXPECT_EQ(capture_format_.width, cropped_width_);
483 EXPECT_EQ(capture_format_.height, cropped_height_);
484 EXPECT_EQ(request_format.width, out_width_);
485 EXPECT_EQ(request_format.height, out_height_);
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000486}
487
488// Adapt the pixel resolution to 0. Expect frame drop.
489TEST_F(VideoAdapterTest, AdaptFrameResolutionDrop) {
Per766ad3b2016-04-05 15:23:49 +0200490 VideoFormat output_format = capture_format_;
491 output_format.width = 0;
492 output_format.height = 0;
493 adapter_.OnOutputFormatRequest(output_format);
nisse47ac4622016-05-25 08:47:01 -0700494 EXPECT_FALSE(adapter_.AdaptFrameResolution(
495 capture_format_.width, capture_format_.height, 0,
496 &cropped_width_, &cropped_height_,
497 &out_width_, &out_height_));
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000498}
499
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000500// Adapt the frame resolution to be a quarter of the capture resolution at the
magjed709f73c2016-05-13 10:26:00 -0700501// beginning. Expect no cropping but a resolution change.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000502TEST_F(VideoAdapterTest, AdaptResolution) {
503 VideoFormat request_format = capture_format_;
504 request_format.width /= 2;
505 request_format.height /= 2;
Per766ad3b2016-04-05 15:23:49 +0200506 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000507 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200508 for (int i = 0; i < 10; ++i)
509 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000510
magjed709f73c2016-05-13 10:26:00 -0700511 // Verify no frame drop, no cropping, and resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000512 VideoCapturerListener::Stats stats = listener_->GetStats();
513 EXPECT_EQ(0, stats.dropped_frames);
magjed709f73c2016-05-13 10:26:00 -0700514 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
515 request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000516}
517
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000518// Adapt the frame resolution to be a quarter of the capture resolution after
519// capturing no less than 10 frames. Expect no resolution change before
520// adaptation and resolution change after adaptation.
521TEST_F(VideoAdapterTest, AdaptResolutionOnTheFly) {
522 VideoFormat request_format = capture_format_;
Per766ad3b2016-04-05 15:23:49 +0200523 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000524 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200525 for (int i = 0; i < 10; ++i)
526 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000527
528 // Verify no resolution change before adaptation.
magjed709f73c2016-05-13 10:26:00 -0700529 VerifyAdaptedResolution(listener_->GetStats(),
530 capture_format_.width, capture_format_.height,
531 request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000532
533 // Adapt the frame resolution.
534 request_format.width /= 2;
535 request_format.height /= 2;
Per766ad3b2016-04-05 15:23:49 +0200536 adapter_.OnOutputFormatRequest(request_format);
Magnus Jedvert01840572015-04-10 11:18:39 +0200537 for (int i = 0; i < 10; ++i)
538 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000539
540 // Verify resolution change after adaptation.
magjed709f73c2016-05-13 10:26:00 -0700541 VerifyAdaptedResolution(listener_->GetStats(),
542 capture_format_.width, capture_format_.height,
543 request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000544}
545
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000546// Drop all frames.
547TEST_F(VideoAdapterTest, DropAllFrames) {
548 VideoFormat format; // with resolution 0x0.
Per766ad3b2016-04-05 15:23:49 +0200549 adapter_.OnOutputFormatRequest(format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000550 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200551 for (int i = 0; i < 10; ++i)
552 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000553
554 // Verify all frames are dropped.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000555 VideoCapturerListener::Stats stats = listener_->GetStats();
556 EXPECT_GE(stats.captured_frames, 10);
557 EXPECT_EQ(stats.captured_frames, stats.dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000558}
559
Per766ad3b2016-04-05 15:23:49 +0200560TEST_F(VideoAdapterTest, TestOnOutputFormatRequest) {
magjed604abe02016-05-19 06:05:40 -0700561 VideoFormat format(640, 400, 0, 0);
nisse47ac4622016-05-25 08:47:01 -0700562 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
563 &cropped_width_, &cropped_height_,
564 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700565 EXPECT_EQ(640, cropped_width_);
566 EXPECT_EQ(400, cropped_height_);
567 EXPECT_EQ(640, out_width_);
568 EXPECT_EQ(400, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000569
Per766ad3b2016-04-05 15:23:49 +0200570 // Format request 640x400.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000571 format.height = 400;
Per766ad3b2016-04-05 15:23:49 +0200572 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700573 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
574 &cropped_width_, &cropped_height_,
575 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700576 EXPECT_EQ(640, cropped_width_);
577 EXPECT_EQ(400, cropped_height_);
578 EXPECT_EQ(640, out_width_);
579 EXPECT_EQ(400, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000580
magjed709f73c2016-05-13 10:26:00 -0700581 // Request 1280x720, higher than input, but aspect 16:9. Expect cropping but
582 // no scaling.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000583 format.width = 1280;
584 format.height = 720;
Per766ad3b2016-04-05 15:23:49 +0200585 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700586 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
587 &cropped_width_, &cropped_height_,
588 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700589 EXPECT_EQ(640, cropped_width_);
590 EXPECT_EQ(360, cropped_height_);
591 EXPECT_EQ(640, out_width_);
592 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000593
Per766ad3b2016-04-05 15:23:49 +0200594 // Request 0x0.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000595 format.width = 0;
596 format.height = 0;
Per766ad3b2016-04-05 15:23:49 +0200597 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700598 EXPECT_FALSE(adapter_.AdaptFrameResolution(640, 400, 0,
599 &cropped_width_, &cropped_height_,
600 &out_width_, &out_height_));
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000601
magjed709f73c2016-05-13 10:26:00 -0700602 // Request 320x200. Expect scaling, but no cropping.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000603 format.width = 320;
604 format.height = 200;
Per766ad3b2016-04-05 15:23:49 +0200605 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700606 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
607 &cropped_width_, &cropped_height_,
608 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700609 EXPECT_EQ(640, cropped_width_);
610 EXPECT_EQ(400, cropped_height_);
611 EXPECT_EQ(320, out_width_);
612 EXPECT_EQ(200, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000613
magjed709f73c2016-05-13 10:26:00 -0700614 // Request resolution close to 2/3 scale. Expect adapt down. Scaling to 2/3
615 // is not optimized and not allowed, therefore 1/2 scaling will be used
616 // instead.
617 format.width = 424;
618 format.height = 265;
Per766ad3b2016-04-05 15:23:49 +0200619 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700620 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
621 &cropped_width_, &cropped_height_,
622 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700623 EXPECT_EQ(640, cropped_width_);
624 EXPECT_EQ(400, cropped_height_);
625 EXPECT_EQ(320, out_width_);
626 EXPECT_EQ(200, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000627
Per766ad3b2016-04-05 15:23:49 +0200628 // Request resolution of 3 / 8. Expect adapt down.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000629 format.width = 640 * 3 / 8;
630 format.height = 400 * 3 / 8;
Per766ad3b2016-04-05 15:23:49 +0200631 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700632 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
633 &cropped_width_, &cropped_height_,
634 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700635 EXPECT_EQ(640, cropped_width_);
636 EXPECT_EQ(400, cropped_height_);
637 EXPECT_EQ(640 * 3 / 8, out_width_);
638 EXPECT_EQ(400 * 3 / 8, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000639
Per766ad3b2016-04-05 15:23:49 +0200640 // Switch back up. Expect adapt.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000641 format.width = 320;
642 format.height = 200;
Per766ad3b2016-04-05 15:23:49 +0200643 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700644 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
645 &cropped_width_, &cropped_height_,
646 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700647 EXPECT_EQ(640, cropped_width_);
648 EXPECT_EQ(400, cropped_height_);
649 EXPECT_EQ(320, out_width_);
650 EXPECT_EQ(200, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000651
Per766ad3b2016-04-05 15:23:49 +0200652 // Format request 480x300.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000653 format.width = 480;
654 format.height = 300;
Per766ad3b2016-04-05 15:23:49 +0200655 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700656 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
657 &cropped_width_, &cropped_height_,
658 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700659 EXPECT_EQ(640, cropped_width_);
660 EXPECT_EQ(400, cropped_height_);
661 EXPECT_EQ(480, out_width_);
662 EXPECT_EQ(300, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000663}
664
Per766ad3b2016-04-05 15:23:49 +0200665TEST_F(VideoAdapterTest, TestViewRequestPlusCameraSwitch) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000666 // Start at HD.
magjed604abe02016-05-19 06:05:40 -0700667 VideoFormat format(1280, 720, 0, 0);
nisse47ac4622016-05-25 08:47:01 -0700668 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
669 &cropped_width_, &cropped_height_,
670 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700671 EXPECT_EQ(1280, cropped_width_);
672 EXPECT_EQ(720, cropped_height_);
673 EXPECT_EQ(1280, out_width_);
674 EXPECT_EQ(720, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000675
Per766ad3b2016-04-05 15:23:49 +0200676 // Format request for VGA.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000677 format.width = 640;
678 format.height = 360;
Per766ad3b2016-04-05 15:23:49 +0200679 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700680 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
681 &cropped_width_, &cropped_height_,
682 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700683 EXPECT_EQ(1280, cropped_width_);
684 EXPECT_EQ(720, cropped_height_);
685 EXPECT_EQ(640, out_width_);
686 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000687
688 // Now, the camera reopens at VGA.
689 // Both the frame and the output format should be 640x360.
nisse47ac4622016-05-25 08:47:01 -0700690 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0,
691 &cropped_width_, &cropped_height_,
692 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700693 EXPECT_EQ(640, cropped_width_);
694 EXPECT_EQ(360, cropped_height_);
695 EXPECT_EQ(640, out_width_);
696 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000697
698 // And another view request comes in for 640x360, which should have no
699 // real impact.
Per766ad3b2016-04-05 15:23:49 +0200700 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700701 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0,
702 &cropped_width_, &cropped_height_,
703 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700704 EXPECT_EQ(640, cropped_width_);
705 EXPECT_EQ(360, cropped_height_);
706 EXPECT_EQ(640, out_width_);
707 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000708}
709
Per766ad3b2016-04-05 15:23:49 +0200710TEST_F(VideoAdapterTest, TestVGAWidth) {
711 // Reqeuested Output format is 640x360.
magjed604abe02016-05-19 06:05:40 -0700712 VideoFormat format(640, 360, 0, FOURCC_I420);
Per766ad3b2016-04-05 15:23:49 +0200713 adapter_.OnOutputFormatRequest(format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000714
nisse47ac4622016-05-25 08:47:01 -0700715 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
716 &cropped_width_, &cropped_height_,
717 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700718 // Expect cropping.
719 EXPECT_EQ(640, cropped_width_);
720 EXPECT_EQ(360, cropped_height_);
721 EXPECT_EQ(640, out_width_);
722 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000723
724 // But if frames come in at 640x360, we shouldn't adapt them down.
nisse47ac4622016-05-25 08:47:01 -0700725 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0,
726 &cropped_width_, &cropped_height_,
727 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700728 EXPECT_EQ(640, cropped_width_);
729 EXPECT_EQ(360, cropped_height_);
730 EXPECT_EQ(640, out_width_);
731 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000732
nisse47ac4622016-05-25 08:47:01 -0700733 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
734 &cropped_width_, &cropped_height_,
735 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700736 EXPECT_EQ(640, cropped_width_);
737 EXPECT_EQ(360, cropped_height_);
738 EXPECT_EQ(640, out_width_);
739 EXPECT_EQ(360, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200740}
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000741
Per766ad3b2016-04-05 15:23:49 +0200742TEST_F(VideoAdapterTest, TestOnResolutionRequestInSmallSteps) {
nisse47ac4622016-05-25 08:47:01 -0700743 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
744 &cropped_width_, &cropped_height_,
745 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700746 EXPECT_EQ(1280, cropped_width_);
747 EXPECT_EQ(720, cropped_height_);
748 EXPECT_EQ(1280, out_width_);
749 EXPECT_EQ(720, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200750
751 // Adapt down one step.
sprangc5d62e22017-04-02 23:53:04 -0700752 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 1280 * 720 - 1,
753 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700754 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
755 &cropped_width_, &cropped_height_,
756 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700757 EXPECT_EQ(1280, cropped_width_);
758 EXPECT_EQ(720, cropped_height_);
759 EXPECT_EQ(960, out_width_);
760 EXPECT_EQ(540, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200761
762 // Adapt down one step more.
sprangc5d62e22017-04-02 23:53:04 -0700763 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 960 * 540 - 1,
764 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700765 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
766 &cropped_width_, &cropped_height_,
767 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700768 EXPECT_EQ(1280, cropped_width_);
769 EXPECT_EQ(720, cropped_height_);
770 EXPECT_EQ(640, out_width_);
771 EXPECT_EQ(360, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200772
773 // Adapt down one step more.
sprangc5d62e22017-04-02 23:53:04 -0700774 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 640 * 360 - 1,
775 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700776 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
777 &cropped_width_, &cropped_height_,
778 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700779 EXPECT_EQ(1280, cropped_width_);
780 EXPECT_EQ(720, cropped_height_);
781 EXPECT_EQ(480, out_width_);
782 EXPECT_EQ(270, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200783
784 // Adapt up one step.
sprangc5d62e22017-04-02 23:53:04 -0700785 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(640 * 360),
786 960 * 540,
787 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700788 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
789 &cropped_width_, &cropped_height_,
790 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700791 EXPECT_EQ(1280, cropped_width_);
792 EXPECT_EQ(720, cropped_height_);
793 EXPECT_EQ(640, out_width_);
794 EXPECT_EQ(360, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200795
796 // Adapt up one step more.
sprangc5d62e22017-04-02 23:53:04 -0700797 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(960 * 540),
798 1280 * 720,
799 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700800 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
801 &cropped_width_, &cropped_height_,
802 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700803 EXPECT_EQ(1280, cropped_width_);
804 EXPECT_EQ(720, cropped_height_);
805 EXPECT_EQ(960, out_width_);
806 EXPECT_EQ(540, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200807
808 // Adapt up one step more.
sprangc5d62e22017-04-02 23:53:04 -0700809 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(1280 * 720),
810 1920 * 1080,
811 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700812 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
813 &cropped_width_, &cropped_height_,
814 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700815 EXPECT_EQ(1280, cropped_width_);
816 EXPECT_EQ(720, cropped_height_);
817 EXPECT_EQ(1280, out_width_);
818 EXPECT_EQ(720, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200819}
820
821TEST_F(VideoAdapterTest, TestOnResolutionRequestMaxZero) {
nisse47ac4622016-05-25 08:47:01 -0700822 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
823 &cropped_width_, &cropped_height_,
824 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700825 EXPECT_EQ(1280, cropped_width_);
826 EXPECT_EQ(720, cropped_height_);
827 EXPECT_EQ(1280, out_width_);
828 EXPECT_EQ(720, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200829
sprangc5d62e22017-04-02 23:53:04 -0700830 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 0,
831 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700832 EXPECT_FALSE(adapter_.AdaptFrameResolution(1280, 720, 0,
833 &cropped_width_, &cropped_height_,
834 &out_width_, &out_height_));
Per766ad3b2016-04-05 15:23:49 +0200835}
836
837TEST_F(VideoAdapterTest, TestOnResolutionRequestInLargeSteps) {
sprang84a37592017-02-10 07:04:27 -0800838 // Large step down.
sprangc5d62e22017-04-02 23:53:04 -0700839 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 640 * 360 - 1,
840 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700841 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
842 &cropped_width_, &cropped_height_,
843 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700844 EXPECT_EQ(1280, cropped_width_);
845 EXPECT_EQ(720, cropped_height_);
846 EXPECT_EQ(480, out_width_);
847 EXPECT_EQ(270, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200848
sprang84a37592017-02-10 07:04:27 -0800849 // Large step up.
sprangc5d62e22017-04-02 23:53:04 -0700850 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(1280 * 720),
851 1920 * 1080,
852 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700853 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
854 &cropped_width_, &cropped_height_,
855 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700856 EXPECT_EQ(1280, cropped_width_);
857 EXPECT_EQ(720, cropped_height_);
858 EXPECT_EQ(1280, out_width_);
859 EXPECT_EQ(720, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200860}
861
862TEST_F(VideoAdapterTest, TestOnOutputFormatRequestCapsMaxResolution) {
sprangc5d62e22017-04-02 23:53:04 -0700863 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 640 * 360 - 1,
864 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700865 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
866 &cropped_width_, &cropped_height_,
867 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700868 EXPECT_EQ(1280, cropped_width_);
869 EXPECT_EQ(720, cropped_height_);
870 EXPECT_EQ(480, out_width_);
871 EXPECT_EQ(270, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200872
magjed604abe02016-05-19 06:05:40 -0700873 VideoFormat new_format(640, 360, 0, FOURCC_I420);
Per766ad3b2016-04-05 15:23:49 +0200874 adapter_.OnOutputFormatRequest(new_format);
nisse47ac4622016-05-25 08:47:01 -0700875 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
876 &cropped_width_, &cropped_height_,
877 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700878 EXPECT_EQ(1280, cropped_width_);
879 EXPECT_EQ(720, cropped_height_);
880 EXPECT_EQ(480, out_width_);
881 EXPECT_EQ(270, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200882
sprangc5d62e22017-04-02 23:53:04 -0700883 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 960 * 720,
884 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700885 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
886 &cropped_width_, &cropped_height_,
887 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700888 EXPECT_EQ(1280, cropped_width_);
889 EXPECT_EQ(720, cropped_height_);
890 EXPECT_EQ(640, out_width_);
891 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000892}
893
Per766ad3b2016-04-05 15:23:49 +0200894TEST_F(VideoAdapterTest, TestOnResolutionRequestReset) {
nisse47ac4622016-05-25 08:47:01 -0700895 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
896 &cropped_width_, &cropped_height_,
897 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700898 EXPECT_EQ(1280, cropped_width_);
899 EXPECT_EQ(720, cropped_height_);
900 EXPECT_EQ(1280, out_width_);
901 EXPECT_EQ(720, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000902
sprangc5d62e22017-04-02 23:53:04 -0700903 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 640 * 360 - 1,
904 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700905 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
906 &cropped_width_, &cropped_height_,
907 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700908 EXPECT_EQ(1280, cropped_width_);
909 EXPECT_EQ(720, cropped_height_);
910 EXPECT_EQ(480, out_width_);
911 EXPECT_EQ(270, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000912
sprangc5d62e22017-04-02 23:53:04 -0700913 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(),
914 std::numeric_limits<int>::max(),
915 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700916 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
917 &cropped_width_, &cropped_height_,
918 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700919 EXPECT_EQ(1280, cropped_width_);
920 EXPECT_EQ(720, cropped_height_);
921 EXPECT_EQ(1280, out_width_);
922 EXPECT_EQ(720, out_height_);
923}
924
925TEST_F(VideoAdapterTest, TestCroppingWithResolutionRequest) {
926 // Ask for 640x360 (16:9 aspect).
magjed604abe02016-05-19 06:05:40 -0700927 adapter_.OnOutputFormatRequest(VideoFormat(640, 360, 0, FOURCC_I420));
magjed709f73c2016-05-13 10:26:00 -0700928 // Send 640x480 (4:3 aspect).
nisse47ac4622016-05-25 08:47:01 -0700929 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
930 &cropped_width_, &cropped_height_,
931 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700932 // Expect cropping to 16:9 format and no scaling.
933 EXPECT_EQ(640, cropped_width_);
934 EXPECT_EQ(360, cropped_height_);
935 EXPECT_EQ(640, out_width_);
936 EXPECT_EQ(360, out_height_);
937
938 // Adapt down one step.
sprangc5d62e22017-04-02 23:53:04 -0700939 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 640 * 360 - 1,
940 std::numeric_limits<int>::max());
magjed709f73c2016-05-13 10:26:00 -0700941 // Expect cropping to 16:9 format and 3/4 scaling.
nisse47ac4622016-05-25 08:47:01 -0700942 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
943 &cropped_width_, &cropped_height_,
944 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700945 EXPECT_EQ(640, cropped_width_);
946 EXPECT_EQ(360, cropped_height_);
947 EXPECT_EQ(480, out_width_);
948 EXPECT_EQ(270, out_height_);
949
950 // Adapt down one step more.
sprangc5d62e22017-04-02 23:53:04 -0700951 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 480 * 270 - 1,
952 std::numeric_limits<int>::max());
magjed709f73c2016-05-13 10:26:00 -0700953 // Expect cropping to 16:9 format and 1/2 scaling.
nisse47ac4622016-05-25 08:47:01 -0700954 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
955 &cropped_width_, &cropped_height_,
956 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700957 EXPECT_EQ(640, cropped_width_);
958 EXPECT_EQ(360, cropped_height_);
959 EXPECT_EQ(320, out_width_);
960 EXPECT_EQ(180, out_height_);
961
962 // Adapt up one step.
sprangc5d62e22017-04-02 23:53:04 -0700963 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(480 * 270),
964 640 * 360,
965 std::numeric_limits<int>::max());
magjed709f73c2016-05-13 10:26:00 -0700966 // Expect cropping to 16:9 format and 3/4 scaling.
nisse47ac4622016-05-25 08:47:01 -0700967 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
968 &cropped_width_, &cropped_height_,
969 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700970 EXPECT_EQ(640, cropped_width_);
971 EXPECT_EQ(360, cropped_height_);
972 EXPECT_EQ(480, out_width_);
973 EXPECT_EQ(270, out_height_);
974
975 // Adapt up one step more.
sprangc5d62e22017-04-02 23:53:04 -0700976 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(640 * 360),
977 960 * 540,
978 std::numeric_limits<int>::max());
magjed709f73c2016-05-13 10:26:00 -0700979 // Expect cropping to 16:9 format and no scaling.
nisse47ac4622016-05-25 08:47:01 -0700980 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
981 &cropped_width_, &cropped_height_,
982 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700983 EXPECT_EQ(640, cropped_width_);
984 EXPECT_EQ(360, cropped_height_);
985 EXPECT_EQ(640, out_width_);
986 EXPECT_EQ(360, out_height_);
987
988 // Try to adapt up one step more.
sprangc5d62e22017-04-02 23:53:04 -0700989 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(960 * 540),
990 1280 * 720,
991 std::numeric_limits<int>::max());
magjed709f73c2016-05-13 10:26:00 -0700992 // Expect cropping to 16:9 format and no scaling.
nisse47ac4622016-05-25 08:47:01 -0700993 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
994 &cropped_width_, &cropped_height_,
995 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700996 EXPECT_EQ(640, cropped_width_);
997 EXPECT_EQ(360, cropped_height_);
998 EXPECT_EQ(640, out_width_);
999 EXPECT_EQ(360, out_height_);
1000}
1001
1002TEST_F(VideoAdapterTest, TestCroppingOddResolution) {
1003 // Ask for 640x360 (16:9 aspect), with 3/16 scaling.
magjed709f73c2016-05-13 10:26:00 -07001004 adapter_.OnOutputFormatRequest(
magjed604abe02016-05-19 06:05:40 -07001005 VideoFormat(640, 360, 0, FOURCC_I420));
sprangc5d62e22017-04-02 23:53:04 -07001006 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(),
1007 640 * 360 * 3 / 16 * 3 / 16,
1008 std::numeric_limits<int>::max());
magjed709f73c2016-05-13 10:26:00 -07001009
1010 // Send 640x480 (4:3 aspect).
nisse47ac4622016-05-25 08:47:01 -07001011 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
1012 &cropped_width_, &cropped_height_,
1013 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -07001014
1015 // Instead of getting the exact aspect ratio with cropped resolution 640x360,
1016 // the resolution should be adjusted to get a perfect scale factor instead.
1017 EXPECT_EQ(640, cropped_width_);
1018 EXPECT_EQ(368, cropped_height_);
1019 EXPECT_EQ(120, out_width_);
1020 EXPECT_EQ(69, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00001021}
1022
kthelgasonc8474172016-12-08 08:04:51 -08001023TEST_F(VideoAdapterTest, TestAdaptToVerySmallResolution) {
1024 // Ask for 1920x1080 (16:9 aspect), with 1/16 scaling.
1025 const int w = 1920;
1026 const int h = 1080;
1027 adapter_.OnOutputFormatRequest(VideoFormat(w, h, 0, FOURCC_I420));
sprangc5d62e22017-04-02 23:53:04 -07001028 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(),
1029 w * h * 1 / 16 * 1 / 16,
1030 std::numeric_limits<int>::max());
kthelgasonc8474172016-12-08 08:04:51 -08001031
1032 // Send 1920x1080 (16:9 aspect).
1033 EXPECT_TRUE(adapter_.AdaptFrameResolution(
1034 w, h, 0, &cropped_width_, &cropped_height_, &out_width_, &out_height_));
1035
1036 // Instead of getting the exact aspect ratio with cropped resolution 1920x1080
1037 // the resolution should be adjusted to get a perfect scale factor instead.
1038 EXPECT_EQ(1920, cropped_width_);
1039 EXPECT_EQ(1072, cropped_height_);
1040 EXPECT_EQ(120, out_width_);
1041 EXPECT_EQ(67, out_height_);
1042
1043 // Adapt back up one step to 3/32.
sprangc5d62e22017-04-02 23:53:04 -07001044 adapter_.OnResolutionFramerateRequest(
1045 rtc::Optional<int>(w * h * 3 / 32 * 3 / 32), w * h * 1 / 8 * 1 / 8,
1046 std::numeric_limits<int>::max());
kthelgasonc8474172016-12-08 08:04:51 -08001047
1048 // Send 1920x1080 (16:9 aspect).
1049 EXPECT_TRUE(adapter_.AdaptFrameResolution(
1050 w, h, 0, &cropped_width_, &cropped_height_, &out_width_, &out_height_));
1051
1052 EXPECT_EQ(180, out_width_);
1053 EXPECT_EQ(99, out_height_);
1054}
1055
1056TEST_F(VideoAdapterTest, AdaptFrameResolutionDropWithResolutionRequest) {
1057 VideoFormat output_format = capture_format_;
1058 output_format.width = 0;
1059 output_format.height = 0;
1060 adapter_.OnOutputFormatRequest(output_format);
1061 EXPECT_FALSE(adapter_.AdaptFrameResolution(
1062 capture_format_.width, capture_format_.height, 0,
1063 &cropped_width_, &cropped_height_,
1064 &out_width_, &out_height_));
1065
sprangc5d62e22017-04-02 23:53:04 -07001066 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(960 * 540),
1067 std::numeric_limits<int>::max(),
1068 std::numeric_limits<int>::max());
kthelgasonc8474172016-12-08 08:04:51 -08001069
1070 // Still expect all frames to be dropped
1071 EXPECT_FALSE(adapter_.AdaptFrameResolution(
1072 capture_format_.width, capture_format_.height, 0,
1073 &cropped_width_, &cropped_height_,
1074 &out_width_, &out_height_));
1075
sprangc5d62e22017-04-02 23:53:04 -07001076 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 640 * 480 - 1,
1077 std::numeric_limits<int>::max());
kthelgasonc8474172016-12-08 08:04:51 -08001078
1079 // Still expect all frames to be dropped
1080 EXPECT_FALSE(adapter_.AdaptFrameResolution(
1081 capture_format_.width, capture_format_.height, 0,
1082 &cropped_width_, &cropped_height_,
1083 &out_width_, &out_height_));
1084}
1085
Magnus Jedvert6d230d72017-02-22 18:30:27 +01001086// Test that we will adapt to max given a target pixel count close to max.
1087TEST_F(VideoAdapterTest, TestAdaptToMax) {
1088 adapter_.OnOutputFormatRequest(VideoFormat(640, 360, 0, FOURCC_I420));
sprangc5d62e22017-04-02 23:53:04 -07001089 adapter_.OnResolutionFramerateRequest(
1090 rtc::Optional<int>(640 * 360 - 1) /* target */,
1091 std::numeric_limits<int>::max(), std::numeric_limits<int>::max());
Magnus Jedvert6d230d72017-02-22 18:30:27 +01001092
1093 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0, &cropped_width_,
1094 &cropped_height_, &out_width_,
1095 &out_height_));
1096 EXPECT_EQ(640, out_width_);
1097 EXPECT_EQ(360, out_height_);
1098}
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00001099} // namespace cricket