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 |