blob: ae461a9845d63531fa5e2b28ec7235e04e11e1d5 [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
197TEST_F(VideoCapturerTest, TestFourccMatch) {
198 cricket::VideoFormat desired(640, 480,
199 cricket::VideoFormat::FpsToInterval(30),
200 cricket::FOURCC_ANY);
201 cricket::VideoFormat best;
202 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
203 EXPECT_EQ(640, best.width);
204 EXPECT_EQ(480, best.height);
205 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
206
207 desired.fourcc = cricket::FOURCC_MJPG;
208 EXPECT_FALSE(capturer_.GetBestCaptureFormat(desired, &best));
209
210 desired.fourcc = cricket::FOURCC_I420;
211 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
212}
213
214TEST_F(VideoCapturerTest, TestResolutionMatch) {
215 cricket::VideoFormat desired(1920, 1080,
216 cricket::VideoFormat::FpsToInterval(30),
217 cricket::FOURCC_ANY);
218 cricket::VideoFormat best;
219 // Ask for 1920x1080. Get HD 1280x720 which is the highest.
220 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
221 EXPECT_EQ(1280, best.width);
222 EXPECT_EQ(720, best.height);
223 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
224
225 desired.width = 360;
226 desired.height = 250;
227 // Ask for a little higher than QVGA. Get QVGA.
228 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
229 EXPECT_EQ(320, best.width);
230 EXPECT_EQ(240, best.height);
231 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
232
233 desired.width = 480;
234 desired.height = 270;
235 // Ask for HVGA. Get VGA.
236 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
237 EXPECT_EQ(640, best.width);
238 EXPECT_EQ(480, best.height);
239 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
240
241 desired.width = 320;
242 desired.height = 240;
243 // Ask for QVGA. Get QVGA.
244 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
245 EXPECT_EQ(320, best.width);
246 EXPECT_EQ(240, best.height);
247 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
248
249 desired.width = 80;
250 desired.height = 60;
251 // Ask for lower than QQVGA. Get QQVGA, which is the lowest.
252 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
253 EXPECT_EQ(160, best.width);
254 EXPECT_EQ(120, best.height);
255 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
256}
257
258TEST_F(VideoCapturerTest, TestHDResolutionMatch) {
259 // Add some HD formats typical of a mediocre HD webcam.
260 std::vector<cricket::VideoFormat> formats;
261 formats.push_back(cricket::VideoFormat(320, 240,
262 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
263 formats.push_back(cricket::VideoFormat(640, 480,
264 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
265 formats.push_back(cricket::VideoFormat(960, 544,
266 cricket::VideoFormat::FpsToInterval(24), cricket::FOURCC_I420));
267 formats.push_back(cricket::VideoFormat(1280, 720,
268 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
269 formats.push_back(cricket::VideoFormat(2592, 1944,
270 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
271 capturer_.ResetSupportedFormats(formats);
272
273 cricket::VideoFormat desired(960, 720,
274 cricket::VideoFormat::FpsToInterval(30),
275 cricket::FOURCC_ANY);
276 cricket::VideoFormat best;
277 // Ask for 960x720 30 fps. Get qHD 24 fps
278 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
279 EXPECT_EQ(960, best.width);
280 EXPECT_EQ(544, best.height);
281 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
282
283 desired.width = 960;
284 desired.height = 544;
285 desired.interval = cricket::VideoFormat::FpsToInterval(30);
286 // Ask for qHD 30 fps. Get qHD 24 fps
287 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
288 EXPECT_EQ(960, best.width);
289 EXPECT_EQ(544, best.height);
290 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval);
291
292 desired.width = 360;
293 desired.height = 250;
294 desired.interval = cricket::VideoFormat::FpsToInterval(30);
295 // Ask for a little higher than QVGA. Get QVGA.
296 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
297 EXPECT_EQ(320, best.width);
298 EXPECT_EQ(240, best.height);
299 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
300
301 desired.width = 480;
302 desired.height = 270;
303 // Ask for HVGA. Get VGA.
304 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
305 EXPECT_EQ(640, best.width);
306 EXPECT_EQ(480, best.height);
307 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
308
309 desired.width = 320;
310 desired.height = 240;
311 // Ask for QVGA. Get QVGA.
312 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
313 EXPECT_EQ(320, best.width);
314 EXPECT_EQ(240, best.height);
315 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
316
317 desired.width = 160;
318 desired.height = 120;
319 // Ask for lower than QVGA. Get QVGA, which is the lowest.
320 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
321 EXPECT_EQ(320, best.width);
322 EXPECT_EQ(240, best.height);
323 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
324
325 desired.width = 1280;
326 desired.height = 720;
327 // Ask for HD. 720p fps is too low. Get VGA which has 30 fps.
328 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
329 EXPECT_EQ(640, best.width);
330 EXPECT_EQ(480, best.height);
331 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
332
333 desired.width = 1280;
334 desired.height = 720;
335 desired.interval = cricket::VideoFormat::FpsToInterval(15);
336 // Ask for HD 15 fps. Fps matches. Get HD
337 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
338 EXPECT_EQ(1280, best.width);
339 EXPECT_EQ(720, best.height);
340 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval);
341
342 desired.width = 1920;
343 desired.height = 1080;
344 desired.interval = cricket::VideoFormat::FpsToInterval(30);
345 // Ask for 1080p. Fps of HD formats is too low. Get VGA which can do 30 fps.
346 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best));
347 EXPECT_EQ(640, best.width);
348 EXPECT_EQ(480, best.height);
349 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
350}
351
352// Some cameras support 320x240 and 320x640. Verify we choose 320x240.
353TEST_F(VideoCapturerTest, TestStrangeFormats) {
354 std::vector<cricket::VideoFormat> supported_formats;
355 supported_formats.push_back(cricket::VideoFormat(320, 240,
356 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
357 supported_formats.push_back(cricket::VideoFormat(320, 640,
358 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
359 capturer_.ResetSupportedFormats(supported_formats);
360
361 std::vector<cricket::VideoFormat> required_formats;
362 required_formats.push_back(cricket::VideoFormat(320, 240,
363 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
364 required_formats.push_back(cricket::VideoFormat(320, 200,
365 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
366 required_formats.push_back(cricket::VideoFormat(320, 180,
367 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
368 cricket::VideoFormat best;
369 for (size_t i = 0; i < required_formats.size(); ++i) {
370 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
371 EXPECT_EQ(320, best.width);
372 EXPECT_EQ(240, best.height);
373 }
374
375 supported_formats.clear();
376 supported_formats.push_back(cricket::VideoFormat(320, 640,
377 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
378 supported_formats.push_back(cricket::VideoFormat(320, 240,
379 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
380 capturer_.ResetSupportedFormats(supported_formats);
381
382 for (size_t i = 0; i < required_formats.size(); ++i) {
383 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
384 EXPECT_EQ(320, best.width);
385 EXPECT_EQ(240, best.height);
386 }
387}
388
389// Some cameras only have very low fps. Verify we choose something sensible.
390TEST_F(VideoCapturerTest, TestPoorFpsFormats) {
391 // all formats are low framerate
392 std::vector<cricket::VideoFormat> supported_formats;
393 supported_formats.push_back(cricket::VideoFormat(320, 240,
394 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
395 supported_formats.push_back(cricket::VideoFormat(640, 480,
396 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
397 supported_formats.push_back(cricket::VideoFormat(1280, 720,
398 cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
399 capturer_.ResetSupportedFormats(supported_formats);
400
401 std::vector<cricket::VideoFormat> required_formats;
402 required_formats.push_back(cricket::VideoFormat(320, 240,
403 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
404 required_formats.push_back(cricket::VideoFormat(640, 480,
405 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
406 cricket::VideoFormat best;
407 for (size_t i = 0; i < required_formats.size(); ++i) {
408 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
409 EXPECT_EQ(required_formats[i].width, best.width);
410 EXPECT_EQ(required_formats[i].height, best.height);
411 }
412
413 // Increase framerate of 320x240. Expect low fps VGA avoided.
414 supported_formats.clear();
415 supported_formats.push_back(cricket::VideoFormat(320, 240,
416 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
417 supported_formats.push_back(cricket::VideoFormat(640, 480,
418 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420));
419 supported_formats.push_back(cricket::VideoFormat(1280, 720,
420 cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420));
421 capturer_.ResetSupportedFormats(supported_formats);
422
423 for (size_t i = 0; i < required_formats.size(); ++i) {
424 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
425 EXPECT_EQ(320, best.width);
426 EXPECT_EQ(240, best.height);
427 }
428}
429
430// Some cameras support same size with different frame rates. Verify we choose
431// the frame rate properly.
432TEST_F(VideoCapturerTest, TestSameSizeDifferentFpsFormats) {
433 std::vector<cricket::VideoFormat> supported_formats;
434 supported_formats.push_back(cricket::VideoFormat(320, 240,
435 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420));
436 supported_formats.push_back(cricket::VideoFormat(320, 240,
437 cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_I420));
438 supported_formats.push_back(cricket::VideoFormat(320, 240,
439 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
440 capturer_.ResetSupportedFormats(supported_formats);
441
442 std::vector<cricket::VideoFormat> required_formats = supported_formats;
443 cricket::VideoFormat best;
444 for (size_t i = 0; i < required_formats.size(); ++i) {
445 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
446 EXPECT_EQ(320, best.width);
447 EXPECT_EQ(240, best.height);
448 EXPECT_EQ(required_formats[i].interval, best.interval);
449 }
450}
451
452// Some cameras support the correct resolution but at a lower fps than
453// we'd like. This tests we get the expected resolution and fps.
454TEST_F(VideoCapturerTest, TestFpsFormats) {
455 // We have VGA but low fps. Choose VGA, not HD
456 std::vector<cricket::VideoFormat> supported_formats;
457 supported_formats.push_back(cricket::VideoFormat(1280, 720,
458 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
459 supported_formats.push_back(cricket::VideoFormat(640, 480,
460 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
461 supported_formats.push_back(cricket::VideoFormat(640, 400,
462 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
463 supported_formats.push_back(cricket::VideoFormat(640, 360,
464 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
465 capturer_.ResetSupportedFormats(supported_formats);
466
467 std::vector<cricket::VideoFormat> required_formats;
468 required_formats.push_back(cricket::VideoFormat(640, 480,
469 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_ANY));
470 required_formats.push_back(cricket::VideoFormat(640, 480,
471 cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_ANY));
472 required_formats.push_back(cricket::VideoFormat(640, 480,
473 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_ANY));
474 cricket::VideoFormat best;
475
476 // expect 30 fps to choose 30 fps format
477 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
478 EXPECT_EQ(640, best.width);
479 EXPECT_EQ(400, best.height);
480 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
481
482 // expect 20 fps to choose 20 fps format
483 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
484 EXPECT_EQ(640, best.width);
485 EXPECT_EQ(400, best.height);
486 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(20), best.interval);
487
488 // expect 10 fps to choose 15 fps format but set fps to 10
489 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
490 EXPECT_EQ(640, best.width);
491 EXPECT_EQ(480, best.height);
492 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(10), best.interval);
493
494 // We have VGA 60 fps and 15 fps. Choose best fps.
495 supported_formats.clear();
496 supported_formats.push_back(cricket::VideoFormat(1280, 720,
497 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
498 supported_formats.push_back(cricket::VideoFormat(640, 480,
499 cricket::VideoFormat::FpsToInterval(60), cricket::FOURCC_MJPG));
500 supported_formats.push_back(cricket::VideoFormat(640, 480,
501 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420));
502 supported_formats.push_back(cricket::VideoFormat(640, 400,
503 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
504 supported_formats.push_back(cricket::VideoFormat(640, 360,
505 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
506 capturer_.ResetSupportedFormats(supported_formats);
507
508 // expect 30 fps to choose 60 fps format, but will set best fps to 30
509 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best));
510 EXPECT_EQ(640, best.width);
511 EXPECT_EQ(480, best.height);
512 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval);
513
514 // expect 20 fps to choose 60 fps format, but will set best fps to 20
515 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best));
516 EXPECT_EQ(640, best.width);
517 EXPECT_EQ(480, best.height);
518 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(20), best.interval);
519
520 // expect 10 fps to choose 10 fps
521 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
522 EXPECT_EQ(640, best.width);
523 EXPECT_EQ(480, best.height);
524 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(10), best.interval);
525}
526
527TEST_F(VideoCapturerTest, TestRequest16x10_9) {
528 std::vector<cricket::VideoFormat> supported_formats;
529 // We do not support HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
530 supported_formats.push_back(cricket::VideoFormat(640, 480,
531 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
532 supported_formats.push_back(cricket::VideoFormat(640, 400,
533 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
534 supported_formats.push_back(cricket::VideoFormat(640, 360,
535 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
536 capturer_.ResetSupportedFormats(supported_formats);
537
538 std::vector<cricket::VideoFormat> required_formats = supported_formats;
539 cricket::VideoFormat best;
540 // Expect 4x3, 16x10, and 16x9 requests are respected.
541 for (size_t i = 0; i < required_formats.size(); ++i) {
542 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
543 EXPECT_EQ(required_formats[i].width, best.width);
544 EXPECT_EQ(required_formats[i].height, best.height);
545 }
546
547 // We do not support 16x9 HD, expect 4x3 for 4x3, 16x10, and 16x9 requests.
548 supported_formats.clear();
549 supported_formats.push_back(cricket::VideoFormat(960, 720,
550 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
551 supported_formats.push_back(cricket::VideoFormat(640, 480,
552 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
553 supported_formats.push_back(cricket::VideoFormat(640, 400,
554 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
555 supported_formats.push_back(cricket::VideoFormat(640, 360,
556 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
557 capturer_.ResetSupportedFormats(supported_formats);
558
559 // Expect 4x3, 16x10, and 16x9 requests are respected.
560 for (size_t i = 0; i < required_formats.size(); ++i) {
561 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
562 EXPECT_EQ(required_formats[i].width, best.width);
563 EXPECT_EQ(required_formats[i].height, best.height);
564 }
565
566 // We support 16x9HD, Expect 4x3, 16x10, and 16x9 requests are respected.
567 supported_formats.clear();
568 supported_formats.push_back(cricket::VideoFormat(1280, 720,
569 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
570 supported_formats.push_back(cricket::VideoFormat(640, 480,
571 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
572 supported_formats.push_back(cricket::VideoFormat(640, 400,
573 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
574 supported_formats.push_back(cricket::VideoFormat(640, 360,
575 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
576 capturer_.ResetSupportedFormats(supported_formats);
577
578 // Expect 4x3 for 4x3 and 16x10 requests.
579 for (size_t i = 0; i < required_formats.size() - 1; ++i) {
580 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best));
581 EXPECT_EQ(required_formats[i].width, best.width);
582 EXPECT_EQ(required_formats[i].height, best.height);
583 }
584
585 // Expect 16x9 for 16x9 request.
586 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best));
587 EXPECT_EQ(640, best.width);
588 EXPECT_EQ(360, best.height);
589}
590
591#if defined(HAS_I420_FRAME)
592TEST_F(VideoCapturerTest, VideoFrame) {
593 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
594 640,
595 480,
596 cricket::VideoFormat::FpsToInterval(30),
597 cricket::FOURCC_I420)));
598 EXPECT_TRUE(capturer_.IsRunning());
599 EXPECT_EQ(0, video_frames_received());
600 EXPECT_TRUE(capturer_.CaptureFrame());
601 EXPECT_EQ(1, video_frames_received());
602}
603
604TEST_F(VideoCapturerTest, ProcessorChainTest) {
605 VideoProcessor0 processor0;
606 VideoProcessor1 processor1;
607 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
608 640,
609 480,
610 cricket::VideoFormat::FpsToInterval(30),
611 cricket::FOURCC_I420)));
612 EXPECT_TRUE(capturer_.IsRunning());
613 EXPECT_EQ(0, video_frames_received());
614 // First processor sets elapsed time to 0.
615 capturer_.AddVideoProcessor(&processor0);
616 // Second processor adds 1 to the elapsed time. I.e. a frames elapsed time
617 // should now always be 1 (and not 0).
618 capturer_.AddVideoProcessor(&processor1);
619 EXPECT_TRUE(capturer_.CaptureFrame());
620 EXPECT_EQ(1, video_frames_received());
621 EXPECT_EQ(1u, last_frame_elapsed_time());
622 capturer_.RemoveVideoProcessor(&processor1);
623 EXPECT_TRUE(capturer_.CaptureFrame());
624 // Since processor1 has been removed the elapsed time should now be 0.
625 EXPECT_EQ(2, video_frames_received());
626 EXPECT_EQ(0u, last_frame_elapsed_time());
627}
628
629TEST_F(VideoCapturerTest, ProcessorDropFrame) {
630 cricket::FakeMediaProcessor dropping_processor_;
631 dropping_processor_.set_drop_frames(true);
632 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat(
633 640,
634 480,
635 cricket::VideoFormat::FpsToInterval(30),
636 cricket::FOURCC_I420)));
637 EXPECT_TRUE(capturer_.IsRunning());
638 EXPECT_EQ(0, video_frames_received());
639 // Install a processor that always drop frames.
640 capturer_.AddVideoProcessor(&dropping_processor_);
641 EXPECT_TRUE(capturer_.CaptureFrame());
642 EXPECT_EQ(0, video_frames_received());
643}
644#endif // HAS_I420_FRAME
645
646bool HdFormatInList(const std::vector<cricket::VideoFormat>& formats) {
647 for (std::vector<cricket::VideoFormat>::const_iterator found =
648 formats.begin(); found != formats.end(); ++found) {
649 if (found->height >= kMinHdHeight) {
650 return true;
651 }
652 }
653 return false;
654}
655
656TEST_F(VideoCapturerTest, Whitelist) {
657 // The definition of HD only applies to the height. Set the HD width to the
658 // smallest legal number to document this fact in this test.
659 const int kMinHdWidth = 1;
660 cricket::VideoFormat hd_format(kMinHdWidth,
661 kMinHdHeight,
662 cricket::VideoFormat::FpsToInterval(30),
663 cricket::FOURCC_I420);
664 cricket::VideoFormat vga_format(640, 480,
665 cricket::VideoFormat::FpsToInterval(30),
666 cricket::FOURCC_I420);
667 std::vector<cricket::VideoFormat> formats = *capturer_.GetSupportedFormats();
668 formats.push_back(hd_format);
669
670 // Enable whitelist. Expect HD not in list.
671 capturer_.set_enable_camera_list(true);
672 capturer_.ResetSupportedFormats(formats);
673 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
674 capturer_.ConstrainSupportedFormats(vga_format);
675 EXPECT_FALSE(HdFormatInList(*capturer_.GetSupportedFormats()));
676
677 // Disable whitelist. Expect HD in list.
678 capturer_.set_enable_camera_list(false);
679 capturer_.ResetSupportedFormats(formats);
680 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
681 capturer_.ConstrainSupportedFormats(vga_format);
682 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats()));
683}
sergeyu@chromium.org0be6aa02013-08-23 23:21:25 +0000684
685TEST_F(VideoCapturerTest, BlacklistAllFormats) {
686 cricket::VideoFormat vga_format(640, 480,
687 cricket::VideoFormat::FpsToInterval(30),
688 cricket::FOURCC_I420);
689 std::vector<cricket::VideoFormat> supported_formats;
690 // Mock a device that only supports HD formats.
691 supported_formats.push_back(cricket::VideoFormat(1280, 720,
692 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
693 supported_formats.push_back(cricket::VideoFormat(1920, 1080,
694 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420));
695 capturer_.ResetSupportedFormats(supported_formats);
696 EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size());
697 // Now, enable the list, which would exclude both formats. However, since
698 // only HD formats are available, we refuse to filter at all, so we don't
699 // break this camera.
700 capturer_.set_enable_camera_list(true);
701 capturer_.ConstrainSupportedFormats(vga_format);
702 EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size());
703 // To make sure it's not just the camera list being broken, add in VGA and
704 // try again. This time, only the VGA format should be there.
705 supported_formats.push_back(vga_format);
706 capturer_.ResetSupportedFormats(supported_formats);
707 ASSERT_EQ(1u, capturer_.GetSupportedFormats()->size());
708 EXPECT_EQ(vga_format.height, capturer_.GetSupportedFormats()->at(0).height);
709}