blob: 522cd5ddea6f3e72a2f0854d46bfce0f5948e1c7 [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
Steve Antone78bcb92017-10-31 09:53:08 -070013#include <limits>
kwibergbfefb032016-05-01 14:53:46 -070014#include <memory>
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000015#include <string>
16#include <vector>
17
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "media/base/fakevideocapturer.h"
19#include "media/base/mediachannel.h"
20#include "media/base/testutils.h"
21#include "media/base/videoadapter.h"
22#include "rtc_base/gunit.h"
23#include "rtc_base/logging.h"
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000024
25namespace cricket {
sprangc5d62e22017-04-02 23:53:04 -070026namespace {
27const int kDefaultFps = 30;
28} // namespace
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000029
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000030class VideoAdapterTest : public testing::Test {
31 public:
32 virtual void SetUp() {
Magnus Jedvert01840572015-04-10 11:18:39 +020033 capturer_.reset(new FakeVideoCapturer);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000034 capture_format_ = capturer_->GetSupportedFormats()->at(0);
sprangc5d62e22017-04-02 23:53:04 -070035 capture_format_.interval = VideoFormat::FpsToInterval(kDefaultFps);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000036
Per766ad3b2016-04-05 15:23:49 +020037 listener_.reset(new VideoCapturerListener(&adapter_));
nissef5297a02016-09-30 01:34:27 -070038 capturer_->AddOrUpdateSink(listener_.get(), rtc::VideoSinkWants());
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000039 }
40
pbos@webrtc.org75c3ec12014-08-27 18:16:13 +000041 virtual void TearDown() {
42 // Explicitly disconnect the VideoCapturer before to avoid data races
43 // (frames delivered to VideoCapturerListener while it's being destructed).
nissef5297a02016-09-30 01:34:27 -070044 capturer_->RemoveSink(listener_.get());
pbos@webrtc.org75c3ec12014-08-27 18:16:13 +000045 }
46
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000047 protected:
nissef5297a02016-09-30 01:34:27 -070048 class VideoCapturerListener
nisseacd935b2016-11-11 03:55:13 -080049 : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000050 public:
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000051 struct Stats {
52 int captured_frames;
53 int dropped_frames;
54 bool last_adapt_was_no_op;
55
magjed709f73c2016-05-13 10:26:00 -070056 int cropped_width;
57 int cropped_height;
58 int out_width;
59 int out_height;
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000060 };
61
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000062 explicit VideoCapturerListener(VideoAdapter* adapter)
63 : video_adapter_(adapter),
sprang84a37592017-02-10 07:04:27 -080064 cropped_width_(0),
65 cropped_height_(0),
66 out_width_(0),
67 out_height_(0),
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000068 captured_frames_(0),
69 dropped_frames_(0),
sprang84a37592017-02-10 07:04:27 -080070 last_adapt_was_no_op_(false) {}
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000071
nisseacd935b2016-11-11 03:55:13 -080072 void OnFrame(const webrtc::VideoFrame& frame) {
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000073 rtc::CritScope lock(&crit_);
nissef5297a02016-09-30 01:34:27 -070074 const int in_width = frame.width();
75 const int in_height = frame.height();
magjed709f73c2016-05-13 10:26:00 -070076 int cropped_width;
77 int cropped_height;
78 int out_width;
79 int out_height;
nissef5297a02016-09-30 01:34:27 -070080 if (video_adapter_->AdaptFrameResolution(
81 in_width, in_height,
82 frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec,
83 &cropped_width, &cropped_height, &out_width, &out_height)) {
magjed709f73c2016-05-13 10:26:00 -070084 cropped_width_ = cropped_width;
85 cropped_height_ = cropped_height;
86 out_width_ = out_width;
87 out_height_ = out_height;
88 last_adapt_was_no_op_ =
89 (in_width == cropped_width && in_height == cropped_height &&
90 in_width == out_width && in_height == out_height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000091 } else {
92 ++dropped_frames_;
93 }
94 ++captured_frames_;
95 }
96
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000097 Stats GetStats() {
98 rtc::CritScope lock(&crit_);
99 Stats stats;
100 stats.captured_frames = captured_frames_;
101 stats.dropped_frames = dropped_frames_;
102 stats.last_adapt_was_no_op = last_adapt_was_no_op_;
magjed709f73c2016-05-13 10:26:00 -0700103 stats.cropped_width = cropped_width_;
104 stats.cropped_height = cropped_height_;
105 stats.out_width = out_width_;
106 stats.out_height = out_height_;
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000107 return stats;
108 }
109
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000110 private:
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000111 rtc::CriticalSection crit_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000112 VideoAdapter* video_adapter_;
magjed709f73c2016-05-13 10:26:00 -0700113 int cropped_width_;
114 int cropped_height_;
115 int out_width_;
116 int out_height_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000117 int captured_frames_;
118 int dropped_frames_;
119 bool last_adapt_was_no_op_;
120 };
121
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000122
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000123 void VerifyAdaptedResolution(const VideoCapturerListener::Stats& stats,
magjed709f73c2016-05-13 10:26:00 -0700124 int cropped_width,
125 int cropped_height,
126 int out_width,
127 int out_height) {
128 EXPECT_EQ(cropped_width, stats.cropped_width);
129 EXPECT_EQ(cropped_height, stats.cropped_height);
130 EXPECT_EQ(out_width, stats.out_width);
131 EXPECT_EQ(out_height, stats.out_height);
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000132 }
133
kwiberg686a8ef2016-02-26 03:00:35 -0800134 std::unique_ptr<FakeVideoCapturer> capturer_;
Per766ad3b2016-04-05 15:23:49 +0200135 VideoAdapter adapter_;
magjed709f73c2016-05-13 10:26:00 -0700136 int cropped_width_;
137 int cropped_height_;
138 int out_width_;
139 int out_height_;
kwiberg686a8ef2016-02-26 03:00:35 -0800140 std::unique_ptr<VideoCapturerListener> listener_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000141 VideoFormat capture_format_;
142};
143
magjed709f73c2016-05-13 10:26:00 -0700144// Do not adapt the frame rate or the resolution. Expect no frame drop, no
145// cropping, and no resolution change.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000146TEST_F(VideoAdapterTest, AdaptNothing) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000147 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200148 for (int i = 0; i < 10; ++i)
149 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000150
151 // Verify no frame drop and no resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000152 VideoCapturerListener::Stats stats = listener_->GetStats();
153 EXPECT_GE(stats.captured_frames, 10);
154 EXPECT_EQ(0, stats.dropped_frames);
magjed709f73c2016-05-13 10:26:00 -0700155 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
156 capture_format_.width, capture_format_.height);
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000157 EXPECT_TRUE(stats.last_adapt_was_no_op);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000158}
159
160TEST_F(VideoAdapterTest, AdaptZeroInterval) {
161 VideoFormat format = capturer_->GetSupportedFormats()->at(0);
162 format.interval = 0;
Per766ad3b2016-04-05 15:23:49 +0200163 adapter_.OnOutputFormatRequest(format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000164 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200165 for (int i = 0; i < 10; ++i)
166 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000167
168 // Verify no crash and that frames aren't dropped.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000169 VideoCapturerListener::Stats stats = listener_->GetStats();
170 EXPECT_GE(stats.captured_frames, 10);
171 EXPECT_EQ(0, stats.dropped_frames);
magjed709f73c2016-05-13 10:26:00 -0700172 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
173 capture_format_.width, capture_format_.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000174}
175
176// Adapt the frame rate to be half of the capture rate at the beginning. Expect
177// the number of dropped frames to be half of the number the captured frames.
magjed604abe02016-05-19 06:05:40 -0700178TEST_F(VideoAdapterTest, AdaptFramerateToHalf) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000179 VideoFormat request_format = capture_format_;
180 request_format.interval *= 2;
Per766ad3b2016-04-05 15:23:49 +0200181 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000182 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
magjed604abe02016-05-19 06:05:40 -0700183
184 // Capture 10 frames and verify that every other frame is dropped. The first
185 // frame should not be dropped.
186 capturer_->CaptureFrame();
187 EXPECT_GE(listener_->GetStats().captured_frames, 1);
188 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
189
190 capturer_->CaptureFrame();
191 EXPECT_GE(listener_->GetStats().captured_frames, 2);
nissef5297a02016-09-30 01:34:27 -0700192 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700193
194 capturer_->CaptureFrame();
195 EXPECT_GE(listener_->GetStats().captured_frames, 3);
196 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
197
198 capturer_->CaptureFrame();
199 EXPECT_GE(listener_->GetStats().captured_frames, 4);
nissef5297a02016-09-30 01:34:27 -0700200 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700201
202 capturer_->CaptureFrame();
203 EXPECT_GE(listener_->GetStats().captured_frames, 5);
204 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
205
206 capturer_->CaptureFrame();
207 EXPECT_GE(listener_->GetStats().captured_frames, 6);
nissef5297a02016-09-30 01:34:27 -0700208 EXPECT_EQ(3, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700209
210 capturer_->CaptureFrame();
211 EXPECT_GE(listener_->GetStats().captured_frames, 7);
212 EXPECT_EQ(3, listener_->GetStats().dropped_frames);
213
214 capturer_->CaptureFrame();
215 EXPECT_GE(listener_->GetStats().captured_frames, 8);
nissef5297a02016-09-30 01:34:27 -0700216 EXPECT_EQ(4, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700217
218 capturer_->CaptureFrame();
219 EXPECT_GE(listener_->GetStats().captured_frames, 9);
220 EXPECT_EQ(4, listener_->GetStats().dropped_frames);
221
222 capturer_->CaptureFrame();
223 EXPECT_GE(listener_->GetStats().captured_frames, 10);
nissef5297a02016-09-30 01:34:27 -0700224 EXPECT_EQ(5, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700225}
226
227// Adapt the frame rate to be two thirds of the capture rate at the beginning.
228// Expect the number of dropped frames to be one thirds of the number the
229// captured frames.
230TEST_F(VideoAdapterTest, AdaptFramerateToTwoThirds) {
231 VideoFormat request_format = capture_format_;
232 request_format.interval = request_format.interval * 3 / 2;
233 adapter_.OnOutputFormatRequest(request_format);
234 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
235
236 // Capture 10 frames and verify that every third frame is dropped. The first
237 // frame should not be dropped.
238 capturer_->CaptureFrame();
239 EXPECT_GE(listener_->GetStats().captured_frames, 1);
240 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
241
242 capturer_->CaptureFrame();
243 EXPECT_GE(listener_->GetStats().captured_frames, 2);
244 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
245
246 capturer_->CaptureFrame();
247 EXPECT_GE(listener_->GetStats().captured_frames, 3);
248 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
249
250 capturer_->CaptureFrame();
251 EXPECT_GE(listener_->GetStats().captured_frames, 4);
252 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
253
254 capturer_->CaptureFrame();
255 EXPECT_GE(listener_->GetStats().captured_frames, 5);
256 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
257
258 capturer_->CaptureFrame();
259 EXPECT_GE(listener_->GetStats().captured_frames, 6);
260 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
261
262 capturer_->CaptureFrame();
263 EXPECT_GE(listener_->GetStats().captured_frames, 7);
264 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
265
266 capturer_->CaptureFrame();
267 EXPECT_GE(listener_->GetStats().captured_frames, 8);
268 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
269
270 capturer_->CaptureFrame();
271 EXPECT_GE(listener_->GetStats().captured_frames, 9);
272 EXPECT_EQ(3, listener_->GetStats().dropped_frames);
273
274 capturer_->CaptureFrame();
275 EXPECT_GE(listener_->GetStats().captured_frames, 10);
276 EXPECT_EQ(3, listener_->GetStats().dropped_frames);
277}
278
279// Request frame rate twice as high as captured frame rate. Expect no frame
280// drop.
281TEST_F(VideoAdapterTest, AdaptFramerateHighLimit) {
282 VideoFormat request_format = capture_format_;
283 request_format.interval /= 2;
284 adapter_.OnOutputFormatRequest(request_format);
285 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200286 for (int i = 0; i < 10; ++i)
287 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000288
magjed604abe02016-05-19 06:05:40 -0700289 // Verify no frame drop.
290 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000291}
292
magjed604abe02016-05-19 06:05:40 -0700293// After the first timestamp, add a big offset to the timestamps. Expect that
294// the adapter is conservative and resets to the new offset and does not drop
295// any frame.
296TEST_F(VideoAdapterTest, AdaptFramerateTimestampOffset) {
sprangc5d62e22017-04-02 23:53:04 -0700297 const int64_t capture_interval = VideoFormat::FpsToInterval(kDefaultFps);
magjed604abe02016-05-19 06:05:40 -0700298 adapter_.OnOutputFormatRequest(
299 VideoFormat(640, 480, capture_interval, cricket::FOURCC_ANY));
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000300
magjed604abe02016-05-19 06:05:40 -0700301 const int64_t first_timestamp = 0;
302 adapter_.AdaptFrameResolution(640, 480, first_timestamp,
303 &cropped_width_, &cropped_height_,
304 &out_width_, &out_height_);
305 EXPECT_GT(out_width_, 0);
306 EXPECT_GT(out_height_, 0);
307
308 const int64_t big_offset = -987654321LL * 1000;
309 const int64_t second_timestamp = big_offset;
310 adapter_.AdaptFrameResolution(640, 480, second_timestamp,
311 &cropped_width_, &cropped_height_,
312 &out_width_, &out_height_);
313 EXPECT_GT(out_width_, 0);
314 EXPECT_GT(out_height_, 0);
315
316 const int64_t third_timestamp = big_offset + capture_interval;
317 adapter_.AdaptFrameResolution(640, 480, third_timestamp,
318 &cropped_width_, &cropped_height_,
319 &out_width_, &out_height_);
320 EXPECT_GT(out_width_, 0);
321 EXPECT_GT(out_height_, 0);
322}
323
324// Request 30 fps and send 30 fps with jitter. Expect that no frame is dropped.
325TEST_F(VideoAdapterTest, AdaptFramerateTimestampJitter) {
sprangc5d62e22017-04-02 23:53:04 -0700326 const int64_t capture_interval = VideoFormat::FpsToInterval(kDefaultFps);
magjed604abe02016-05-19 06:05:40 -0700327 adapter_.OnOutputFormatRequest(
328 VideoFormat(640, 480, capture_interval, cricket::FOURCC_ANY));
329
330 adapter_.AdaptFrameResolution(640, 480, capture_interval * 0 / 10,
331 &cropped_width_, &cropped_height_,
332 &out_width_, &out_height_);
333 EXPECT_GT(out_width_, 0);
334 EXPECT_GT(out_height_, 0);
335
336 adapter_.AdaptFrameResolution(640, 480, capture_interval * 10 / 10 - 1,
337 &cropped_width_, &cropped_height_,
338 &out_width_, &out_height_);
339 EXPECT_GT(out_width_, 0);
340 EXPECT_GT(out_height_, 0);
341
342 adapter_.AdaptFrameResolution(640, 480, capture_interval * 25 / 10,
343 &cropped_width_, &cropped_height_,
344 &out_width_, &out_height_);
345 EXPECT_GT(out_width_, 0);
346 EXPECT_GT(out_height_, 0);
347
348 adapter_.AdaptFrameResolution(640, 480, capture_interval * 30 / 10,
349 &cropped_width_, &cropped_height_,
350 &out_width_, &out_height_);
351 EXPECT_GT(out_width_, 0);
352 EXPECT_GT(out_height_, 0);
353
354 adapter_.AdaptFrameResolution(640, 480, capture_interval * 35 / 10,
355 &cropped_width_, &cropped_height_,
356 &out_width_, &out_height_);
357 EXPECT_GT(out_width_, 0);
358 EXPECT_GT(out_height_, 0);
359
360 adapter_.AdaptFrameResolution(640, 480, capture_interval * 50 / 10,
361 &cropped_width_, &cropped_height_,
362 &out_width_, &out_height_);
363 EXPECT_GT(out_width_, 0);
364 EXPECT_GT(out_height_, 0);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000365}
366
367// Adapt the frame rate to be half of the capture rate after capturing no less
368// than 10 frames. Expect no frame dropped before adaptation and frame dropped
369// after adaptation.
370TEST_F(VideoAdapterTest, AdaptFramerateOntheFly) {
371 VideoFormat request_format = capture_format_;
Per766ad3b2016-04-05 15:23:49 +0200372 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000373 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200374 for (int i = 0; i < 10; ++i)
375 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000376
377 // Verify no frame drop before adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000378 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000379
380 // Adapat the frame rate.
381 request_format.interval *= 2;
Per766ad3b2016-04-05 15:23:49 +0200382 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000383
Magnus Jedvert01840572015-04-10 11:18:39 +0200384 for (int i = 0; i < 20; ++i)
385 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000386
387 // Verify frame drop after adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000388 EXPECT_GT(listener_->GetStats().dropped_frames, 0);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000389}
390
sprangc5d62e22017-04-02 23:53:04 -0700391// Do not adapt the frame rate or the resolution. Expect no frame drop, no
392// cropping, and no resolution change.
393TEST_F(VideoAdapterTest, OnFramerateRequestMax) {
394 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(),
395 std::numeric_limits<int>::max(),
396 std::numeric_limits<int>::max());
397
398 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
399 for (int i = 0; i < 10; ++i)
400 capturer_->CaptureFrame();
401
402 // Verify no frame drop and no resolution change.
403 VideoCapturerListener::Stats stats = listener_->GetStats();
404 EXPECT_GE(stats.captured_frames, 10);
405 EXPECT_EQ(0, stats.dropped_frames);
406 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
407 capture_format_.width, capture_format_.height);
408 EXPECT_TRUE(stats.last_adapt_was_no_op);
409}
410
411TEST_F(VideoAdapterTest, OnFramerateRequestZero) {
412 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(),
413 std::numeric_limits<int>::max(), 0);
414 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
415 for (int i = 0; i < 10; ++i)
416 capturer_->CaptureFrame();
417
418 // Verify no crash and that frames aren't dropped.
419 VideoCapturerListener::Stats stats = listener_->GetStats();
420 EXPECT_GE(stats.captured_frames, 10);
421 EXPECT_EQ(10, stats.dropped_frames);
422}
423
424// Adapt the frame rate to be half of the capture rate at the beginning. Expect
425// the number of dropped frames to be half of the number the captured frames.
426TEST_F(VideoAdapterTest, OnFramerateRequestHalf) {
427 adapter_.OnResolutionFramerateRequest(
428 rtc::Optional<int>(), std::numeric_limits<int>::max(), kDefaultFps / 2);
429 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
430 for (int i = 0; i < 10; ++i)
431 capturer_->CaptureFrame();
432
433 // Verify no crash and that frames aren't dropped.
434 VideoCapturerListener::Stats stats = listener_->GetStats();
435 EXPECT_GE(stats.captured_frames, 10);
436 EXPECT_EQ(5, stats.dropped_frames);
437 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
438 capture_format_.width, capture_format_.height);
439}
440
magjed709f73c2016-05-13 10:26:00 -0700441// Set a very high output pixel resolution. Expect no cropping or resolution
442// change.
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000443TEST_F(VideoAdapterTest, AdaptFrameResolutionHighLimit) {
Per766ad3b2016-04-05 15:23:49 +0200444 VideoFormat output_format = capture_format_;
magjed709f73c2016-05-13 10:26:00 -0700445 output_format.width *= 10;
446 output_format.height *= 10;
Per766ad3b2016-04-05 15:23:49 +0200447 adapter_.OnOutputFormatRequest(output_format);
nisse47ac4622016-05-25 08:47:01 -0700448 EXPECT_TRUE(adapter_.AdaptFrameResolution(
449 capture_format_.width, capture_format_.height, 0,
450 &cropped_width_, &cropped_height_,
451 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700452 EXPECT_EQ(capture_format_.width, cropped_width_);
453 EXPECT_EQ(capture_format_.height, cropped_height_);
454 EXPECT_EQ(capture_format_.width, out_width_);
455 EXPECT_EQ(capture_format_.height, out_height_);
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000456}
457
458// Adapt the frame resolution to be the same as capture resolution. Expect no
magjed709f73c2016-05-13 10:26:00 -0700459// cropping or resolution change.
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000460TEST_F(VideoAdapterTest, AdaptFrameResolutionIdentical) {
Per766ad3b2016-04-05 15:23:49 +0200461 adapter_.OnOutputFormatRequest(capture_format_);
nisse47ac4622016-05-25 08:47:01 -0700462 EXPECT_TRUE(adapter_.AdaptFrameResolution(
463 capture_format_.width, capture_format_.height, 0,
464 &cropped_width_, &cropped_height_,
465 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700466 EXPECT_EQ(capture_format_.width, cropped_width_);
467 EXPECT_EQ(capture_format_.height, cropped_height_);
468 EXPECT_EQ(capture_format_.width, out_width_);
469 EXPECT_EQ(capture_format_.height, out_height_);
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000470}
471
472// Adapt the frame resolution to be a quarter of the capture resolution. Expect
magjed709f73c2016-05-13 10:26:00 -0700473// no cropping, but a resolution change.
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000474TEST_F(VideoAdapterTest, AdaptFrameResolutionQuarter) {
475 VideoFormat request_format = capture_format_;
476 request_format.width /= 2;
477 request_format.height /= 2;
Per766ad3b2016-04-05 15:23:49 +0200478 adapter_.OnOutputFormatRequest(request_format);
nisse47ac4622016-05-25 08:47:01 -0700479 EXPECT_TRUE(adapter_.AdaptFrameResolution(
480 capture_format_.width, capture_format_.height, 0,
481 &cropped_width_, &cropped_height_,
482 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700483 EXPECT_EQ(capture_format_.width, cropped_width_);
484 EXPECT_EQ(capture_format_.height, cropped_height_);
485 EXPECT_EQ(request_format.width, out_width_);
486 EXPECT_EQ(request_format.height, out_height_);
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000487}
488
489// Adapt the pixel resolution to 0. Expect frame drop.
490TEST_F(VideoAdapterTest, AdaptFrameResolutionDrop) {
Per766ad3b2016-04-05 15:23:49 +0200491 VideoFormat output_format = capture_format_;
492 output_format.width = 0;
493 output_format.height = 0;
494 adapter_.OnOutputFormatRequest(output_format);
nisse47ac4622016-05-25 08:47:01 -0700495 EXPECT_FALSE(adapter_.AdaptFrameResolution(
496 capture_format_.width, capture_format_.height, 0,
497 &cropped_width_, &cropped_height_,
498 &out_width_, &out_height_));
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000499}
500
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000501// Adapt the frame resolution to be a quarter of the capture resolution at the
magjed709f73c2016-05-13 10:26:00 -0700502// beginning. Expect no cropping but a resolution change.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000503TEST_F(VideoAdapterTest, AdaptResolution) {
504 VideoFormat request_format = capture_format_;
505 request_format.width /= 2;
506 request_format.height /= 2;
Per766ad3b2016-04-05 15:23:49 +0200507 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000508 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200509 for (int i = 0; i < 10; ++i)
510 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000511
magjed709f73c2016-05-13 10:26:00 -0700512 // Verify no frame drop, no cropping, and resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000513 VideoCapturerListener::Stats stats = listener_->GetStats();
514 EXPECT_EQ(0, stats.dropped_frames);
magjed709f73c2016-05-13 10:26:00 -0700515 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
516 request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000517}
518
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000519// Adapt the frame resolution to be a quarter of the capture resolution after
520// capturing no less than 10 frames. Expect no resolution change before
521// adaptation and resolution change after adaptation.
522TEST_F(VideoAdapterTest, AdaptResolutionOnTheFly) {
523 VideoFormat request_format = capture_format_;
Per766ad3b2016-04-05 15:23:49 +0200524 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000525 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200526 for (int i = 0; i < 10; ++i)
527 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000528
529 // Verify no resolution change before adaptation.
magjed709f73c2016-05-13 10:26:00 -0700530 VerifyAdaptedResolution(listener_->GetStats(),
531 capture_format_.width, capture_format_.height,
532 request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000533
534 // Adapt the frame resolution.
535 request_format.width /= 2;
536 request_format.height /= 2;
Per766ad3b2016-04-05 15:23:49 +0200537 adapter_.OnOutputFormatRequest(request_format);
Magnus Jedvert01840572015-04-10 11:18:39 +0200538 for (int i = 0; i < 10; ++i)
539 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000540
541 // Verify resolution change after adaptation.
magjed709f73c2016-05-13 10:26:00 -0700542 VerifyAdaptedResolution(listener_->GetStats(),
543 capture_format_.width, capture_format_.height,
544 request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000545}
546
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000547// Drop all frames.
548TEST_F(VideoAdapterTest, DropAllFrames) {
549 VideoFormat format; // with resolution 0x0.
Per766ad3b2016-04-05 15:23:49 +0200550 adapter_.OnOutputFormatRequest(format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000551 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200552 for (int i = 0; i < 10; ++i)
553 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000554
555 // Verify all frames are dropped.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000556 VideoCapturerListener::Stats stats = listener_->GetStats();
557 EXPECT_GE(stats.captured_frames, 10);
558 EXPECT_EQ(stats.captured_frames, stats.dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000559}
560
Per766ad3b2016-04-05 15:23:49 +0200561TEST_F(VideoAdapterTest, TestOnOutputFormatRequest) {
magjed604abe02016-05-19 06:05:40 -0700562 VideoFormat format(640, 400, 0, 0);
nisse47ac4622016-05-25 08:47:01 -0700563 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
564 &cropped_width_, &cropped_height_,
565 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700566 EXPECT_EQ(640, cropped_width_);
567 EXPECT_EQ(400, cropped_height_);
568 EXPECT_EQ(640, out_width_);
569 EXPECT_EQ(400, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000570
Per766ad3b2016-04-05 15:23:49 +0200571 // Format request 640x400.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000572 format.height = 400;
Per766ad3b2016-04-05 15:23:49 +0200573 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700574 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
575 &cropped_width_, &cropped_height_,
576 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700577 EXPECT_EQ(640, cropped_width_);
578 EXPECT_EQ(400, cropped_height_);
579 EXPECT_EQ(640, out_width_);
580 EXPECT_EQ(400, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000581
magjed709f73c2016-05-13 10:26:00 -0700582 // Request 1280x720, higher than input, but aspect 16:9. Expect cropping but
583 // no scaling.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000584 format.width = 1280;
585 format.height = 720;
Per766ad3b2016-04-05 15:23:49 +0200586 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700587 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
588 &cropped_width_, &cropped_height_,
589 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700590 EXPECT_EQ(640, cropped_width_);
591 EXPECT_EQ(360, cropped_height_);
592 EXPECT_EQ(640, out_width_);
593 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000594
Per766ad3b2016-04-05 15:23:49 +0200595 // Request 0x0.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000596 format.width = 0;
597 format.height = 0;
Per766ad3b2016-04-05 15:23:49 +0200598 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700599 EXPECT_FALSE(adapter_.AdaptFrameResolution(640, 400, 0,
600 &cropped_width_, &cropped_height_,
601 &out_width_, &out_height_));
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000602
magjed709f73c2016-05-13 10:26:00 -0700603 // Request 320x200. Expect scaling, but no cropping.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000604 format.width = 320;
605 format.height = 200;
Per766ad3b2016-04-05 15:23:49 +0200606 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700607 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
608 &cropped_width_, &cropped_height_,
609 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700610 EXPECT_EQ(640, cropped_width_);
611 EXPECT_EQ(400, cropped_height_);
612 EXPECT_EQ(320, out_width_);
613 EXPECT_EQ(200, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000614
magjed709f73c2016-05-13 10:26:00 -0700615 // Request resolution close to 2/3 scale. Expect adapt down. Scaling to 2/3
616 // is not optimized and not allowed, therefore 1/2 scaling will be used
617 // instead.
618 format.width = 424;
619 format.height = 265;
Per766ad3b2016-04-05 15:23:49 +0200620 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700621 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
622 &cropped_width_, &cropped_height_,
623 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700624 EXPECT_EQ(640, cropped_width_);
625 EXPECT_EQ(400, cropped_height_);
626 EXPECT_EQ(320, out_width_);
627 EXPECT_EQ(200, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000628
Per766ad3b2016-04-05 15:23:49 +0200629 // Request resolution of 3 / 8. Expect adapt down.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000630 format.width = 640 * 3 / 8;
631 format.height = 400 * 3 / 8;
Per766ad3b2016-04-05 15:23:49 +0200632 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700633 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
634 &cropped_width_, &cropped_height_,
635 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700636 EXPECT_EQ(640, cropped_width_);
637 EXPECT_EQ(400, cropped_height_);
638 EXPECT_EQ(640 * 3 / 8, out_width_);
639 EXPECT_EQ(400 * 3 / 8, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000640
Per766ad3b2016-04-05 15:23:49 +0200641 // Switch back up. Expect adapt.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000642 format.width = 320;
643 format.height = 200;
Per766ad3b2016-04-05 15:23:49 +0200644 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700645 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
646 &cropped_width_, &cropped_height_,
647 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700648 EXPECT_EQ(640, cropped_width_);
649 EXPECT_EQ(400, cropped_height_);
650 EXPECT_EQ(320, out_width_);
651 EXPECT_EQ(200, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000652
Per766ad3b2016-04-05 15:23:49 +0200653 // Format request 480x300.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000654 format.width = 480;
655 format.height = 300;
Per766ad3b2016-04-05 15:23:49 +0200656 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700657 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
658 &cropped_width_, &cropped_height_,
659 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700660 EXPECT_EQ(640, cropped_width_);
661 EXPECT_EQ(400, cropped_height_);
662 EXPECT_EQ(480, out_width_);
663 EXPECT_EQ(300, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000664}
665
Per766ad3b2016-04-05 15:23:49 +0200666TEST_F(VideoAdapterTest, TestViewRequestPlusCameraSwitch) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000667 // Start at HD.
magjed604abe02016-05-19 06:05:40 -0700668 VideoFormat format(1280, 720, 0, 0);
nisse47ac4622016-05-25 08:47:01 -0700669 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
670 &cropped_width_, &cropped_height_,
671 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700672 EXPECT_EQ(1280, cropped_width_);
673 EXPECT_EQ(720, cropped_height_);
674 EXPECT_EQ(1280, out_width_);
675 EXPECT_EQ(720, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000676
Per766ad3b2016-04-05 15:23:49 +0200677 // Format request for VGA.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000678 format.width = 640;
679 format.height = 360;
Per766ad3b2016-04-05 15:23:49 +0200680 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700681 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
682 &cropped_width_, &cropped_height_,
683 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700684 EXPECT_EQ(1280, cropped_width_);
685 EXPECT_EQ(720, cropped_height_);
686 EXPECT_EQ(640, out_width_);
687 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000688
689 // Now, the camera reopens at VGA.
690 // Both the frame and the output format should be 640x360.
nisse47ac4622016-05-25 08:47:01 -0700691 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0,
692 &cropped_width_, &cropped_height_,
693 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700694 EXPECT_EQ(640, cropped_width_);
695 EXPECT_EQ(360, cropped_height_);
696 EXPECT_EQ(640, out_width_);
697 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000698
699 // And another view request comes in for 640x360, which should have no
700 // real impact.
Per766ad3b2016-04-05 15:23:49 +0200701 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700702 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0,
703 &cropped_width_, &cropped_height_,
704 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700705 EXPECT_EQ(640, cropped_width_);
706 EXPECT_EQ(360, cropped_height_);
707 EXPECT_EQ(640, out_width_);
708 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000709}
710
Per766ad3b2016-04-05 15:23:49 +0200711TEST_F(VideoAdapterTest, TestVGAWidth) {
712 // Reqeuested Output format is 640x360.
magjed604abe02016-05-19 06:05:40 -0700713 VideoFormat format(640, 360, 0, FOURCC_I420);
Per766ad3b2016-04-05 15:23:49 +0200714 adapter_.OnOutputFormatRequest(format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000715
nisse47ac4622016-05-25 08:47:01 -0700716 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
717 &cropped_width_, &cropped_height_,
718 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700719 // Expect cropping.
720 EXPECT_EQ(640, cropped_width_);
721 EXPECT_EQ(360, cropped_height_);
722 EXPECT_EQ(640, out_width_);
723 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000724
725 // But if frames come in at 640x360, we shouldn't adapt them down.
nisse47ac4622016-05-25 08:47:01 -0700726 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0,
727 &cropped_width_, &cropped_height_,
728 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700729 EXPECT_EQ(640, cropped_width_);
730 EXPECT_EQ(360, cropped_height_);
731 EXPECT_EQ(640, out_width_);
732 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000733
nisse47ac4622016-05-25 08:47:01 -0700734 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
735 &cropped_width_, &cropped_height_,
736 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700737 EXPECT_EQ(640, cropped_width_);
738 EXPECT_EQ(360, cropped_height_);
739 EXPECT_EQ(640, out_width_);
740 EXPECT_EQ(360, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200741}
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000742
Per766ad3b2016-04-05 15:23:49 +0200743TEST_F(VideoAdapterTest, TestOnResolutionRequestInSmallSteps) {
nisse47ac4622016-05-25 08:47:01 -0700744 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
745 &cropped_width_, &cropped_height_,
746 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700747 EXPECT_EQ(1280, cropped_width_);
748 EXPECT_EQ(720, cropped_height_);
749 EXPECT_EQ(1280, out_width_);
750 EXPECT_EQ(720, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200751
752 // Adapt down one step.
sprangc5d62e22017-04-02 23:53:04 -0700753 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 1280 * 720 - 1,
754 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700755 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
756 &cropped_width_, &cropped_height_,
757 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700758 EXPECT_EQ(1280, cropped_width_);
759 EXPECT_EQ(720, cropped_height_);
760 EXPECT_EQ(960, out_width_);
761 EXPECT_EQ(540, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200762
763 // Adapt down one step more.
sprangc5d62e22017-04-02 23:53:04 -0700764 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 960 * 540 - 1,
765 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700766 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
767 &cropped_width_, &cropped_height_,
768 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700769 EXPECT_EQ(1280, cropped_width_);
770 EXPECT_EQ(720, cropped_height_);
771 EXPECT_EQ(640, out_width_);
772 EXPECT_EQ(360, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200773
774 // Adapt down one step more.
sprangc5d62e22017-04-02 23:53:04 -0700775 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 640 * 360 - 1,
776 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700777 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
778 &cropped_width_, &cropped_height_,
779 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700780 EXPECT_EQ(1280, cropped_width_);
781 EXPECT_EQ(720, cropped_height_);
782 EXPECT_EQ(480, out_width_);
783 EXPECT_EQ(270, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200784
785 // Adapt up one step.
sprangc5d62e22017-04-02 23:53:04 -0700786 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(640 * 360),
787 960 * 540,
788 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700789 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
790 &cropped_width_, &cropped_height_,
791 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700792 EXPECT_EQ(1280, cropped_width_);
793 EXPECT_EQ(720, cropped_height_);
794 EXPECT_EQ(640, out_width_);
795 EXPECT_EQ(360, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200796
797 // Adapt up one step more.
sprangc5d62e22017-04-02 23:53:04 -0700798 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(960 * 540),
799 1280 * 720,
800 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700801 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
802 &cropped_width_, &cropped_height_,
803 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700804 EXPECT_EQ(1280, cropped_width_);
805 EXPECT_EQ(720, cropped_height_);
806 EXPECT_EQ(960, out_width_);
807 EXPECT_EQ(540, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200808
809 // Adapt up one step more.
sprangc5d62e22017-04-02 23:53:04 -0700810 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(1280 * 720),
811 1920 * 1080,
812 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700813 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
814 &cropped_width_, &cropped_height_,
815 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700816 EXPECT_EQ(1280, cropped_width_);
817 EXPECT_EQ(720, cropped_height_);
818 EXPECT_EQ(1280, out_width_);
819 EXPECT_EQ(720, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200820}
821
822TEST_F(VideoAdapterTest, TestOnResolutionRequestMaxZero) {
nisse47ac4622016-05-25 08:47:01 -0700823 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
824 &cropped_width_, &cropped_height_,
825 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700826 EXPECT_EQ(1280, cropped_width_);
827 EXPECT_EQ(720, cropped_height_);
828 EXPECT_EQ(1280, out_width_);
829 EXPECT_EQ(720, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200830
sprangc5d62e22017-04-02 23:53:04 -0700831 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 0,
832 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700833 EXPECT_FALSE(adapter_.AdaptFrameResolution(1280, 720, 0,
834 &cropped_width_, &cropped_height_,
835 &out_width_, &out_height_));
Per766ad3b2016-04-05 15:23:49 +0200836}
837
838TEST_F(VideoAdapterTest, TestOnResolutionRequestInLargeSteps) {
sprang84a37592017-02-10 07:04:27 -0800839 // Large step down.
sprangc5d62e22017-04-02 23:53:04 -0700840 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 640 * 360 - 1,
841 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700842 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
843 &cropped_width_, &cropped_height_,
844 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700845 EXPECT_EQ(1280, cropped_width_);
846 EXPECT_EQ(720, cropped_height_);
847 EXPECT_EQ(480, out_width_);
848 EXPECT_EQ(270, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200849
sprang84a37592017-02-10 07:04:27 -0800850 // Large step up.
sprangc5d62e22017-04-02 23:53:04 -0700851 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(1280 * 720),
852 1920 * 1080,
853 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700854 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
855 &cropped_width_, &cropped_height_,
856 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700857 EXPECT_EQ(1280, cropped_width_);
858 EXPECT_EQ(720, cropped_height_);
859 EXPECT_EQ(1280, out_width_);
860 EXPECT_EQ(720, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200861}
862
863TEST_F(VideoAdapterTest, TestOnOutputFormatRequestCapsMaxResolution) {
sprangc5d62e22017-04-02 23:53:04 -0700864 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 640 * 360 - 1,
865 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700866 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
867 &cropped_width_, &cropped_height_,
868 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700869 EXPECT_EQ(1280, cropped_width_);
870 EXPECT_EQ(720, cropped_height_);
871 EXPECT_EQ(480, out_width_);
872 EXPECT_EQ(270, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200873
magjed604abe02016-05-19 06:05:40 -0700874 VideoFormat new_format(640, 360, 0, FOURCC_I420);
Per766ad3b2016-04-05 15:23:49 +0200875 adapter_.OnOutputFormatRequest(new_format);
nisse47ac4622016-05-25 08:47:01 -0700876 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
877 &cropped_width_, &cropped_height_,
878 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700879 EXPECT_EQ(1280, cropped_width_);
880 EXPECT_EQ(720, cropped_height_);
881 EXPECT_EQ(480, out_width_);
882 EXPECT_EQ(270, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200883
sprangc5d62e22017-04-02 23:53:04 -0700884 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 960 * 720,
885 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700886 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
887 &cropped_width_, &cropped_height_,
888 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700889 EXPECT_EQ(1280, cropped_width_);
890 EXPECT_EQ(720, cropped_height_);
891 EXPECT_EQ(640, out_width_);
892 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000893}
894
Per766ad3b2016-04-05 15:23:49 +0200895TEST_F(VideoAdapterTest, TestOnResolutionRequestReset) {
nisse47ac4622016-05-25 08:47:01 -0700896 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
897 &cropped_width_, &cropped_height_,
898 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700899 EXPECT_EQ(1280, cropped_width_);
900 EXPECT_EQ(720, cropped_height_);
901 EXPECT_EQ(1280, out_width_);
902 EXPECT_EQ(720, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000903
sprangc5d62e22017-04-02 23:53:04 -0700904 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 640 * 360 - 1,
905 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700906 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
907 &cropped_width_, &cropped_height_,
908 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700909 EXPECT_EQ(1280, cropped_width_);
910 EXPECT_EQ(720, cropped_height_);
911 EXPECT_EQ(480, out_width_);
912 EXPECT_EQ(270, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000913
sprangc5d62e22017-04-02 23:53:04 -0700914 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(),
915 std::numeric_limits<int>::max(),
916 std::numeric_limits<int>::max());
nisse47ac4622016-05-25 08:47:01 -0700917 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
918 &cropped_width_, &cropped_height_,
919 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700920 EXPECT_EQ(1280, cropped_width_);
921 EXPECT_EQ(720, cropped_height_);
922 EXPECT_EQ(1280, out_width_);
923 EXPECT_EQ(720, out_height_);
924}
925
926TEST_F(VideoAdapterTest, TestCroppingWithResolutionRequest) {
927 // Ask for 640x360 (16:9 aspect).
magjed604abe02016-05-19 06:05:40 -0700928 adapter_.OnOutputFormatRequest(VideoFormat(640, 360, 0, FOURCC_I420));
magjed709f73c2016-05-13 10:26:00 -0700929 // Send 640x480 (4:3 aspect).
nisse47ac4622016-05-25 08:47:01 -0700930 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
931 &cropped_width_, &cropped_height_,
932 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700933 // Expect cropping to 16:9 format and no scaling.
934 EXPECT_EQ(640, cropped_width_);
935 EXPECT_EQ(360, cropped_height_);
936 EXPECT_EQ(640, out_width_);
937 EXPECT_EQ(360, out_height_);
938
939 // Adapt down one step.
sprangc5d62e22017-04-02 23:53:04 -0700940 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 640 * 360 - 1,
941 std::numeric_limits<int>::max());
magjed709f73c2016-05-13 10:26:00 -0700942 // Expect cropping to 16:9 format and 3/4 scaling.
nisse47ac4622016-05-25 08:47:01 -0700943 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
944 &cropped_width_, &cropped_height_,
945 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700946 EXPECT_EQ(640, cropped_width_);
947 EXPECT_EQ(360, cropped_height_);
948 EXPECT_EQ(480, out_width_);
949 EXPECT_EQ(270, out_height_);
950
951 // Adapt down one step more.
sprangc5d62e22017-04-02 23:53:04 -0700952 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 480 * 270 - 1,
953 std::numeric_limits<int>::max());
magjed709f73c2016-05-13 10:26:00 -0700954 // Expect cropping to 16:9 format and 1/2 scaling.
nisse47ac4622016-05-25 08:47:01 -0700955 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
956 &cropped_width_, &cropped_height_,
957 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700958 EXPECT_EQ(640, cropped_width_);
959 EXPECT_EQ(360, cropped_height_);
960 EXPECT_EQ(320, out_width_);
961 EXPECT_EQ(180, out_height_);
962
963 // Adapt up one step.
sprangc5d62e22017-04-02 23:53:04 -0700964 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(480 * 270),
965 640 * 360,
966 std::numeric_limits<int>::max());
magjed709f73c2016-05-13 10:26:00 -0700967 // Expect cropping to 16:9 format and 3/4 scaling.
nisse47ac4622016-05-25 08:47:01 -0700968 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
969 &cropped_width_, &cropped_height_,
970 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700971 EXPECT_EQ(640, cropped_width_);
972 EXPECT_EQ(360, cropped_height_);
973 EXPECT_EQ(480, out_width_);
974 EXPECT_EQ(270, out_height_);
975
976 // Adapt up one step more.
sprangc5d62e22017-04-02 23:53:04 -0700977 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(640 * 360),
978 960 * 540,
979 std::numeric_limits<int>::max());
magjed709f73c2016-05-13 10:26:00 -0700980 // Expect cropping to 16:9 format and no scaling.
nisse47ac4622016-05-25 08:47:01 -0700981 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
982 &cropped_width_, &cropped_height_,
983 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700984 EXPECT_EQ(640, cropped_width_);
985 EXPECT_EQ(360, cropped_height_);
986 EXPECT_EQ(640, out_width_);
987 EXPECT_EQ(360, out_height_);
988
989 // Try to adapt up one step more.
sprangc5d62e22017-04-02 23:53:04 -0700990 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(960 * 540),
991 1280 * 720,
992 std::numeric_limits<int>::max());
magjed709f73c2016-05-13 10:26:00 -0700993 // Expect cropping to 16:9 format and no scaling.
nisse47ac4622016-05-25 08:47:01 -0700994 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
995 &cropped_width_, &cropped_height_,
996 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700997 EXPECT_EQ(640, cropped_width_);
998 EXPECT_EQ(360, cropped_height_);
999 EXPECT_EQ(640, out_width_);
1000 EXPECT_EQ(360, out_height_);
1001}
1002
1003TEST_F(VideoAdapterTest, TestCroppingOddResolution) {
1004 // Ask for 640x360 (16:9 aspect), with 3/16 scaling.
magjed709f73c2016-05-13 10:26:00 -07001005 adapter_.OnOutputFormatRequest(
magjed604abe02016-05-19 06:05:40 -07001006 VideoFormat(640, 360, 0, FOURCC_I420));
sprangc5d62e22017-04-02 23:53:04 -07001007 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(),
1008 640 * 360 * 3 / 16 * 3 / 16,
1009 std::numeric_limits<int>::max());
magjed709f73c2016-05-13 10:26:00 -07001010
1011 // Send 640x480 (4:3 aspect).
nisse47ac4622016-05-25 08:47:01 -07001012 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
1013 &cropped_width_, &cropped_height_,
1014 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -07001015
1016 // Instead of getting the exact aspect ratio with cropped resolution 640x360,
1017 // the resolution should be adjusted to get a perfect scale factor instead.
1018 EXPECT_EQ(640, cropped_width_);
1019 EXPECT_EQ(368, cropped_height_);
1020 EXPECT_EQ(120, out_width_);
1021 EXPECT_EQ(69, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00001022}
1023
kthelgasonc8474172016-12-08 08:04:51 -08001024TEST_F(VideoAdapterTest, TestAdaptToVerySmallResolution) {
1025 // Ask for 1920x1080 (16:9 aspect), with 1/16 scaling.
1026 const int w = 1920;
1027 const int h = 1080;
1028 adapter_.OnOutputFormatRequest(VideoFormat(w, h, 0, FOURCC_I420));
sprangc5d62e22017-04-02 23:53:04 -07001029 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(),
1030 w * h * 1 / 16 * 1 / 16,
1031 std::numeric_limits<int>::max());
kthelgasonc8474172016-12-08 08:04:51 -08001032
1033 // Send 1920x1080 (16:9 aspect).
1034 EXPECT_TRUE(adapter_.AdaptFrameResolution(
1035 w, h, 0, &cropped_width_, &cropped_height_, &out_width_, &out_height_));
1036
1037 // Instead of getting the exact aspect ratio with cropped resolution 1920x1080
1038 // the resolution should be adjusted to get a perfect scale factor instead.
1039 EXPECT_EQ(1920, cropped_width_);
1040 EXPECT_EQ(1072, cropped_height_);
1041 EXPECT_EQ(120, out_width_);
1042 EXPECT_EQ(67, out_height_);
1043
1044 // Adapt back up one step to 3/32.
sprangc5d62e22017-04-02 23:53:04 -07001045 adapter_.OnResolutionFramerateRequest(
1046 rtc::Optional<int>(w * h * 3 / 32 * 3 / 32), w * h * 1 / 8 * 1 / 8,
1047 std::numeric_limits<int>::max());
kthelgasonc8474172016-12-08 08:04:51 -08001048
1049 // Send 1920x1080 (16:9 aspect).
1050 EXPECT_TRUE(adapter_.AdaptFrameResolution(
1051 w, h, 0, &cropped_width_, &cropped_height_, &out_width_, &out_height_));
1052
1053 EXPECT_EQ(180, out_width_);
1054 EXPECT_EQ(99, out_height_);
1055}
1056
1057TEST_F(VideoAdapterTest, AdaptFrameResolutionDropWithResolutionRequest) {
1058 VideoFormat output_format = capture_format_;
1059 output_format.width = 0;
1060 output_format.height = 0;
1061 adapter_.OnOutputFormatRequest(output_format);
1062 EXPECT_FALSE(adapter_.AdaptFrameResolution(
1063 capture_format_.width, capture_format_.height, 0,
1064 &cropped_width_, &cropped_height_,
1065 &out_width_, &out_height_));
1066
sprangc5d62e22017-04-02 23:53:04 -07001067 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(960 * 540),
1068 std::numeric_limits<int>::max(),
1069 std::numeric_limits<int>::max());
kthelgasonc8474172016-12-08 08:04:51 -08001070
1071 // Still expect all frames to be dropped
1072 EXPECT_FALSE(adapter_.AdaptFrameResolution(
1073 capture_format_.width, capture_format_.height, 0,
1074 &cropped_width_, &cropped_height_,
1075 &out_width_, &out_height_));
1076
sprangc5d62e22017-04-02 23:53:04 -07001077 adapter_.OnResolutionFramerateRequest(rtc::Optional<int>(), 640 * 480 - 1,
1078 std::numeric_limits<int>::max());
kthelgasonc8474172016-12-08 08:04:51 -08001079
1080 // Still expect all frames to be dropped
1081 EXPECT_FALSE(adapter_.AdaptFrameResolution(
1082 capture_format_.width, capture_format_.height, 0,
1083 &cropped_width_, &cropped_height_,
1084 &out_width_, &out_height_));
1085}
1086
Magnus Jedvert6d230d72017-02-22 18:30:27 +01001087// Test that we will adapt to max given a target pixel count close to max.
1088TEST_F(VideoAdapterTest, TestAdaptToMax) {
1089 adapter_.OnOutputFormatRequest(VideoFormat(640, 360, 0, FOURCC_I420));
sprangc5d62e22017-04-02 23:53:04 -07001090 adapter_.OnResolutionFramerateRequest(
1091 rtc::Optional<int>(640 * 360 - 1) /* target */,
1092 std::numeric_limits<int>::max(), std::numeric_limits<int>::max());
Magnus Jedvert6d230d72017-02-22 18:30:27 +01001093
1094 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0, &cropped_width_,
1095 &cropped_height_, &out_width_,
1096 &out_height_));
1097 EXPECT_EQ(640, out_width_);
1098 EXPECT_EQ(360, out_height_);
1099}
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00001100} // namespace cricket