Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/media/capture/desktop_capture_device.h" | 5 #include "content/browser/media/capture/desktop_capture_device.h" |
| 6 | 6 |
| 7 #include <algorithm> | |
| 7 #include <string> | 8 #include <string> |
| 8 | 9 |
| 9 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| 10 #include "base/synchronization/waitable_event.h" | 11 #include "base/synchronization/waitable_event.h" |
| 11 #include "base/test/test_timeouts.h" | 12 #include "base/test/test_timeouts.h" |
| 12 #include "base/time/time.h" | 13 #include "base/time/time.h" |
| 13 #include "content/public/test/test_browser_thread_bundle.h" | 14 #include "content/public/test/test_browser_thread_bundle.h" |
| 14 #include "testing/gmock/include/gmock/gmock.h" | 15 #include "testing/gmock/include/gmock/gmock.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 16 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h" | 17 #include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h" |
| 17 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" | 18 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
| 18 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" | 19 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h" |
| 19 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" | 20 #include "third_party/webrtc/modules/desktop_capture/screen_capturer.h" |
| 20 | 21 |
| 21 using ::testing::_; | 22 using ::testing::_; |
| 22 using ::testing::AnyNumber; | 23 using ::testing::AnyNumber; |
| 23 using ::testing::DoAll; | 24 using ::testing::DoAll; |
| 24 using ::testing::Expectation; | 25 using ::testing::Expectation; |
| 26 using ::testing::Invoke; | |
| 25 using ::testing::InvokeWithoutArgs; | 27 using ::testing::InvokeWithoutArgs; |
| 26 using ::testing::SaveArg; | 28 using ::testing::SaveArg; |
| 29 using ::testing::WithArg; | |
| 27 | 30 |
| 28 namespace content { | 31 namespace content { |
| 29 | 32 |
| 30 namespace { | 33 namespace { |
| 31 | 34 |
| 32 MATCHER_P2(EqualsCaptureCapability, width, height, "") { | 35 MATCHER_P2(EqualsCaptureCapability, width, height, "") { |
| 33 return arg.width == width && arg.height == height; | 36 return arg.width == width && arg.height == height; |
| 34 } | 37 } |
| 35 | 38 |
| 36 const int kTestFrameWidth1 = 100; | 39 const int kTestFrameWidth1 = 500; |
| 37 const int kTestFrameHeight1 = 100; | 40 const int kTestFrameHeight1 = 500; |
| 38 const int kTestFrameWidth2 = 200; | 41 const int kTestFrameWidth2 = 400; |
| 39 const int kTestFrameHeight2 = 150; | 42 const int kTestFrameHeight2 = 300; |
| 40 | 43 |
| 41 const int kFrameRate = 30; | 44 const int kFrameRate = 30; |
| 42 | 45 |
| 43 // The value of the padding bytes in unpacked frames. | 46 // The value of the padding bytes in unpacked frames. |
| 44 const uint8_t kFramePaddingValue = 0; | 47 const uint8_t kFramePaddingValue = 0; |
| 45 | 48 |
| 46 // Use a special value for frame pixels to tell pixel bytes apart from the | 49 // Use a special value for frame pixels to tell pixel bytes apart from the |
| 47 // padding bytes in the unpacked frame test. | 50 // padding bytes in the unpacked frame test. |
| 48 const uint8_t kFakePixelValue = 1; | 51 const uint8_t kFakePixelValue = 1; |
| 49 | 52 |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 EXPECT_GT(format.frame_size.height(), 0); | 269 EXPECT_GT(format.frame_size.height(), 0); |
| 267 EXPECT_EQ(kFrameRate, format.frame_rate); | 270 EXPECT_EQ(kFrameRate, format.frame_rate); |
| 268 EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format); | 271 EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format); |
| 269 | 272 |
| 270 EXPECT_EQ(format.frame_size.GetArea() * 4, frame_size); | 273 EXPECT_EQ(format.frame_size.GetArea() * 4, frame_size); |
| 271 } | 274 } |
| 272 | 275 |
| 273 // Test that screen capturer behaves correctly if the source frame size changes | 276 // Test that screen capturer behaves correctly if the source frame size changes |
| 274 // but the caller cannot cope with variable resolution output. | 277 // but the caller cannot cope with variable resolution output. |
| 275 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) { | 278 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) { |
| 279 // Helper used to check that only one distinct frame size is delivered and | |
| 280 // that it exactly matches the configured frame size. | |
| 281 struct FormatChecker { | |
| 282 static void ExpectAcceptableSize(const media::VideoCaptureFormat& format) { | |
|
Wez
2015/05/15 00:55:42
Why is this in a struct rather than being a static
miu
2015/05/15 21:14:01
No particular reason, other than it's only used wi
| |
| 283 const gfx::Size& size = format.frame_size; | |
| 284 EXPECT_EQ(gfx::Size(kTestFrameWidth1, kTestFrameHeight1), size); | |
| 285 EXPECT_EQ(kFrameRate, format.frame_rate); | |
| 286 EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format); | |
| 287 } | |
| 288 }; | |
| 289 | |
| 276 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); | 290 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); |
| 277 | 291 |
| 278 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); | 292 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); |
| 279 | 293 |
| 280 media::VideoCaptureFormat format; | |
| 281 base::WaitableEvent done_event(false, false); | 294 base::WaitableEvent done_event(false, false); |
| 282 int frame_size; | |
| 283 | 295 |
| 284 scoped_ptr<MockDeviceClient> client(new MockDeviceClient()); | 296 scoped_ptr<MockDeviceClient> client(new MockDeviceClient()); |
| 285 EXPECT_CALL(*client, OnError(_)).Times(0); | 297 EXPECT_CALL(*client, OnError(_)).Times(0); |
| 286 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly( | 298 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly( |
| 287 DoAll(SaveArg<1>(&frame_size), | 299 DoAll(WithArg<2>(Invoke(&FormatChecker::ExpectAcceptableSize)), |
| 288 SaveArg<2>(&format), | |
| 289 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal))); | 300 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal))); |
| 290 | 301 |
| 291 media::VideoCaptureParams capture_params; | 302 media::VideoCaptureParams capture_params; |
| 292 capture_params.requested_format.frame_size.SetSize(kTestFrameWidth1, | 303 capture_params.requested_format.frame_size.SetSize(kTestFrameWidth1, |
| 293 kTestFrameHeight1); | 304 kTestFrameHeight1); |
| 294 capture_params.requested_format.frame_rate = kFrameRate; | 305 capture_params.requested_format.frame_rate = kFrameRate; |
| 295 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | 306 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; |
| 307 capture_params.resolution_change_policy = | |
| 308 media::RESOLUTION_POLICY_FIXED_RESOLUTION; | |
| 296 | 309 |
| 297 capture_device_->AllocateAndStart(capture_params, client.Pass()); | 310 capture_device_->AllocateAndStart(capture_params, client.Pass()); |
| 298 | 311 |
| 299 // Capture at least two frames, to ensure that the source frame size has | 312 // Capture at least two frames, to ensure that the source frame size has |
| 300 // changed while capturing. | 313 // changed to two different sizes while capturing. The mock for |
| 301 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | 314 // OnIncomingCapturedData() will use FormatChecker to examine the format of |
| 302 done_event.Reset(); | 315 // each frame being delivered. |
| 303 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | 316 for (int i = 0; i < 2; ++i) { |
| 317 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | |
| 318 done_event.Reset(); | |
| 319 } | |
| 304 | 320 |
| 305 capture_device_->StopAndDeAllocate(); | 321 capture_device_->StopAndDeAllocate(); |
| 322 } | |
| 306 | 323 |
| 307 EXPECT_EQ(kTestFrameWidth1, format.frame_size.width()); | 324 // Test that screen capturer behaves correctly if the source frame size changes, |
| 308 EXPECT_EQ(kTestFrameHeight1, format.frame_size.height()); | 325 // where the video frames sent the the client vary in resolution but maintain |
| 309 EXPECT_EQ(kFrameRate, format.frame_rate); | 326 // the same aspect ratio. |
| 310 EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format); | 327 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeFixedAspectRatio) { |
| 328 // Helper used to check that only the two test frame sizes, adjusted to the | |
| 329 // 16:9 aspect ratio requirement, are delivered to the | |
| 330 // OnIncomingCapturedData() callback. | |
| 331 class FormatChecker { | |
| 332 public: | |
| 333 FormatChecker() : frame_count_(0) {} | |
| 311 | 334 |
| 312 EXPECT_EQ(format.frame_size.GetArea() * 4, frame_size); | 335 void ExpectAcceptableSize(const media::VideoCaptureFormat& format) { |
| 336 if (frame_count_ % 2 == 0) { | |
| 337 const gfx::Size expected_size(888, 500); | |
| 338 EXPECT_EQ(expected_size, format.frame_size); | |
| 339 } else { | |
| 340 const gfx::Size expected_size(532, 300); | |
| 341 EXPECT_EQ(expected_size, format.frame_size); | |
| 342 } | |
| 343 ++frame_count_; | |
| 344 EXPECT_EQ(kFrameRate, format.frame_rate); | |
| 345 EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format); | |
| 346 } | |
| 347 | |
| 348 private: | |
| 349 int frame_count_; | |
| 350 }; | |
| 351 | |
| 352 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); | |
| 353 | |
| 354 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); | |
| 355 | |
| 356 FormatChecker format_checker; | |
| 357 base::WaitableEvent done_event(false, false); | |
| 358 | |
| 359 scoped_ptr<MockDeviceClient> client(new MockDeviceClient()); | |
| 360 EXPECT_CALL(*client, OnError(_)).Times(0); | |
| 361 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly( | |
| 362 DoAll(WithArg<2>(Invoke(&format_checker, | |
| 363 &FormatChecker::ExpectAcceptableSize)), | |
| 364 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal))); | |
| 365 | |
| 366 media::VideoCaptureParams capture_params; | |
| 367 const gfx::Size high_def_16_by_9(1920, 1080); | |
| 368 ASSERT_GE(high_def_16_by_9.width(), | |
| 369 std::max(kTestFrameWidth1, kTestFrameWidth2)); | |
| 370 ASSERT_GE(high_def_16_by_9.height(), | |
| 371 std::max(kTestFrameHeight1, kTestFrameHeight2)); | |
| 372 capture_params.requested_format.frame_size = high_def_16_by_9; | |
| 373 capture_params.requested_format.frame_rate = kFrameRate; | |
| 374 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | |
| 375 capture_params.resolution_change_policy = | |
| 376 media::RESOLUTION_POLICY_FIXED_ASPECT_RATIO; | |
| 377 | |
| 378 capture_device_->AllocateAndStart( | |
| 379 capture_params, client.Pass()); | |
| 380 | |
| 381 // Capture at least three frames, to ensure that the source frame size has | |
| 382 // changed to two different sizes while capturing. The mock for | |
| 383 // OnIncomingCapturedData() will use FormatChecker to examine the format of | |
| 384 // each frame being delivered. | |
| 385 for (int i = 0; i < 3; ++i) { | |
| 386 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | |
| 387 done_event.Reset(); | |
| 388 } | |
| 389 | |
| 390 capture_device_->StopAndDeAllocate(); | |
| 313 } | 391 } |
| 314 | 392 |
| 315 // Test that screen capturer behaves correctly if the source frame size changes | 393 // Test that screen capturer behaves correctly if the source frame size changes |
| 316 // and the caller can cope with variable resolution output. | 394 // and the caller can cope with variable resolution output. |
| 317 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) { | 395 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) { |
| 396 // Helper used to check that only the two test frame sizes are delivered to | |
| 397 // the OnIncomingCapturedData() callback. | |
| 398 class FormatChecker { | |
|
Wez
2015/05/15 00:55:42
Seems that this could be turned into a parameteriz
miu
2015/05/15 21:14:01
Done. Good point.
| |
| 399 public: | |
| 400 FormatChecker() : frame_count_(0) {} | |
| 401 | |
| 402 void ExpectAcceptableSize(const media::VideoCaptureFormat& format) { | |
| 403 if (frame_count_ % 2 == 0) { | |
| 404 EXPECT_EQ(gfx::Size(kTestFrameWidth1, kTestFrameHeight1), | |
| 405 format.frame_size); | |
| 406 } else { | |
| 407 EXPECT_EQ(gfx::Size(kTestFrameWidth2, kTestFrameHeight2), | |
| 408 format.frame_size); | |
| 409 } | |
| 410 ++frame_count_; | |
| 411 EXPECT_EQ(kFrameRate, format.frame_rate); | |
| 412 EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format); | |
| 413 } | |
| 414 | |
| 415 private: | |
| 416 int frame_count_; | |
| 417 }; | |
| 418 | |
| 318 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); | 419 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); |
| 319 | 420 |
| 320 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); | 421 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); |
| 321 | 422 |
| 322 media::VideoCaptureFormat format; | 423 FormatChecker format_checker; |
| 323 base::WaitableEvent done_event(false, false); | 424 base::WaitableEvent done_event(false, false); |
| 324 | 425 |
| 325 scoped_ptr<MockDeviceClient> client(new MockDeviceClient()); | 426 scoped_ptr<MockDeviceClient> client(new MockDeviceClient()); |
| 326 EXPECT_CALL(*client, OnError(_)).Times(0); | 427 EXPECT_CALL(*client, OnError(_)).Times(0); |
| 327 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly( | 428 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly( |
| 328 DoAll(SaveArg<2>(&format), | 429 DoAll(WithArg<2>(Invoke(&format_checker, |
| 430 &FormatChecker::ExpectAcceptableSize)), | |
| 329 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal))); | 431 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal))); |
| 330 | 432 |
| 331 media::VideoCaptureParams capture_params; | 433 media::VideoCaptureParams capture_params; |
| 332 capture_params.requested_format.frame_size.SetSize(kTestFrameWidth2, | 434 const gfx::Size high_def_16_by_9(1920, 1080); |
| 333 kTestFrameHeight2); | 435 ASSERT_GE(high_def_16_by_9.width(), |
| 436 std::max(kTestFrameWidth1, kTestFrameWidth2)); | |
| 437 ASSERT_GE(high_def_16_by_9.height(), | |
| 438 std::max(kTestFrameHeight1, kTestFrameHeight2)); | |
| 439 capture_params.requested_format.frame_size = high_def_16_by_9; | |
| 334 capture_params.requested_format.frame_rate = kFrameRate; | 440 capture_params.requested_format.frame_rate = kFrameRate; |
| 335 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | 441 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; |
| 442 capture_params.resolution_change_policy = | |
| 443 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT; | |
| 336 | 444 |
| 337 capture_device_->AllocateAndStart( | 445 capture_device_->AllocateAndStart( |
| 338 capture_params, client.Pass()); | 446 capture_params, client.Pass()); |
| 339 | 447 |
| 340 // Capture at least three frames, to ensure that the source frame size has | 448 // Capture at least three frames, to ensure that the source frame size has |
| 341 // changed at least twice while capturing. | 449 // changed to two different sizes while capturing. The mock for |
| 342 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | 450 // OnIncomingCapturedData() will use FormatChecker to examine the format of |
| 343 done_event.Reset(); | 451 // each frame being delivered. |
| 344 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | 452 for (int i = 0; i < 3; ++i) { |
| 345 done_event.Reset(); | 453 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); |
| 346 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | 454 done_event.Reset(); |
| 455 } | |
| 347 | 456 |
| 348 capture_device_->StopAndDeAllocate(); | 457 capture_device_->StopAndDeAllocate(); |
| 349 | |
| 350 EXPECT_EQ(kTestFrameWidth1, format.frame_size.width()); | |
| 351 EXPECT_EQ(kTestFrameHeight1, format.frame_size.height()); | |
| 352 EXPECT_EQ(kFrameRate, format.frame_rate); | |
| 353 EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format); | |
| 354 } | 458 } |
| 355 | 459 |
| 356 // This test verifies that an unpacked frame is converted to a packed frame. | 460 // This test verifies that an unpacked frame is converted to a packed frame. |
| 357 TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) { | 461 TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) { |
| 358 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); | 462 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); |
| 359 mock_capturer->set_generate_cropped_frames(true); | 463 mock_capturer->set_generate_cropped_frames(true); |
| 360 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); | 464 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); |
| 361 | 465 |
| 362 media::VideoCaptureFormat format; | 466 media::VideoCaptureFormat format; |
| 363 base::WaitableEvent done_event(false, false); | 467 base::WaitableEvent done_event(false, false); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 436 frame_size); | 540 frame_size); |
| 437 for (int i = 0; i < output_frame_->size().height(); ++i) { | 541 for (int i = 0; i < output_frame_->size().height(); ++i) { |
| 438 EXPECT_EQ(0, | 542 EXPECT_EQ(0, |
| 439 memcmp(inverted_frame->data() + i * inverted_frame->stride(), | 543 memcmp(inverted_frame->data() + i * inverted_frame->stride(), |
| 440 output_frame_->data() + i * output_frame_->stride(), | 544 output_frame_->data() + i * output_frame_->stride(), |
| 441 output_frame_->stride())); | 545 output_frame_->stride())); |
| 442 } | 546 } |
| 443 } | 547 } |
| 444 | 548 |
| 445 } // namespace content | 549 } // namespace content |
| OLD | NEW |