| 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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 | 204 |
| 202 bool SelectScreen(webrtc::ScreenId id) override { return false; } | 205 bool SelectScreen(webrtc::ScreenId id) override { return false; } |
| 203 | 206 |
| 204 private: | 207 private: |
| 205 Callback* callback_; | 208 Callback* callback_; |
| 206 int frame_index_; | 209 int frame_index_; |
| 207 bool generate_inverted_frames_; | 210 bool generate_inverted_frames_; |
| 208 bool generate_cropped_frames_; | 211 bool generate_cropped_frames_; |
| 209 }; | 212 }; |
| 210 | 213 |
| 214 // Helper used to check that only two specific frame sizes are delivered to the |
| 215 // OnIncomingCapturedData() callback. |
| 216 class FormatChecker { |
| 217 public: |
| 218 FormatChecker(const gfx::Size& size_for_even_frames, |
| 219 const gfx::Size& size_for_odd_frames) |
| 220 : size_for_even_frames_(size_for_even_frames), |
| 221 size_for_odd_frames_(size_for_odd_frames), |
| 222 frame_count_(0) {} |
| 223 |
| 224 void ExpectAcceptableSize(const media::VideoCaptureFormat& format) { |
| 225 if (frame_count_ % 2 == 0) |
| 226 EXPECT_EQ(size_for_even_frames_, format.frame_size); |
| 227 else |
| 228 EXPECT_EQ(size_for_odd_frames_, format.frame_size); |
| 229 ++frame_count_; |
| 230 EXPECT_EQ(kFrameRate, format.frame_rate); |
| 231 EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format); |
| 232 } |
| 233 |
| 234 private: |
| 235 const gfx::Size size_for_even_frames_; |
| 236 const gfx::Size size_for_odd_frames_; |
| 237 int frame_count_; |
| 238 }; |
| 239 |
| 211 } // namespace | 240 } // namespace |
| 212 | 241 |
| 213 class DesktopCaptureDeviceTest : public testing::Test { | 242 class DesktopCaptureDeviceTest : public testing::Test { |
| 214 public: | 243 public: |
| 215 void CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer> capturer) { | 244 void CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer> capturer) { |
| 216 capture_device_.reset( | 245 capture_device_.reset( |
| 217 new DesktopCaptureDevice(capturer.Pass(), DesktopMediaID::TYPE_SCREEN)); | 246 new DesktopCaptureDevice(capturer.Pass(), DesktopMediaID::TYPE_SCREEN)); |
| 218 } | 247 } |
| 219 | 248 |
| 220 void CopyFrame(const uint8_t* frame, int size, | 249 void CopyFrame(const uint8_t* frame, int size, |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 EXPECT_EQ(format.frame_size.GetArea() * 4, frame_size); | 299 EXPECT_EQ(format.frame_size.GetArea() * 4, frame_size); |
| 271 } | 300 } |
| 272 | 301 |
| 273 // Test that screen capturer behaves correctly if the source frame size changes | 302 // Test that screen capturer behaves correctly if the source frame size changes |
| 274 // but the caller cannot cope with variable resolution output. | 303 // but the caller cannot cope with variable resolution output. |
| 275 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) { | 304 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) { |
| 276 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); | 305 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); |
| 277 | 306 |
| 278 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); | 307 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); |
| 279 | 308 |
| 280 media::VideoCaptureFormat format; | 309 FormatChecker format_checker(gfx::Size(kTestFrameWidth1, kTestFrameHeight1), |
| 310 gfx::Size(kTestFrameWidth1, kTestFrameHeight1)); |
| 281 base::WaitableEvent done_event(false, false); | 311 base::WaitableEvent done_event(false, false); |
| 282 int frame_size; | |
| 283 | 312 |
| 284 scoped_ptr<MockDeviceClient> client(new MockDeviceClient()); | 313 scoped_ptr<MockDeviceClient> client(new MockDeviceClient()); |
| 285 EXPECT_CALL(*client, OnError(_)).Times(0); | 314 EXPECT_CALL(*client, OnError(_)).Times(0); |
| 286 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly( | 315 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly( |
| 287 DoAll(SaveArg<1>(&frame_size), | 316 DoAll(WithArg<2>(Invoke(&format_checker, |
| 288 SaveArg<2>(&format), | 317 &FormatChecker::ExpectAcceptableSize)), |
| 289 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal))); | 318 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal))); |
| 290 | 319 |
| 291 media::VideoCaptureParams capture_params; | 320 media::VideoCaptureParams capture_params; |
| 292 capture_params.requested_format.frame_size.SetSize(kTestFrameWidth1, | 321 capture_params.requested_format.frame_size.SetSize(kTestFrameWidth1, |
| 293 kTestFrameHeight1); | 322 kTestFrameHeight1); |
| 294 capture_params.requested_format.frame_rate = kFrameRate; | 323 capture_params.requested_format.frame_rate = kFrameRate; |
| 295 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | 324 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; |
| 325 capture_params.resolution_change_policy = |
| 326 media::RESOLUTION_POLICY_FIXED_RESOLUTION; |
| 296 | 327 |
| 297 capture_device_->AllocateAndStart(capture_params, client.Pass()); | 328 capture_device_->AllocateAndStart(capture_params, client.Pass()); |
| 298 | 329 |
| 299 // Capture at least two frames, to ensure that the source frame size has | 330 // Capture at least two frames, to ensure that the source frame size has |
| 300 // changed while capturing. | 331 // changed to two different sizes while capturing. The mock for |
| 301 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | 332 // OnIncomingCapturedData() will use FormatChecker to examine the format of |
| 302 done_event.Reset(); | 333 // each frame being delivered. |
| 303 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | 334 for (int i = 0; i < 2; ++i) { |
| 335 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); |
| 336 done_event.Reset(); |
| 337 } |
| 304 | 338 |
| 305 capture_device_->StopAndDeAllocate(); | 339 capture_device_->StopAndDeAllocate(); |
| 340 } |
| 306 | 341 |
| 307 EXPECT_EQ(kTestFrameWidth1, format.frame_size.width()); | 342 // Test that screen capturer behaves correctly if the source frame size changes, |
| 308 EXPECT_EQ(kTestFrameHeight1, format.frame_size.height()); | 343 // where the video frames sent the the client vary in resolution but maintain |
| 309 EXPECT_EQ(kFrameRate, format.frame_rate); | 344 // the same aspect ratio. |
| 310 EXPECT_EQ(media::PIXEL_FORMAT_ARGB, format.pixel_format); | 345 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeFixedAspectRatio) { |
| 346 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); |
| 311 | 347 |
| 312 EXPECT_EQ(format.frame_size.GetArea() * 4, frame_size); | 348 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); |
| 349 |
| 350 FormatChecker format_checker(gfx::Size(888, 500), gfx::Size(532, 300)); |
| 351 base::WaitableEvent done_event(false, false); |
| 352 |
| 353 scoped_ptr<MockDeviceClient> client(new MockDeviceClient()); |
| 354 EXPECT_CALL(*client, OnError(_)).Times(0); |
| 355 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly( |
| 356 DoAll(WithArg<2>(Invoke(&format_checker, |
| 357 &FormatChecker::ExpectAcceptableSize)), |
| 358 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal))); |
| 359 |
| 360 media::VideoCaptureParams capture_params; |
| 361 const gfx::Size high_def_16_by_9(1920, 1080); |
| 362 ASSERT_GE(high_def_16_by_9.width(), |
| 363 std::max(kTestFrameWidth1, kTestFrameWidth2)); |
| 364 ASSERT_GE(high_def_16_by_9.height(), |
| 365 std::max(kTestFrameHeight1, kTestFrameHeight2)); |
| 366 capture_params.requested_format.frame_size = high_def_16_by_9; |
| 367 capture_params.requested_format.frame_rate = kFrameRate; |
| 368 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; |
| 369 capture_params.resolution_change_policy = |
| 370 media::RESOLUTION_POLICY_FIXED_ASPECT_RATIO; |
| 371 |
| 372 capture_device_->AllocateAndStart( |
| 373 capture_params, client.Pass()); |
| 374 |
| 375 // Capture at least three frames, to ensure that the source frame size has |
| 376 // changed to two different sizes while capturing. The mock for |
| 377 // OnIncomingCapturedData() will use FormatChecker to examine the format of |
| 378 // each frame being delivered. |
| 379 for (int i = 0; i < 3; ++i) { |
| 380 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); |
| 381 done_event.Reset(); |
| 382 } |
| 383 |
| 384 capture_device_->StopAndDeAllocate(); |
| 313 } | 385 } |
| 314 | 386 |
| 315 // Test that screen capturer behaves correctly if the source frame size changes | 387 // Test that screen capturer behaves correctly if the source frame size changes |
| 316 // and the caller can cope with variable resolution output. | 388 // and the caller can cope with variable resolution output. |
| 317 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) { | 389 TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) { |
| 318 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); | 390 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); |
| 319 | 391 |
| 320 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); | 392 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); |
| 321 | 393 |
| 322 media::VideoCaptureFormat format; | 394 FormatChecker format_checker(gfx::Size(kTestFrameWidth1, kTestFrameHeight1), |
| 395 gfx::Size(kTestFrameWidth2, kTestFrameHeight2)); |
| 323 base::WaitableEvent done_event(false, false); | 396 base::WaitableEvent done_event(false, false); |
| 324 | 397 |
| 325 scoped_ptr<MockDeviceClient> client(new MockDeviceClient()); | 398 scoped_ptr<MockDeviceClient> client(new MockDeviceClient()); |
| 326 EXPECT_CALL(*client, OnError(_)).Times(0); | 399 EXPECT_CALL(*client, OnError(_)).Times(0); |
| 327 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly( | 400 EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly( |
| 328 DoAll(SaveArg<2>(&format), | 401 DoAll(WithArg<2>(Invoke(&format_checker, |
| 402 &FormatChecker::ExpectAcceptableSize)), |
| 329 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal))); | 403 InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal))); |
| 330 | 404 |
| 331 media::VideoCaptureParams capture_params; | 405 media::VideoCaptureParams capture_params; |
| 332 capture_params.requested_format.frame_size.SetSize(kTestFrameWidth2, | 406 const gfx::Size high_def_16_by_9(1920, 1080); |
| 333 kTestFrameHeight2); | 407 ASSERT_GE(high_def_16_by_9.width(), |
| 408 std::max(kTestFrameWidth1, kTestFrameWidth2)); |
| 409 ASSERT_GE(high_def_16_by_9.height(), |
| 410 std::max(kTestFrameHeight1, kTestFrameHeight2)); |
| 411 capture_params.requested_format.frame_size = high_def_16_by_9; |
| 334 capture_params.requested_format.frame_rate = kFrameRate; | 412 capture_params.requested_format.frame_rate = kFrameRate; |
| 335 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | 413 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; |
| 414 capture_params.resolution_change_policy = |
| 415 media::RESOLUTION_POLICY_ANY_WITHIN_LIMIT; |
| 336 | 416 |
| 337 capture_device_->AllocateAndStart( | 417 capture_device_->AllocateAndStart( |
| 338 capture_params, client.Pass()); | 418 capture_params, client.Pass()); |
| 339 | 419 |
| 340 // Capture at least three frames, to ensure that the source frame size has | 420 // Capture at least three frames, to ensure that the source frame size has |
| 341 // changed at least twice while capturing. | 421 // changed to two different sizes while capturing. The mock for |
| 342 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | 422 // OnIncomingCapturedData() will use FormatChecker to examine the format of |
| 343 done_event.Reset(); | 423 // each frame being delivered. |
| 344 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | 424 for (int i = 0; i < 3; ++i) { |
| 345 done_event.Reset(); | 425 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); |
| 346 EXPECT_TRUE(done_event.TimedWait(TestTimeouts::action_max_timeout())); | 426 done_event.Reset(); |
| 427 } |
| 347 | 428 |
| 348 capture_device_->StopAndDeAllocate(); | 429 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 } | 430 } |
| 355 | 431 |
| 356 // This test verifies that an unpacked frame is converted to a packed frame. | 432 // This test verifies that an unpacked frame is converted to a packed frame. |
| 357 TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) { | 433 TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) { |
| 358 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); | 434 FakeScreenCapturer* mock_capturer = new FakeScreenCapturer(); |
| 359 mock_capturer->set_generate_cropped_frames(true); | 435 mock_capturer->set_generate_cropped_frames(true); |
| 360 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); | 436 CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer)); |
| 361 | 437 |
| 362 media::VideoCaptureFormat format; | 438 media::VideoCaptureFormat format; |
| 363 base::WaitableEvent done_event(false, false); | 439 base::WaitableEvent done_event(false, false); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 436 frame_size); | 512 frame_size); |
| 437 for (int i = 0; i < output_frame_->size().height(); ++i) { | 513 for (int i = 0; i < output_frame_->size().height(); ++i) { |
| 438 EXPECT_EQ(0, | 514 EXPECT_EQ(0, |
| 439 memcmp(inverted_frame->data() + i * inverted_frame->stride(), | 515 memcmp(inverted_frame->data() + i * inverted_frame->stride(), |
| 440 output_frame_->data() + i * output_frame_->stride(), | 516 output_frame_->data() + i * output_frame_->stride(), |
| 441 output_frame_->stride())); | 517 output_frame_->stride())); |
| 442 } | 518 } |
| 443 } | 519 } |
| 444 | 520 |
| 445 } // namespace content | 521 } // namespace content |
| OLD | NEW |