blob: 6ec90d841d26d77d8d8d9135a2e831c06bbf030d [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
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000017#include "webrtc/base/gunit.h"
18#include "webrtc/base/logging.h"
kjellandera96e2d72016-02-04 23:52:28 -080019#include "webrtc/media/base/fakevideocapturer.h"
20#include "webrtc/media/base/mediachannel.h"
21#include "webrtc/media/base/testutils.h"
22#include "webrtc/media/base/videoadapter.h"
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000023
24namespace cricket {
25
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000026class VideoAdapterTest : public testing::Test {
27 public:
28 virtual void SetUp() {
Magnus Jedvert01840572015-04-10 11:18:39 +020029 capturer_.reset(new FakeVideoCapturer);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000030 capture_format_ = capturer_->GetSupportedFormats()->at(0);
lliuuf9ed2352017-03-30 10:44:38 -070031 capture_format_.interval = VideoFormat::FpsToInterval(30);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000032
Per766ad3b2016-04-05 15:23:49 +020033 listener_.reset(new VideoCapturerListener(&adapter_));
nissef5297a02016-09-30 01:34:27 -070034 capturer_->AddOrUpdateSink(listener_.get(), rtc::VideoSinkWants());
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000035 }
36
pbos@webrtc.org75c3ec12014-08-27 18:16:13 +000037 virtual void TearDown() {
38 // Explicitly disconnect the VideoCapturer before to avoid data races
39 // (frames delivered to VideoCapturerListener while it's being destructed).
nissef5297a02016-09-30 01:34:27 -070040 capturer_->RemoveSink(listener_.get());
pbos@webrtc.org75c3ec12014-08-27 18:16:13 +000041 }
42
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000043 protected:
nissef5297a02016-09-30 01:34:27 -070044 class VideoCapturerListener
nisseacd935b2016-11-11 03:55:13 -080045 : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000046 public:
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000047 struct Stats {
48 int captured_frames;
49 int dropped_frames;
50 bool last_adapt_was_no_op;
51
magjed709f73c2016-05-13 10:26:00 -070052 int cropped_width;
53 int cropped_height;
54 int out_width;
55 int out_height;
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000056 };
57
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000058 explicit VideoCapturerListener(VideoAdapter* adapter)
59 : video_adapter_(adapter),
sprang84a37592017-02-10 07:04:27 -080060 cropped_width_(0),
61 cropped_height_(0),
62 out_width_(0),
63 out_height_(0),
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000064 captured_frames_(0),
65 dropped_frames_(0),
sprang84a37592017-02-10 07:04:27 -080066 last_adapt_was_no_op_(false) {}
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000067
nisseacd935b2016-11-11 03:55:13 -080068 void OnFrame(const webrtc::VideoFrame& frame) {
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000069 rtc::CritScope lock(&crit_);
nissef5297a02016-09-30 01:34:27 -070070 const int in_width = frame.width();
71 const int in_height = frame.height();
magjed709f73c2016-05-13 10:26:00 -070072 int cropped_width;
73 int cropped_height;
74 int out_width;
75 int out_height;
nissef5297a02016-09-30 01:34:27 -070076 if (video_adapter_->AdaptFrameResolution(
77 in_width, in_height,
78 frame.timestamp_us() * rtc::kNumNanosecsPerMicrosec,
79 &cropped_width, &cropped_height, &out_width, &out_height)) {
magjed709f73c2016-05-13 10:26:00 -070080 cropped_width_ = cropped_width;
81 cropped_height_ = cropped_height;
82 out_width_ = out_width;
83 out_height_ = out_height;
84 last_adapt_was_no_op_ =
85 (in_width == cropped_width && in_height == cropped_height &&
86 in_width == out_width && in_height == out_height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +000087 } else {
88 ++dropped_frames_;
89 }
90 ++captured_frames_;
91 }
92
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +000093 Stats GetStats() {
94 rtc::CritScope lock(&crit_);
95 Stats stats;
96 stats.captured_frames = captured_frames_;
97 stats.dropped_frames = dropped_frames_;
98 stats.last_adapt_was_no_op = last_adapt_was_no_op_;
magjed709f73c2016-05-13 10:26:00 -070099 stats.cropped_width = cropped_width_;
100 stats.cropped_height = cropped_height_;
101 stats.out_width = out_width_;
102 stats.out_height = out_height_;
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000103 return stats;
104 }
105
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000106 private:
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000107 rtc::CriticalSection crit_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000108 VideoAdapter* video_adapter_;
magjed709f73c2016-05-13 10:26:00 -0700109 int cropped_width_;
110 int cropped_height_;
111 int out_width_;
112 int out_height_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000113 int captured_frames_;
114 int dropped_frames_;
115 bool last_adapt_was_no_op_;
116 };
117
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000118
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000119 void VerifyAdaptedResolution(const VideoCapturerListener::Stats& stats,
magjed709f73c2016-05-13 10:26:00 -0700120 int cropped_width,
121 int cropped_height,
122 int out_width,
123 int out_height) {
124 EXPECT_EQ(cropped_width, stats.cropped_width);
125 EXPECT_EQ(cropped_height, stats.cropped_height);
126 EXPECT_EQ(out_width, stats.out_width);
127 EXPECT_EQ(out_height, stats.out_height);
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000128 }
129
kwiberg686a8ef2016-02-26 03:00:35 -0800130 std::unique_ptr<FakeVideoCapturer> capturer_;
Per766ad3b2016-04-05 15:23:49 +0200131 VideoAdapter adapter_;
magjed709f73c2016-05-13 10:26:00 -0700132 int cropped_width_;
133 int cropped_height_;
134 int out_width_;
135 int out_height_;
kwiberg686a8ef2016-02-26 03:00:35 -0800136 std::unique_ptr<VideoCapturerListener> listener_;
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000137 VideoFormat capture_format_;
138};
139
magjed709f73c2016-05-13 10:26:00 -0700140// Do not adapt the frame rate or the resolution. Expect no frame drop, no
141// cropping, and no resolution change.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000142TEST_F(VideoAdapterTest, AdaptNothing) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000143 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200144 for (int i = 0; i < 10; ++i)
145 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000146
147 // Verify no frame drop and no resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000148 VideoCapturerListener::Stats stats = listener_->GetStats();
149 EXPECT_GE(stats.captured_frames, 10);
150 EXPECT_EQ(0, stats.dropped_frames);
magjed709f73c2016-05-13 10:26:00 -0700151 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
152 capture_format_.width, capture_format_.height);
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000153 EXPECT_TRUE(stats.last_adapt_was_no_op);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000154}
155
156TEST_F(VideoAdapterTest, AdaptZeroInterval) {
157 VideoFormat format = capturer_->GetSupportedFormats()->at(0);
158 format.interval = 0;
Per766ad3b2016-04-05 15:23:49 +0200159 adapter_.OnOutputFormatRequest(format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000160 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200161 for (int i = 0; i < 10; ++i)
162 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000163
164 // Verify no crash and that frames aren't dropped.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000165 VideoCapturerListener::Stats stats = listener_->GetStats();
166 EXPECT_GE(stats.captured_frames, 10);
167 EXPECT_EQ(0, stats.dropped_frames);
magjed709f73c2016-05-13 10:26:00 -0700168 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
169 capture_format_.width, capture_format_.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000170}
171
172// Adapt the frame rate to be half of the capture rate at the beginning. Expect
173// the number of dropped frames to be half of the number the captured frames.
magjed604abe02016-05-19 06:05:40 -0700174TEST_F(VideoAdapterTest, AdaptFramerateToHalf) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000175 VideoFormat request_format = capture_format_;
176 request_format.interval *= 2;
Per766ad3b2016-04-05 15:23:49 +0200177 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000178 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
magjed604abe02016-05-19 06:05:40 -0700179
180 // Capture 10 frames and verify that every other frame is dropped. The first
181 // frame should not be dropped.
182 capturer_->CaptureFrame();
183 EXPECT_GE(listener_->GetStats().captured_frames, 1);
184 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
185
186 capturer_->CaptureFrame();
187 EXPECT_GE(listener_->GetStats().captured_frames, 2);
nissef5297a02016-09-30 01:34:27 -0700188 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700189
190 capturer_->CaptureFrame();
191 EXPECT_GE(listener_->GetStats().captured_frames, 3);
192 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
193
194 capturer_->CaptureFrame();
195 EXPECT_GE(listener_->GetStats().captured_frames, 4);
nissef5297a02016-09-30 01:34:27 -0700196 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700197
198 capturer_->CaptureFrame();
199 EXPECT_GE(listener_->GetStats().captured_frames, 5);
200 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
201
202 capturer_->CaptureFrame();
203 EXPECT_GE(listener_->GetStats().captured_frames, 6);
nissef5297a02016-09-30 01:34:27 -0700204 EXPECT_EQ(3, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700205
206 capturer_->CaptureFrame();
207 EXPECT_GE(listener_->GetStats().captured_frames, 7);
208 EXPECT_EQ(3, listener_->GetStats().dropped_frames);
209
210 capturer_->CaptureFrame();
211 EXPECT_GE(listener_->GetStats().captured_frames, 8);
nissef5297a02016-09-30 01:34:27 -0700212 EXPECT_EQ(4, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700213
214 capturer_->CaptureFrame();
215 EXPECT_GE(listener_->GetStats().captured_frames, 9);
216 EXPECT_EQ(4, listener_->GetStats().dropped_frames);
217
218 capturer_->CaptureFrame();
219 EXPECT_GE(listener_->GetStats().captured_frames, 10);
nissef5297a02016-09-30 01:34:27 -0700220 EXPECT_EQ(5, listener_->GetStats().dropped_frames);
magjed604abe02016-05-19 06:05:40 -0700221}
222
223// Adapt the frame rate to be two thirds of the capture rate at the beginning.
224// Expect the number of dropped frames to be one thirds of the number the
225// captured frames.
226TEST_F(VideoAdapterTest, AdaptFramerateToTwoThirds) {
227 VideoFormat request_format = capture_format_;
228 request_format.interval = request_format.interval * 3 / 2;
229 adapter_.OnOutputFormatRequest(request_format);
230 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
231
232 // Capture 10 frames and verify that every third frame is dropped. The first
233 // frame should not be dropped.
234 capturer_->CaptureFrame();
235 EXPECT_GE(listener_->GetStats().captured_frames, 1);
236 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
237
238 capturer_->CaptureFrame();
239 EXPECT_GE(listener_->GetStats().captured_frames, 2);
240 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
241
242 capturer_->CaptureFrame();
243 EXPECT_GE(listener_->GetStats().captured_frames, 3);
244 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
245
246 capturer_->CaptureFrame();
247 EXPECT_GE(listener_->GetStats().captured_frames, 4);
248 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
249
250 capturer_->CaptureFrame();
251 EXPECT_GE(listener_->GetStats().captured_frames, 5);
252 EXPECT_EQ(1, listener_->GetStats().dropped_frames);
253
254 capturer_->CaptureFrame();
255 EXPECT_GE(listener_->GetStats().captured_frames, 6);
256 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
257
258 capturer_->CaptureFrame();
259 EXPECT_GE(listener_->GetStats().captured_frames, 7);
260 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
261
262 capturer_->CaptureFrame();
263 EXPECT_GE(listener_->GetStats().captured_frames, 8);
264 EXPECT_EQ(2, listener_->GetStats().dropped_frames);
265
266 capturer_->CaptureFrame();
267 EXPECT_GE(listener_->GetStats().captured_frames, 9);
268 EXPECT_EQ(3, listener_->GetStats().dropped_frames);
269
270 capturer_->CaptureFrame();
271 EXPECT_GE(listener_->GetStats().captured_frames, 10);
272 EXPECT_EQ(3, listener_->GetStats().dropped_frames);
273}
274
275// Request frame rate twice as high as captured frame rate. Expect no frame
276// drop.
277TEST_F(VideoAdapterTest, AdaptFramerateHighLimit) {
278 VideoFormat request_format = capture_format_;
279 request_format.interval /= 2;
280 adapter_.OnOutputFormatRequest(request_format);
281 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200282 for (int i = 0; i < 10; ++i)
283 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000284
magjed604abe02016-05-19 06:05:40 -0700285 // Verify no frame drop.
286 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000287}
288
magjed604abe02016-05-19 06:05:40 -0700289// After the first timestamp, add a big offset to the timestamps. Expect that
290// the adapter is conservative and resets to the new offset and does not drop
291// any frame.
292TEST_F(VideoAdapterTest, AdaptFramerateTimestampOffset) {
lliuuf9ed2352017-03-30 10:44:38 -0700293 const int64_t capture_interval = VideoFormat::FpsToInterval(30);
magjed604abe02016-05-19 06:05:40 -0700294 adapter_.OnOutputFormatRequest(
295 VideoFormat(640, 480, capture_interval, cricket::FOURCC_ANY));
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000296
magjed604abe02016-05-19 06:05:40 -0700297 const int64_t first_timestamp = 0;
298 adapter_.AdaptFrameResolution(640, 480, first_timestamp,
299 &cropped_width_, &cropped_height_,
300 &out_width_, &out_height_);
301 EXPECT_GT(out_width_, 0);
302 EXPECT_GT(out_height_, 0);
303
304 const int64_t big_offset = -987654321LL * 1000;
305 const int64_t second_timestamp = big_offset;
306 adapter_.AdaptFrameResolution(640, 480, second_timestamp,
307 &cropped_width_, &cropped_height_,
308 &out_width_, &out_height_);
309 EXPECT_GT(out_width_, 0);
310 EXPECT_GT(out_height_, 0);
311
312 const int64_t third_timestamp = big_offset + capture_interval;
313 adapter_.AdaptFrameResolution(640, 480, third_timestamp,
314 &cropped_width_, &cropped_height_,
315 &out_width_, &out_height_);
316 EXPECT_GT(out_width_, 0);
317 EXPECT_GT(out_height_, 0);
318}
319
320// Request 30 fps and send 30 fps with jitter. Expect that no frame is dropped.
321TEST_F(VideoAdapterTest, AdaptFramerateTimestampJitter) {
lliuuf9ed2352017-03-30 10:44:38 -0700322 const int64_t capture_interval = VideoFormat::FpsToInterval(30);
magjed604abe02016-05-19 06:05:40 -0700323 adapter_.OnOutputFormatRequest(
324 VideoFormat(640, 480, capture_interval, cricket::FOURCC_ANY));
325
326 adapter_.AdaptFrameResolution(640, 480, capture_interval * 0 / 10,
327 &cropped_width_, &cropped_height_,
328 &out_width_, &out_height_);
329 EXPECT_GT(out_width_, 0);
330 EXPECT_GT(out_height_, 0);
331
332 adapter_.AdaptFrameResolution(640, 480, capture_interval * 10 / 10 - 1,
333 &cropped_width_, &cropped_height_,
334 &out_width_, &out_height_);
335 EXPECT_GT(out_width_, 0);
336 EXPECT_GT(out_height_, 0);
337
338 adapter_.AdaptFrameResolution(640, 480, capture_interval * 25 / 10,
339 &cropped_width_, &cropped_height_,
340 &out_width_, &out_height_);
341 EXPECT_GT(out_width_, 0);
342 EXPECT_GT(out_height_, 0);
343
344 adapter_.AdaptFrameResolution(640, 480, capture_interval * 30 / 10,
345 &cropped_width_, &cropped_height_,
346 &out_width_, &out_height_);
347 EXPECT_GT(out_width_, 0);
348 EXPECT_GT(out_height_, 0);
349
350 adapter_.AdaptFrameResolution(640, 480, capture_interval * 35 / 10,
351 &cropped_width_, &cropped_height_,
352 &out_width_, &out_height_);
353 EXPECT_GT(out_width_, 0);
354 EXPECT_GT(out_height_, 0);
355
356 adapter_.AdaptFrameResolution(640, 480, capture_interval * 50 / 10,
357 &cropped_width_, &cropped_height_,
358 &out_width_, &out_height_);
359 EXPECT_GT(out_width_, 0);
360 EXPECT_GT(out_height_, 0);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000361}
362
363// Adapt the frame rate to be half of the capture rate after capturing no less
364// than 10 frames. Expect no frame dropped before adaptation and frame dropped
365// after adaptation.
366TEST_F(VideoAdapterTest, AdaptFramerateOntheFly) {
367 VideoFormat request_format = capture_format_;
Per766ad3b2016-04-05 15:23:49 +0200368 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000369 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200370 for (int i = 0; i < 10; ++i)
371 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000372
373 // Verify no frame drop before adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000374 EXPECT_EQ(0, listener_->GetStats().dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000375
376 // Adapat the frame rate.
377 request_format.interval *= 2;
Per766ad3b2016-04-05 15:23:49 +0200378 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000379
Magnus Jedvert01840572015-04-10 11:18:39 +0200380 for (int i = 0; i < 20; ++i)
381 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000382
383 // Verify frame drop after adaptation.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000384 EXPECT_GT(listener_->GetStats().dropped_frames, 0);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000385}
386
magjed709f73c2016-05-13 10:26:00 -0700387// Set a very high output pixel resolution. Expect no cropping or resolution
388// change.
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000389TEST_F(VideoAdapterTest, AdaptFrameResolutionHighLimit) {
Per766ad3b2016-04-05 15:23:49 +0200390 VideoFormat output_format = capture_format_;
magjed709f73c2016-05-13 10:26:00 -0700391 output_format.width *= 10;
392 output_format.height *= 10;
Per766ad3b2016-04-05 15:23:49 +0200393 adapter_.OnOutputFormatRequest(output_format);
nisse47ac4622016-05-25 08:47:01 -0700394 EXPECT_TRUE(adapter_.AdaptFrameResolution(
395 capture_format_.width, capture_format_.height, 0,
396 &cropped_width_, &cropped_height_,
397 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700398 EXPECT_EQ(capture_format_.width, cropped_width_);
399 EXPECT_EQ(capture_format_.height, cropped_height_);
400 EXPECT_EQ(capture_format_.width, out_width_);
401 EXPECT_EQ(capture_format_.height, out_height_);
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000402}
403
404// Adapt the frame resolution to be the same as capture resolution. Expect no
magjed709f73c2016-05-13 10:26:00 -0700405// cropping or resolution change.
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000406TEST_F(VideoAdapterTest, AdaptFrameResolutionIdentical) {
Per766ad3b2016-04-05 15:23:49 +0200407 adapter_.OnOutputFormatRequest(capture_format_);
nisse47ac4622016-05-25 08:47:01 -0700408 EXPECT_TRUE(adapter_.AdaptFrameResolution(
409 capture_format_.width, capture_format_.height, 0,
410 &cropped_width_, &cropped_height_,
411 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700412 EXPECT_EQ(capture_format_.width, cropped_width_);
413 EXPECT_EQ(capture_format_.height, cropped_height_);
414 EXPECT_EQ(capture_format_.width, out_width_);
415 EXPECT_EQ(capture_format_.height, out_height_);
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000416}
417
418// Adapt the frame resolution to be a quarter of the capture resolution. Expect
magjed709f73c2016-05-13 10:26:00 -0700419// no cropping, but a resolution change.
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000420TEST_F(VideoAdapterTest, AdaptFrameResolutionQuarter) {
421 VideoFormat request_format = capture_format_;
422 request_format.width /= 2;
423 request_format.height /= 2;
Per766ad3b2016-04-05 15:23:49 +0200424 adapter_.OnOutputFormatRequest(request_format);
nisse47ac4622016-05-25 08:47:01 -0700425 EXPECT_TRUE(adapter_.AdaptFrameResolution(
426 capture_format_.width, capture_format_.height, 0,
427 &cropped_width_, &cropped_height_,
428 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700429 EXPECT_EQ(capture_format_.width, cropped_width_);
430 EXPECT_EQ(capture_format_.height, cropped_height_);
431 EXPECT_EQ(request_format.width, out_width_);
432 EXPECT_EQ(request_format.height, out_height_);
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000433}
434
435// Adapt the pixel resolution to 0. Expect frame drop.
436TEST_F(VideoAdapterTest, AdaptFrameResolutionDrop) {
Per766ad3b2016-04-05 15:23:49 +0200437 VideoFormat output_format = capture_format_;
438 output_format.width = 0;
439 output_format.height = 0;
440 adapter_.OnOutputFormatRequest(output_format);
nisse47ac4622016-05-25 08:47:01 -0700441 EXPECT_FALSE(adapter_.AdaptFrameResolution(
442 capture_format_.width, capture_format_.height, 0,
443 &cropped_width_, &cropped_height_,
444 &out_width_, &out_height_));
magjed@webrtc.orgf58b4552014-11-19 18:09:14 +0000445}
446
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000447// Adapt the frame resolution to be a quarter of the capture resolution at the
magjed709f73c2016-05-13 10:26:00 -0700448// beginning. Expect no cropping but a resolution change.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000449TEST_F(VideoAdapterTest, AdaptResolution) {
450 VideoFormat request_format = capture_format_;
451 request_format.width /= 2;
452 request_format.height /= 2;
Per766ad3b2016-04-05 15:23:49 +0200453 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000454 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200455 for (int i = 0; i < 10; ++i)
456 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000457
magjed709f73c2016-05-13 10:26:00 -0700458 // Verify no frame drop, no cropping, and resolution change.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000459 VideoCapturerListener::Stats stats = listener_->GetStats();
460 EXPECT_EQ(0, stats.dropped_frames);
magjed709f73c2016-05-13 10:26:00 -0700461 VerifyAdaptedResolution(stats, capture_format_.width, capture_format_.height,
462 request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000463}
464
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000465// Adapt the frame resolution to be a quarter of the capture resolution after
466// capturing no less than 10 frames. Expect no resolution change before
467// adaptation and resolution change after adaptation.
468TEST_F(VideoAdapterTest, AdaptResolutionOnTheFly) {
469 VideoFormat request_format = capture_format_;
Per766ad3b2016-04-05 15:23:49 +0200470 adapter_.OnOutputFormatRequest(request_format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000471 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200472 for (int i = 0; i < 10; ++i)
473 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000474
475 // Verify no resolution change before adaptation.
magjed709f73c2016-05-13 10:26:00 -0700476 VerifyAdaptedResolution(listener_->GetStats(),
477 capture_format_.width, capture_format_.height,
478 request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000479
480 // Adapt the frame resolution.
481 request_format.width /= 2;
482 request_format.height /= 2;
Per766ad3b2016-04-05 15:23:49 +0200483 adapter_.OnOutputFormatRequest(request_format);
Magnus Jedvert01840572015-04-10 11:18:39 +0200484 for (int i = 0; i < 10; ++i)
485 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000486
487 // Verify resolution change after adaptation.
magjed709f73c2016-05-13 10:26:00 -0700488 VerifyAdaptedResolution(listener_->GetStats(),
489 capture_format_.width, capture_format_.height,
490 request_format.width, request_format.height);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000491}
492
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000493// Drop all frames.
494TEST_F(VideoAdapterTest, DropAllFrames) {
495 VideoFormat format; // with resolution 0x0.
Per766ad3b2016-04-05 15:23:49 +0200496 adapter_.OnOutputFormatRequest(format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000497 EXPECT_EQ(CS_RUNNING, capturer_->Start(capture_format_));
Magnus Jedvert01840572015-04-10 11:18:39 +0200498 for (int i = 0; i < 10; ++i)
499 capturer_->CaptureFrame();
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000500
501 // Verify all frames are dropped.
pbos@webrtc.orgc9b3f772014-08-26 12:33:18 +0000502 VideoCapturerListener::Stats stats = listener_->GetStats();
503 EXPECT_GE(stats.captured_frames, 10);
504 EXPECT_EQ(stats.captured_frames, stats.dropped_frames);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000505}
506
Per766ad3b2016-04-05 15:23:49 +0200507TEST_F(VideoAdapterTest, TestOnOutputFormatRequest) {
magjed604abe02016-05-19 06:05:40 -0700508 VideoFormat format(640, 400, 0, 0);
nisse47ac4622016-05-25 08:47:01 -0700509 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
510 &cropped_width_, &cropped_height_,
511 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700512 EXPECT_EQ(640, cropped_width_);
513 EXPECT_EQ(400, cropped_height_);
514 EXPECT_EQ(640, out_width_);
515 EXPECT_EQ(400, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000516
Per766ad3b2016-04-05 15:23:49 +0200517 // Format request 640x400.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000518 format.height = 400;
Per766ad3b2016-04-05 15:23:49 +0200519 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700520 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
521 &cropped_width_, &cropped_height_,
522 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700523 EXPECT_EQ(640, cropped_width_);
524 EXPECT_EQ(400, cropped_height_);
525 EXPECT_EQ(640, out_width_);
526 EXPECT_EQ(400, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000527
magjed709f73c2016-05-13 10:26:00 -0700528 // Request 1280x720, higher than input, but aspect 16:9. Expect cropping but
529 // no scaling.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000530 format.width = 1280;
531 format.height = 720;
Per766ad3b2016-04-05 15:23:49 +0200532 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700533 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
534 &cropped_width_, &cropped_height_,
535 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700536 EXPECT_EQ(640, cropped_width_);
537 EXPECT_EQ(360, cropped_height_);
538 EXPECT_EQ(640, out_width_);
539 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000540
Per766ad3b2016-04-05 15:23:49 +0200541 // Request 0x0.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000542 format.width = 0;
543 format.height = 0;
Per766ad3b2016-04-05 15:23:49 +0200544 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700545 EXPECT_FALSE(adapter_.AdaptFrameResolution(640, 400, 0,
546 &cropped_width_, &cropped_height_,
547 &out_width_, &out_height_));
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000548
magjed709f73c2016-05-13 10:26:00 -0700549 // Request 320x200. Expect scaling, but no cropping.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000550 format.width = 320;
551 format.height = 200;
Per766ad3b2016-04-05 15:23:49 +0200552 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700553 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
554 &cropped_width_, &cropped_height_,
555 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700556 EXPECT_EQ(640, cropped_width_);
557 EXPECT_EQ(400, cropped_height_);
558 EXPECT_EQ(320, out_width_);
559 EXPECT_EQ(200, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000560
magjed709f73c2016-05-13 10:26:00 -0700561 // Request resolution close to 2/3 scale. Expect adapt down. Scaling to 2/3
562 // is not optimized and not allowed, therefore 1/2 scaling will be used
563 // instead.
564 format.width = 424;
565 format.height = 265;
Per766ad3b2016-04-05 15:23:49 +0200566 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700567 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
568 &cropped_width_, &cropped_height_,
569 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700570 EXPECT_EQ(640, cropped_width_);
571 EXPECT_EQ(400, cropped_height_);
572 EXPECT_EQ(320, out_width_);
573 EXPECT_EQ(200, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000574
Per766ad3b2016-04-05 15:23:49 +0200575 // Request resolution of 3 / 8. Expect adapt down.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000576 format.width = 640 * 3 / 8;
577 format.height = 400 * 3 / 8;
Per766ad3b2016-04-05 15:23:49 +0200578 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700579 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
580 &cropped_width_, &cropped_height_,
581 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700582 EXPECT_EQ(640, cropped_width_);
583 EXPECT_EQ(400, cropped_height_);
584 EXPECT_EQ(640 * 3 / 8, out_width_);
585 EXPECT_EQ(400 * 3 / 8, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000586
Per766ad3b2016-04-05 15:23:49 +0200587 // Switch back up. Expect adapt.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000588 format.width = 320;
589 format.height = 200;
Per766ad3b2016-04-05 15:23:49 +0200590 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700591 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
592 &cropped_width_, &cropped_height_,
593 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700594 EXPECT_EQ(640, cropped_width_);
595 EXPECT_EQ(400, cropped_height_);
596 EXPECT_EQ(320, out_width_);
597 EXPECT_EQ(200, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000598
Per766ad3b2016-04-05 15:23:49 +0200599 // Format request 480x300.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000600 format.width = 480;
601 format.height = 300;
Per766ad3b2016-04-05 15:23:49 +0200602 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700603 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 400, 0,
604 &cropped_width_, &cropped_height_,
605 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700606 EXPECT_EQ(640, cropped_width_);
607 EXPECT_EQ(400, cropped_height_);
608 EXPECT_EQ(480, out_width_);
609 EXPECT_EQ(300, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000610}
611
Per766ad3b2016-04-05 15:23:49 +0200612TEST_F(VideoAdapterTest, TestViewRequestPlusCameraSwitch) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000613 // Start at HD.
magjed604abe02016-05-19 06:05:40 -0700614 VideoFormat format(1280, 720, 0, 0);
nisse47ac4622016-05-25 08:47:01 -0700615 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
616 &cropped_width_, &cropped_height_,
617 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700618 EXPECT_EQ(1280, cropped_width_);
619 EXPECT_EQ(720, cropped_height_);
620 EXPECT_EQ(1280, out_width_);
621 EXPECT_EQ(720, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000622
Per766ad3b2016-04-05 15:23:49 +0200623 // Format request for VGA.
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000624 format.width = 640;
625 format.height = 360;
Per766ad3b2016-04-05 15:23:49 +0200626 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700627 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
628 &cropped_width_, &cropped_height_,
629 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700630 EXPECT_EQ(1280, cropped_width_);
631 EXPECT_EQ(720, cropped_height_);
632 EXPECT_EQ(640, out_width_);
633 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000634
635 // Now, the camera reopens at VGA.
636 // Both the frame and the output format should be 640x360.
nisse47ac4622016-05-25 08:47:01 -0700637 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0,
638 &cropped_width_, &cropped_height_,
639 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700640 EXPECT_EQ(640, cropped_width_);
641 EXPECT_EQ(360, cropped_height_);
642 EXPECT_EQ(640, out_width_);
643 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000644
645 // And another view request comes in for 640x360, which should have no
646 // real impact.
Per766ad3b2016-04-05 15:23:49 +0200647 adapter_.OnOutputFormatRequest(format);
nisse47ac4622016-05-25 08:47:01 -0700648 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0,
649 &cropped_width_, &cropped_height_,
650 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700651 EXPECT_EQ(640, cropped_width_);
652 EXPECT_EQ(360, cropped_height_);
653 EXPECT_EQ(640, out_width_);
654 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000655}
656
Per766ad3b2016-04-05 15:23:49 +0200657TEST_F(VideoAdapterTest, TestVGAWidth) {
658 // Reqeuested Output format is 640x360.
magjed604abe02016-05-19 06:05:40 -0700659 VideoFormat format(640, 360, 0, FOURCC_I420);
Per766ad3b2016-04-05 15:23:49 +0200660 adapter_.OnOutputFormatRequest(format);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000661
nisse47ac4622016-05-25 08:47:01 -0700662 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
663 &cropped_width_, &cropped_height_,
664 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700665 // Expect cropping.
666 EXPECT_EQ(640, cropped_width_);
667 EXPECT_EQ(360, cropped_height_);
668 EXPECT_EQ(640, out_width_);
669 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000670
671 // But if frames come in at 640x360, we shouldn't adapt them down.
nisse47ac4622016-05-25 08:47:01 -0700672 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0,
673 &cropped_width_, &cropped_height_,
674 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700675 EXPECT_EQ(640, cropped_width_);
676 EXPECT_EQ(360, cropped_height_);
677 EXPECT_EQ(640, out_width_);
678 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000679
nisse47ac4622016-05-25 08:47:01 -0700680 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
681 &cropped_width_, &cropped_height_,
682 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700683 EXPECT_EQ(640, cropped_width_);
684 EXPECT_EQ(360, cropped_height_);
685 EXPECT_EQ(640, out_width_);
686 EXPECT_EQ(360, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200687}
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000688
Per766ad3b2016-04-05 15:23:49 +0200689TEST_F(VideoAdapterTest, TestOnResolutionRequestInSmallSteps) {
nisse47ac4622016-05-25 08:47:01 -0700690 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
691 &cropped_width_, &cropped_height_,
692 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700693 EXPECT_EQ(1280, cropped_width_);
694 EXPECT_EQ(720, cropped_height_);
695 EXPECT_EQ(1280, out_width_);
696 EXPECT_EQ(720, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200697
698 // Adapt down one step.
lliuuf9ed2352017-03-30 10:44:38 -0700699 adapter_.OnResolutionRequest(rtc::Optional<int>(),
700 rtc::Optional<int>(1280 * 720 - 1));
nisse47ac4622016-05-25 08:47:01 -0700701 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
702 &cropped_width_, &cropped_height_,
703 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700704 EXPECT_EQ(1280, cropped_width_);
705 EXPECT_EQ(720, cropped_height_);
706 EXPECT_EQ(960, out_width_);
707 EXPECT_EQ(540, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200708
709 // Adapt down one step more.
lliuuf9ed2352017-03-30 10:44:38 -0700710 adapter_.OnResolutionRequest(rtc::Optional<int>(),
711 rtc::Optional<int>(960 * 540 - 1));
nisse47ac4622016-05-25 08:47:01 -0700712 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
713 &cropped_width_, &cropped_height_,
714 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700715 EXPECT_EQ(1280, cropped_width_);
716 EXPECT_EQ(720, cropped_height_);
717 EXPECT_EQ(640, out_width_);
718 EXPECT_EQ(360, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200719
720 // Adapt down one step more.
lliuuf9ed2352017-03-30 10:44:38 -0700721 adapter_.OnResolutionRequest(rtc::Optional<int>(),
722 rtc::Optional<int>(640 * 360 - 1));
nisse47ac4622016-05-25 08:47:01 -0700723 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
724 &cropped_width_, &cropped_height_,
725 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700726 EXPECT_EQ(1280, cropped_width_);
727 EXPECT_EQ(720, cropped_height_);
728 EXPECT_EQ(480, out_width_);
729 EXPECT_EQ(270, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200730
731 // Adapt up one step.
lliuuf9ed2352017-03-30 10:44:38 -0700732 adapter_.OnResolutionRequest(rtc::Optional<int>(640 * 360),
733 rtc::Optional<int>(960 * 540));
nisse47ac4622016-05-25 08:47:01 -0700734 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
735 &cropped_width_, &cropped_height_,
736 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700737 EXPECT_EQ(1280, cropped_width_);
738 EXPECT_EQ(720, cropped_height_);
739 EXPECT_EQ(640, out_width_);
740 EXPECT_EQ(360, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200741
742 // Adapt up one step more.
lliuuf9ed2352017-03-30 10:44:38 -0700743 adapter_.OnResolutionRequest(rtc::Optional<int>(960 * 540),
744 rtc::Optional<int>(1280 * 720));
nisse47ac4622016-05-25 08:47:01 -0700745 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
746 &cropped_width_, &cropped_height_,
747 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700748 EXPECT_EQ(1280, cropped_width_);
749 EXPECT_EQ(720, cropped_height_);
750 EXPECT_EQ(960, out_width_);
751 EXPECT_EQ(540, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200752
753 // Adapt up one step more.
lliuuf9ed2352017-03-30 10:44:38 -0700754 adapter_.OnResolutionRequest(rtc::Optional<int>(1280 * 720),
755 rtc::Optional<int>(1920 * 1080));
nisse47ac4622016-05-25 08:47:01 -0700756 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
757 &cropped_width_, &cropped_height_,
758 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700759 EXPECT_EQ(1280, cropped_width_);
760 EXPECT_EQ(720, cropped_height_);
761 EXPECT_EQ(1280, out_width_);
762 EXPECT_EQ(720, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200763}
764
765TEST_F(VideoAdapterTest, TestOnResolutionRequestMaxZero) {
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(1280, out_width_);
772 EXPECT_EQ(720, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200773
lliuuf9ed2352017-03-30 10:44:38 -0700774 adapter_.OnResolutionRequest(rtc::Optional<int>(), rtc::Optional<int>(0));
nisse47ac4622016-05-25 08:47:01 -0700775 EXPECT_FALSE(adapter_.AdaptFrameResolution(1280, 720, 0,
776 &cropped_width_, &cropped_height_,
777 &out_width_, &out_height_));
Per766ad3b2016-04-05 15:23:49 +0200778}
779
780TEST_F(VideoAdapterTest, TestOnResolutionRequestInLargeSteps) {
sprang84a37592017-02-10 07:04:27 -0800781 // Large step down.
lliuuf9ed2352017-03-30 10:44:38 -0700782 adapter_.OnResolutionRequest(rtc::Optional<int>(),
783 rtc::Optional<int>(640 * 360 - 1));
nisse47ac4622016-05-25 08:47:01 -0700784 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
785 &cropped_width_, &cropped_height_,
786 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700787 EXPECT_EQ(1280, cropped_width_);
788 EXPECT_EQ(720, cropped_height_);
789 EXPECT_EQ(480, out_width_);
790 EXPECT_EQ(270, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200791
sprang84a37592017-02-10 07:04:27 -0800792 // Large step up.
lliuuf9ed2352017-03-30 10:44:38 -0700793 adapter_.OnResolutionRequest(rtc::Optional<int>(1280 * 720),
794 rtc::Optional<int>(1920 * 1080));
nisse47ac4622016-05-25 08:47:01 -0700795 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
796 &cropped_width_, &cropped_height_,
797 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700798 EXPECT_EQ(1280, cropped_width_);
799 EXPECT_EQ(720, cropped_height_);
800 EXPECT_EQ(1280, out_width_);
801 EXPECT_EQ(720, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200802}
803
804TEST_F(VideoAdapterTest, TestOnOutputFormatRequestCapsMaxResolution) {
lliuuf9ed2352017-03-30 10:44:38 -0700805 adapter_.OnResolutionRequest(rtc::Optional<int>(),
806 rtc::Optional<int>(640 * 360 - 1));
nisse47ac4622016-05-25 08:47:01 -0700807 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
808 &cropped_width_, &cropped_height_,
809 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700810 EXPECT_EQ(1280, cropped_width_);
811 EXPECT_EQ(720, cropped_height_);
812 EXPECT_EQ(480, out_width_);
813 EXPECT_EQ(270, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200814
magjed604abe02016-05-19 06:05:40 -0700815 VideoFormat new_format(640, 360, 0, FOURCC_I420);
Per766ad3b2016-04-05 15:23:49 +0200816 adapter_.OnOutputFormatRequest(new_format);
nisse47ac4622016-05-25 08:47:01 -0700817 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
818 &cropped_width_, &cropped_height_,
819 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700820 EXPECT_EQ(1280, cropped_width_);
821 EXPECT_EQ(720, cropped_height_);
822 EXPECT_EQ(480, out_width_);
823 EXPECT_EQ(270, out_height_);
Per766ad3b2016-04-05 15:23:49 +0200824
lliuuf9ed2352017-03-30 10:44:38 -0700825 adapter_.OnResolutionRequest(rtc::Optional<int>(),
826 rtc::Optional<int>(960 * 720));
nisse47ac4622016-05-25 08:47:01 -0700827 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
828 &cropped_width_, &cropped_height_,
829 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700830 EXPECT_EQ(1280, cropped_width_);
831 EXPECT_EQ(720, cropped_height_);
832 EXPECT_EQ(640, out_width_);
833 EXPECT_EQ(360, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000834}
835
Per766ad3b2016-04-05 15:23:49 +0200836TEST_F(VideoAdapterTest, TestOnResolutionRequestReset) {
nisse47ac4622016-05-25 08:47:01 -0700837 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
838 &cropped_width_, &cropped_height_,
839 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700840 EXPECT_EQ(1280, cropped_width_);
841 EXPECT_EQ(720, cropped_height_);
842 EXPECT_EQ(1280, out_width_);
843 EXPECT_EQ(720, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000844
lliuuf9ed2352017-03-30 10:44:38 -0700845 adapter_.OnResolutionRequest(rtc::Optional<int>(),
846 rtc::Optional<int>(640 * 360 - 1));
nisse47ac4622016-05-25 08:47:01 -0700847 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
848 &cropped_width_, &cropped_height_,
849 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700850 EXPECT_EQ(1280, cropped_width_);
851 EXPECT_EQ(720, cropped_height_);
852 EXPECT_EQ(480, out_width_);
853 EXPECT_EQ(270, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000854
lliuuf9ed2352017-03-30 10:44:38 -0700855 adapter_.OnResolutionRequest(rtc::Optional<int>(), rtc::Optional<int>());
nisse47ac4622016-05-25 08:47:01 -0700856 EXPECT_TRUE(adapter_.AdaptFrameResolution(1280, 720, 0,
857 &cropped_width_, &cropped_height_,
858 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700859 EXPECT_EQ(1280, cropped_width_);
860 EXPECT_EQ(720, cropped_height_);
861 EXPECT_EQ(1280, out_width_);
862 EXPECT_EQ(720, out_height_);
863}
864
865TEST_F(VideoAdapterTest, TestCroppingWithResolutionRequest) {
866 // Ask for 640x360 (16:9 aspect).
magjed604abe02016-05-19 06:05:40 -0700867 adapter_.OnOutputFormatRequest(VideoFormat(640, 360, 0, FOURCC_I420));
magjed709f73c2016-05-13 10:26:00 -0700868 // Send 640x480 (4:3 aspect).
nisse47ac4622016-05-25 08:47:01 -0700869 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
870 &cropped_width_, &cropped_height_,
871 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700872 // Expect cropping to 16:9 format and no scaling.
873 EXPECT_EQ(640, cropped_width_);
874 EXPECT_EQ(360, cropped_height_);
875 EXPECT_EQ(640, out_width_);
876 EXPECT_EQ(360, out_height_);
877
878 // Adapt down one step.
lliuuf9ed2352017-03-30 10:44:38 -0700879 adapter_.OnResolutionRequest(rtc::Optional<int>(),
880 rtc::Optional<int>(640 * 360 - 1));
magjed709f73c2016-05-13 10:26:00 -0700881 // Expect cropping to 16:9 format and 3/4 scaling.
nisse47ac4622016-05-25 08:47:01 -0700882 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
883 &cropped_width_, &cropped_height_,
884 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700885 EXPECT_EQ(640, cropped_width_);
886 EXPECT_EQ(360, cropped_height_);
887 EXPECT_EQ(480, out_width_);
888 EXPECT_EQ(270, out_height_);
889
890 // Adapt down one step more.
lliuuf9ed2352017-03-30 10:44:38 -0700891 adapter_.OnResolutionRequest(rtc::Optional<int>(),
892 rtc::Optional<int>(480 * 270 - 1));
magjed709f73c2016-05-13 10:26:00 -0700893 // Expect cropping to 16:9 format and 1/2 scaling.
nisse47ac4622016-05-25 08:47:01 -0700894 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
895 &cropped_width_, &cropped_height_,
896 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700897 EXPECT_EQ(640, cropped_width_);
898 EXPECT_EQ(360, cropped_height_);
899 EXPECT_EQ(320, out_width_);
900 EXPECT_EQ(180, out_height_);
901
902 // Adapt up one step.
lliuuf9ed2352017-03-30 10:44:38 -0700903 adapter_.OnResolutionRequest(rtc::Optional<int>(480 * 270),
904 rtc::Optional<int>(640 * 360));
magjed709f73c2016-05-13 10:26:00 -0700905 // Expect cropping to 16:9 format and 3/4 scaling.
nisse47ac4622016-05-25 08:47:01 -0700906 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
907 &cropped_width_, &cropped_height_,
908 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700909 EXPECT_EQ(640, cropped_width_);
910 EXPECT_EQ(360, cropped_height_);
911 EXPECT_EQ(480, out_width_);
912 EXPECT_EQ(270, out_height_);
913
914 // Adapt up one step more.
lliuuf9ed2352017-03-30 10:44:38 -0700915 adapter_.OnResolutionRequest(rtc::Optional<int>(640 * 360),
916 rtc::Optional<int>(960 * 540));
magjed709f73c2016-05-13 10:26:00 -0700917 // Expect cropping to 16:9 format and no scaling.
nisse47ac4622016-05-25 08:47:01 -0700918 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
919 &cropped_width_, &cropped_height_,
920 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700921 EXPECT_EQ(640, cropped_width_);
922 EXPECT_EQ(360, cropped_height_);
923 EXPECT_EQ(640, out_width_);
924 EXPECT_EQ(360, out_height_);
925
926 // Try to adapt up one step more.
lliuuf9ed2352017-03-30 10:44:38 -0700927 adapter_.OnResolutionRequest(rtc::Optional<int>(960 * 540),
928 rtc::Optional<int>(1280 * 720));
magjed709f73c2016-05-13 10:26:00 -0700929 // Expect cropping to 16:9 format and no scaling.
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_EQ(640, cropped_width_);
934 EXPECT_EQ(360, cropped_height_);
935 EXPECT_EQ(640, out_width_);
936 EXPECT_EQ(360, out_height_);
937}
938
939TEST_F(VideoAdapterTest, TestCroppingOddResolution) {
940 // Ask for 640x360 (16:9 aspect), with 3/16 scaling.
magjed709f73c2016-05-13 10:26:00 -0700941 adapter_.OnOutputFormatRequest(
magjed604abe02016-05-19 06:05:40 -0700942 VideoFormat(640, 360, 0, FOURCC_I420));
lliuuf9ed2352017-03-30 10:44:38 -0700943 adapter_.OnResolutionRequest(rtc::Optional<int>(),
944 rtc::Optional<int>(640 * 360 * 3 / 16 * 3 / 16));
magjed709f73c2016-05-13 10:26:00 -0700945
946 // Send 640x480 (4:3 aspect).
nisse47ac4622016-05-25 08:47:01 -0700947 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 480, 0,
948 &cropped_width_, &cropped_height_,
949 &out_width_, &out_height_));
magjed709f73c2016-05-13 10:26:00 -0700950
951 // Instead of getting the exact aspect ratio with cropped resolution 640x360,
952 // the resolution should be adjusted to get a perfect scale factor instead.
953 EXPECT_EQ(640, cropped_width_);
954 EXPECT_EQ(368, cropped_height_);
955 EXPECT_EQ(120, out_width_);
956 EXPECT_EQ(69, out_height_);
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000957}
958
kthelgasonc8474172016-12-08 08:04:51 -0800959TEST_F(VideoAdapterTest, TestAdaptToVerySmallResolution) {
960 // Ask for 1920x1080 (16:9 aspect), with 1/16 scaling.
961 const int w = 1920;
962 const int h = 1080;
963 adapter_.OnOutputFormatRequest(VideoFormat(w, h, 0, FOURCC_I420));
lliuuf9ed2352017-03-30 10:44:38 -0700964 adapter_.OnResolutionRequest(rtc::Optional<int>(),
965 rtc::Optional<int>(w * h * 1 / 16 * 1 / 16));
kthelgasonc8474172016-12-08 08:04:51 -0800966
967 // Send 1920x1080 (16:9 aspect).
968 EXPECT_TRUE(adapter_.AdaptFrameResolution(
969 w, h, 0, &cropped_width_, &cropped_height_, &out_width_, &out_height_));
970
971 // Instead of getting the exact aspect ratio with cropped resolution 1920x1080
972 // the resolution should be adjusted to get a perfect scale factor instead.
973 EXPECT_EQ(1920, cropped_width_);
974 EXPECT_EQ(1072, cropped_height_);
975 EXPECT_EQ(120, out_width_);
976 EXPECT_EQ(67, out_height_);
977
978 // Adapt back up one step to 3/32.
lliuuf9ed2352017-03-30 10:44:38 -0700979 adapter_.OnResolutionRequest(rtc::Optional<int>(w * h * 3 / 32 * 3 / 32),
980 rtc::Optional<int>(w * h * 1 / 8 * 1 / 8));
kthelgasonc8474172016-12-08 08:04:51 -0800981
982 // Send 1920x1080 (16:9 aspect).
983 EXPECT_TRUE(adapter_.AdaptFrameResolution(
984 w, h, 0, &cropped_width_, &cropped_height_, &out_width_, &out_height_));
985
986 EXPECT_EQ(180, out_width_);
987 EXPECT_EQ(99, out_height_);
988}
989
990TEST_F(VideoAdapterTest, AdaptFrameResolutionDropWithResolutionRequest) {
991 VideoFormat output_format = capture_format_;
992 output_format.width = 0;
993 output_format.height = 0;
994 adapter_.OnOutputFormatRequest(output_format);
995 EXPECT_FALSE(adapter_.AdaptFrameResolution(
996 capture_format_.width, capture_format_.height, 0,
997 &cropped_width_, &cropped_height_,
998 &out_width_, &out_height_));
999
lliuuf9ed2352017-03-30 10:44:38 -07001000 adapter_.OnResolutionRequest(rtc::Optional<int>(960 * 540),
1001 rtc::Optional<int>());
kthelgasonc8474172016-12-08 08:04:51 -08001002
1003 // Still expect all frames to be dropped
1004 EXPECT_FALSE(adapter_.AdaptFrameResolution(
1005 capture_format_.width, capture_format_.height, 0,
1006 &cropped_width_, &cropped_height_,
1007 &out_width_, &out_height_));
1008
lliuuf9ed2352017-03-30 10:44:38 -07001009 adapter_.OnResolutionRequest(rtc::Optional<int>(),
1010 rtc::Optional<int>(640 * 480 - 1));
kthelgasonc8474172016-12-08 08:04:51 -08001011
1012 // Still expect all frames to be dropped
1013 EXPECT_FALSE(adapter_.AdaptFrameResolution(
1014 capture_format_.width, capture_format_.height, 0,
1015 &cropped_width_, &cropped_height_,
1016 &out_width_, &out_height_));
1017}
1018
Magnus Jedvert6d230d72017-02-22 18:30:27 +01001019// Test that we will adapt to max given a target pixel count close to max.
1020TEST_F(VideoAdapterTest, TestAdaptToMax) {
1021 adapter_.OnOutputFormatRequest(VideoFormat(640, 360, 0, FOURCC_I420));
lliuuf9ed2352017-03-30 10:44:38 -07001022 adapter_.OnResolutionRequest(rtc::Optional<int>(640 * 360 - 1) /* target */,
1023 rtc::Optional<int>());
Magnus Jedvert6d230d72017-02-22 18:30:27 +01001024
1025 EXPECT_TRUE(adapter_.AdaptFrameResolution(640, 360, 0, &cropped_width_,
1026 &cropped_height_, &out_width_,
1027 &out_height_));
1028 EXPECT_EQ(640, out_width_);
1029 EXPECT_EQ(360, out_height_);
1030}
lliuuf9ed2352017-03-30 10:44:38 -07001031
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00001032} // namespace cricket