blob: 59bc4f78d35f1b23fa6c38c83eec79ace23e731b [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) {
97 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
98 640,
99 480,
100 cricket::VideoFormat::FpsToInterval(30),
101 cricket::FOURCC_I420)));
102 EXPECT_TRUE(capturer_.IsRunning());
103 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
104 EXPECT_EQ(1, num_state_changes());
105 capturer_.Stop();
106 EXPECT_EQ_WAIT(cricket::CS_STOPPED, capture_state(), kMsCallbackWait);
107 EXPECT_EQ(2, num_state_changes());
108 capturer_.Stop();
109 talk_base::Thread::Current()->ProcessMessages(100);
110 EXPECT_EQ(2, num_state_changes());
111}
112
113TEST_F(VideoCapturerTest, TestRestart) {
114 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
115 640,
116 480,
117 cricket::VideoFormat::FpsToInterval(30),
118 cricket::FOURCC_I420)));
119 EXPECT_TRUE(capturer_.IsRunning());
120 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
121 EXPECT_EQ(1, num_state_changes());
122 EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat(
123 320,
124 240,
125 cricket::VideoFormat::FpsToInterval(30),
126 cricket::FOURCC_I420)));
127 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
128 EXPECT_TRUE(capturer_.IsRunning());
129 EXPECT_GE(1, num_state_changes());
130 capturer_.Stop();
131 talk_base::Thread::Current()->ProcessMessages(100);
132 EXPECT_FALSE(capturer_.IsRunning());
133}
134
135TEST_F(VideoCapturerTest, TestStartingWithRestart) {
136 EXPECT_FALSE(capturer_.IsRunning());
137 EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat(
138 640,
139 480,
140 cricket::VideoFormat::FpsToInterval(30),
141 cricket::FOURCC_I420)));
142 EXPECT_TRUE(capturer_.IsRunning());
143 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
144}
145
146TEST_F(VideoCapturerTest, TestRestartWithSameFormat) {
147 cricket::VideoFormat format(640, 480,
148 cricket::VideoFormat::FpsToInterval(30),
149 cricket::FOURCC_I420);
150 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(format));
151 EXPECT_TRUE(capturer_.IsRunning());
152 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait);
153 EXPECT_EQ(1, num_state_changes());
154 EXPECT_TRUE(capturer_.Restart(format));
155 EXPECT_EQ(cricket::CS_RUNNING, capture_state());
156 EXPECT_TRUE(capturer_.IsRunning());
157 EXPECT_EQ(1, num_state_changes());
158}
159
160TEST_F(VideoCapturerTest, CameraOffOnMute) {
161 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
162 640,
163 480,
164 cricket::VideoFormat::FpsToInterval(30),
165 cricket::FOURCC_I420)));
166 EXPECT_TRUE(capturer_.IsRunning());
167 EXPECT_EQ(0, video_frames_received());
168 EXPECT_TRUE(capturer_.CaptureFrame());
169 EXPECT_EQ(1, video_frames_received());
170 EXPECT_FALSE(capturer_.IsMuted());
171
172 // Mute the camera and expect black output frame.
173 capturer_.MuteToBlackThenPause(true);
174 EXPECT_TRUE(capturer_.IsMuted());
175 for (int i = 0; i < 31; ++i) {
176 EXPECT_TRUE(capturer_.CaptureFrame());
177 EXPECT_TRUE(renderer_.black_frame());
178 }
179 EXPECT_EQ(32, video_frames_received());
180 EXPECT_EQ_WAIT(cricket::CS_PAUSED,
181 capturer_.capture_state(), kTimeout);
182
183 // Verify that the camera is off.
184 EXPECT_FALSE(capturer_.CaptureFrame());
185 EXPECT_EQ(32, video_frames_received());
186
187 // Unmute the camera and expect non-black output frame.
188 capturer_.MuteToBlackThenPause(false);
189 EXPECT_FALSE(capturer_.IsMuted());
190 EXPECT_EQ_WAIT(cricket::CS_RUNNING,
191 capturer_.capture_state(), kTimeout);
192 EXPECT_TRUE(capturer_.CaptureFrame());
193 EXPECT_FALSE(renderer_.black_frame());
194 EXPECT_EQ(33, video_frames_received());
195}
196
wu@webrtc.orgcadf9042013-08-30 21:24:16 +0000197TEST_F(VideoCapturerTest, ScreencastScaledMaxPixels) {
198 capturer_.SetScreencast(true);
199
200 int kWidth = 1280;
201 int kHeight = 720;
202
203 // Screencasts usually have large weird dimensions and are ARGB.
204 std::vector<cricket::VideoFormat> formats;
205 formats.push_back(cricket::VideoFormat(kWidth, kHeight,
206 cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB));
207 formats.push_back(cricket::VideoFormat(2 * kWidth, 2 * kHeight,
208 cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB));
209 capturer_.ResetSupportedFormats(formats);
210
211
212 EXPECT_EQ(0, capturer_.screencast_max_pixels());
213 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
214 2 * kWidth,
215 2 * kHeight,
216 cricket::VideoFormat::FpsToInterval(30),
217 cricket::FOURCC_ARGB)));
218 EXPECT_TRUE(capturer_.IsRunning());
219 EXPECT_EQ(0, renderer_.num_rendered_frames());
220 renderer_.SetSize(2 * kWidth, 2 * kHeight, 0);
221 EXPECT_TRUE(capturer_.CaptureFrame());
222 EXPECT_EQ(1, renderer_.num_rendered_frames());
223
224 capturer_.set_screencast_max_pixels(kWidth * kHeight);
225 renderer_.SetSize(kWidth, kHeight, 0);
226 EXPECT_TRUE(capturer_.CaptureFrame());
227 EXPECT_EQ(2, renderer_.num_rendered_frames());
228}
229
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000230TEST_F(VideoCapturerTest, TestFourccMatch) {
231 cricket::VideoFormat desired(640, 480,
232 cricket::VideoFormat::FpsToInterval(30),
233 cricket::FOURCC_ANY);
234 cricket::VideoFormat best;
235 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
236 EXPECT_EQ(640, best.width);
237 EXPECT_EQ(480, best.height);
238 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
239
240 desired.fourcc = cricket::FOURCC_MJPG;
241 EXPECT_FALSE(capturer_.GetBestCaptureFormat(desired, &best));
242
243 desired.fourcc = cricket::FOURCC_I420;
244 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
245}
246
247TEST_F(VideoCapturerTest, TestResolutionMatch) {
248 cricket::VideoFormat desired(1920, 1080,
249 cricket::VideoFormat::FpsToInterval(30),
250 cricket::FOURCC_ANY);
251 cricket::VideoFormat best;
252 // Ask for 1920x1080. Get HD 1280x720 which is the highest.
253 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
254 EXPECT_EQ(1280, best.width);
255 EXPECT_EQ(720, best.height);
256 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
257
258 desired.width = 360;
259 desired.height = 250;
260 // Ask for a little higher than QVGA. Get QVGA.
261 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
262 EXPECT_EQ(320, best.width);
263 EXPECT_EQ(240, best.height);
264 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
265
266 desired.width = 480;
267 desired.height = 270;
268 // Ask for HVGA. Get VGA.
269 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
270 EXPECT_EQ(640, best.width);
271 EXPECT_EQ(480, best.height);
272 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
273
274 desired.width = 320;
275 desired.height = 240;
276 // Ask for QVGA. Get QVGA.
277 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
278 EXPECT_EQ(320, best.width);
279 EXPECT_EQ(240, best.height);
280 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
281
282 desired.width = 80;
283 desired.height = 60;
284 // Ask for lower than QQVGA. Get QQVGA, which is the lowest.
285 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
286 EXPECT_EQ(160, best.width);
287 EXPECT_EQ(120, best.height);
288 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
289}
290
291TEST_F(VideoCapturerTest, TestHDResolutionMatch) {
292 // Add some HD formats typical of a mediocre HD webcam.
293 std::vector<cricket::VideoFormat> formats;
294 formats.push_back(cricket::VideoFormat(320, 240,
295 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
296 formats.push_back(cricket::VideoFormat(640, 480,
297 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
298 formats.push_back(cricket::VideoFormat(960, 544,
299 cricket::VideoFormat::FpsToInterval(24), cricket::FOURCC_I420));
300 formats.push_back(cricket::VideoFormat(1280, 720,
301 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
302 formats.push_back(cricket::VideoFormat(2592, 1944,
303 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
304 capturer_.ResetSupportedFormats(formats);
305
306 cricket::VideoFormat desired(960, 720,
307 cricket::VideoFormat::FpsToInterval(30),
308 cricket::FOURCC_ANY);
309 cricket::VideoFormat best;
310 // Ask for 960x720 30 fps. Get qHD 24 fps
311 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
312 EXPECT_EQ(960, best.width);
313 EXPECT_EQ(544, best.height);
314 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
315
316 desired.width = 960;
317 desired.height = 544;
318 desired.interval = cricket::VideoFormat::FpsToInterval(30);
319 // Ask for qHD 30 fps. Get qHD 24 fps
320 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
321 EXPECT_EQ(960, best.width);
322 EXPECT_EQ(544, best.height);
323 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
324
325 desired.width = 360;
326 desired.height = 250;
327 desired.interval = cricket::VideoFormat::FpsToInterval(30);
328 // Ask for a little higher than QVGA. Get QVGA.
329 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
330 EXPECT_EQ(320, best.width);
331 EXPECT_EQ(240, best.height);
332 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
333
334 desired.width = 480;
335 desired.height = 270;
336 // Ask for HVGA. Get VGA.
337 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
338 EXPECT_EQ(640, best.width);
339 EXPECT_EQ(480, best.height);
340 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
341
342 desired.width = 320;
343 desired.height = 240;
344 // Ask for QVGA. Get QVGA.
345 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
346 EXPECT_EQ(320, best.width);
347 EXPECT_EQ(240, best.height);
348 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
349
350 desired.width = 160;
351 desired.height = 120;
352 // Ask for lower than QVGA. Get QVGA, which is the lowest.
353 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
354 EXPECT_EQ(320, best.width);
355 EXPECT_EQ(240, best.height);
356 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
357
358 desired.width = 1280;
359 desired.height = 720;
360 // Ask for HD. 720p fps is too low. Get VGA which has 30 fps.
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.width = 1280;
367 desired.height = 720;
368 desired.interval = cricket::VideoFormat::FpsToInterval(15);
369 // Ask for HD 15 fps. Fps matches. Get HD
370 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
371 EXPECT_EQ(1280, best.width);
372 EXPECT_EQ(720, best.height);
373 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
374
375 desired.width = 1920;
376 desired.height = 1080;
377 desired.interval = cricket::VideoFormat::FpsToInterval(30);
378 // Ask for 1080p. Fps of HD formats is too low. Get VGA which can do 30 fps.
379 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
380 EXPECT_EQ(640, best.width);
381 EXPECT_EQ(480, best.height);
382 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
383}
384
385// Some cameras support 320x240 and 320x640. Verify we choose 320x240.
386TEST_F(VideoCapturerTest, TestStrangeFormats) {
387 std::vector<cricket::VideoFormat> supported_formats;
388 supported_formats.push_back(cricket::VideoFormat(320, 240,
389 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
390 supported_formats.push_back(cricket::VideoFormat(320, 640,
391 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
392 capturer_.ResetSupportedFormats(supported_formats);
393
394 std::vector<cricket::VideoFormat> required_formats;
395 required_formats.push_back(cricket::VideoFormat(320, 240,
396 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
397 required_formats.push_back(cricket::VideoFormat(320, 200,
398 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
399 required_formats.push_back(cricket::VideoFormat(320, 180,
400 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
401 cricket::VideoFormat best;
402 for (size_t i = 0; i < required_formats.size(); ++i) {
403 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
404 EXPECT_EQ(320, best.width);
405 EXPECT_EQ(240, best.height);
406 }
407
408 supported_formats.clear();
409 supported_formats.push_back(cricket::VideoFormat(320, 640,
410 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
411 supported_formats.push_back(cricket::VideoFormat(320, 240,
412 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
413 capturer_.ResetSupportedFormats(supported_formats);
414
415 for (size_t i = 0; i < required_formats.size(); ++i) {
416 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
417 EXPECT_EQ(320, best.width);
418 EXPECT_EQ(240, best.height);
419 }
420}
421
422// Some cameras only have very low fps. Verify we choose something sensible.
423TEST_F(VideoCapturerTest, TestPoorFpsFormats) {
424 // all formats are low framerate
425 std::vector<cricket::VideoFormat> supported_formats;
426 supported_formats.push_back(cricket::VideoFormat(320, 240,
427 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
428 supported_formats.push_back(cricket::VideoFormat(640, 480,
429 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
430 supported_formats.push_back(cricket::VideoFormat(1280, 720,
431 cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
432 capturer_.ResetSupportedFormats(supported_formats);
433
434 std::vector<cricket::VideoFormat> required_formats;
435 required_formats.push_back(cricket::VideoFormat(320, 240,
436 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
437 required_formats.push_back(cricket::VideoFormat(640, 480,
438 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
439 cricket::VideoFormat best;
440 for (size_t i = 0; i < required_formats.size(); ++i) {
441 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
442 EXPECT_EQ(required_formats[i].width, best.width);
443 EXPECT_EQ(required_formats[i].height, best.height);
444 }
445
446 // Increase framerate of 320x240. Expect low fps VGA avoided.
447 supported_formats.clear();
448 supported_formats.push_back(cricket::VideoFormat(320, 240,
449 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
450 supported_formats.push_back(cricket::VideoFormat(640, 480,
451 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
452 supported_formats.push_back(cricket::VideoFormat(1280, 720,
453 cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
454 capturer_.ResetSupportedFormats(supported_formats);
455
456 for (size_t i = 0; i < required_formats.size(); ++i) {
457 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
458 EXPECT_EQ(320, best.width);
459 EXPECT_EQ(240, best.height);
460 }
461}
462
463// Some cameras support same size with different frame rates. Verify we choose
464// the frame rate properly.
465TEST_F(VideoCapturerTest, TestSameSizeDifferentFpsFormats) {
466 std::vector<cricket::VideoFormat> supported_formats;
467 supported_formats.push_back(cricket::VideoFormat(320, 240,
468 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
469 supported_formats.push_back(cricket::VideoFormat(320, 240,
470 cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_I420));
471 supported_formats.push_back(cricket::VideoFormat(320, 240,
472 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
473 capturer_.ResetSupportedFormats(supported_formats);
474
475 std::vector<cricket::VideoFormat> required_formats = supported_formats;
476 cricket::VideoFormat best;
477 for (size_t i = 0; i < required_formats.size(); ++i) {
478 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
479 EXPECT_EQ(320, best.width);
480 EXPECT_EQ(240, best.height);
481 EXPECT_EQ(required_formats[i].interval, best.interval);
482 }
483}
484
485// Some cameras support the correct resolution but at a lower fps than
486// we'd like. This tests we get the expected resolution and fps.
487TEST_F(VideoCapturerTest, TestFpsFormats) {
488 // We have VGA but low fps. Choose VGA, not HD
489 std::vector<cricket::VideoFormat> supported_formats;
490 supported_formats.push_back(cricket::VideoFormat(1280, 720,
491 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
492 supported_formats.push_back(cricket::VideoFormat(640, 480,
493 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
494 supported_formats.push_back(cricket::VideoFormat(640, 400,
495 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
496 supported_formats.push_back(cricket::VideoFormat(640, 360,
497 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
498 capturer_.ResetSupportedFormats(supported_formats);
499
500 std::vector<cricket::VideoFormat> required_formats;
501 required_formats.push_back(cricket::VideoFormat(640, 480,
502 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_ANY));
503 required_formats.push_back(cricket::VideoFormat(640, 480,
504 cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_ANY));
505 required_formats.push_back(cricket::VideoFormat(640, 480,
506 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_ANY));
507 cricket::VideoFormat best;
508
509 // expect 30 fps to choose 30 fps format
510 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
511 EXPECT_EQ(640, best.width);
512 EXPECT_EQ(400, best.height);
513 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
514
515 // expect 20 fps to choose 20 fps format
516 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
517 EXPECT_EQ(640, best.width);
518 EXPECT_EQ(400, best.height);
519 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(20), best.interval);
520
521 // expect 10 fps to choose 15 fps format but set fps to 10
522 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
523 EXPECT_EQ(640, best.width);
524 EXPECT_EQ(480, best.height);
525 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(10), best.interval);
526
527 // We have VGA 60 fps and 15 fps. Choose best fps.
528 supported_formats.clear();
529 supported_formats.push_back(cricket::VideoFormat(1280, 720,
530 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
531 supported_formats.push_back(cricket::VideoFormat(640, 480,
532 cricket::VideoFormat::FpsToInterval(60), cricket::FOURCC_MJPG));
533 supported_formats.push_back(cricket::VideoFormat(640, 480,
534 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
535 supported_formats.push_back(cricket::VideoFormat(640, 400,
536 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
537 supported_formats.push_back(cricket::VideoFormat(640, 360,
538 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
539 capturer_.ResetSupportedFormats(supported_formats);
540
541 // expect 30 fps to choose 60 fps format, but will set best fps to 30
542 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
543 EXPECT_EQ(640, best.width);
544 EXPECT_EQ(480, best.height);
545 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
546
547 // expect 20 fps to choose 60 fps format, but will set best fps to 20
548 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
549 EXPECT_EQ(640, best.width);
550 EXPECT_EQ(480, best.height);
551 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(20), best.interval);
552
553 // expect 10 fps to choose 10 fps
554 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
555 EXPECT_EQ(640, best.width);
556 EXPECT_EQ(480, best.height);
557 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(10), best.interval);
558}
559
560TEST_F(VideoCapturerTest, TestRequest16x10_9) {
561 std::vector<cricket::VideoFormat> supported_formats;
562 // We do not support HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
563 supported_formats.push_back(cricket::VideoFormat(640, 480,
564 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
565 supported_formats.push_back(cricket::VideoFormat(640, 400,
566 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
567 supported_formats.push_back(cricket::VideoFormat(640, 360,
568 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
569 capturer_.ResetSupportedFormats(supported_formats);
570
571 std::vector<cricket::VideoFormat> required_formats = supported_formats;
572 cricket::VideoFormat best;
573 // Expect 4x3, 16x10, and 16x9 requests are respected.
574 for (size_t i = 0; i < required_formats.size(); ++i) {
575 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
576 EXPECT_EQ(required_formats[i].width, best.width);
577 EXPECT_EQ(required_formats[i].height, best.height);
578 }
579
580 // We do not support 16x9 HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
581 supported_formats.clear();
582 supported_formats.push_back(cricket::VideoFormat(960, 720,
583 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
584 supported_formats.push_back(cricket::VideoFormat(640, 480,
585 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
586 supported_formats.push_back(cricket::VideoFormat(640, 400,
587 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
588 supported_formats.push_back(cricket::VideoFormat(640, 360,
589 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
590 capturer_.ResetSupportedFormats(supported_formats);
591
592 // Expect 4x3, 16x10, and 16x9 requests are respected.
593 for (size_t i = 0; i < required_formats.size(); ++i) {
594 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
595 EXPECT_EQ(required_formats[i].width, best.width);
596 EXPECT_EQ(required_formats[i].height, best.height);
597 }
598
599 // We support 16x9HD, Expect 4x3, 16x10, and 16x9 requests are respected.
600 supported_formats.clear();
601 supported_formats.push_back(cricket::VideoFormat(1280, 720,
602 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
603 supported_formats.push_back(cricket::VideoFormat(640, 480,
604 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
605 supported_formats.push_back(cricket::VideoFormat(640, 400,
606 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
607 supported_formats.push_back(cricket::VideoFormat(640, 360,
608 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
609 capturer_.ResetSupportedFormats(supported_formats);
610
611 // Expect 4x3 for 4x3 and 16x10 requests.
612 for (size_t i = 0; i < required_formats.size() - 1; ++i) {
613 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
614 EXPECT_EQ(required_formats[i].width, best.width);
615 EXPECT_EQ(required_formats[i].height, best.height);
616 }
617
618 // Expect 16x9 for 16x9 request.
619 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
620 EXPECT_EQ(640, best.width);
621 EXPECT_EQ(360, best.height);
622}
623
624#if defined(HAS_I420_FRAME)
625TEST_F(VideoCapturerTest, VideoFrame) {
626 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
627 640,
628 480,
629 cricket::VideoFormat::FpsToInterval(30),
630 cricket::FOURCC_I420)));
631 EXPECT_TRUE(capturer_.IsRunning());
632 EXPECT_EQ(0, video_frames_received());
633 EXPECT_TRUE(capturer_.CaptureFrame());
634 EXPECT_EQ(1, video_frames_received());
635}
636
637TEST_F(VideoCapturerTest, ProcessorChainTest) {
638 VideoProcessor0 processor0;
639 VideoProcessor1 processor1;
640 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
641 640,
642 480,
643 cricket::VideoFormat::FpsToInterval(30),
644 cricket::FOURCC_I420)));
645 EXPECT_TRUE(capturer_.IsRunning());
646 EXPECT_EQ(0, video_frames_received());
647 // First processor sets elapsed time to 0.
648 capturer_.AddVideoProcessor(&processor0);
649 // Second processor adds 1 to the elapsed time. I.e. a frames elapsed time
650 // should now always be 1 (and not 0).
651 capturer_.AddVideoProcessor(&processor1);
652 EXPECT_TRUE(capturer_.CaptureFrame());
653 EXPECT_EQ(1, video_frames_received());
654 EXPECT_EQ(1u, last_frame_elapsed_time());
655 capturer_.RemoveVideoProcessor(&processor1);
656 EXPECT_TRUE(capturer_.CaptureFrame());
657 // Since processor1 has been removed the elapsed time should now be 0.
658 EXPECT_EQ(2, video_frames_received());
659 EXPECT_EQ(0u, last_frame_elapsed_time());
660}
661
662TEST_F(VideoCapturerTest, ProcessorDropFrame) {
663 cricket::FakeMediaProcessor dropping_processor_;
664 dropping_processor_.set_drop_frames(true);
665 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
666 640,
667 480,
668 cricket::VideoFormat::FpsToInterval(30),
669 cricket::FOURCC_I420)));
670 EXPECT_TRUE(capturer_.IsRunning());
671 EXPECT_EQ(0, video_frames_received());
672 // Install a processor that always drop frames.
673 capturer_.AddVideoProcessor(&dropping_processor_);
674 EXPECT_TRUE(capturer_.CaptureFrame());
675 EXPECT_EQ(0, video_frames_received());
676}
677#endif // HAS_I420_FRAME
678
679bool HdFormatInList(const std::vector<cricket::VideoFormat>& formats) {
680 for (std::vector<cricket::VideoFormat>::const_iterator found =
681 formats.begin(); found != formats.end(); ++found) {
682 if (found->height >= kMinHdHeight) {
683 return true;
684 }
685 }
686 return false;
687}
688
689TEST_F(VideoCapturerTest, Whitelist) {
690 // The definition of HD only applies to the height. Set the HD width to the
691 // smallest legal number to document this fact in this test.
692 const int kMinHdWidth = 1;
693 cricket::VideoFormat hd_format(kMinHdWidth,
694 kMinHdHeight,
695 cricket::VideoFormat::FpsToInterval(30),
696 cricket::FOURCC_I420);
697 cricket::VideoFormat vga_format(640, 480,
698 cricket::VideoFormat::FpsToInterval(30),
699 cricket::FOURCC_I420);
700 std::vector<cricket::VideoFormat> formats = *capturer_.GetSupportedFormats();
701 formats.push_back(hd_format);
702
703 // Enable whitelist. Expect HD not in list.
704 capturer_.set_enable_camera_list(true);
705 capturer_.ResetSupportedFormats(formats);
706 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
707 capturer_.ConstrainSupportedFormats(vga_format);
708 EXPECT_FALSE(HdFormatInList(*capturer_.GetSupportedFormats()));
709
710 // Disable whitelist. Expect HD in list.
711 capturer_.set_enable_camera_list(false);
712 capturer_.ResetSupportedFormats(formats);
713 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
714 capturer_.ConstrainSupportedFormats(vga_format);
715 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
716}
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000717
718TEST_F(VideoCapturerTest, BlacklistAllFormats) {
719 cricket::VideoFormat vga_format(640, 480,
720 cricket::VideoFormat::FpsToInterval(30),
721 cricket::FOURCC_I420);
722 std::vector<cricket::VideoFormat> supported_formats;
723 // Mock a device that only supports HD formats.
724 supported_formats.push_back(cricket::VideoFormat(1280, 720,
725 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
726 supported_formats.push_back(cricket::VideoFormat(1920, 1080,
727 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
728 capturer_.ResetSupportedFormats(supported_formats);
729 EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size());
730 // Now, enable the list, which would exclude both formats. However, since
731 // only HD formats are available, we refuse to filter at all, so we don't
732 // break this camera.
733 capturer_.set_enable_camera_list(true);
734 capturer_.ConstrainSupportedFormats(vga_format);
735 EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size());
736 // To make sure it's not just the camera list being broken, add in VGA and
737 // try again. This time, only the VGA format should be there.
738 supported_formats.push_back(vga_format);
739 capturer_.ResetSupportedFormats(supported_formats);
740 ASSERT_EQ(1u, capturer_.GetSupportedFormats()->size());
741 EXPECT_EQ(vga_format.height, capturer_.GetSupportedFormats()->at(0).height);
742}