| 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
|
|
|