Chromium Code Reviews| Index: webrtc/modules/desktop_capture/screen_capturer_unittest.cc | 
| diff --git a/webrtc/modules/desktop_capture/screen_capturer_unittest.cc b/webrtc/modules/desktop_capture/screen_capturer_unittest.cc | 
| index 6d2c0eb0658221f98ebb4f34d18a22076de8521a..a9297584d93def2cd9ffaf7979b81fbc3c26b241 100644 | 
| --- a/webrtc/modules/desktop_capture/screen_capturer_unittest.cc | 
| +++ b/webrtc/modules/desktop_capture/screen_capturer_unittest.cc | 
| @@ -8,6 +8,10 @@ | 
| * be found in the AUTHORS file in the root of the source tree. | 
| */ | 
| +#include <string.h> | 
| + | 
| +#include <algorithm> | 
| +#include <initializer_list> | 
| #include <memory> | 
| #include <utility> | 
| @@ -15,12 +19,16 @@ | 
| #include "testing/gmock/include/gmock/gmock.h" | 
| #include "testing/gtest/include/gtest/gtest.h" | 
| +#include "webrtc/base/checks.h" | 
| #include "webrtc/base/constructormagic.h" | 
| #include "webrtc/base/logging.h" | 
| +#include "webrtc/modules/desktop_capture/rgba_color.h" | 
| #include "webrtc/modules/desktop_capture/desktop_capture_options.h" | 
| #include "webrtc/modules/desktop_capture/desktop_frame.h" | 
| #include "webrtc/modules/desktop_capture/desktop_region.h" | 
| #include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h" | 
| +#include "webrtc/modules/desktop_capture/screen_drawer.h" | 
| +#include "webrtc/system_wrappers/include/sleep.h" | 
| #if defined(WEBRTC_WIN) | 
| #include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h" | 
| @@ -34,6 +42,53 @@ const int kTestSharedMemoryId = 123; | 
| namespace webrtc { | 
| +namespace { | 
| + | 
| +ACTION_P(SaveUniquePtrArg, dest) { | 
| + *dest = std::move(*arg1); | 
| +} | 
| + | 
| +// Expects |capturer| to successfully capture a frame, and returns it. | 
| +std::unique_ptr<DesktopFrame> CaptureFrame( | 
| + ScreenCapturer* capturer, | 
| + MockScreenCapturerCallback* callback) { | 
| + std::unique_ptr<DesktopFrame> frame; | 
| + EXPECT_CALL(*callback, | 
| + OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) | 
| + .WillOnce(SaveUniquePtrArg(&frame)); | 
| + capturer->Capture(DesktopRegion()); | 
| + EXPECT_TRUE(frame); | 
| + return frame; | 
| +} | 
| + | 
| +// Returns true if color in |rect| of |frame| is |color|. | 
| +bool ArePixelsColoredBy(const DesktopFrame& frame, | 
| + DesktopRect rect, | 
| + RgbaColor color) { | 
| + // updated_region() should cover the painted area. | 
| + DesktopRegion updated_region(frame.updated_region()); | 
| + updated_region.IntersectWith(rect); | 
| + if (!updated_region.Equals(DesktopRegion(rect))) { | 
| + return false; | 
| + } | 
| + | 
| + // Color in the |rect| should be |color|. | 
| + uint8_t* row = frame.GetFrameDataAtPos(rect.top_left()); | 
| + for (int i = 0; i < rect.height(); i++) { | 
| + uint8_t* column = row; | 
| + for (int j = 0; j < rect.width(); j++) { | 
| + if (color != RgbaColor(column)) { | 
| + return false; | 
| + } | 
| + column += DesktopFrame::kBytesPerPixel; | 
| + } | 
| + row += frame.stride(); | 
| + } | 
| + return true; | 
| +} | 
| + | 
| +} // namespace | 
| + | 
| class ScreenCapturerTest : public testing::Test { | 
| public: | 
| void SetUp() override { | 
| @@ -42,6 +97,93 @@ class ScreenCapturerTest : public testing::Test { | 
| } | 
| protected: | 
| + void TestCaptureUpdatedRegion( | 
| + std::initializer_list<ScreenCapturer*> capturers) { | 
| + RTC_DCHECK(capturers.size() > 0); | 
| + // A large enough area for the tests, which should be able to fulfill by | 
| + // most of systems. | 
| + const int kTestArea = 512; | 
| + const int kRectSize = 32; | 
| + std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create(); | 
| + if (!drawer || drawer->DrawableRegion().is_empty()) { | 
| + LOG(LS_WARNING) << "No ScreenDrawer implementation for current platform."; | 
| + return; | 
| + } | 
| + if (drawer->DrawableRegion().width() < kTestArea || | 
| + drawer->DrawableRegion().height() < kTestArea) { | 
| + LOG(LS_WARNING) << "ScreenDrawer::DrawableRegion() is too small for the " | 
| + "CaptureUpdatedRegion tests."; | 
| + return; | 
| + } | 
| + | 
| + for (ScreenCapturer* capturer : capturers) { | 
| + capturer->Start(&callback_); | 
| + } | 
| + | 
| + for (int c = 0; c < 3; c++) { | 
| + for (int i = 0; i < kTestArea - kRectSize; i += 16) { | 
| + DesktopRect rect = DesktopRect::MakeXYWH(i, i, kRectSize, kRectSize); | 
| + rect.Translate(drawer->DrawableRegion().top_left()); | 
| + RgbaColor color((c == 0 ? (i & 0xff) : 0x7f), | 
| + (c == 1 ? (i & 0xff) : 0x7f), | 
| + (c == 2 ? (i & 0xff) : 0x7f)); | 
| + drawer->Clear(); | 
| + drawer->DrawRectangle(rect, color); | 
| + | 
| + const int wait_first_capture_round = 20; | 
| + for (int j = 0; j < wait_first_capture_round; j++) { | 
| + drawer->WaitForPendingDraws(); | 
| + std::unique_ptr<DesktopFrame> frame = | 
| + CaptureFrame(*capturers.begin(), &callback_); | 
| + if (!frame) { | 
| + return; | 
| + } | 
| + | 
| + if (ArePixelsColoredBy(*frame, rect, color)) { | 
| + // The first capturer successfully captured the frame we expected. | 
| + // So the others should also be able to capture it. | 
| + break; | 
| + } else { | 
| + ASSERT_LT(j, wait_first_capture_round); | 
| + } | 
| + } | 
| + | 
| + for (ScreenCapturer* capturer : capturers) { | 
| + if (capturer == *capturers.begin()) { | 
| + // TODO(zijiehe): ScreenCapturerX11 and ScreenCapturerWinGdi cannot | 
| + // capture a correct frame again if screen does not update. | 
| + continue; | 
| + } | 
| + std::unique_ptr<DesktopFrame> frame = | 
| + CaptureFrame(capturer, &callback_); | 
| + if (!frame) { | 
| + return; | 
| + } | 
| + | 
| + ASSERT_TRUE(ArePixelsColoredBy(*frame, rect, color)); | 
| + } | 
| + } | 
| + } | 
| + } | 
| + | 
| + void TestCaptureUpdatedRegion() { | 
| + TestCaptureUpdatedRegion({capturer_.get()}); | 
| + } | 
| + | 
| +#if defined(WEBRTC_WIN) | 
| + bool SetDirectxCapturerMode() { | 
| + if (!ScreenCapturerWinDirectx::IsSupported()) { | 
| + LOG(LS_WARNING) << "Directx capturer is not supported"; | 
| + return false; | 
| + } | 
| + | 
| + DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault()); | 
| + options.set_allow_directx_capturer(true); | 
| + capturer_.reset(ScreenCapturer::Create(options)); | 
| + return true; | 
| + } | 
| +#endif // defined(WEBRTC_WIN) | 
| + | 
| std::unique_ptr<ScreenCapturer> capturer_; | 
| MockScreenCapturerCallback callback_; | 
| }; | 
| @@ -74,10 +216,6 @@ class FakeSharedMemoryFactory : public SharedMemoryFactory { | 
| RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemoryFactory); | 
| }; | 
| -ACTION_P(SaveUniquePtrArg, dest) { | 
| - *dest = std::move(*arg1); | 
| -} | 
| - | 
| TEST_F(ScreenCapturerTest, GetScreenListAndSelectScreen) { | 
| webrtc::ScreenCapturer::ScreenList screens; | 
| EXPECT_TRUE(capturer_->GetScreenList(&screens)); | 
| @@ -117,6 +255,10 @@ TEST_F(ScreenCapturerTest, Capture) { | 
| EXPECT_TRUE(it.IsAtEnd()); | 
| } | 
| +TEST_F(ScreenCapturerTest, CaptureUpdatedRegion) { | 
| + TestCaptureUpdatedRegion(); | 
| +} | 
| 
 
stefan-webrtc
2016/09/14 15:37:09
I'm not sure we want to add tests to modules_unitt
 
 | 
| + | 
| #if defined(WEBRTC_WIN) | 
| TEST_F(ScreenCapturerTest, UseSharedBuffers) { | 
| @@ -151,15 +293,10 @@ TEST_F(ScreenCapturerTest, UseMagnifier) { | 
| } | 
| TEST_F(ScreenCapturerTest, UseDirectxCapturer) { | 
| - if (!ScreenCapturerWinDirectx::IsSupported()) { | 
| - LOG(LS_WARNING) << "Directx capturer is not supported"; | 
| + if (!SetDirectxCapturerMode()) { | 
| return; | 
| } | 
| - DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault()); | 
| - options.set_allow_directx_capturer(true); | 
| - capturer_.reset(ScreenCapturer::Create(options)); | 
| - | 
| std::unique_ptr<DesktopFrame> frame; | 
| EXPECT_CALL(callback_, | 
| OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) | 
| @@ -171,15 +308,10 @@ TEST_F(ScreenCapturerTest, UseDirectxCapturer) { | 
| } | 
| TEST_F(ScreenCapturerTest, UseDirectxCapturerWithSharedBuffers) { | 
| - if (!ScreenCapturerWinDirectx::IsSupported()) { | 
| - LOG(LS_WARNING) << "Directx capturer is not supported"; | 
| + if (!SetDirectxCapturerMode()) { | 
| return; | 
| } | 
| - DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault()); | 
| - options.set_allow_directx_capturer(true); | 
| - capturer_.reset(ScreenCapturer::Create(options)); | 
| - | 
| std::unique_ptr<DesktopFrame> frame; | 
| EXPECT_CALL(callback_, | 
| OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) | 
| @@ -194,6 +326,24 @@ TEST_F(ScreenCapturerTest, UseDirectxCapturerWithSharedBuffers) { | 
| EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId); | 
| } | 
| +TEST_F(ScreenCapturerTest, CaptureUpdatedRegionWithDirectxCapturer) { | 
| + if (!SetDirectxCapturerMode()) { | 
| + return; | 
| + } | 
| + | 
| + TestCaptureUpdatedRegion(); | 
| +} | 
| + | 
| +TEST_F(ScreenCapturerTest, TwoDirectxCapturers) { | 
| + if (!SetDirectxCapturerMode()) { | 
| + return; | 
| + } | 
| + | 
| + std::unique_ptr<ScreenCapturer> capturer2(capturer_.release()); | 
| + RTC_CHECK(SetDirectxCapturerMode()); | 
| + TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()}); | 
| +} | 
| + | 
| #endif // defined(WEBRTC_WIN) | 
| } // namespace webrtc |