1 // 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 25 using cricket::FakeVideoCapturer; 26 27 namespace { 28 29 const int kMsCallbackWait = 500; 30 // For HD only the height matters. 31 const int kMinHdHeight = 720; 32 const uint32 kTimeout = 5000U; 33 34 } // namespace 35 36 // Sets the elapsed time in the video frame to 0. 37 class 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. 47 class 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 56 class 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 96 TEST_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 113 TEST_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 135 TEST_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 146 TEST_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 160 TEST_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 197 TEST_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 214 TEST_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 258 TEST_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. 353 TEST_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. 390 TEST_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. 432 TEST_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. 454 TEST_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 527 TEST_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) 592 TEST_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 604 TEST_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 629 TEST_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 646 bool 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 656 TEST_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 } 684