| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/web_contents_video_capture_device.h" | 5 #include "content/browser/media/capture/web_contents_video_capture_device.h" |
| 6 | 6 |
| 7 #include "base/bind_helpers.h" | 7 #include "base/bind_helpers.h" |
| 8 #include "base/debug/debugger.h" | 8 #include "base/debug/debugger.h" |
| 9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "base/test/test_timeouts.h" | 10 #include "base/test/test_timeouts.h" |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "content/public/test/test_utils.h" | 25 #include "content/public/test/test_utils.h" |
| 26 #include "content/test/test_render_view_host.h" | 26 #include "content/test/test_render_view_host.h" |
| 27 #include "content/test/test_web_contents.h" | 27 #include "content/test/test_web_contents.h" |
| 28 #include "media/base/video_frame.h" | 28 #include "media/base/video_frame.h" |
| 29 #include "media/base/video_util.h" | 29 #include "media/base/video_util.h" |
| 30 #include "media/base/yuv_convert.h" | 30 #include "media/base/yuv_convert.h" |
| 31 #include "media/video/capture/video_capture_types.h" | 31 #include "media/video/capture/video_capture_types.h" |
| 32 #include "skia/ext/platform_canvas.h" | 32 #include "skia/ext/platform_canvas.h" |
| 33 #include "testing/gtest/include/gtest/gtest.h" | 33 #include "testing/gtest/include/gtest/gtest.h" |
| 34 #include "third_party/skia/include/core/SkColor.h" | 34 #include "third_party/skia/include/core/SkColor.h" |
| 35 #include "ui/gfx/display.h" |
| 36 #include "ui/gfx/screen.h" |
| 35 | 37 |
| 36 namespace content { | 38 namespace content { |
| 37 namespace { | 39 namespace { |
| 38 | 40 |
| 39 const int kTestWidth = 320; | 41 const int kTestWidth = 320; |
| 40 const int kTestHeight = 240; | 42 const int kTestHeight = 240; |
| 41 const int kTestFramesPerSecond = 20; | 43 const int kTestFramesPerSecond = 20; |
| 44 const float kTestDeviceScaleFactor = 2.0f; |
| 42 const SkColor kNothingYet = 0xdeadbeef; | 45 const SkColor kNothingYet = 0xdeadbeef; |
| 43 const SkColor kNotInterested = ~kNothingYet; | 46 const SkColor kNotInterested = ~kNothingYet; |
| 44 | 47 |
| 45 void DeadlineExceeded(base::Closure quit_closure) { | 48 void DeadlineExceeded(base::Closure quit_closure) { |
| 46 if (!base::debug::BeingDebugged()) { | 49 if (!base::debug::BeingDebugged()) { |
| 47 quit_closure.Run(); | 50 quit_closure.Run(); |
| 48 FAIL() << "Deadline exceeded while waiting, quitting"; | 51 FAIL() << "Deadline exceeded while waiting, quitting"; |
| 49 } else { | 52 } else { |
| 50 LOG(WARNING) << "Deadline exceeded; test would fail if debugger weren't " | 53 LOG(WARNING) << "Deadline exceeded; test would fail if debugger weren't " |
| 51 << "attached."; | 54 << "attached."; |
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 | 462 |
| 460 private: | 463 private: |
| 461 base::Lock lock_; | 464 base::Lock lock_; |
| 462 bool error_encountered_; | 465 bool error_encountered_; |
| 463 SkColor wait_color_yuv_; | 466 SkColor wait_color_yuv_; |
| 464 scoped_ptr<StubClient> client_; | 467 scoped_ptr<StubClient> client_; |
| 465 | 468 |
| 466 DISALLOW_COPY_AND_ASSIGN(StubClientObserver); | 469 DISALLOW_COPY_AND_ASSIGN(StubClientObserver); |
| 467 }; | 470 }; |
| 468 | 471 |
| 472 // A dummy implementation of gfx::Screen, since WebContentsVideoCaptureDevice |
| 473 // needs access to a gfx::Display's device scale factor. |
| 474 class FakeScreen : public gfx::Screen { |
| 475 public: |
| 476 FakeScreen() : the_one_display_(0x1337, gfx::Rect(0, 0, 2560, 1440)) { |
| 477 the_one_display_.set_device_scale_factor(kTestDeviceScaleFactor); |
| 478 } |
| 479 virtual ~FakeScreen() {} |
| 480 |
| 481 // gfx::Screen implementation (only what's needed for testing). |
| 482 virtual bool IsDIPEnabled() OVERRIDE { return true; } |
| 483 virtual gfx::Point GetCursorScreenPoint() OVERRIDE { return gfx::Point(); } |
| 484 virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE { return NULL; } |
| 485 virtual gfx::NativeWindow GetWindowAtScreenPoint( |
| 486 const gfx::Point& point) OVERRIDE { return NULL; } |
| 487 virtual int GetNumDisplays() const OVERRIDE { return 1; } |
| 488 virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE { |
| 489 return std::vector<gfx::Display>(1, the_one_display_); |
| 490 } |
| 491 virtual gfx::Display GetDisplayNearestWindow( |
| 492 gfx::NativeView view) const OVERRIDE { |
| 493 return the_one_display_; |
| 494 } |
| 495 virtual gfx::Display GetDisplayNearestPoint( |
| 496 const gfx::Point& point) const OVERRIDE { |
| 497 return the_one_display_; |
| 498 } |
| 499 virtual gfx::Display GetDisplayMatching( |
| 500 const gfx::Rect& match_rect) const OVERRIDE { |
| 501 return the_one_display_; |
| 502 } |
| 503 virtual gfx::Display GetPrimaryDisplay() const OVERRIDE { |
| 504 return the_one_display_; |
| 505 } |
| 506 virtual void AddObserver(gfx::DisplayObserver* observer) OVERRIDE {} |
| 507 virtual void RemoveObserver(gfx::DisplayObserver* observer) OVERRIDE {} |
| 508 |
| 509 private: |
| 510 gfx::Display the_one_display_; |
| 511 |
| 512 DISALLOW_COPY_AND_ASSIGN(FakeScreen); |
| 513 }; |
| 514 |
| 469 // Test harness that sets up a minimal environment with necessary stubs. | 515 // Test harness that sets up a minimal environment with necessary stubs. |
| 470 class WebContentsVideoCaptureDeviceTest : public testing::Test { | 516 class WebContentsVideoCaptureDeviceTest : public testing::Test { |
| 471 public: | 517 public: |
| 472 // This is public because C++ method pointer scoping rules are silly and make | 518 // This is public because C++ method pointer scoping rules are silly and make |
| 473 // this hard to use with Bind(). | 519 // this hard to use with Bind(). |
| 474 void ResetWebContents() { | 520 void ResetWebContents() { |
| 475 web_contents_.reset(); | 521 web_contents_.reset(); |
| 476 } | 522 } |
| 477 | 523 |
| 478 protected: | 524 protected: |
| 479 virtual void SetUp() { | 525 virtual void SetUp() { |
| 526 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, &fake_screen_); |
| 527 ASSERT_EQ(&fake_screen_, gfx::Screen::GetNativeScreen()); |
| 528 |
| 480 // TODO(nick): Sadness and woe! Much "mock-the-world" boilerplate could be | 529 // TODO(nick): Sadness and woe! Much "mock-the-world" boilerplate could be |
| 481 // eliminated here, if only we could use RenderViewHostTestHarness. The | 530 // eliminated here, if only we could use RenderViewHostTestHarness. The |
| 482 // catch is that we need our TestRenderViewHost to support a | 531 // catch is that we need our TestRenderViewHost to support a |
| 483 // CopyFromBackingStore operation that we control. To accomplish that, | 532 // CopyFromBackingStore operation that we control. To accomplish that, |
| 484 // either RenderViewHostTestHarness would have to support installing a | 533 // either RenderViewHostTestHarness would have to support installing a |
| 485 // custom RenderViewHostFactory, or else we implant some kind of delegated | 534 // custom RenderViewHostFactory, or else we implant some kind of delegated |
| 486 // CopyFromBackingStore functionality into TestRenderViewHost itself. | 535 // CopyFromBackingStore functionality into TestRenderViewHost itself. |
| 487 | 536 |
| 488 render_process_host_factory_.reset(new MockRenderProcessHostFactory()); | 537 render_process_host_factory_.reset(new MockRenderProcessHostFactory()); |
| 489 // Create our (self-registering) RVH factory, so that when we create a | 538 // Create our (self-registering) RVH factory, so that when we create a |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 523 | 572 |
| 524 // Destroy the browser objects. | 573 // Destroy the browser objects. |
| 525 web_contents_.reset(); | 574 web_contents_.reset(); |
| 526 browser_context_.reset(); | 575 browser_context_.reset(); |
| 527 | 576 |
| 528 base::RunLoop().RunUntilIdle(); | 577 base::RunLoop().RunUntilIdle(); |
| 529 | 578 |
| 530 SiteInstanceImpl::set_render_process_host_factory(NULL); | 579 SiteInstanceImpl::set_render_process_host_factory(NULL); |
| 531 render_view_host_factory_.reset(); | 580 render_view_host_factory_.reset(); |
| 532 render_process_host_factory_.reset(); | 581 render_process_host_factory_.reset(); |
| 582 |
| 583 gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, NULL); |
| 533 } | 584 } |
| 534 | 585 |
| 535 // Accessors. | 586 // Accessors. |
| 536 CaptureTestSourceController* source() { return &controller_; } | 587 CaptureTestSourceController* source() { return &controller_; } |
| 588 WebContents* web_contents() const { return web_contents_.get(); } |
| 537 media::VideoCaptureDevice* device() { return device_.get(); } | 589 media::VideoCaptureDevice* device() { return device_.get(); } |
| 538 | 590 |
| 539 void SimulateDrawEvent() { | 591 void SimulateDrawEvent() { |
| 540 if (source()->CanUseFrameSubscriber()) { | 592 if (source()->CanUseFrameSubscriber()) { |
| 541 // Print | 593 // Print |
| 542 CaptureTestView* test_view = static_cast<CaptureTestView*>( | 594 CaptureTestView* test_view = static_cast<CaptureTestView*>( |
| 543 web_contents_->GetRenderViewHost()->GetView()); | 595 web_contents_->GetRenderViewHost()->GetView()); |
| 544 test_view->SimulateUpdate(); | 596 test_view->SimulateUpdate(); |
| 545 } else { | 597 } else { |
| 546 // Simulate a non-accelerated paint. | 598 // Simulate a non-accelerated paint. |
| 547 NotificationService::current()->Notify( | 599 NotificationService::current()->Notify( |
| 548 NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, | 600 NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE, |
| 549 Source<RenderWidgetHost>(web_contents_->GetRenderViewHost()), | 601 Source<RenderWidgetHost>(web_contents_->GetRenderViewHost()), |
| 550 NotificationService::NoDetails()); | 602 NotificationService::NoDetails()); |
| 551 } | 603 } |
| 552 } | 604 } |
| 553 | 605 |
| 554 void DestroyVideoCaptureDevice() { device_.reset(); } | 606 void DestroyVideoCaptureDevice() { device_.reset(); } |
| 555 | 607 |
| 556 StubClientObserver* client_observer() { | 608 StubClientObserver* client_observer() { |
| 557 return &client_observer_; | 609 return &client_observer_; |
| 558 } | 610 } |
| 559 | 611 |
| 560 private: | 612 private: |
| 613 FakeScreen fake_screen_; |
| 614 |
| 561 StubClientObserver client_observer_; | 615 StubClientObserver client_observer_; |
| 562 | 616 |
| 563 // The controller controls which pixel patterns to produce. | 617 // The controller controls which pixel patterns to produce. |
| 564 CaptureTestSourceController controller_; | 618 CaptureTestSourceController controller_; |
| 565 | 619 |
| 566 // Self-registering RenderProcessHostFactory. | 620 // Self-registering RenderProcessHostFactory. |
| 567 scoped_ptr<MockRenderProcessHostFactory> render_process_host_factory_; | 621 scoped_ptr<MockRenderProcessHostFactory> render_process_host_factory_; |
| 568 | 622 |
| 569 // Creates capture-capable RenderViewHosts whose pixel content production is | 623 // Creates capture-capable RenderViewHosts whose pixel content production is |
| 570 // under the control of |controller_|. | 624 // under the control of |controller_|. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 590 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | 644 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); |
| 591 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | 645 capture_params.requested_format.frame_rate = kTestFramesPerSecond; |
| 592 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | 646 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; |
| 593 capture_params.allow_resolution_change = false; | 647 capture_params.allow_resolution_change = false; |
| 594 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | 648 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); |
| 595 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError()); | 649 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError()); |
| 596 device()->StopAndDeAllocate(); | 650 device()->StopAndDeAllocate(); |
| 597 } | 651 } |
| 598 | 652 |
| 599 TEST_F(WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) { | 653 TEST_F(WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) { |
| 654 const gfx::Size capture_preferred_size( |
| 655 static_cast<int>(kTestWidth / kTestDeviceScaleFactor), |
| 656 static_cast<int>(kTestHeight / kTestDeviceScaleFactor)); |
| 657 ASSERT_NE(capture_preferred_size, web_contents()->GetPreferredSize()); |
| 658 |
| 600 // We'll simulate the tab being closed after the capture pipeline is up and | 659 // We'll simulate the tab being closed after the capture pipeline is up and |
| 601 // running. | 660 // running. |
| 602 media::VideoCaptureParams capture_params; | 661 media::VideoCaptureParams capture_params; |
| 603 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); | 662 capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight); |
| 604 capture_params.requested_format.frame_rate = kTestFramesPerSecond; | 663 capture_params.requested_format.frame_rate = kTestFramesPerSecond; |
| 605 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; | 664 capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420; |
| 606 capture_params.allow_resolution_change = false; | 665 capture_params.allow_resolution_change = false; |
| 607 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); | 666 device()->AllocateAndStart(capture_params, client_observer()->PassClient()); |
| 608 // Do one capture to prove | 667 // Do one capture to prove |
| 609 source()->SetSolidColor(SK_ColorRED); | 668 source()->SetSolidColor(SK_ColorRED); |
| 610 SimulateDrawEvent(); | 669 SimulateDrawEvent(); |
| 611 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); | 670 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); |
| 612 | 671 |
| 613 base::RunLoop().RunUntilIdle(); | 672 base::RunLoop().RunUntilIdle(); |
| 614 | 673 |
| 674 // Check that the preferred size of the WebContents matches the one provided |
| 675 // by WebContentsVideoCaptureDevice. |
| 676 EXPECT_EQ(capture_preferred_size, web_contents()->GetPreferredSize()); |
| 677 |
| 615 // Post a task to close the tab. We should see an error reported to the | 678 // Post a task to close the tab. We should see an error reported to the |
| 616 // consumer. | 679 // consumer. |
| 617 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 680 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 618 base::Bind(&WebContentsVideoCaptureDeviceTest::ResetWebContents, | 681 base::Bind(&WebContentsVideoCaptureDeviceTest::ResetWebContents, |
| 619 base::Unretained(this))); | 682 base::Unretained(this))); |
| 620 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError()); | 683 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForError()); |
| 621 device()->StopAndDeAllocate(); | 684 device()->StopAndDeAllocate(); |
| 622 } | 685 } |
| 623 | 686 |
| 624 TEST_F(WebContentsVideoCaptureDeviceTest, | 687 TEST_F(WebContentsVideoCaptureDeviceTest, |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 source()->SetSolidColor(SK_ColorGREEN); | 863 source()->SetSolidColor(SK_ColorGREEN); |
| 801 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); | 864 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN)); |
| 802 source()->SetSolidColor(SK_ColorRED); | 865 source()->SetSolidColor(SK_ColorRED); |
| 803 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); | 866 ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED)); |
| 804 | 867 |
| 805 device()->StopAndDeAllocate(); | 868 device()->StopAndDeAllocate(); |
| 806 } | 869 } |
| 807 | 870 |
| 808 } // namespace | 871 } // namespace |
| 809 } // namespace content | 872 } // namespace content |
| OLD | NEW |