blob: 75da2360edd0c5cda32edbe5990de4ed86fd616e [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001// Copyright 2008 Google Inc.
2
3#include <stdio.h>
4#include <vector>
5
6#include "talk/base/gunit.h"
7#include "talk/base/logging.h"
8#include "talk/base/thread.h"
9#include "talk/media/base/fakemediaprocessor.h"
10#include "talk/media/base/fakevideocapturer.h"
11#include "talk/media/base/fakevideorenderer.h"
12#include "talk/media/base/testutils.h"
13#include "talk/media/base/videocapturer.h"
14#include "talk/media/base/videoprocessor.h"
15
16// If HAS_I420_FRAME is not defined the video capturer will not be able to
17// provide OnVideoFrame-callbacks since they require cricket::CapturedFrame to
18// be decoded as a cricket::VideoFrame (i.e. an I420 frame). This functionality
19// only exist if HAS_I420_FRAME is defined below. I420 frames are also a
20// requirement for the VideoProcessors so they will not be called either.
21#if defined(HAVE_WEBRTC_VIDEO)
22#define HAS_I420_FRAME
23#endif
24
25using cricket::FakeVideoCapturer;
26
27namespace {
28
29const int kMsCallbackWait = 500;
30// For HD only the height matters.
31const int kMinHdHeight = 720;
32const uint32 kTimeout = 5000U;
33
34} // namespace
35
36// Sets the elapsed time in the video frame to 0.
37class VideoProcessor0 : public cricket::VideoProcessor {
38 public:
39 virtual void OnFrame(uint32 /*ssrc*/, cricket::VideoFrame* frame,
40 bool* drop_frame) {
41 frame->SetElapsedTime(0u);
42 }
43};
44
45// Adds one to the video frame's elapsed time. Note that VideoProcessor0 and
46// VideoProcessor1 are not commutative.
47class VideoProcessor1 : public cricket::VideoProcessor {
48 public:
49 virtual void OnFrame(uint32 /*ssrc*/, cricket::VideoFrame* frame,
50 bool* drop_frame) {
51 int64 elapsed_time = frame->GetElapsedTime();
52 frame->SetElapsedTime(elapsed_time + 1);
53 }
54};
55
56class VideoCapturerTest
57 : public sigslot::has_slots<>,
58 public testing::Test {
59 public:
60 VideoCapturerTest()
61 : capture_state_(cricket::CS_STOPPED),
62 num_state_changes_(0),
63 video_frames_received_(0),
64 last_frame_elapsed_time_(0) {
65 capturer_.SignalVideoFrame.connect(this, &VideoCapturerTest::OnVideoFrame);
66 capturer_.SignalStateChange.connect(this,
67 &VideoCapturerTest::OnStateChange);
68 }
69
70 protected:
71 void OnVideoFrame(cricket::VideoCapturer*, const cricket::VideoFrame* frame) {
72 ++video_frames_received_;
73 last_frame_elapsed_time_ = frame->GetElapsedTime();
74 renderer_.RenderFrame(frame);
75 }
76 void OnStateChange(cricket::VideoCapturer*,
77 cricket::CaptureState capture_state) {
78 capture_state_ = capture_state;
79 ++num_state_changes_;
80 }
81 cricket::CaptureState capture_state() { return capture_state_; }
82 int num_state_changes() { return num_state_changes_; }
83 int video_frames_received() const {
84 return video_frames_received_;
85 }
86 int64 last_frame_elapsed_time() const { return last_frame_elapsed_time_; }
87
88 cricket::FakeVideoCapturer capturer_;
89 cricket::CaptureState capture_state_;
90 int num_state_changes_;
91 int video_frames_received_;
92 int64 last_frame_elapsed_time_;
93 cricket::FakeVideoRenderer renderer_;
94};
95
96TEST_F(VideoCapturerTest, CaptureState) {
henrike@webrtc.orga7b98182014-02-21 15:51:43 +000097 EXPECT_TRUE(capturer_.enable_video_adapter());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000098 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
99 640,
100 480,
101 cricket::VideoFormat::FpsToInterval(30),
102 cricket::FOURCC_I420)));
103 EXPECT_TRUE(capturer_.IsRunning());
104 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
105 EXPECT_EQ(1, num_state_changes());
106 capturer_.Stop();
107 EXPECT_EQ_WAIT(cricket::CS_STOPPED, capture_state(), kMsCallbackWait);
108 EXPECT_EQ(2, num_state_changes());
109 capturer_.Stop();
110 talk_base::Thread::Current()->ProcessMessages(100);
111 EXPECT_EQ(2, num_state_changes());
112}
113
114TEST_F(VideoCapturerTest, TestRestart) {
115 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
116 640,
117 480,
118 cricket::VideoFormat::FpsToInterval(30),
119 cricket::FOURCC_I420)));
120 EXPECT_TRUE(capturer_.IsRunning());
121 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
122 EXPECT_EQ(1, num_state_changes());
123 EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat(
124 320,
125 240,
126 cricket::VideoFormat::FpsToInterval(30),
127 cricket::FOURCC_I420)));
128 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
129 EXPECT_TRUE(capturer_.IsRunning());
130 EXPECT_GE(1, num_state_changes());
131 capturer_.Stop();
132 talk_base::Thread::Current()->ProcessMessages(100);
133 EXPECT_FALSE(capturer_.IsRunning());
134}
135
136TEST_F(VideoCapturerTest, TestStartingWithRestart) {
137 EXPECT_FALSE(capturer_.IsRunning());
138 EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat(
139 640,
140 480,
141 cricket::VideoFormat::FpsToInterval(30),
142 cricket::FOURCC_I420)));
143 EXPECT_TRUE(capturer_.IsRunning());
144 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
145}
146
147TEST_F(VideoCapturerTest, TestRestartWithSameFormat) {
148 cricket::VideoFormat format(640, 480,
149 cricket::VideoFormat::FpsToInterval(30),
150 cricket::FOURCC_I420);
151 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(format));
152 EXPECT_TRUE(capturer_.IsRunning());
153 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
154 EXPECT_EQ(1, num_state_changes());
155 EXPECT_TRUE(capturer_.Restart(format));
156 EXPECT_EQ(cricket::CS_RUNNING, capture_state());
157 EXPECT_TRUE(capturer_.IsRunning());
158 EXPECT_EQ(1, num_state_changes());
159}
160
161TEST_F(VideoCapturerTest, CameraOffOnMute) {
162 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
163 640,
164 480,
165 cricket::VideoFormat::FpsToInterval(30),
166 cricket::FOURCC_I420)));
167 EXPECT_TRUE(capturer_.IsRunning());
168 EXPECT_EQ(0, video_frames_received());
169 EXPECT_TRUE(capturer_.CaptureFrame());
170 EXPECT_EQ(1, video_frames_received());
171 EXPECT_FALSE(capturer_.IsMuted());
172
173 // Mute the camera and expect black output frame.
174 capturer_.MuteToBlackThenPause(true);
175 EXPECT_TRUE(capturer_.IsMuted());
176 for (int i = 0; i < 31; ++i) {
177 EXPECT_TRUE(capturer_.CaptureFrame());
178 EXPECT_TRUE(renderer_.black_frame());
179 }
180 EXPECT_EQ(32, video_frames_received());
181 EXPECT_EQ_WAIT(cricket::CS_PAUSED,
182 capturer_.capture_state(), kTimeout);
183
184 // Verify that the camera is off.
185 EXPECT_FALSE(capturer_.CaptureFrame());
186 EXPECT_EQ(32, video_frames_received());
187
188 // Unmute the camera and expect non-black output frame.
189 capturer_.MuteToBlackThenPause(false);
190 EXPECT_FALSE(capturer_.IsMuted());
191 EXPECT_EQ_WAIT(cricket::CS_RUNNING,
192 capturer_.capture_state(), kTimeout);
193 EXPECT_TRUE(capturer_.CaptureFrame());
194 EXPECT_FALSE(renderer_.black_frame());
195 EXPECT_EQ(33, video_frames_received());
196}
197
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000198TEST_F(VideoCapturerTest, ScreencastScaledMaxPixels) {
199 capturer_.SetScreencast(true);
200
201 int kWidth = 1280;
202 int kHeight = 720;
203
204 // Screencasts usually have large weird dimensions and are ARGB.
205 std::vector<cricket::VideoFormat> formats;
206 formats.push_back(cricket::VideoFormat(kWidth, kHeight,
207 cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB));
208 formats.push_back(cricket::VideoFormat(2 * kWidth, 2 * kHeight,
209 cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB));
210 capturer_.ResetSupportedFormats(formats);
211
212
213 EXPECT_EQ(0, capturer_.screencast_max_pixels());
214 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
215 2 * kWidth,
216 2 * kHeight,
217 cricket::VideoFormat::FpsToInterval(30),
218 cricket::FOURCC_ARGB)));
219 EXPECT_TRUE(capturer_.IsRunning());
220 EXPECT_EQ(0, renderer_.num_rendered_frames());
221 renderer_.SetSize(2 * kWidth, 2 * kHeight, 0);
222 EXPECT_TRUE(capturer_.CaptureFrame());
223 EXPECT_EQ(1, renderer_.num_rendered_frames());
224
225 capturer_.set_screencast_max_pixels(kWidth * kHeight);
226 renderer_.SetSize(kWidth, kHeight, 0);
227 EXPECT_TRUE(capturer_.CaptureFrame());
228 EXPECT_EQ(2, renderer_.num_rendered_frames());
229}
230
mallinath@webrtc.org1b15f422013-09-06 22:56:28 +0000231
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000232TEST_F(VideoCapturerTest, TestFourccMatch) {
233 cricket::VideoFormat desired(640, 480,
234 cricket::VideoFormat::FpsToInterval(30),
235 cricket::FOURCC_ANY);
236 cricket::VideoFormat best;
237 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
238 EXPECT_EQ(640, best.width);
239 EXPECT_EQ(480, best.height);
240 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
241
242 desired.fourcc = cricket::FOURCC_MJPG;
243 EXPECT_FALSE(capturer_.GetBestCaptureFormat(desired, &best));
244
245 desired.fourcc = cricket::FOURCC_I420;
246 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
247}
248
249TEST_F(VideoCapturerTest, TestResolutionMatch) {
250 cricket::VideoFormat desired(1920, 1080,
251 cricket::VideoFormat::FpsToInterval(30),
252 cricket::FOURCC_ANY);
253 cricket::VideoFormat best;
254 // Ask for 1920x1080. Get HD 1280x720 which is the highest.
255 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
256 EXPECT_EQ(1280, best.width);
257 EXPECT_EQ(720, best.height);
258 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
259
260 desired.width = 360;
261 desired.height = 250;
262 // Ask for a little higher than QVGA. Get QVGA.
263 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
264 EXPECT_EQ(320, best.width);
265 EXPECT_EQ(240, best.height);
266 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
267
268 desired.width = 480;
269 desired.height = 270;
270 // Ask for HVGA. Get VGA.
271 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
272 EXPECT_EQ(640, best.width);
273 EXPECT_EQ(480, best.height);
274 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
275
276 desired.width = 320;
277 desired.height = 240;
278 // Ask for QVGA. Get QVGA.
279 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
280 EXPECT_EQ(320, best.width);
281 EXPECT_EQ(240, best.height);
282 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
283
284 desired.width = 80;
285 desired.height = 60;
286 // Ask for lower than QQVGA. Get QQVGA, which is the lowest.
287 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
288 EXPECT_EQ(160, best.width);
289 EXPECT_EQ(120, best.height);
290 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
291}
292
293TEST_F(VideoCapturerTest, TestHDResolutionMatch) {
294 // Add some HD formats typical of a mediocre HD webcam.
295 std::vector<cricket::VideoFormat> formats;
296 formats.push_back(cricket::VideoFormat(320, 240,
297 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
298 formats.push_back(cricket::VideoFormat(640, 480,
299 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
300 formats.push_back(cricket::VideoFormat(960, 544,
301 cricket::VideoFormat::FpsToInterval(24), cricket::FOURCC_I420));
302 formats.push_back(cricket::VideoFormat(1280, 720,
303 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
304 formats.push_back(cricket::VideoFormat(2592, 1944,
305 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
306 capturer_.ResetSupportedFormats(formats);
307
308 cricket::VideoFormat desired(960, 720,
309 cricket::VideoFormat::FpsToInterval(30),
310 cricket::FOURCC_ANY);
311 cricket::VideoFormat best;
312 // Ask for 960x720 30 fps. Get qHD 24 fps
313 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
314 EXPECT_EQ(960, best.width);
315 EXPECT_EQ(544, best.height);
316 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
317
318 desired.width = 960;
319 desired.height = 544;
320 desired.interval = cricket::VideoFormat::FpsToInterval(30);
321 // Ask for qHD 30 fps. Get qHD 24 fps
322 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
323 EXPECT_EQ(960, best.width);
324 EXPECT_EQ(544, best.height);
325 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
326
327 desired.width = 360;
328 desired.height = 250;
329 desired.interval = cricket::VideoFormat::FpsToInterval(30);
330 // Ask for a little higher than QVGA. Get QVGA.
331 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
332 EXPECT_EQ(320, best.width);
333 EXPECT_EQ(240, best.height);
334 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
335
336 desired.width = 480;
337 desired.height = 270;
338 // Ask for HVGA. Get VGA.
339 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
340 EXPECT_EQ(640, best.width);
341 EXPECT_EQ(480, best.height);
342 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
343
344 desired.width = 320;
345 desired.height = 240;
346 // Ask for QVGA. Get QVGA.
347 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
348 EXPECT_EQ(320, best.width);
349 EXPECT_EQ(240, best.height);
350 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
351
352 desired.width = 160;
353 desired.height = 120;
354 // Ask for lower than QVGA. Get QVGA, which is the lowest.
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 = 1280;
361 desired.height = 720;
362 // Ask for HD. 720p fps is too low. Get VGA which has 30 fps.
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 = 1280;
369 desired.height = 720;
370 desired.interval = cricket::VideoFormat::FpsToInterval(15);
371 // Ask for HD 15 fps. Fps matches. Get HD
372 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
373 EXPECT_EQ(1280, best.width);
374 EXPECT_EQ(720, best.height);
375 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
376
377 desired.width = 1920;
378 desired.height = 1080;
379 desired.interval = cricket::VideoFormat::FpsToInterval(30);
380 // Ask for 1080p. Fps of HD formats is too low. Get VGA which can do 30 fps.
381 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
382 EXPECT_EQ(640, best.width);
383 EXPECT_EQ(480, best.height);
384 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
385}
386
387// Some cameras support 320x240 and 320x640. Verify we choose 320x240.
388TEST_F(VideoCapturerTest, TestStrangeFormats) {
389 std::vector<cricket::VideoFormat> supported_formats;
390 supported_formats.push_back(cricket::VideoFormat(320, 240,
391 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
392 supported_formats.push_back(cricket::VideoFormat(320, 640,
393 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
394 capturer_.ResetSupportedFormats(supported_formats);
395
396 std::vector<cricket::VideoFormat> required_formats;
397 required_formats.push_back(cricket::VideoFormat(320, 240,
398 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
399 required_formats.push_back(cricket::VideoFormat(320, 200,
400 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
401 required_formats.push_back(cricket::VideoFormat(320, 180,
402 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
403 cricket::VideoFormat best;
404 for (size_t i = 0; i < required_formats.size(); ++i) {
405 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
406 EXPECT_EQ(320, best.width);
407 EXPECT_EQ(240, best.height);
408 }
409
410 supported_formats.clear();
411 supported_formats.push_back(cricket::VideoFormat(320, 640,
412 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
413 supported_formats.push_back(cricket::VideoFormat(320, 240,
414 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
415 capturer_.ResetSupportedFormats(supported_formats);
416
417 for (size_t i = 0; i < required_formats.size(); ++i) {
418 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
419 EXPECT_EQ(320, best.width);
420 EXPECT_EQ(240, best.height);
421 }
422}
423
424// Some cameras only have very low fps. Verify we choose something sensible.
425TEST_F(VideoCapturerTest, TestPoorFpsFormats) {
426 // all formats are low framerate
427 std::vector<cricket::VideoFormat> supported_formats;
428 supported_formats.push_back(cricket::VideoFormat(320, 240,
429 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
430 supported_formats.push_back(cricket::VideoFormat(640, 480,
431 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
432 supported_formats.push_back(cricket::VideoFormat(1280, 720,
433 cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
434 capturer_.ResetSupportedFormats(supported_formats);
435
436 std::vector<cricket::VideoFormat> required_formats;
437 required_formats.push_back(cricket::VideoFormat(320, 240,
438 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
439 required_formats.push_back(cricket::VideoFormat(640, 480,
440 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
441 cricket::VideoFormat best;
442 for (size_t i = 0; i < required_formats.size(); ++i) {
443 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
444 EXPECT_EQ(required_formats[i].width, best.width);
445 EXPECT_EQ(required_formats[i].height, best.height);
446 }
447
448 // Increase framerate of 320x240. Expect low fps VGA avoided.
449 supported_formats.clear();
450 supported_formats.push_back(cricket::VideoFormat(320, 240,
451 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
452 supported_formats.push_back(cricket::VideoFormat(640, 480,
453 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
454 supported_formats.push_back(cricket::VideoFormat(1280, 720,
455 cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
456 capturer_.ResetSupportedFormats(supported_formats);
457
458 for (size_t i = 0; i < required_formats.size(); ++i) {
459 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
460 EXPECT_EQ(320, best.width);
461 EXPECT_EQ(240, best.height);
462 }
463}
464
465// Some cameras support same size with different frame rates. Verify we choose
466// the frame rate properly.
467TEST_F(VideoCapturerTest, TestSameSizeDifferentFpsFormats) {
468 std::vector<cricket::VideoFormat> supported_formats;
469 supported_formats.push_back(cricket::VideoFormat(320, 240,
470 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
471 supported_formats.push_back(cricket::VideoFormat(320, 240,
472 cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_I420));
473 supported_formats.push_back(cricket::VideoFormat(320, 240,
474 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
475 capturer_.ResetSupportedFormats(supported_formats);
476
477 std::vector<cricket::VideoFormat> required_formats = supported_formats;
478 cricket::VideoFormat best;
479 for (size_t i = 0; i < required_formats.size(); ++i) {
480 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
481 EXPECT_EQ(320, best.width);
482 EXPECT_EQ(240, best.height);
483 EXPECT_EQ(required_formats[i].interval, best.interval);
484 }
485}
486
487// Some cameras support the correct resolution but at a lower fps than
488// we'd like. This tests we get the expected resolution and fps.
489TEST_F(VideoCapturerTest, TestFpsFormats) {
490 // We have VGA but low fps. Choose VGA, not HD
491 std::vector<cricket::VideoFormat> supported_formats;
492 supported_formats.push_back(cricket::VideoFormat(1280, 720,
493 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
494 supported_formats.push_back(cricket::VideoFormat(640, 480,
495 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
496 supported_formats.push_back(cricket::VideoFormat(640, 400,
497 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
498 supported_formats.push_back(cricket::VideoFormat(640, 360,
499 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
500 capturer_.ResetSupportedFormats(supported_formats);
501
502 std::vector<cricket::VideoFormat> required_formats;
503 required_formats.push_back(cricket::VideoFormat(640, 480,
504 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_ANY));
505 required_formats.push_back(cricket::VideoFormat(640, 480,
506 cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_ANY));
507 required_formats.push_back(cricket::VideoFormat(640, 480,
508 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_ANY));
509 cricket::VideoFormat best;
510
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000511 // Expect 30 fps to choose 30 fps format.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000512 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
513 EXPECT_EQ(640, best.width);
514 EXPECT_EQ(400, best.height);
515 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
516
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000517 // Expect 20 fps to choose 30 fps format.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000518 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
519 EXPECT_EQ(640, best.width);
520 EXPECT_EQ(400, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000521 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000522
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000523 // Expect 10 fps to choose 15 fps format and set fps to 15.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000524 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
525 EXPECT_EQ(640, best.width);
526 EXPECT_EQ(480, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000527 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000528
529 // We have VGA 60 fps and 15 fps. Choose best fps.
530 supported_formats.clear();
531 supported_formats.push_back(cricket::VideoFormat(1280, 720,
532 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
533 supported_formats.push_back(cricket::VideoFormat(640, 480,
534 cricket::VideoFormat::FpsToInterval(60), cricket::FOURCC_MJPG));
535 supported_formats.push_back(cricket::VideoFormat(640, 480,
536 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
537 supported_formats.push_back(cricket::VideoFormat(640, 400,
538 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
539 supported_formats.push_back(cricket::VideoFormat(640, 360,
540 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
541 capturer_.ResetSupportedFormats(supported_formats);
542
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000543 // Expect 30 fps to choose 60 fps format and will set best fps to 60.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000544 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
545 EXPECT_EQ(640, best.width);
546 EXPECT_EQ(480, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000547 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000548
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000549 // Expect 20 fps to choose 60 fps format, and will set best fps to 60.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000550 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
551 EXPECT_EQ(640, best.width);
552 EXPECT_EQ(480, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000553 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000554
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000555 // Expect 10 fps to choose 15 fps.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000556 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
557 EXPECT_EQ(640, best.width);
558 EXPECT_EQ(480, best.height);
sergeyu@chromium.org4b26e2e2014-01-15 23:15:54 +0000559 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000560}
561
562TEST_F(VideoCapturerTest, TestRequest16x10_9) {
563 std::vector<cricket::VideoFormat> supported_formats;
564 // We do not support HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
565 supported_formats.push_back(cricket::VideoFormat(640, 480,
566 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
567 supported_formats.push_back(cricket::VideoFormat(640, 400,
568 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
569 supported_formats.push_back(cricket::VideoFormat(640, 360,
570 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
571 capturer_.ResetSupportedFormats(supported_formats);
572
573 std::vector<cricket::VideoFormat> required_formats = supported_formats;
574 cricket::VideoFormat best;
575 // Expect 4x3, 16x10, and 16x9 requests are respected.
576 for (size_t i = 0; i < required_formats.size(); ++i) {
577 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
578 EXPECT_EQ(required_formats[i].width, best.width);
579 EXPECT_EQ(required_formats[i].height, best.height);
580 }
581
582 // We do not support 16x9 HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
583 supported_formats.clear();
584 supported_formats.push_back(cricket::VideoFormat(960, 720,
585 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
586 supported_formats.push_back(cricket::VideoFormat(640, 480,
587 cricket::VideoFormat::FpsToInterval(30), 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 // Expect 4x3, 16x10, and 16x9 requests are respected.
595 for (size_t i = 0; i < required_formats.size(); ++i) {
596 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
597 EXPECT_EQ(required_formats[i].width, best.width);
598 EXPECT_EQ(required_formats[i].height, best.height);
599 }
600
601 // We support 16x9HD, Expect 4x3, 16x10, and 16x9 requests are respected.
602 supported_formats.clear();
603 supported_formats.push_back(cricket::VideoFormat(1280, 720,
604 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
605 supported_formats.push_back(cricket::VideoFormat(640, 480,
606 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
607 supported_formats.push_back(cricket::VideoFormat(640, 400,
608 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
609 supported_formats.push_back(cricket::VideoFormat(640, 360,
610 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
611 capturer_.ResetSupportedFormats(supported_formats);
612
613 // Expect 4x3 for 4x3 and 16x10 requests.
614 for (size_t i = 0; i < required_formats.size() - 1; ++i) {
615 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
616 EXPECT_EQ(required_formats[i].width, best.width);
617 EXPECT_EQ(required_formats[i].height, best.height);
618 }
619
620 // Expect 16x9 for 16x9 request.
621 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
622 EXPECT_EQ(640, best.width);
623 EXPECT_EQ(360, best.height);
624}
625
626#if defined(HAS_I420_FRAME)
627TEST_F(VideoCapturerTest, VideoFrame) {
628 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
629 640,
630 480,
631 cricket::VideoFormat::FpsToInterval(30),
632 cricket::FOURCC_I420)));
633 EXPECT_TRUE(capturer_.IsRunning());
634 EXPECT_EQ(0, video_frames_received());
635 EXPECT_TRUE(capturer_.CaptureFrame());
636 EXPECT_EQ(1, video_frames_received());
637}
638
639TEST_F(VideoCapturerTest, ProcessorChainTest) {
640 VideoProcessor0 processor0;
641 VideoProcessor1 processor1;
642 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
643 640,
644 480,
645 cricket::VideoFormat::FpsToInterval(30),
646 cricket::FOURCC_I420)));
647 EXPECT_TRUE(capturer_.IsRunning());
648 EXPECT_EQ(0, video_frames_received());
649 // First processor sets elapsed time to 0.
650 capturer_.AddVideoProcessor(&processor0);
651 // Second processor adds 1 to the elapsed time. I.e. a frames elapsed time
652 // should now always be 1 (and not 0).
653 capturer_.AddVideoProcessor(&processor1);
654 EXPECT_TRUE(capturer_.CaptureFrame());
655 EXPECT_EQ(1, video_frames_received());
656 EXPECT_EQ(1u, last_frame_elapsed_time());
657 capturer_.RemoveVideoProcessor(&processor1);
658 EXPECT_TRUE(capturer_.CaptureFrame());
659 // Since processor1 has been removed the elapsed time should now be 0.
660 EXPECT_EQ(2, video_frames_received());
661 EXPECT_EQ(0u, last_frame_elapsed_time());
662}
663
664TEST_F(VideoCapturerTest, ProcessorDropFrame) {
665 cricket::FakeMediaProcessor dropping_processor_;
666 dropping_processor_.set_drop_frames(true);
667 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
668 640,
669 480,
670 cricket::VideoFormat::FpsToInterval(30),
671 cricket::FOURCC_I420)));
672 EXPECT_TRUE(capturer_.IsRunning());
673 EXPECT_EQ(0, video_frames_received());
674 // Install a processor that always drop frames.
675 capturer_.AddVideoProcessor(&dropping_processor_);
676 EXPECT_TRUE(capturer_.CaptureFrame());
677 EXPECT_EQ(0, video_frames_received());
678}
679#endif // HAS_I420_FRAME
680
681bool HdFormatInList(const std::vector<cricket::VideoFormat>& formats) {
682 for (std::vector<cricket::VideoFormat>::const_iterator found =
683 formats.begin(); found != formats.end(); ++found) {
684 if (found->height >= kMinHdHeight) {
685 return true;
686 }
687 }
688 return false;
689}
690
691TEST_F(VideoCapturerTest, Whitelist) {
692 // The definition of HD only applies to the height. Set the HD width to the
693 // smallest legal number to document this fact in this test.
694 const int kMinHdWidth = 1;
695 cricket::VideoFormat hd_format(kMinHdWidth,
696 kMinHdHeight,
697 cricket::VideoFormat::FpsToInterval(30),
698 cricket::FOURCC_I420);
699 cricket::VideoFormat vga_format(640, 480,
700 cricket::VideoFormat::FpsToInterval(30),
701 cricket::FOURCC_I420);
702 std::vector<cricket::VideoFormat> formats = *capturer_.GetSupportedFormats();
703 formats.push_back(hd_format);
704
705 // Enable whitelist. Expect HD not in list.
706 capturer_.set_enable_camera_list(true);
707 capturer_.ResetSupportedFormats(formats);
708 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
709 capturer_.ConstrainSupportedFormats(vga_format);
710 EXPECT_FALSE(HdFormatInList(*capturer_.GetSupportedFormats()));
711
712 // Disable whitelist. Expect HD in list.
713 capturer_.set_enable_camera_list(false);
714 capturer_.ResetSupportedFormats(formats);
715 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
716 capturer_.ConstrainSupportedFormats(vga_format);
717 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
718}
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000719
720TEST_F(VideoCapturerTest, BlacklistAllFormats) {
721 cricket::VideoFormat vga_format(640, 480,
722 cricket::VideoFormat::FpsToInterval(30),
723 cricket::FOURCC_I420);
724 std::vector<cricket::VideoFormat> supported_formats;
725 // Mock a device that only supports HD formats.
726 supported_formats.push_back(cricket::VideoFormat(1280, 720,
727 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
728 supported_formats.push_back(cricket::VideoFormat(1920, 1080,
729 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
730 capturer_.ResetSupportedFormats(supported_formats);
731 EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size());
732 // Now, enable the list, which would exclude both formats. However, since
733 // only HD formats are available, we refuse to filter at all, so we don't
734 // break this camera.
735 capturer_.set_enable_camera_list(true);
736 capturer_.ConstrainSupportedFormats(vga_format);
737 EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size());
738 // To make sure it's not just the camera list being broken, add in VGA and
739 // try again. This time, only the VGA format should be there.
740 supported_formats.push_back(vga_format);
741 capturer_.ResetSupportedFormats(supported_formats);
742 ASSERT_EQ(1u, capturer_.GetSupportedFormats()->size());
743 EXPECT_EQ(vga_format.height, capturer_.GetSupportedFormats()->at(0).height);
744}