1 /* 2 * libjingle 3 * Copyright 2008 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <stdio.h> 29 #include <vector> 30 31 #include "talk/media/base/fakemediaprocessor.h" 32 #include "talk/media/base/fakevideocapturer.h" 33 #include "talk/media/base/fakevideorenderer.h" 34 #include "talk/media/base/testutils.h" 35 #include "talk/media/base/videocapturer.h" 36 #include "talk/media/base/videoprocessor.h" 37 #include "webrtc/base/gunit.h" 38 #include "webrtc/base/logging.h" 39 #include "webrtc/base/thread.h" 40 41 using cricket::FakeVideoCapturer; 42 43 namespace { 44 45 const int kMsCallbackWait = 500; 46 // For HD only the height matters. 47 const int kMinHdHeight = 720; 48 const uint32 kTimeout = 5000U; 49 50 void NormalizeVideoSize(int* expected_width, int* expected_height) { 51 // WebRtcVideoFrame truncates the frame size to a multiple of 4. 52 *expected_width = *expected_width & ~3; 53 *expected_height = *expected_height & ~3; 54 } 55 56 } // namespace 57 58 // Sets the elapsed time in the video frame to 0. 59 class VideoProcessor0 : public cricket::VideoProcessor { 60 public: 61 virtual void OnFrame(uint32 /*ssrc*/, cricket::VideoFrame* frame, 62 bool* drop_frame) { 63 frame->SetElapsedTime(0u); 64 } 65 }; 66 67 // Adds one to the video frame's elapsed time. Note that VideoProcessor0 and 68 // VideoProcessor1 are not commutative. 69 class VideoProcessor1 : public cricket::VideoProcessor { 70 public: 71 virtual void OnFrame(uint32 /*ssrc*/, cricket::VideoFrame* frame, 72 bool* drop_frame) { 73 int64 elapsed_time = frame->GetElapsedTime(); 74 frame->SetElapsedTime(elapsed_time + 1); 75 } 76 }; 77 78 class VideoCapturerTest 79 : public sigslot::has_slots<>, 80 public testing::Test { 81 public: 82 VideoCapturerTest() 83 : capture_state_(cricket::CS_STOPPED), 84 num_state_changes_(0), 85 video_frames_received_(0), 86 last_frame_elapsed_time_(0) { 87 capturer_.SignalVideoFrame.connect(this, &VideoCapturerTest::OnVideoFrame); 88 capturer_.SignalStateChange.connect(this, 89 &VideoCapturerTest::OnStateChange); 90 } 91 92 protected: 93 void OnVideoFrame(cricket::VideoCapturer*, const cricket::VideoFrame* frame) { 94 ++video_frames_received_; 95 last_frame_elapsed_time_ = frame->GetElapsedTime(); 96 renderer_.RenderFrame(frame); 97 } 98 void OnStateChange(cricket::VideoCapturer*, 99 cricket::CaptureState capture_state) { 100 capture_state_ = capture_state; 101 ++num_state_changes_; 102 } 103 cricket::CaptureState capture_state() { return capture_state_; } 104 int num_state_changes() { return num_state_changes_; } 105 int video_frames_received() const { 106 return video_frames_received_; 107 } 108 int64 last_frame_elapsed_time() const { return last_frame_elapsed_time_; } 109 110 cricket::FakeVideoCapturer capturer_; 111 cricket::CaptureState capture_state_; 112 int num_state_changes_; 113 int video_frames_received_; 114 int64 last_frame_elapsed_time_; 115 cricket::FakeVideoRenderer renderer_; 116 }; 117 118 TEST_F(VideoCapturerTest, CaptureState) { 119 EXPECT_TRUE(capturer_.enable_video_adapter()); 120 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat( 121 640, 122 480, 123 cricket::VideoFormat::FpsToInterval(30), 124 cricket::FOURCC_I420))); 125 EXPECT_TRUE(capturer_.IsRunning()); 126 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait); 127 EXPECT_EQ(1, num_state_changes()); 128 capturer_.Stop(); 129 EXPECT_EQ_WAIT(cricket::CS_STOPPED, capture_state(), kMsCallbackWait); 130 EXPECT_EQ(2, num_state_changes()); 131 capturer_.Stop(); 132 rtc::Thread::Current()->ProcessMessages(100); 133 EXPECT_EQ(2, num_state_changes()); 134 } 135 136 TEST_F(VideoCapturerTest, TestRestart) { 137 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(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 EXPECT_EQ(1, num_state_changes()); 145 EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat( 146 320, 147 240, 148 cricket::VideoFormat::FpsToInterval(30), 149 cricket::FOURCC_I420))); 150 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait); 151 EXPECT_TRUE(capturer_.IsRunning()); 152 EXPECT_GE(1, num_state_changes()); 153 capturer_.Stop(); 154 rtc::Thread::Current()->ProcessMessages(100); 155 EXPECT_FALSE(capturer_.IsRunning()); 156 } 157 158 TEST_F(VideoCapturerTest, TestStartingWithRestart) { 159 EXPECT_FALSE(capturer_.IsRunning()); 160 EXPECT_TRUE(capturer_.Restart(cricket::VideoFormat( 161 640, 162 480, 163 cricket::VideoFormat::FpsToInterval(30), 164 cricket::FOURCC_I420))); 165 EXPECT_TRUE(capturer_.IsRunning()); 166 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait); 167 } 168 169 TEST_F(VideoCapturerTest, TestRestartWithSameFormat) { 170 cricket::VideoFormat format(640, 480, 171 cricket::VideoFormat::FpsToInterval(30), 172 cricket::FOURCC_I420); 173 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(format)); 174 EXPECT_TRUE(capturer_.IsRunning()); 175 EXPECT_EQ_WAIT(cricket::CS_RUNNING, capture_state(), kMsCallbackWait); 176 EXPECT_EQ(1, num_state_changes()); 177 EXPECT_TRUE(capturer_.Restart(format)); 178 EXPECT_EQ(cricket::CS_RUNNING, capture_state()); 179 EXPECT_TRUE(capturer_.IsRunning()); 180 EXPECT_EQ(1, num_state_changes()); 181 } 182 183 TEST_F(VideoCapturerTest, CameraOffOnMute) { 184 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat( 185 640, 186 480, 187 cricket::VideoFormat::FpsToInterval(30), 188 cricket::FOURCC_I420))); 189 EXPECT_TRUE(capturer_.IsRunning()); 190 EXPECT_EQ(0, video_frames_received()); 191 EXPECT_TRUE(capturer_.CaptureFrame()); 192 EXPECT_EQ(1, video_frames_received()); 193 EXPECT_FALSE(capturer_.IsMuted()); 194 195 // Mute the camera and expect black output frame. 196 capturer_.MuteToBlackThenPause(true); 197 EXPECT_TRUE(capturer_.IsMuted()); 198 for (int i = 0; i < 31; ++i) { 199 EXPECT_TRUE(capturer_.CaptureFrame()); 200 EXPECT_TRUE(renderer_.black_frame()); 201 } 202 EXPECT_EQ(32, video_frames_received()); 203 EXPECT_EQ_WAIT(cricket::CS_PAUSED, 204 capturer_.capture_state(), kTimeout); 205 206 // Verify that the camera is off. 207 EXPECT_FALSE(capturer_.CaptureFrame()); 208 EXPECT_EQ(32, video_frames_received()); 209 210 // Unmute the camera and expect non-black output frame. 211 capturer_.MuteToBlackThenPause(false); 212 EXPECT_FALSE(capturer_.IsMuted()); 213 EXPECT_EQ_WAIT(cricket::CS_RUNNING, 214 capturer_.capture_state(), kTimeout); 215 EXPECT_TRUE(capturer_.CaptureFrame()); 216 EXPECT_FALSE(renderer_.black_frame()); 217 EXPECT_EQ(33, video_frames_received()); 218 } 219 220 TEST_F(VideoCapturerTest, ScreencastScaledMaxPixels) { 221 capturer_.SetScreencast(true); 222 223 int kWidth = 1280; 224 int kHeight = 720; 225 226 // Screencasts usually have large weird dimensions and are ARGB. 227 std::vector<cricket::VideoFormat> formats; 228 formats.push_back(cricket::VideoFormat(kWidth, kHeight, 229 cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB)); 230 formats.push_back(cricket::VideoFormat(2 * kWidth, 2 * kHeight, 231 cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB)); 232 capturer_.ResetSupportedFormats(formats); 233 234 235 EXPECT_EQ(0, capturer_.screencast_max_pixels()); 236 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat( 237 2 * kWidth, 238 2 * kHeight, 239 cricket::VideoFormat::FpsToInterval(30), 240 cricket::FOURCC_ARGB))); 241 EXPECT_TRUE(capturer_.IsRunning()); 242 EXPECT_EQ(0, renderer_.num_rendered_frames()); 243 renderer_.SetSize(2 * kWidth, 2 * kHeight, 0); 244 EXPECT_TRUE(capturer_.CaptureFrame()); 245 EXPECT_EQ(1, renderer_.num_rendered_frames()); 246 247 capturer_.set_screencast_max_pixels(kWidth * kHeight); 248 renderer_.SetSize(kWidth, kHeight, 0); 249 EXPECT_TRUE(capturer_.CaptureFrame()); 250 EXPECT_EQ(2, renderer_.num_rendered_frames()); 251 } 252 253 TEST_F(VideoCapturerTest, ScreencastScaledOddWidth) { 254 capturer_.SetScreencast(true); 255 256 int kWidth = 1281; 257 int kHeight = 720; 258 259 std::vector<cricket::VideoFormat> formats; 260 formats.push_back(cricket::VideoFormat(kWidth, kHeight, 261 cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB)); 262 capturer_.ResetSupportedFormats(formats); 263 264 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat( 265 kWidth, 266 kHeight, 267 cricket::VideoFormat::FpsToInterval(30), 268 cricket::FOURCC_ARGB))); 269 EXPECT_TRUE(capturer_.IsRunning()); 270 EXPECT_EQ(0, renderer_.num_rendered_frames()); 271 int expected_width = kWidth; 272 int expected_height = kHeight; 273 NormalizeVideoSize(&expected_width, &expected_height); 274 renderer_.SetSize(expected_width, expected_height, 0); 275 EXPECT_TRUE(capturer_.CaptureFrame()); 276 EXPECT_EQ(1, renderer_.num_rendered_frames()); 277 } 278 279 TEST_F(VideoCapturerTest, ScreencastScaledSuperLarge) { 280 capturer_.SetScreencast(true); 281 282 const int kMaxWidth = 4096; 283 const int kMaxHeight = 3072; 284 int kWidth = kMaxWidth + 4; 285 int kHeight = kMaxHeight + 4; 286 287 std::vector<cricket::VideoFormat> formats; 288 formats.push_back(cricket::VideoFormat(kWidth, kHeight, 289 cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB)); 290 capturer_.ResetSupportedFormats(formats); 291 292 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat( 293 kWidth, 294 kHeight, 295 cricket::VideoFormat::FpsToInterval(30), 296 cricket::FOURCC_ARGB))); 297 EXPECT_TRUE(capturer_.IsRunning()); 298 EXPECT_EQ(0, renderer_.num_rendered_frames()); 299 int expected_width = 2050; 300 int expected_height = 1538; 301 NormalizeVideoSize(&expected_width, &expected_height); 302 renderer_.SetSize(expected_width, expected_height, 0); 303 EXPECT_TRUE(capturer_.CaptureFrame()); 304 EXPECT_EQ(1, renderer_.num_rendered_frames()); 305 } 306 307 TEST_F(VideoCapturerTest, TestFourccMatch) { 308 cricket::VideoFormat desired(640, 480, 309 cricket::VideoFormat::FpsToInterval(30), 310 cricket::FOURCC_ANY); 311 cricket::VideoFormat best; 312 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 313 EXPECT_EQ(640, best.width); 314 EXPECT_EQ(480, best.height); 315 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); 316 317 desired.fourcc = cricket::FOURCC_MJPG; 318 EXPECT_FALSE(capturer_.GetBestCaptureFormat(desired, &best)); 319 320 desired.fourcc = cricket::FOURCC_I420; 321 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 322 } 323 324 TEST_F(VideoCapturerTest, TestResolutionMatch) { 325 cricket::VideoFormat desired(1920, 1080, 326 cricket::VideoFormat::FpsToInterval(30), 327 cricket::FOURCC_ANY); 328 cricket::VideoFormat best; 329 // Ask for 1920x1080. Get HD 1280x720 which is the highest. 330 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 331 EXPECT_EQ(1280, best.width); 332 EXPECT_EQ(720, best.height); 333 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); 334 335 desired.width = 360; 336 desired.height = 250; 337 // Ask for a little higher than QVGA. Get QVGA. 338 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 339 EXPECT_EQ(320, best.width); 340 EXPECT_EQ(240, best.height); 341 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); 342 343 desired.width = 480; 344 desired.height = 270; 345 // Ask for HVGA. Get VGA. 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 desired.width = 320; 352 desired.height = 240; 353 // Ask for QVGA. Get QVGA. 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 = 80; 360 desired.height = 60; 361 // Ask for lower than QQVGA. Get QQVGA, which is the lowest. 362 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 363 EXPECT_EQ(160, best.width); 364 EXPECT_EQ(120, best.height); 365 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); 366 } 367 368 TEST_F(VideoCapturerTest, TestHDResolutionMatch) { 369 // Add some HD formats typical of a mediocre HD webcam. 370 std::vector<cricket::VideoFormat> formats; 371 formats.push_back(cricket::VideoFormat(320, 240, 372 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 373 formats.push_back(cricket::VideoFormat(640, 480, 374 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 375 formats.push_back(cricket::VideoFormat(960, 544, 376 cricket::VideoFormat::FpsToInterval(24), cricket::FOURCC_I420)); 377 formats.push_back(cricket::VideoFormat(1280, 720, 378 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420)); 379 formats.push_back(cricket::VideoFormat(2592, 1944, 380 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420)); 381 capturer_.ResetSupportedFormats(formats); 382 383 cricket::VideoFormat desired(960, 720, 384 cricket::VideoFormat::FpsToInterval(30), 385 cricket::FOURCC_ANY); 386 cricket::VideoFormat best; 387 // Ask for 960x720 30 fps. Get qHD 24 fps 388 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 389 EXPECT_EQ(960, best.width); 390 EXPECT_EQ(544, best.height); 391 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval); 392 393 desired.width = 960; 394 desired.height = 544; 395 desired.interval = cricket::VideoFormat::FpsToInterval(30); 396 // Ask for qHD 30 fps. Get qHD 24 fps 397 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 398 EXPECT_EQ(960, best.width); 399 EXPECT_EQ(544, best.height); 400 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(24), best.interval); 401 402 desired.width = 360; 403 desired.height = 250; 404 desired.interval = cricket::VideoFormat::FpsToInterval(30); 405 // Ask for a little higher than QVGA. Get QVGA. 406 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 407 EXPECT_EQ(320, best.width); 408 EXPECT_EQ(240, best.height); 409 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); 410 411 desired.width = 480; 412 desired.height = 270; 413 // Ask for HVGA. Get VGA. 414 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 415 EXPECT_EQ(640, best.width); 416 EXPECT_EQ(480, best.height); 417 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); 418 419 desired.width = 320; 420 desired.height = 240; 421 // Ask for QVGA. Get QVGA. 422 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 423 EXPECT_EQ(320, best.width); 424 EXPECT_EQ(240, best.height); 425 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); 426 427 desired.width = 160; 428 desired.height = 120; 429 // Ask for lower than QVGA. Get QVGA, which is the lowest. 430 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 431 EXPECT_EQ(320, best.width); 432 EXPECT_EQ(240, best.height); 433 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); 434 435 desired.width = 1280; 436 desired.height = 720; 437 // Ask for HD. 720p fps is too low. Get VGA which has 30 fps. 438 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 439 EXPECT_EQ(640, best.width); 440 EXPECT_EQ(480, best.height); 441 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); 442 443 desired.width = 1280; 444 desired.height = 720; 445 desired.interval = cricket::VideoFormat::FpsToInterval(15); 446 // Ask for HD 15 fps. Fps matches. Get HD 447 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 448 EXPECT_EQ(1280, best.width); 449 EXPECT_EQ(720, best.height); 450 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval); 451 452 desired.width = 1920; 453 desired.height = 1080; 454 desired.interval = cricket::VideoFormat::FpsToInterval(30); 455 // Ask for 1080p. Fps of HD formats is too low. Get VGA which can do 30 fps. 456 EXPECT_TRUE(capturer_.GetBestCaptureFormat(desired, &best)); 457 EXPECT_EQ(640, best.width); 458 EXPECT_EQ(480, best.height); 459 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); 460 } 461 462 // Some cameras support 320x240 and 320x640. Verify we choose 320x240. 463 TEST_F(VideoCapturerTest, TestStrangeFormats) { 464 std::vector<cricket::VideoFormat> supported_formats; 465 supported_formats.push_back(cricket::VideoFormat(320, 240, 466 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 467 supported_formats.push_back(cricket::VideoFormat(320, 640, 468 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 469 capturer_.ResetSupportedFormats(supported_formats); 470 471 std::vector<cricket::VideoFormat> required_formats; 472 required_formats.push_back(cricket::VideoFormat(320, 240, 473 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 474 required_formats.push_back(cricket::VideoFormat(320, 200, 475 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 476 required_formats.push_back(cricket::VideoFormat(320, 180, 477 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 478 cricket::VideoFormat best; 479 for (size_t i = 0; i < required_formats.size(); ++i) { 480 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best)); 481 EXPECT_EQ(320, best.width); 482 EXPECT_EQ(240, best.height); 483 } 484 485 supported_formats.clear(); 486 supported_formats.push_back(cricket::VideoFormat(320, 640, 487 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 488 supported_formats.push_back(cricket::VideoFormat(320, 240, 489 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 490 capturer_.ResetSupportedFormats(supported_formats); 491 492 for (size_t i = 0; i < required_formats.size(); ++i) { 493 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best)); 494 EXPECT_EQ(320, best.width); 495 EXPECT_EQ(240, best.height); 496 } 497 } 498 499 // Some cameras only have very low fps. Verify we choose something sensible. 500 TEST_F(VideoCapturerTest, TestPoorFpsFormats) { 501 // all formats are low framerate 502 std::vector<cricket::VideoFormat> supported_formats; 503 supported_formats.push_back(cricket::VideoFormat(320, 240, 504 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420)); 505 supported_formats.push_back(cricket::VideoFormat(640, 480, 506 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420)); 507 supported_formats.push_back(cricket::VideoFormat(1280, 720, 508 cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420)); 509 capturer_.ResetSupportedFormats(supported_formats); 510 511 std::vector<cricket::VideoFormat> required_formats; 512 required_formats.push_back(cricket::VideoFormat(320, 240, 513 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 514 required_formats.push_back(cricket::VideoFormat(640, 480, 515 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 516 cricket::VideoFormat best; 517 for (size_t i = 0; i < required_formats.size(); ++i) { 518 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best)); 519 EXPECT_EQ(required_formats[i].width, best.width); 520 EXPECT_EQ(required_formats[i].height, best.height); 521 } 522 523 // Increase framerate of 320x240. Expect low fps VGA avoided. 524 supported_formats.clear(); 525 supported_formats.push_back(cricket::VideoFormat(320, 240, 526 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 527 supported_formats.push_back(cricket::VideoFormat(640, 480, 528 cricket::VideoFormat::FpsToInterval(7), cricket::FOURCC_I420)); 529 supported_formats.push_back(cricket::VideoFormat(1280, 720, 530 cricket::VideoFormat::FpsToInterval(2), cricket::FOURCC_I420)); 531 capturer_.ResetSupportedFormats(supported_formats); 532 533 for (size_t i = 0; i < required_formats.size(); ++i) { 534 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best)); 535 EXPECT_EQ(320, best.width); 536 EXPECT_EQ(240, best.height); 537 } 538 } 539 540 // Some cameras support same size with different frame rates. Verify we choose 541 // the frame rate properly. 542 TEST_F(VideoCapturerTest, TestSameSizeDifferentFpsFormats) { 543 std::vector<cricket::VideoFormat> supported_formats; 544 supported_formats.push_back(cricket::VideoFormat(320, 240, 545 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_I420)); 546 supported_formats.push_back(cricket::VideoFormat(320, 240, 547 cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_I420)); 548 supported_formats.push_back(cricket::VideoFormat(320, 240, 549 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 550 capturer_.ResetSupportedFormats(supported_formats); 551 552 std::vector<cricket::VideoFormat> required_formats = supported_formats; 553 cricket::VideoFormat best; 554 for (size_t i = 0; i < required_formats.size(); ++i) { 555 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best)); 556 EXPECT_EQ(320, best.width); 557 EXPECT_EQ(240, best.height); 558 EXPECT_EQ(required_formats[i].interval, best.interval); 559 } 560 } 561 562 // Some cameras support the correct resolution but at a lower fps than 563 // we'd like. This tests we get the expected resolution and fps. 564 TEST_F(VideoCapturerTest, TestFpsFormats) { 565 // We have VGA but low fps. Choose VGA, not HD 566 std::vector<cricket::VideoFormat> supported_formats; 567 supported_formats.push_back(cricket::VideoFormat(1280, 720, 568 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 569 supported_formats.push_back(cricket::VideoFormat(640, 480, 570 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420)); 571 supported_formats.push_back(cricket::VideoFormat(640, 400, 572 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 573 supported_formats.push_back(cricket::VideoFormat(640, 360, 574 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 575 capturer_.ResetSupportedFormats(supported_formats); 576 577 std::vector<cricket::VideoFormat> required_formats; 578 required_formats.push_back(cricket::VideoFormat(640, 480, 579 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_ANY)); 580 required_formats.push_back(cricket::VideoFormat(640, 480, 581 cricket::VideoFormat::FpsToInterval(20), cricket::FOURCC_ANY)); 582 required_formats.push_back(cricket::VideoFormat(640, 480, 583 cricket::VideoFormat::FpsToInterval(10), cricket::FOURCC_ANY)); 584 cricket::VideoFormat best; 585 586 // Expect 30 fps to choose 30 fps format. 587 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best)); 588 EXPECT_EQ(640, best.width); 589 EXPECT_EQ(400, best.height); 590 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); 591 592 // Expect 20 fps to choose 30 fps format. 593 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best)); 594 EXPECT_EQ(640, best.width); 595 EXPECT_EQ(400, best.height); 596 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(30), best.interval); 597 598 // Expect 10 fps to choose 15 fps format and set fps to 15. 599 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best)); 600 EXPECT_EQ(640, best.width); 601 EXPECT_EQ(480, best.height); 602 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval); 603 604 // We have VGA 60 fps and 15 fps. Choose best fps. 605 supported_formats.clear(); 606 supported_formats.push_back(cricket::VideoFormat(1280, 720, 607 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 608 supported_formats.push_back(cricket::VideoFormat(640, 480, 609 cricket::VideoFormat::FpsToInterval(60), cricket::FOURCC_MJPG)); 610 supported_formats.push_back(cricket::VideoFormat(640, 480, 611 cricket::VideoFormat::FpsToInterval(15), cricket::FOURCC_I420)); 612 supported_formats.push_back(cricket::VideoFormat(640, 400, 613 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 614 supported_formats.push_back(cricket::VideoFormat(640, 360, 615 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 616 capturer_.ResetSupportedFormats(supported_formats); 617 618 // Expect 30 fps to choose 60 fps format and will set best fps to 60. 619 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[0], &best)); 620 EXPECT_EQ(640, best.width); 621 EXPECT_EQ(480, best.height); 622 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval); 623 624 // Expect 20 fps to choose 60 fps format, and will set best fps to 60. 625 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[1], &best)); 626 EXPECT_EQ(640, best.width); 627 EXPECT_EQ(480, best.height); 628 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(60), best.interval); 629 630 // Expect 10 fps to choose 15 fps. 631 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best)); 632 EXPECT_EQ(640, best.width); 633 EXPECT_EQ(480, best.height); 634 EXPECT_EQ(cricket::VideoFormat::FpsToInterval(15), best.interval); 635 } 636 637 TEST_F(VideoCapturerTest, TestRequest16x10_9) { 638 std::vector<cricket::VideoFormat> supported_formats; 639 // We do not support HD, expect 4x3 for 4x3, 16x10, and 16x9 requests. 640 supported_formats.push_back(cricket::VideoFormat(640, 480, 641 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 642 supported_formats.push_back(cricket::VideoFormat(640, 400, 643 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 644 supported_formats.push_back(cricket::VideoFormat(640, 360, 645 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 646 capturer_.ResetSupportedFormats(supported_formats); 647 648 std::vector<cricket::VideoFormat> required_formats = supported_formats; 649 cricket::VideoFormat best; 650 // Expect 4x3, 16x10, and 16x9 requests are respected. 651 for (size_t i = 0; i < required_formats.size(); ++i) { 652 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best)); 653 EXPECT_EQ(required_formats[i].width, best.width); 654 EXPECT_EQ(required_formats[i].height, best.height); 655 } 656 657 // We do not support 16x9 HD, expect 4x3 for 4x3, 16x10, and 16x9 requests. 658 supported_formats.clear(); 659 supported_formats.push_back(cricket::VideoFormat(960, 720, 660 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 661 supported_formats.push_back(cricket::VideoFormat(640, 480, 662 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 663 supported_formats.push_back(cricket::VideoFormat(640, 400, 664 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 665 supported_formats.push_back(cricket::VideoFormat(640, 360, 666 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 667 capturer_.ResetSupportedFormats(supported_formats); 668 669 // Expect 4x3, 16x10, and 16x9 requests are respected. 670 for (size_t i = 0; i < required_formats.size(); ++i) { 671 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best)); 672 EXPECT_EQ(required_formats[i].width, best.width); 673 EXPECT_EQ(required_formats[i].height, best.height); 674 } 675 676 // We support 16x9HD, Expect 4x3, 16x10, and 16x9 requests are respected. 677 supported_formats.clear(); 678 supported_formats.push_back(cricket::VideoFormat(1280, 720, 679 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 680 supported_formats.push_back(cricket::VideoFormat(640, 480, 681 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 682 supported_formats.push_back(cricket::VideoFormat(640, 400, 683 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 684 supported_formats.push_back(cricket::VideoFormat(640, 360, 685 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 686 capturer_.ResetSupportedFormats(supported_formats); 687 688 // Expect 4x3 for 4x3 and 16x10 requests. 689 for (size_t i = 0; i < required_formats.size() - 1; ++i) { 690 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[i], &best)); 691 EXPECT_EQ(required_formats[i].width, best.width); 692 EXPECT_EQ(required_formats[i].height, best.height); 693 } 694 695 // Expect 16x9 for 16x9 request. 696 EXPECT_TRUE(capturer_.GetBestCaptureFormat(required_formats[2], &best)); 697 EXPECT_EQ(640, best.width); 698 EXPECT_EQ(360, best.height); 699 } 700 701 // If HAVE_WEBRTC_VIDEO is not defined the video capturer will not be able to 702 // provide OnVideoFrame-callbacks since they require cricket::CapturedFrame to 703 // be decoded as a cricket::VideoFrame (i.e. an I420 frame). This functionality 704 // only exist if HAVE_WEBRTC_VIDEO is defined below. I420 frames are also a 705 // requirement for the VideoProcessors so they will not be called either. 706 #if defined(HAVE_WEBRTC_VIDEO) 707 TEST_F(VideoCapturerTest, VideoFrame) { 708 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat( 709 640, 710 480, 711 cricket::VideoFormat::FpsToInterval(30), 712 cricket::FOURCC_I420))); 713 EXPECT_TRUE(capturer_.IsRunning()); 714 EXPECT_EQ(0, video_frames_received()); 715 EXPECT_TRUE(capturer_.CaptureFrame()); 716 EXPECT_EQ(1, video_frames_received()); 717 } 718 719 TEST_F(VideoCapturerTest, ProcessorChainTest) { 720 VideoProcessor0 processor0; 721 VideoProcessor1 processor1; 722 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat( 723 640, 724 480, 725 cricket::VideoFormat::FpsToInterval(30), 726 cricket::FOURCC_I420))); 727 EXPECT_TRUE(capturer_.IsRunning()); 728 EXPECT_EQ(0, video_frames_received()); 729 // First processor sets elapsed time to 0. 730 capturer_.AddVideoProcessor(&processor0); 731 // Second processor adds 1 to the elapsed time. I.e. a frames elapsed time 732 // should now always be 1 (and not 0). 733 capturer_.AddVideoProcessor(&processor1); 734 EXPECT_TRUE(capturer_.CaptureFrame()); 735 EXPECT_EQ(1, video_frames_received()); 736 EXPECT_EQ(1u, last_frame_elapsed_time()); 737 capturer_.RemoveVideoProcessor(&processor1); 738 EXPECT_TRUE(capturer_.CaptureFrame()); 739 // Since processor1 has been removed the elapsed time should now be 0. 740 EXPECT_EQ(2, video_frames_received()); 741 EXPECT_EQ(0u, last_frame_elapsed_time()); 742 } 743 744 TEST_F(VideoCapturerTest, ProcessorDropFrame) { 745 cricket::FakeMediaProcessor dropping_processor_; 746 dropping_processor_.set_drop_frames(true); 747 EXPECT_EQ(cricket::CS_RUNNING, capturer_.Start(cricket::VideoFormat( 748 640, 749 480, 750 cricket::VideoFormat::FpsToInterval(30), 751 cricket::FOURCC_I420))); 752 EXPECT_TRUE(capturer_.IsRunning()); 753 EXPECT_EQ(0, video_frames_received()); 754 // Install a processor that always drop frames. 755 capturer_.AddVideoProcessor(&dropping_processor_); 756 EXPECT_TRUE(capturer_.CaptureFrame()); 757 EXPECT_EQ(0, video_frames_received()); 758 } 759 #endif // HAVE_WEBRTC_VIDEO 760 761 bool HdFormatInList(const std::vector<cricket::VideoFormat>& formats) { 762 for (std::vector<cricket::VideoFormat>::const_iterator found = 763 formats.begin(); found != formats.end(); ++found) { 764 if (found->height >= kMinHdHeight) { 765 return true; 766 } 767 } 768 return false; 769 } 770 771 TEST_F(VideoCapturerTest, Whitelist) { 772 // The definition of HD only applies to the height. Set the HD width to the 773 // smallest legal number to document this fact in this test. 774 const int kMinHdWidth = 1; 775 cricket::VideoFormat hd_format(kMinHdWidth, 776 kMinHdHeight, 777 cricket::VideoFormat::FpsToInterval(30), 778 cricket::FOURCC_I420); 779 cricket::VideoFormat vga_format(640, 480, 780 cricket::VideoFormat::FpsToInterval(30), 781 cricket::FOURCC_I420); 782 std::vector<cricket::VideoFormat> formats = *capturer_.GetSupportedFormats(); 783 formats.push_back(hd_format); 784 785 // Enable whitelist. Expect HD not in list. 786 capturer_.set_enable_camera_list(true); 787 capturer_.ResetSupportedFormats(formats); 788 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats())); 789 capturer_.ConstrainSupportedFormats(vga_format); 790 EXPECT_FALSE(HdFormatInList(*capturer_.GetSupportedFormats())); 791 792 // Disable whitelist. Expect HD in list. 793 capturer_.set_enable_camera_list(false); 794 capturer_.ResetSupportedFormats(formats); 795 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats())); 796 capturer_.ConstrainSupportedFormats(vga_format); 797 EXPECT_TRUE(HdFormatInList(*capturer_.GetSupportedFormats())); 798 } 799 800 TEST_F(VideoCapturerTest, BlacklistAllFormats) { 801 cricket::VideoFormat vga_format(640, 480, 802 cricket::VideoFormat::FpsToInterval(30), 803 cricket::FOURCC_I420); 804 std::vector<cricket::VideoFormat> supported_formats; 805 // Mock a device that only supports HD formats. 806 supported_formats.push_back(cricket::VideoFormat(1280, 720, 807 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 808 supported_formats.push_back(cricket::VideoFormat(1920, 1080, 809 cricket::VideoFormat::FpsToInterval(30), cricket::FOURCC_I420)); 810 capturer_.ResetSupportedFormats(supported_formats); 811 EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size()); 812 // Now, enable the list, which would exclude both formats. However, since 813 // only HD formats are available, we refuse to filter at all, so we don't 814 // break this camera. 815 capturer_.set_enable_camera_list(true); 816 capturer_.ConstrainSupportedFormats(vga_format); 817 EXPECT_EQ(2u, capturer_.GetSupportedFormats()->size()); 818 // To make sure it's not just the camera list being broken, add in VGA and 819 // try again. This time, only the VGA format should be there. 820 supported_formats.push_back(vga_format); 821 capturer_.ResetSupportedFormats(supported_formats); 822 ASSERT_EQ(1u, capturer_.GetSupportedFormats()->size()); 823 EXPECT_EQ(vga_format.height, capturer_.GetSupportedFormats()->at(0).height); 824 } 825