blob: cbd92c5b8c32cf804b85274c652b88fb5b7b02ce [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;
Peter Boström0c4e06b2015-10-07 12:23:21 +020029const 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()
38 : capture_state_(cricket::CS_STOPPED),
39 num_state_changes_(0),
40 video_frames_received_(0),
guoweis@webrtc.org1226e922015-02-11 18:37:54 +000041 expects_rotation_applied_(true) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000042 capturer_.SignalVideoFrame.connect(this, &VideoCapturerTest::OnVideoFrame);
43 capturer_.SignalStateChange.connect(this,
44 &VideoCapturerTest::OnStateChange);
45 }
46
guoweis@webrtc.org1226e922015-02-11 18:37:54 +000047 void set_expected_compensation(bool compensation) {
48 expects_rotation_applied_ = compensation;
49 }
50
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051 protected:
52 void OnVideoFrame(cricket::VideoCapturer*, const cricket::VideoFrame* frame) {
53 ++video_frames_received_;
guoweis@webrtc.org1226e922015-02-11 18:37:54 +000054 if (expects_rotation_applied_) {
55 EXPECT_EQ(webrtc::kVideoRotation_0, frame->GetRotation());
56 } else {
57 EXPECT_EQ(capturer_.GetRotation(), frame->GetRotation());
58 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000059 renderer_.RenderFrame(frame);
60 }
61 void OnStateChange(cricket::VideoCapturer*,
62 cricket::CaptureState capture_state) {
63 capture_state_ = capture_state;
64 ++num_state_changes_;
65 }
66 cricket::CaptureState capture_state() { return capture_state_; }
67 int num_state_changes() { return num_state_changes_; }
68 int video_frames_received() const {
69 return video_frames_received_;
70 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000071
72 cricket::FakeVideoCapturer capturer_;
73 cricket::CaptureState capture_state_;
74 int num_state_changes_;
75 int video_frames_received_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000076 cricket::FakeVideoRenderer renderer_;
guoweis@webrtc.org1226e922015-02-11 18:37:54 +000077 bool expects_rotation_applied_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000078};
79
80TEST_F(VideoCapturerTest, CaptureState) {
henrike@webrtc.orga7b98182014-02-21 15:51:43 +000081 EXPECT_TRUE(capturer_.enable_video_adapter());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000082 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
83 640,
84 480,
85 cricket::VideoFormat::FpsToInterval(30),
86 cricket::FOURCC_I420)));
87 EXPECT_TRUE(capturer_.IsRunning());
88 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
89 EXPECT_EQ(1, num_state_changes());
90 capturer_.Stop();
91 EXPECT_EQ_WAIT(cricket::CS_STOPPED, capture_state(), kMsCallbackWait);
92 EXPECT_EQ(2, num_state_changes());
93 capturer_.Stop();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000094 rtc::Thread::Current()->ProcessMessages(100);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095 EXPECT_EQ(2, num_state_changes());
96}
97
98TEST_F(VideoCapturerTest, TestRestart) {
99 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
100 640,
101 480,
102 cricket::VideoFormat::FpsToInterval(30),
103 cricket::FOURCC_I420)));
104 EXPECT_TRUE(capturer_.IsRunning());
105 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
106 EXPECT_EQ(1, num_state_changes());
107 EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat(
108 320,
109 240,
110 cricket::VideoFormat::FpsToInterval(30),
111 cricket::FOURCC_I420)));
112 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
113 EXPECT_TRUE(capturer_.IsRunning());
114 EXPECT_GE(1, num_state_changes());
115 capturer_.Stop();
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000116 rtc::Thread::Current()->ProcessMessages(100);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000117 EXPECT_FALSE(capturer_.IsRunning());
118}
119
120TEST_F(VideoCapturerTest, TestStartingWithRestart) {
121 EXPECT_FALSE(capturer_.IsRunning());
122 EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat(
123 640,
124 480,
125 cricket::VideoFormat::FpsToInterval(30),
126 cricket::FOURCC_I420)));
127 EXPECT_TRUE(capturer_.IsRunning());
128 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
129}
130
131TEST_F(VideoCapturerTest, TestRestartWithSameFormat) {
132 cricket::VideoFormat format(640, 480,
133 cricket::VideoFormat::FpsToInterval(30),
134 cricket::FOURCC_I420);
135 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(format));
136 EXPECT_TRUE(capturer_.IsRunning());
137 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
138 EXPECT_EQ(1, num_state_changes());
139 EXPECT_TRUE(capturer_.Restart(format));
140 EXPECT_EQ(cricket::CS_RUNNING, capture_state());
141 EXPECT_TRUE(capturer_.IsRunning());
142 EXPECT_EQ(1, num_state_changes());
143}
144
145TEST_F(VideoCapturerTest, CameraOffOnMute) {
146 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
147 640,
148 480,
149 cricket::VideoFormat::FpsToInterval(30),
150 cricket::FOURCC_I420)));
151 EXPECT_TRUE(capturer_.IsRunning());
152 EXPECT_EQ(0, video_frames_received());
153 EXPECT_TRUE(capturer_.CaptureFrame());
154 EXPECT_EQ(1, video_frames_received());
155 EXPECT_FALSE(capturer_.IsMuted());
156
157 // Mute the camera and expect black output frame.
158 capturer_.MuteToBlackThenPause(true);
159 EXPECT_TRUE(capturer_.IsMuted());
160 for (int i = 0; i < 31; ++i) {
161 EXPECT_TRUE(capturer_.CaptureFrame());
162 EXPECT_TRUE(renderer_.black_frame());
163 }
164 EXPECT_EQ(32, video_frames_received());
165 EXPECT_EQ_WAIT(cricket::CS_PAUSED,
166 capturer_.capture_state(), kTimeout);
167
168 // Verify that the camera is off.
169 EXPECT_FALSE(capturer_.CaptureFrame());
170 EXPECT_EQ(32, video_frames_received());
171
172 // Unmute the camera and expect non-black output frame.
173 capturer_.MuteToBlackThenPause(false);
174 EXPECT_FALSE(capturer_.IsMuted());
175 EXPECT_EQ_WAIT(cricket::CS_RUNNING,
176 capturer_.capture_state(), kTimeout);
177 EXPECT_TRUE(capturer_.CaptureFrame());
178 EXPECT_FALSE(renderer_.black_frame());
179 EXPECT_EQ(33, video_frames_received());
180}
181
buildbot@webrtc.org53f57932014-06-16 21:08:51 +0000182TEST_F(VideoCapturerTest, ScreencastScaledOddWidth) {
183 capturer_.SetScreencast(true);
184
185 int kWidth = 1281;
186 int kHeight = 720;
187
188 std::vector<cricket::VideoFormat> formats;
189 formats.push_back(cricket::VideoFormat(kWidth, kHeight,
190 cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB));
191 capturer_.ResetSupportedFormats(formats);
192
193 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
194 kWidth,
195 kHeight,
196 cricket::VideoFormat::FpsToInterval(30),
197 cricket::FOURCC_ARGB)));
198 EXPECT_TRUE(capturer_.IsRunning());
199 EXPECT_EQ(0, renderer_.num_rendered_frames());
buildbot@webrtc.org53f57932014-06-16 21:08:51 +0000200 EXPECT_TRUE(capturer_.CaptureFrame());
201 EXPECT_EQ(1, renderer_.num_rendered_frames());
nissec4c84852016-01-19 00:52:47 -0800202 EXPECT_EQ(kWidth, renderer_.width());
203 EXPECT_EQ(kHeight, renderer_.height());
buildbot@webrtc.org53f57932014-06-16 21:08:51 +0000204}
205
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000206TEST_F(VideoCapturerTest, TestRotationPending) {
207 int kWidth = 800;
208 int kHeight = 400;
209 int frame_count = 0;
210
211 std::vector<cricket::VideoFormat> formats;
212 formats.push_back(cricket::VideoFormat(kWidth, kHeight,
213 cricket::VideoFormat::FpsToInterval(5),
214 cricket::FOURCC_I420));
215
216 capturer_.ResetSupportedFormats(formats);
217 // capturer_ should compensate rotation as default.
218 capturer_.UpdateAspectRatio(400, 200);
219
220 EXPECT_EQ(cricket::CS_RUNNING,
221 capturer_.Start(cricket::VideoFormat(
222 kWidth, kHeight, cricket::VideoFormat::FpsToInterval(30),
223 cricket::FOURCC_I420)));
224 EXPECT_TRUE(capturer_.IsRunning());
225 EXPECT_EQ(0, renderer_.num_rendered_frames());
226
227 // If the frame's rotation is compensated anywhere in the pipeline based on
228 // the rotation information, the renderer should be given the right dimension
229 // such that the frame could be rendered.
230
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000231 capturer_.SetRotation(webrtc::kVideoRotation_90);
232 EXPECT_TRUE(capturer_.CaptureFrame());
233 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
nissec4c84852016-01-19 00:52:47 -0800234 // Swapped width and height
235 EXPECT_EQ(kWidth, renderer_.height());
236 EXPECT_EQ(kHeight, renderer_.width());
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000237
238 capturer_.SetRotation(webrtc::kVideoRotation_270);
239 EXPECT_TRUE(capturer_.CaptureFrame());
240 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
nissec4c84852016-01-19 00:52:47 -0800241 // Swapped width and height
242 EXPECT_EQ(kWidth, renderer_.height());
243 EXPECT_EQ(kHeight, renderer_.width());
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000244
245 capturer_.SetRotation(webrtc::kVideoRotation_180);
246 EXPECT_TRUE(capturer_.CaptureFrame());
247 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
nissec4c84852016-01-19 00:52:47 -0800248 // Back to normal width and height
249 EXPECT_EQ(kWidth, renderer_.width());
250 EXPECT_EQ(kHeight, renderer_.height());
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000251}
252
253TEST_F(VideoCapturerTest, TestRotationApplied) {
254 int kWidth = 800;
255 int kHeight = 400;
256
257 std::vector<cricket::VideoFormat> formats;
258 formats.push_back(cricket::VideoFormat(kWidth, kHeight,
259 cricket::VideoFormat::FpsToInterval(5),
260 cricket::FOURCC_I420));
261
262 capturer_.ResetSupportedFormats(formats);
263 // capturer_ should not compensate rotation.
264 capturer_.SetApplyRotation(false);
265 capturer_.UpdateAspectRatio(400, 200);
266 set_expected_compensation(false);
267
268 EXPECT_EQ(cricket::CS_RUNNING,
269 capturer_.Start(cricket::VideoFormat(
270 kWidth, kHeight, cricket::VideoFormat::FpsToInterval(30),
271 cricket::FOURCC_I420)));
272 EXPECT_TRUE(capturer_.IsRunning());
273 EXPECT_EQ(0, renderer_.num_rendered_frames());
274
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000275 // If the frame's rotation is compensated anywhere in the pipeline, the frame
276 // won't have its original dimension out from capturer. Since the renderer
277 // here has the same dimension as the capturer, it will skip that frame as the
278 // resolution won't match anymore.
279
280 int frame_count = 0;
281 capturer_.SetRotation(webrtc::kVideoRotation_0);
282 EXPECT_TRUE(capturer_.CaptureFrame());
283 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
284
285 capturer_.SetRotation(webrtc::kVideoRotation_90);
286 EXPECT_TRUE(capturer_.CaptureFrame());
287 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
288
289 capturer_.SetRotation(webrtc::kVideoRotation_180);
290 EXPECT_TRUE(capturer_.CaptureFrame());
291 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
292
293 capturer_.SetRotation(webrtc::kVideoRotation_270);
294 EXPECT_TRUE(capturer_.CaptureFrame());
295 EXPECT_EQ(++frame_count, renderer_.num_rendered_frames());
296}
297
buildbot@webrtc.org53f57932014-06-16 21:08:51 +0000298TEST_F(VideoCapturerTest, ScreencastScaledSuperLarge) {
299 capturer_.SetScreencast(true);
300
301 const int kMaxWidth = 4096;
302 const int kMaxHeight = 3072;
303 int kWidth = kMaxWidth + 4;
304 int kHeight = kMaxHeight + 4;
305
306 std::vector<cricket::VideoFormat> formats;
307 formats.push_back(cricket::VideoFormat(kWidth, kHeight,
308 cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB));
309 capturer_.ResetSupportedFormats(formats);
310
311 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
312 kWidth,
313 kHeight,
314 cricket::VideoFormat::FpsToInterval(30),
315 cricket::FOURCC_ARGB)));
316 EXPECT_TRUE(capturer_.IsRunning());
317 EXPECT_EQ(0, renderer_.num_rendered_frames());
buildbot@webrtc.org53f57932014-06-16 21:08:51 +0000318 EXPECT_TRUE(capturer_.CaptureFrame());
319 EXPECT_EQ(1, renderer_.num_rendered_frames());
nissec4c84852016-01-19 00:52:47 -0800320 EXPECT_EQ(kWidth / 2, renderer_.width());
321 EXPECT_EQ(kHeight / 2, renderer_.height());
buildbot@webrtc.org53f57932014-06-16 21:08:51 +0000322}
mallinath@webrtc.org1b15f422013-09-06 22:56:28 +0000323
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000324TEST_F(VideoCapturerTest, TestFourccMatch) {
325 cricket::VideoFormat desired(640, 480,
326 cricket::VideoFormat::FpsToInterval(30),
327 cricket::FOURCC_ANY);
328 cricket::VideoFormat best;
329 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
330 EXPECT_EQ(640, best.width);
331 EXPECT_EQ(480, best.height);
332 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
333
334 desired.fourcc = cricket::FOURCC_MJPG;
335 EXPECT_FALSE(capturer_.GetBestCaptureFormat(desired, &best));
336
337 desired.fourcc = cricket::FOURCC_I420;
338 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
339}
340
341TEST_F(VideoCapturerTest, TestResolutionMatch) {
342 cricket::VideoFormat desired(1920, 1080,
343 cricket::VideoFormat::FpsToInterval(30),
344 cricket::FOURCC_ANY);
345 cricket::VideoFormat best;
346 // Ask for 1920x1080. Get HD 1280x720 which is the highest.
347 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
348 EXPECT_EQ(1280, best.width);
349 EXPECT_EQ(720, best.height);
350 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
351
352 desired.width = 360;
353 desired.height = 250;
354 // Ask for a little higher than QVGA. Get QVGA.
355 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
356 EXPECT_EQ(320, best.width);
357 EXPECT_EQ(240, best.height);
358 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
359
360 desired.width = 480;
magjed@webrtc.org35c1ace2014-11-13 16:21:49 +0000361 desired.height = 270;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000362 // Ask for HVGA. Get VGA.
363 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
364 EXPECT_EQ(640, best.width);
365 EXPECT_EQ(480, best.height);
366 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
367
368 desired.width = 320;
369 desired.height = 240;
370 // Ask for QVGA. Get QVGA.
371 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
372 EXPECT_EQ(320, best.width);
373 EXPECT_EQ(240, best.height);
374 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
375
376 desired.width = 80;
377 desired.height = 60;
378 // Ask for lower than QQVGA. Get QQVGA, which is the lowest.
379 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
380 EXPECT_EQ(160, best.width);
381 EXPECT_EQ(120, best.height);
382 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
383}
384
385TEST_F(VideoCapturerTest, TestHDResolutionMatch) {
386 // Add some HD formats typical of a mediocre HD webcam.
387 std::vector<cricket::VideoFormat> formats;
388 formats.push_back(cricket::VideoFormat(320, 240,
389 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
390 formats.push_back(cricket::VideoFormat(640, 480,
391 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
392 formats.push_back(cricket::VideoFormat(960, 544,
393 cricket::VideoFormat::FpsToInterval(24), cricket::FOURCC_I420));
394 formats.push_back(cricket::VideoFormat(1280, 720,
395 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
396 formats.push_back(cricket::VideoFormat(2592, 1944,
397 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
398 capturer_.ResetSupportedFormats(formats);
399
400 cricket::VideoFormat desired(960, 720,
401 cricket::VideoFormat::FpsToInterval(30),
402 cricket::FOURCC_ANY);
403 cricket::VideoFormat best;
404 // Ask for 960x720 30 fps. Get qHD 24 fps
405 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
406 EXPECT_EQ(960, best.width);
407 EXPECT_EQ(544, best.height);
408 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
409
410 desired.width = 960;
411 desired.height = 544;
412 desired.interval = cricket::VideoFormat::FpsToInterval(30);
413 // Ask for qHD 30 fps. Get qHD 24 fps
414 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
415 EXPECT_EQ(960, best.width);
416 EXPECT_EQ(544, best.height);
417 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
418
419 desired.width = 360;
420 desired.height = 250;
421 desired.interval = cricket::VideoFormat::FpsToInterval(30);
422 // Ask for a little higher than QVGA. Get QVGA.
423 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
424 EXPECT_EQ(320, best.width);
425 EXPECT_EQ(240, best.height);
426 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
427
428 desired.width = 480;
429 desired.height = 270;
430 // Ask for HVGA. Get VGA.
431 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
432 EXPECT_EQ(640, best.width);
433 EXPECT_EQ(480, best.height);
434 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
435
436 desired.width = 320;
437 desired.height = 240;
438 // Ask for QVGA. Get QVGA.
439 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
440 EXPECT_EQ(320, best.width);
441 EXPECT_EQ(240, best.height);
442 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
443
444 desired.width = 160;
445 desired.height = 120;
446 // Ask for lower than QVGA. Get QVGA, which is the lowest.
447 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
448 EXPECT_EQ(320, best.width);
449 EXPECT_EQ(240, best.height);
450 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
451
452 desired.width = 1280;
453 desired.height = 720;
454 // Ask for HD. 720p fps is too low. Get VGA which has 30 fps.
455 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
456 EXPECT_EQ(640, best.width);
457 EXPECT_EQ(480, best.height);
458 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
459
460 desired.width = 1280;
461 desired.height = 720;
462 desired.interval = cricket::VideoFormat::FpsToInterval(15);
463 // Ask for HD 15 fps. Fps matches. Get HD
464 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
465 EXPECT_EQ(1280, best.width);
466 EXPECT_EQ(720, best.height);
467 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
468
469 desired.width = 1920;
470 desired.height = 1080;
471 desired.interval = cricket::VideoFormat::FpsToInterval(30);
472 // Ask for 1080p. Fps of HD formats is too low. Get VGA which can do 30 fps.
473 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
474 EXPECT_EQ(640, best.width);
475 EXPECT_EQ(480, best.height);
476 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
477}
478
479// Some cameras support 320x240 and 320x640. Verify we choose 320x240.
480TEST_F(VideoCapturerTest, TestStrangeFormats) {
481 std::vector<cricket::VideoFormat> supported_formats;
482 supported_formats.push_back(cricket::VideoFormat(320, 240,
483 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
484 supported_formats.push_back(cricket::VideoFormat(320, 640,
485 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
486 capturer_.ResetSupportedFormats(supported_formats);
487
488 std::vector<cricket::VideoFormat> required_formats;
489 required_formats.push_back(cricket::VideoFormat(320, 240,
490 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
491 required_formats.push_back(cricket::VideoFormat(320, 200,
492 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
493 required_formats.push_back(cricket::VideoFormat(320, 180,
494 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
495 cricket::VideoFormat best;
496 for (size_t i = 0; i < required_formats.size(); ++i) {
497 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
498 EXPECT_EQ(320, best.width);
499 EXPECT_EQ(240, best.height);
500 }
501
502 supported_formats.clear();
503 supported_formats.push_back(cricket::VideoFormat(320, 640,
504 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
505 supported_formats.push_back(cricket::VideoFormat(320, 240,
506 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
507 capturer_.ResetSupportedFormats(supported_formats);
508
509 for (size_t i = 0; i < required_formats.size(); ++i) {
510 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
511 EXPECT_EQ(320, best.width);
512 EXPECT_EQ(240, best.height);
513 }
514}
515
516// Some cameras only have very low fps. Verify we choose something sensible.
517TEST_F(VideoCapturerTest, TestPoorFpsFormats) {
518 // all formats are low framerate
519 std::vector<cricket::VideoFormat> supported_formats;
520 supported_formats.push_back(cricket::VideoFormat(320, 240,
521 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
522 supported_formats.push_back(cricket::VideoFormat(640, 480,
523 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
524 supported_formats.push_back(cricket::VideoFormat(1280, 720,
525 cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
526 capturer_.ResetSupportedFormats(supported_formats);
527
528 std::vector<cricket::VideoFormat> required_formats;
529 required_formats.push_back(cricket::VideoFormat(320, 240,
530 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
531 required_formats.push_back(cricket::VideoFormat(640, 480,
532 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
533 cricket::VideoFormat best;
534 for (size_t i = 0; i < required_formats.size(); ++i) {
535 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
536 EXPECT_EQ(required_formats[i].width, best.width);
537 EXPECT_EQ(required_formats[i].height, best.height);
538 }
539
540 // Increase framerate of 320x240. Expect low fps VGA avoided.
541 supported_formats.clear();
542 supported_formats.push_back(cricket::VideoFormat(320, 240,
543 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
544 supported_formats.push_back(cricket::VideoFormat(640, 480,
545 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
546 supported_formats.push_back(cricket::VideoFormat(1280, 720,
547 cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
548 capturer_.ResetSupportedFormats(supported_formats);
549
550 for (size_t i = 0; i < required_formats.size(); ++i) {
551 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
552 EXPECT_EQ(320, best.width);
553 EXPECT_EQ(240, best.height);
554 }
555}
556
557// Some cameras support same size with different frame rates. Verify we choose
558// the frame rate properly.
559TEST_F(VideoCapturerTest, TestSameSizeDifferentFpsFormats) {
560 std::vector<cricket::VideoFormat> supported_formats;
561 supported_formats.push_back(cricket::VideoFormat(320, 240,
562 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
563 supported_formats.push_back(cricket::VideoFormat(320, 240,
564 cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_I420));
565 supported_formats.push_back(cricket::VideoFormat(320, 240,
566 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
567 capturer_.ResetSupportedFormats(supported_formats);
568
569 std::vector<cricket::VideoFormat> required_formats = supported_formats;
570 cricket::VideoFormat best;
571 for (size_t i = 0; i < required_formats.size(); ++i) {
572 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
573 EXPECT_EQ(320, best.width);
574 EXPECT_EQ(240, best.height);
575 EXPECT_EQ(required_formats[i].interval, best.interval);
576 }
577}
578
579// Some cameras support the correct resolution but at a lower fps than
580// we'd like. This tests we get the expected resolution and fps.
581TEST_F(VideoCapturerTest, TestFpsFormats) {
582 // We have VGA but low fps. Choose VGA, not HD
583 std::vector<cricket::VideoFormat> supported_formats;
584 supported_formats.push_back(cricket::VideoFormat(1280, 720,
585 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
586 supported_formats.push_back(cricket::VideoFormat(640, 480,
587 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
588 supported_formats.push_back(cricket::VideoFormat(640, 400,
589 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
590 supported_formats.push_back(cricket::VideoFormat(640, 360,
591 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
592 capturer_.ResetSupportedFormats(supported_formats);
593
594 std::vector<cricket::VideoFormat> required_formats;
595 required_formats.push_back(cricket::VideoFormat(640, 480,
596 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_ANY));
597 required_formats.push_back(cricket::VideoFormat(640, 480,
598 cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_ANY));
599 required_formats.push_back(cricket::VideoFormat(640, 480,
600 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_ANY));
601 cricket::VideoFormat best;
602
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000603 // Expect 30 fps to choose 30 fps format.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000604 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
605 EXPECT_EQ(640, best.width);
606 EXPECT_EQ(400, best.height);
607 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
608
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000609 // Expect 20 fps to choose 30 fps format.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000610 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
611 EXPECT_EQ(640, best.width);
612 EXPECT_EQ(400, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000613 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000614
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000615 // Expect 10 fps to choose 15 fps format and set fps to 15.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000616 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
617 EXPECT_EQ(640, best.width);
618 EXPECT_EQ(480, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000619 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000620
621 // We have VGA 60 fps and 15 fps. Choose best fps.
622 supported_formats.clear();
623 supported_formats.push_back(cricket::VideoFormat(1280, 720,
624 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
625 supported_formats.push_back(cricket::VideoFormat(640, 480,
626 cricket::VideoFormat::FpsToInterval(60), cricket::FOURCC_MJPG));
627 supported_formats.push_back(cricket::VideoFormat(640, 480,
628 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
629 supported_formats.push_back(cricket::VideoFormat(640, 400,
630 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
631 supported_formats.push_back(cricket::VideoFormat(640, 360,
632 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
633 capturer_.ResetSupportedFormats(supported_formats);
634
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000635 // Expect 30 fps to choose 60 fps format and will set best fps to 60.
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(480, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000639 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000640
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000641 // Expect 20 fps to choose 60 fps format, and will set best fps to 60.
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(480, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000645 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), 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.
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
654TEST_F(VideoCapturerTest, TestRequest16x10_9) {
655 std::vector<cricket::VideoFormat> supported_formats;
656 // We do not support HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
657 supported_formats.push_back(cricket::VideoFormat(640, 480,
658 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
659 supported_formats.push_back(cricket::VideoFormat(640, 400,
660 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
661 supported_formats.push_back(cricket::VideoFormat(640, 360,
662 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
663 capturer_.ResetSupportedFormats(supported_formats);
664
665 std::vector<cricket::VideoFormat> required_formats = supported_formats;
666 cricket::VideoFormat best;
667 // Expect 4x3, 16x10, and 16x9 requests are respected.
668 for (size_t i = 0; i < required_formats.size(); ++i) {
669 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
670 EXPECT_EQ(required_formats[i].width, best.width);
671 EXPECT_EQ(required_formats[i].height, best.height);
672 }
673
674 // We do not support 16x9 HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
675 supported_formats.clear();
676 supported_formats.push_back(cricket::VideoFormat(960, 720,
677 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
678 supported_formats.push_back(cricket::VideoFormat(640, 480,
679 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
680 supported_formats.push_back(cricket::VideoFormat(640, 400,
681 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
682 supported_formats.push_back(cricket::VideoFormat(640, 360,
683 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
684 capturer_.ResetSupportedFormats(supported_formats);
685
686 // Expect 4x3, 16x10, and 16x9 requests are respected.
687 for (size_t i = 0; i < required_formats.size(); ++i) {
688 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
689 EXPECT_EQ(required_formats[i].width, best.width);
690 EXPECT_EQ(required_formats[i].height, best.height);
691 }
692
693 // We support 16x9HD, Expect 4x3, 16x10, and 16x9 requests are respected.
694 supported_formats.clear();
695 supported_formats.push_back(cricket::VideoFormat(1280, 720,
696 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
697 supported_formats.push_back(cricket::VideoFormat(640, 480,
698 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
699 supported_formats.push_back(cricket::VideoFormat(640, 400,
700 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
701 supported_formats.push_back(cricket::VideoFormat(640, 360,
702 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
703 capturer_.ResetSupportedFormats(supported_formats);
704
705 // Expect 4x3 for 4x3 and 16x10 requests.
706 for (size_t i = 0; i < required_formats.size() - 1; ++i) {
707 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
708 EXPECT_EQ(required_formats[i].width, best.width);
709 EXPECT_EQ(required_formats[i].height, best.height);
710 }
711
712 // Expect 16x9 for 16x9 request.
713 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
714 EXPECT_EQ(640, best.width);
715 EXPECT_EQ(360, best.height);
716}
717
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000718// If HAVE_WEBRTC_VIDEO is not defined the video capturer will not be able to
719// provide OnVideoFrame-callbacks since they require cricket::CapturedFrame to
720// be decoded as a cricket::VideoFrame (i.e. an I420 frame). This functionality
721// only exist if HAVE_WEBRTC_VIDEO is defined below. I420 frames are also a
722// requirement for the VideoProcessors so they will not be called either.
723#if defined(HAVE_WEBRTC_VIDEO)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000724TEST_F(VideoCapturerTest, VideoFrame) {
725 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
726 640,
727 480,
728 cricket::VideoFormat::FpsToInterval(30),
729 cricket::FOURCC_I420)));
730 EXPECT_TRUE(capturer_.IsRunning());
731 EXPECT_EQ(0, video_frames_received());
732 EXPECT_TRUE(capturer_.CaptureFrame());
733 EXPECT_EQ(1, video_frames_received());
734}
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000735#endif // HAVE_WEBRTC_VIDEO
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000736
737bool HdFormatInList(const std::vector<cricket::VideoFormat>& formats) {
738 for (std::vector<cricket::VideoFormat>::const_iterator found =
739 formats.begin(); found != formats.end(); ++found) {
740 if (found->height >= kMinHdHeight) {
741 return true;
742 }
743 }
744 return false;
745}
746
747TEST_F(VideoCapturerTest, Whitelist) {
748 // The definition of HD only applies to the height. Set the HD width to the
749 // smallest legal number to document this fact in this test.
750 const int kMinHdWidth = 1;
751 cricket::VideoFormat hd_format(kMinHdWidth,
752 kMinHdHeight,
753 cricket::VideoFormat::FpsToInterval(30),
754 cricket::FOURCC_I420);
755 cricket::VideoFormat vga_format(640, 480,
756 cricket::VideoFormat::FpsToInterval(30),
757 cricket::FOURCC_I420);
758 std::vector<cricket::VideoFormat> formats = *capturer_.GetSupportedFormats();
759 formats.push_back(hd_format);
760
761 // Enable whitelist. Expect HD not in list.
762 capturer_.set_enable_camera_list(true);
763 capturer_.ResetSupportedFormats(formats);
764 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
765 capturer_.ConstrainSupportedFormats(vga_format);
766 EXPECT_FALSE(HdFormatInList(*capturer_.GetSupportedFormats()));
767
768 // Disable whitelist. Expect HD in list.
769 capturer_.set_enable_camera_list(false);
770 capturer_.ResetSupportedFormats(formats);
771 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
772 capturer_.ConstrainSupportedFormats(vga_format);
773 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
774}
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000775
776TEST_F(VideoCapturerTest, BlacklistAllFormats) {
777 cricket::VideoFormat vga_format(640, 480,
778 cricket::VideoFormat::FpsToInterval(30),
779 cricket::FOURCC_I420);
780 std::vector<cricket::VideoFormat> supported_formats;
781 // Mock a device that only supports HD formats.
782 supported_formats.push_back(cricket::VideoFormat(1280, 720,
783 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
784 supported_formats.push_back(cricket::VideoFormat(1920, 1080,
785 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
786 capturer_.ResetSupportedFormats(supported_formats);
787 EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size());
788 // Now, enable the list, which would exclude both formats. However, since
789 // only HD formats are available, we refuse to filter at all, so we don't
790 // break this camera.
791 capturer_.set_enable_camera_list(true);
792 capturer_.ConstrainSupportedFormats(vga_format);
793 EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size());
794 // To make sure it's not just the camera list being broken, add in VGA and
795 // try again. This time, only the VGA format should be there.
796 supported_formats.push_back(vga_format);
797 capturer_.ResetSupportedFormats(supported_formats);
798 ASSERT_EQ(1u, capturer_.GetSupportedFormats()->size());
799 EXPECT_EQ(vga_format.height, capturer_.GetSupportedFormats()->at(0).height);
800}