blob: f385d59551f84d740fc792704cca51a89bd620e2 [file] [log] [blame]
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2008 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 */
henrike@webrtc.org28e20752013-07-10 00:45:36 +000010
11#include <stdio.h>
12#include <vector>
13
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000014#include "webrtc/base/gunit.h"
15#include "webrtc/base/logging.h"
16#include "webrtc/base/thread.h"
kjellandera96e2d72016-02-04 23:52:28 -080017#include "webrtc/media/base/fakevideocapturer.h"
18#include "webrtc/media/base/fakevideorenderer.h"
19#include "webrtc/media/base/testutils.h"
20#include "webrtc/media/base/videocapturer.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000021
henrike@webrtc.org28e20752013-07-10 00:45:36 +000022using cricket::FakeVideoCapturer;
23
24namespace {
25
26const int kMsCallbackWait = 500;
27// For HD only the height matters.
28const int kMinHdHeight = 720;
perkj74622e02016-02-26 02:54:38 -080029const uint32_t kTimeout = 5000U;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000030
31} // namespace
32
henrike@webrtc.org28e20752013-07-10 00:45:36 +000033class VideoCapturerTest
34 : public sigslot::has_slots<>,
35 public testing::Test {
36 public:
37 VideoCapturerTest()
Pera5092412016-02-12 13:30:57 +010038 : capture_state_(cricket::CS_STOPPED), num_state_changes_(0) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000039 capturer_.SignalStateChange.connect(this,
40 &VideoCapturerTest::OnStateChange);
Pera5092412016-02-12 13:30:57 +010041 capturer_.AddOrUpdateSink(&renderer_, rtc::VideoSinkWants());
guoweis@webrtc.org1226e922015-02-11 18:37:54 +000042 }
43
henrike@webrtc.org28e20752013-07-10 00:45:36 +000044 protected:
henrike@webrtc.org28e20752013-07-10 00:45:36 +000045 void OnStateChange(cricket::VideoCapturer*,
46 cricket::CaptureState capture_state) {
47 capture_state_ = capture_state;
48 ++num_state_changes_;
49 }
50 cricket::CaptureState capture_state() { return capture_state_; }
51 int num_state_changes() { return num_state_changes_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000052
53 cricket::FakeVideoCapturer capturer_;
54 cricket::CaptureState capture_state_;
55 int num_state_changes_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000056 cricket::FakeVideoRenderer renderer_;
guoweis@webrtc.org1226e922015-02-11 18:37:54 +000057 bool expects_rotation_applied_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000058};
59
60TEST_F(VideoCapturerTest, CaptureState) {
henrike@webrtc.orga7b98182014-02-21 15:51:43 +000061 EXPECT_TRUE(capturer_.enable_video_adapter());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000062 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
63 640,
64 480,
65 cricket::VideoFormat::FpsToInterval(30),
66 cricket::FOURCC_I420)));
67 EXPECT_TRUE(capturer_.IsRunning());
68 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
69 EXPECT_EQ(1, num_state_changes());
70 capturer_.Stop();
71 EXPECT_EQ_WAIT(cricket::CS_STOPPED, capture_state(), kMsCallbackWait);
72 EXPECT_EQ(2, num_state_changes());
73 capturer_.Stop();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000074 rtc::Thread::Current()->ProcessMessages(100);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075 EXPECT_EQ(2, num_state_changes());
76}
77
perkj74622e02016-02-26 02:54:38 -080078TEST_F(VideoCapturerTest, TestRestart) {
79 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
80 640,
81 480,
82 cricket::VideoFormat::FpsToInterval(30),
83 cricket::FOURCC_I420)));
84 EXPECT_TRUE(capturer_.IsRunning());
85 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
86 EXPECT_EQ(1, num_state_changes());
87 EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat(
88 320,
89 240,
90 cricket::VideoFormat::FpsToInterval(30),
91 cricket::FOURCC_I420)));
92 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
93 EXPECT_TRUE(capturer_.IsRunning());
94 EXPECT_GE(1, num_state_changes());
95 capturer_.Stop();
96 rtc::Thread::Current()->ProcessMessages(100);
97 EXPECT_FALSE(capturer_.IsRunning());
98}
99
100TEST_F(VideoCapturerTest, TestStartingWithRestart) {
101 EXPECT_FALSE(capturer_.IsRunning());
102 EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat(
103 640,
104 480,
105 cricket::VideoFormat::FpsToInterval(30),
106 cricket::FOURCC_I420)));
107 EXPECT_TRUE(capturer_.IsRunning());
108 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
109}
110
111TEST_F(VideoCapturerTest, TestRestartWithSameFormat) {
112 cricket::VideoFormat format(640, 480,
113 cricket::VideoFormat::FpsToInterval(30),
114 cricket::FOURCC_I420);
115 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(format));
116 EXPECT_TRUE(capturer_.IsRunning());
117 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
118 EXPECT_EQ(1, num_state_changes());
119 EXPECT_TRUE(capturer_.Restart(format));
120 EXPECT_EQ(cricket::CS_RUNNING, capture_state());
121 EXPECT_TRUE(capturer_.IsRunning());
122 EXPECT_EQ(1, num_state_changes());
123}
124
125TEST_F(VideoCapturerTest, CameraOffOnMute) {
126 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
127 640,
128 480,
129 cricket::VideoFormat::FpsToInterval(30),
130 cricket::FOURCC_I420)));
131 EXPECT_TRUE(capturer_.IsRunning());
132 EXPECT_EQ(0, renderer_.num_rendered_frames());
133 EXPECT_TRUE(capturer_.CaptureFrame());
134 EXPECT_EQ(1, renderer_.num_rendered_frames());
135 EXPECT_FALSE(capturer_.IsMuted());
136
137 // Mute the camera and expect black output frame.
138 capturer_.MuteToBlackThenPause(true);
139 EXPECT_TRUE(capturer_.IsMuted());
140 for (int i = 0; i < 31; ++i) {
141 EXPECT_TRUE(capturer_.CaptureFrame());
142 EXPECT_TRUE(renderer_.black_frame());
143 }
144 EXPECT_EQ(32, renderer_.num_rendered_frames());
145 EXPECT_EQ_WAIT(cricket::CS_PAUSED,
146 capturer_.capture_state(), kTimeout);
147
148 // Verify that the camera is off.
149 EXPECT_FALSE(capturer_.CaptureFrame());
150 EXPECT_EQ(32, renderer_.num_rendered_frames());
151
152 // Unmute the camera and expect non-black output frame.
153 capturer_.MuteToBlackThenPause(false);
154 EXPECT_FALSE(capturer_.IsMuted());
155 EXPECT_EQ_WAIT(cricket::CS_RUNNING,
156 capturer_.capture_state(), kTimeout);
157 EXPECT_TRUE(capturer_.CaptureFrame());
158 EXPECT_FALSE(renderer_.black_frame());
159 EXPECT_EQ(33, renderer_.num_rendered_frames());
160}
161
buildbot@webrtc.org53f57932014-06-16 21:08:51 +0000162TEST_F(VideoCapturerTest, ScreencastScaledOddWidth) {
163 capturer_.SetScreencast(true);
164
165 int kWidth = 1281;
166 int kHeight = 720;
167
168 std::vector<cricket::VideoFormat> formats;
169 formats.push_back(cricket::VideoFormat(kWidth, kHeight,
170 cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB));
171 capturer_.ResetSupportedFormats(formats);
172
173 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
174 kWidth,
175 kHeight,
176 cricket::VideoFormat::FpsToInterval(30),
177 cricket::FOURCC_ARGB)));
178 EXPECT_TRUE(capturer_.IsRunning());
179 EXPECT_EQ(0, renderer_.num_rendered_frames());
buildbot@webrtc.org53f57932014-06-16 21:08:51 +0000180 EXPECT_TRUE(capturer_.CaptureFrame());
181 EXPECT_EQ(1, renderer_.num_rendered_frames());
nissec4c84852016-01-19 00:52:47 -0800182 EXPECT_EQ(kWidth, renderer_.width());
183 EXPECT_EQ(kHeight, renderer_.height());
buildbot@webrtc.org53f57932014-06-16 21:08:51 +0000184}
185
Pera5092412016-02-12 13:30:57 +0100186TEST_F(VideoCapturerTest, TestRotationAppliedBySource) {
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000187 int kWidth = 800;
188 int kHeight = 400;
189 int frame_count = 0;
190
191 std::vector<cricket::VideoFormat> formats;
192 formats.push_back(cricket::VideoFormat(kWidth, kHeight,
193 cricket::VideoFormat::FpsToInterval(5),
194 cricket::FOURCC_I420));
195
196 capturer_.ResetSupportedFormats(formats);
Pera5092412016-02-12 13:30:57 +0100197
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000198 // capturer_ should compensate rotation as default.
perkj74622e02016-02-26 02:54:38 -0800199 capturer_.UpdateAspectRatio(400, 200);
200
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000201 EXPECT_EQ(cricket::CS_RUNNING,
202 capturer_.Start(cricket::VideoFormat(
203 kWidth, kHeight, cricket::VideoFormat::FpsToInterval(30),
204 cricket::FOURCC_I420)));
205 EXPECT_TRUE(capturer_.IsRunning());
206 EXPECT_EQ(0, renderer_.num_rendered_frames());
207
208 // If the frame's rotation is compensated anywhere in the pipeline based on
209 // the rotation information, the renderer should be given the right dimension
210 // such that the frame could be rendered.
211
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000212 capturer_.SetRotation(webrtc::kVideoRotation_90);
213 EXPECT_TRUE(capturer_.CaptureFrame());
214 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
nissec4c84852016-01-19 00:52:47 -0800215 // Swapped width and height
216 EXPECT_EQ(kWidth, renderer_.height());
217 EXPECT_EQ(kHeight, renderer_.width());
Pera5092412016-02-12 13:30:57 +0100218 EXPECT_EQ(webrtc::kVideoRotation_0, renderer_.rotation());
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000219
220 capturer_.SetRotation(webrtc::kVideoRotation_270);
221 EXPECT_TRUE(capturer_.CaptureFrame());
222 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
nissec4c84852016-01-19 00:52:47 -0800223 // Swapped width and height
224 EXPECT_EQ(kWidth, renderer_.height());
225 EXPECT_EQ(kHeight, renderer_.width());
Pera5092412016-02-12 13:30:57 +0100226 EXPECT_EQ(webrtc::kVideoRotation_0, renderer_.rotation());
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000227
228 capturer_.SetRotation(webrtc::kVideoRotation_180);
229 EXPECT_TRUE(capturer_.CaptureFrame());
230 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
nissec4c84852016-01-19 00:52:47 -0800231 // Back to normal width and height
232 EXPECT_EQ(kWidth, renderer_.width());
233 EXPECT_EQ(kHeight, renderer_.height());
Pera5092412016-02-12 13:30:57 +0100234 EXPECT_EQ(webrtc::kVideoRotation_0, renderer_.rotation());
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000235}
236
Pera5092412016-02-12 13:30:57 +0100237TEST_F(VideoCapturerTest, TestRotationAppliedBySink) {
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000238 int kWidth = 800;
239 int kHeight = 400;
240
241 std::vector<cricket::VideoFormat> formats;
242 formats.push_back(cricket::VideoFormat(kWidth, kHeight,
243 cricket::VideoFormat::FpsToInterval(5),
244 cricket::FOURCC_I420));
245
246 capturer_.ResetSupportedFormats(formats);
Pera5092412016-02-12 13:30:57 +0100247 rtc::VideoSinkWants wants;
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000248 // capturer_ should not compensate rotation.
Pera5092412016-02-12 13:30:57 +0100249 wants.rotation_applied = false;
250 capturer_.AddOrUpdateSink(&renderer_, wants);
251
perkj74622e02016-02-26 02:54:38 -0800252 capturer_.UpdateAspectRatio(400, 200);
253
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000254 EXPECT_EQ(cricket::CS_RUNNING,
255 capturer_.Start(cricket::VideoFormat(
256 kWidth, kHeight, cricket::VideoFormat::FpsToInterval(30),
257 cricket::FOURCC_I420)));
258 EXPECT_TRUE(capturer_.IsRunning());
259 EXPECT_EQ(0, renderer_.num_rendered_frames());
260
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000261 // If the frame's rotation is compensated anywhere in the pipeline, the frame
262 // won't have its original dimension out from capturer. Since the renderer
263 // here has the same dimension as the capturer, it will skip that frame as the
264 // resolution won't match anymore.
265
266 int frame_count = 0;
267 capturer_.SetRotation(webrtc::kVideoRotation_0);
268 EXPECT_TRUE(capturer_.CaptureFrame());
269 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
Pera5092412016-02-12 13:30:57 +0100270 EXPECT_EQ(capturer_.GetRotation(), renderer_.rotation());
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000271
272 capturer_.SetRotation(webrtc::kVideoRotation_90);
273 EXPECT_TRUE(capturer_.CaptureFrame());
274 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
Pera5092412016-02-12 13:30:57 +0100275 EXPECT_EQ(capturer_.GetRotation(), renderer_.rotation());
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000276
277 capturer_.SetRotation(webrtc::kVideoRotation_180);
278 EXPECT_TRUE(capturer_.CaptureFrame());
279 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
Pera5092412016-02-12 13:30:57 +0100280 EXPECT_EQ(capturer_.GetRotation(), renderer_.rotation());
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000281
282 capturer_.SetRotation(webrtc::kVideoRotation_270);
283 EXPECT_TRUE(capturer_.CaptureFrame());
284 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
Pera5092412016-02-12 13:30:57 +0100285 EXPECT_EQ(capturer_.GetRotation(), renderer_.rotation());
286}
287
288TEST_F(VideoCapturerTest, TestRotationAppliedBySourceWhenDifferentWants) {
289 int kWidth = 800;
290 int kHeight = 400;
291
292 std::vector<cricket::VideoFormat> formats;
293 formats.push_back(cricket::VideoFormat(kWidth, kHeight,
294 cricket::VideoFormat::FpsToInterval(5),
295 cricket::FOURCC_I420));
296
297 capturer_.ResetSupportedFormats(formats);
298 rtc::VideoSinkWants wants;
299 // capturer_ should not compensate rotation.
300 wants.rotation_applied = false;
301 capturer_.AddOrUpdateSink(&renderer_, wants);
302
perkj74622e02016-02-26 02:54:38 -0800303 capturer_.UpdateAspectRatio(400, 200);
304
Pera5092412016-02-12 13:30:57 +0100305 EXPECT_EQ(cricket::CS_RUNNING,
306 capturer_.Start(cricket::VideoFormat(
307 kWidth, kHeight, cricket::VideoFormat::FpsToInterval(30),
308 cricket::FOURCC_I420)));
309 EXPECT_TRUE(capturer_.IsRunning());
310 EXPECT_EQ(0, renderer_.num_rendered_frames());
311
312 int frame_count = 0;
313 capturer_.SetRotation(webrtc::kVideoRotation_90);
314 EXPECT_TRUE(capturer_.CaptureFrame());
315 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
316 EXPECT_EQ(capturer_.GetRotation(), renderer_.rotation());
317
318 // Add another sink that wants frames to be rotated.
319 cricket::FakeVideoRenderer renderer2;
320 wants.rotation_applied = true;
321 capturer_.AddOrUpdateSink(&renderer2, wants);
322
323 EXPECT_TRUE(capturer_.CaptureFrame());
324 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
325 EXPECT_EQ(1, renderer2.num_rendered_frames());
326 EXPECT_EQ(webrtc::kVideoRotation_0, renderer_.rotation());
327 EXPECT_EQ(webrtc::kVideoRotation_0, renderer2.rotation());
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000328}
329
buildbot@webrtc.org53f57932014-06-16 21:08:51 +0000330TEST_F(VideoCapturerTest, ScreencastScaledSuperLarge) {
331 capturer_.SetScreencast(true);
332
333 const int kMaxWidth = 4096;
334 const int kMaxHeight = 3072;
335 int kWidth = kMaxWidth + 4;
336 int kHeight = kMaxHeight + 4;
337
338 std::vector<cricket::VideoFormat> formats;
339 formats.push_back(cricket::VideoFormat(kWidth, kHeight,
340 cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB));
341 capturer_.ResetSupportedFormats(formats);
342
343 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
344 kWidth,
345 kHeight,
346 cricket::VideoFormat::FpsToInterval(30),
347 cricket::FOURCC_ARGB)));
348 EXPECT_TRUE(capturer_.IsRunning());
349 EXPECT_EQ(0, renderer_.num_rendered_frames());
buildbot@webrtc.org53f57932014-06-16 21:08:51 +0000350 EXPECT_TRUE(capturer_.CaptureFrame());
351 EXPECT_EQ(1, renderer_.num_rendered_frames());
nissec4c84852016-01-19 00:52:47 -0800352 EXPECT_EQ(kWidth / 2, renderer_.width());
353 EXPECT_EQ(kHeight / 2, renderer_.height());
buildbot@webrtc.org53f57932014-06-16 21:08:51 +0000354}
mallinath@webrtc.org1b15f422013-09-06 22:56:28 +0000355
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000356TEST_F(VideoCapturerTest, TestFourccMatch) {
357 cricket::VideoFormat desired(640, 480,
358 cricket::VideoFormat::FpsToInterval(30),
359 cricket::FOURCC_ANY);
360 cricket::VideoFormat best;
361 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
362 EXPECT_EQ(640, best.width);
363 EXPECT_EQ(480, best.height);
364 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
365
366 desired.fourcc = cricket::FOURCC_MJPG;
367 EXPECT_FALSE(capturer_.GetBestCaptureFormat(desired, &best));
368
369 desired.fourcc = cricket::FOURCC_I420;
370 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
371}
372
373TEST_F(VideoCapturerTest, TestResolutionMatch) {
374 cricket::VideoFormat desired(1920, 1080,
375 cricket::VideoFormat::FpsToInterval(30),
376 cricket::FOURCC_ANY);
377 cricket::VideoFormat best;
378 // Ask for 1920x1080. Get HD 1280x720 which is the highest.
379 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
380 EXPECT_EQ(1280, best.width);
381 EXPECT_EQ(720, best.height);
382 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
383
384 desired.width = 360;
385 desired.height = 250;
386 // Ask for a little higher than QVGA. Get QVGA.
387 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
388 EXPECT_EQ(320, best.width);
389 EXPECT_EQ(240, best.height);
390 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
391
392 desired.width = 480;
magjed@webrtc.org35c1ace2014-11-13 16:21:49 +0000393 desired.height = 270;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000394 // Ask for HVGA. Get VGA.
395 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
396 EXPECT_EQ(640, best.width);
397 EXPECT_EQ(480, best.height);
398 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
399
400 desired.width = 320;
401 desired.height = 240;
402 // Ask for QVGA. Get QVGA.
403 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
404 EXPECT_EQ(320, best.width);
405 EXPECT_EQ(240, best.height);
406 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
407
408 desired.width = 80;
409 desired.height = 60;
410 // Ask for lower than QQVGA. Get QQVGA, which is the lowest.
411 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
412 EXPECT_EQ(160, best.width);
413 EXPECT_EQ(120, best.height);
414 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
415}
416
417TEST_F(VideoCapturerTest, TestHDResolutionMatch) {
418 // Add some HD formats typical of a mediocre HD webcam.
419 std::vector<cricket::VideoFormat> formats;
420 formats.push_back(cricket::VideoFormat(320, 240,
421 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
422 formats.push_back(cricket::VideoFormat(640, 480,
423 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
424 formats.push_back(cricket::VideoFormat(960, 544,
425 cricket::VideoFormat::FpsToInterval(24), cricket::FOURCC_I420));
426 formats.push_back(cricket::VideoFormat(1280, 720,
427 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
428 formats.push_back(cricket::VideoFormat(2592, 1944,
429 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
430 capturer_.ResetSupportedFormats(formats);
431
432 cricket::VideoFormat desired(960, 720,
433 cricket::VideoFormat::FpsToInterval(30),
434 cricket::FOURCC_ANY);
435 cricket::VideoFormat best;
436 // Ask for 960x720 30 fps. Get qHD 24 fps
437 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
438 EXPECT_EQ(960, best.width);
439 EXPECT_EQ(544, best.height);
440 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
441
442 desired.width = 960;
443 desired.height = 544;
444 desired.interval = cricket::VideoFormat::FpsToInterval(30);
445 // Ask for qHD 30 fps. Get qHD 24 fps
446 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
447 EXPECT_EQ(960, best.width);
448 EXPECT_EQ(544, best.height);
449 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
450
451 desired.width = 360;
452 desired.height = 250;
453 desired.interval = cricket::VideoFormat::FpsToInterval(30);
454 // Ask for a little higher than QVGA. Get QVGA.
455 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
456 EXPECT_EQ(320, best.width);
457 EXPECT_EQ(240, best.height);
458 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
459
460 desired.width = 480;
461 desired.height = 270;
462 // Ask for HVGA. Get VGA.
463 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
464 EXPECT_EQ(640, best.width);
465 EXPECT_EQ(480, best.height);
466 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
467
468 desired.width = 320;
469 desired.height = 240;
470 // Ask for QVGA. Get QVGA.
471 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
472 EXPECT_EQ(320, best.width);
473 EXPECT_EQ(240, best.height);
474 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
475
476 desired.width = 160;
477 desired.height = 120;
478 // Ask for lower than QVGA. Get QVGA, which is the lowest.
479 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
480 EXPECT_EQ(320, best.width);
481 EXPECT_EQ(240, best.height);
482 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
483
484 desired.width = 1280;
485 desired.height = 720;
486 // Ask for HD. 720p fps is too low. Get VGA which has 30 fps.
487 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
488 EXPECT_EQ(640, best.width);
489 EXPECT_EQ(480, best.height);
490 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
491
492 desired.width = 1280;
493 desired.height = 720;
494 desired.interval = cricket::VideoFormat::FpsToInterval(15);
495 // Ask for HD 15 fps. Fps matches. Get HD
496 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
497 EXPECT_EQ(1280, best.width);
498 EXPECT_EQ(720, best.height);
499 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
500
501 desired.width = 1920;
502 desired.height = 1080;
503 desired.interval = cricket::VideoFormat::FpsToInterval(30);
504 // Ask for 1080p. Fps of HD formats is too low. Get VGA which can do 30 fps.
505 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
506 EXPECT_EQ(640, best.width);
507 EXPECT_EQ(480, best.height);
508 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
509}
510
511// Some cameras support 320x240 and 320x640. Verify we choose 320x240.
512TEST_F(VideoCapturerTest, TestStrangeFormats) {
513 std::vector<cricket::VideoFormat> supported_formats;
514 supported_formats.push_back(cricket::VideoFormat(320, 240,
515 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
516 supported_formats.push_back(cricket::VideoFormat(320, 640,
517 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
518 capturer_.ResetSupportedFormats(supported_formats);
519
520 std::vector<cricket::VideoFormat> required_formats;
521 required_formats.push_back(cricket::VideoFormat(320, 240,
522 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
523 required_formats.push_back(cricket::VideoFormat(320, 200,
524 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
525 required_formats.push_back(cricket::VideoFormat(320, 180,
526 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
527 cricket::VideoFormat best;
528 for (size_t i = 0; i < required_formats.size(); ++i) {
529 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
530 EXPECT_EQ(320, best.width);
531 EXPECT_EQ(240, best.height);
532 }
533
534 supported_formats.clear();
535 supported_formats.push_back(cricket::VideoFormat(320, 640,
536 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
537 supported_formats.push_back(cricket::VideoFormat(320, 240,
538 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
539 capturer_.ResetSupportedFormats(supported_formats);
540
541 for (size_t i = 0; i < required_formats.size(); ++i) {
542 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
543 EXPECT_EQ(320, best.width);
544 EXPECT_EQ(240, best.height);
545 }
546}
547
548// Some cameras only have very low fps. Verify we choose something sensible.
549TEST_F(VideoCapturerTest, TestPoorFpsFormats) {
550 // all formats are low framerate
551 std::vector<cricket::VideoFormat> supported_formats;
552 supported_formats.push_back(cricket::VideoFormat(320, 240,
553 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
554 supported_formats.push_back(cricket::VideoFormat(640, 480,
555 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
556 supported_formats.push_back(cricket::VideoFormat(1280, 720,
557 cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
558 capturer_.ResetSupportedFormats(supported_formats);
559
560 std::vector<cricket::VideoFormat> required_formats;
561 required_formats.push_back(cricket::VideoFormat(320, 240,
562 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
563 required_formats.push_back(cricket::VideoFormat(640, 480,
564 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
565 cricket::VideoFormat best;
566 for (size_t i = 0; i < required_formats.size(); ++i) {
567 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
568 EXPECT_EQ(required_formats[i].width, best.width);
569 EXPECT_EQ(required_formats[i].height, best.height);
570 }
571
572 // Increase framerate of 320x240. Expect low fps VGA avoided.
573 supported_formats.clear();
574 supported_formats.push_back(cricket::VideoFormat(320, 240,
575 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
576 supported_formats.push_back(cricket::VideoFormat(640, 480,
577 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
578 supported_formats.push_back(cricket::VideoFormat(1280, 720,
579 cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
580 capturer_.ResetSupportedFormats(supported_formats);
581
582 for (size_t i = 0; i < required_formats.size(); ++i) {
583 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
584 EXPECT_EQ(320, best.width);
585 EXPECT_EQ(240, best.height);
586 }
587}
588
589// Some cameras support same size with different frame rates. Verify we choose
590// the frame rate properly.
591TEST_F(VideoCapturerTest, TestSameSizeDifferentFpsFormats) {
592 std::vector<cricket::VideoFormat> supported_formats;
593 supported_formats.push_back(cricket::VideoFormat(320, 240,
594 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
595 supported_formats.push_back(cricket::VideoFormat(320, 240,
596 cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_I420));
597 supported_formats.push_back(cricket::VideoFormat(320, 240,
598 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
599 capturer_.ResetSupportedFormats(supported_formats);
600
601 std::vector<cricket::VideoFormat> required_formats = supported_formats;
602 cricket::VideoFormat best;
603 for (size_t i = 0; i < required_formats.size(); ++i) {
604 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
605 EXPECT_EQ(320, best.width);
606 EXPECT_EQ(240, best.height);
607 EXPECT_EQ(required_formats[i].interval, best.interval);
608 }
609}
610
611// Some cameras support the correct resolution but at a lower fps than
612// we'd like. This tests we get the expected resolution and fps.
613TEST_F(VideoCapturerTest, TestFpsFormats) {
614 // We have VGA but low fps. Choose VGA, not HD
615 std::vector<cricket::VideoFormat> supported_formats;
616 supported_formats.push_back(cricket::VideoFormat(1280, 720,
617 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
618 supported_formats.push_back(cricket::VideoFormat(640, 480,
619 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
620 supported_formats.push_back(cricket::VideoFormat(640, 400,
621 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
622 supported_formats.push_back(cricket::VideoFormat(640, 360,
623 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
624 capturer_.ResetSupportedFormats(supported_formats);
625
626 std::vector<cricket::VideoFormat> required_formats;
627 required_formats.push_back(cricket::VideoFormat(640, 480,
628 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_ANY));
629 required_formats.push_back(cricket::VideoFormat(640, 480,
630 cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_ANY));
631 required_formats.push_back(cricket::VideoFormat(640, 480,
632 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_ANY));
633 cricket::VideoFormat best;
634
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000635 // Expect 30 fps to choose 30 fps format.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000636 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
637 EXPECT_EQ(640, best.width);
638 EXPECT_EQ(400, best.height);
639 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
640
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000641 // Expect 20 fps to choose 30 fps format.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000642 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
643 EXPECT_EQ(640, best.width);
644 EXPECT_EQ(400, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000645 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000646
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000647 // Expect 10 fps to choose 15 fps format and set fps to 15.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000648 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
649 EXPECT_EQ(640, best.width);
650 EXPECT_EQ(480, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000651 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000652
653 // We have VGA 60 fps and 15 fps. Choose best fps.
654 supported_formats.clear();
655 supported_formats.push_back(cricket::VideoFormat(1280, 720,
656 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
657 supported_formats.push_back(cricket::VideoFormat(640, 480,
658 cricket::VideoFormat::FpsToInterval(60), cricket::FOURCC_MJPG));
659 supported_formats.push_back(cricket::VideoFormat(640, 480,
660 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
661 supported_formats.push_back(cricket::VideoFormat(640, 400,
662 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
663 supported_formats.push_back(cricket::VideoFormat(640, 360,
664 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
665 capturer_.ResetSupportedFormats(supported_formats);
666
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000667 // Expect 30 fps to choose 60 fps format and will set best fps to 60.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000668 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
669 EXPECT_EQ(640, best.width);
670 EXPECT_EQ(480, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000671 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000672
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000673 // Expect 20 fps to choose 60 fps format, and will set best fps to 60.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000674 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
675 EXPECT_EQ(640, best.width);
676 EXPECT_EQ(480, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000677 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000678
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000679 // Expect 10 fps to choose 15 fps.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000680 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
681 EXPECT_EQ(640, best.width);
682 EXPECT_EQ(480, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000683 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000684}
685
686TEST_F(VideoCapturerTest, TestRequest16x10_9) {
687 std::vector<cricket::VideoFormat> supported_formats;
688 // We do not support HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
689 supported_formats.push_back(cricket::VideoFormat(640, 480,
690 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
691 supported_formats.push_back(cricket::VideoFormat(640, 400,
692 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
693 supported_formats.push_back(cricket::VideoFormat(640, 360,
694 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
695 capturer_.ResetSupportedFormats(supported_formats);
696
697 std::vector<cricket::VideoFormat> required_formats = supported_formats;
698 cricket::VideoFormat best;
699 // Expect 4x3, 16x10, and 16x9 requests are respected.
700 for (size_t i = 0; i < required_formats.size(); ++i) {
701 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
702 EXPECT_EQ(required_formats[i].width, best.width);
703 EXPECT_EQ(required_formats[i].height, best.height);
704 }
705
706 // We do not support 16x9 HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
707 supported_formats.clear();
708 supported_formats.push_back(cricket::VideoFormat(960, 720,
709 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
710 supported_formats.push_back(cricket::VideoFormat(640, 480,
711 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
712 supported_formats.push_back(cricket::VideoFormat(640, 400,
713 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
714 supported_formats.push_back(cricket::VideoFormat(640, 360,
715 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
716 capturer_.ResetSupportedFormats(supported_formats);
717
718 // Expect 4x3, 16x10, and 16x9 requests are respected.
719 for (size_t i = 0; i < required_formats.size(); ++i) {
720 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
721 EXPECT_EQ(required_formats[i].width, best.width);
722 EXPECT_EQ(required_formats[i].height, best.height);
723 }
724
725 // We support 16x9HD, Expect 4x3, 16x10, and 16x9 requests are respected.
726 supported_formats.clear();
727 supported_formats.push_back(cricket::VideoFormat(1280, 720,
728 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
729 supported_formats.push_back(cricket::VideoFormat(640, 480,
730 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
731 supported_formats.push_back(cricket::VideoFormat(640, 400,
732 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
733 supported_formats.push_back(cricket::VideoFormat(640, 360,
734 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
735 capturer_.ResetSupportedFormats(supported_formats);
736
737 // Expect 4x3 for 4x3 and 16x10 requests.
738 for (size_t i = 0; i < required_formats.size() - 1; ++i) {
739 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
740 EXPECT_EQ(required_formats[i].width, best.width);
741 EXPECT_EQ(required_formats[i].height, best.height);
742 }
743
744 // Expect 16x9 for 16x9 request.
745 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
746 EXPECT_EQ(640, best.width);
747 EXPECT_EQ(360, best.height);
748}
749
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000750bool HdFormatInList(const std::vector<cricket::VideoFormat>& formats) {
751 for (std::vector<cricket::VideoFormat>::const_iterator found =
752 formats.begin(); found != formats.end(); ++found) {
753 if (found->height >= kMinHdHeight) {
754 return true;
755 }
756 }
757 return false;
758}
759
760TEST_F(VideoCapturerTest, Whitelist) {
761 // The definition of HD only applies to the height. Set the HD width to the
762 // smallest legal number to document this fact in this test.
763 const int kMinHdWidth = 1;
764 cricket::VideoFormat hd_format(kMinHdWidth,
765 kMinHdHeight,
766 cricket::VideoFormat::FpsToInterval(30),
767 cricket::FOURCC_I420);
768 cricket::VideoFormat vga_format(640, 480,
769 cricket::VideoFormat::FpsToInterval(30),
770 cricket::FOURCC_I420);
771 std::vector<cricket::VideoFormat> formats = *capturer_.GetSupportedFormats();
772 formats.push_back(hd_format);
773
774 // Enable whitelist. Expect HD not in list.
775 capturer_.set_enable_camera_list(true);
776 capturer_.ResetSupportedFormats(formats);
777 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
778 capturer_.ConstrainSupportedFormats(vga_format);
779 EXPECT_FALSE(HdFormatInList(*capturer_.GetSupportedFormats()));
780
781 // Disable whitelist. Expect HD in list.
782 capturer_.set_enable_camera_list(false);
783 capturer_.ResetSupportedFormats(formats);
784 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
785 capturer_.ConstrainSupportedFormats(vga_format);
786 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
787}
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000788
789TEST_F(VideoCapturerTest, BlacklistAllFormats) {
790 cricket::VideoFormat vga_format(640, 480,
791 cricket::VideoFormat::FpsToInterval(30),
792 cricket::FOURCC_I420);
793 std::vector<cricket::VideoFormat> supported_formats;
794 // Mock a device that only supports HD formats.
795 supported_formats.push_back(cricket::VideoFormat(1280, 720,
796 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
797 supported_formats.push_back(cricket::VideoFormat(1920, 1080,
798 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
799 capturer_.ResetSupportedFormats(supported_formats);
800 EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size());
801 // Now, enable the list, which would exclude both formats. However, since
802 // only HD formats are available, we refuse to filter at all, so we don't
803 // break this camera.
804 capturer_.set_enable_camera_list(true);
805 capturer_.ConstrainSupportedFormats(vga_format);
806 EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size());
807 // To make sure it's not just the camera list being broken, add in VGA and
808 // try again. This time, only the VGA format should be there.
809 supported_formats.push_back(vga_format);
810 capturer_.ResetSupportedFormats(supported_formats);
811 ASSERT_EQ(1u, capturer_.GetSupportedFormats()->size());
812 EXPECT_EQ(vga_format.height, capturer_.GetSupportedFormats()->at(0).height);
813}