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(); |
+} |
+ |
#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 |