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