1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <memory>
12
13 #include "modules/desktop_capture/desktop_capture_options.h"
14 #include "modules/desktop_capture/desktop_capturer.h"
15 #include "modules/desktop_capture/desktop_frame.h"
16 #include "modules/desktop_capture/desktop_region.h"
17 #include "modules/desktop_capture/mock_desktop_capturer_callback.h"
18 #include "rtc_base/logging.h"
19 #include "test/gmock.h"
20 #include "test/gtest.h"
21
22 #if defined(WEBRTC_WIN)
23 #include "modules/desktop_capture/win/screen_capturer_win_directx.h"
24 #endif // defined(WEBRTC_WIN)
25
26 using ::testing::_;
27
28 const int kTestSharedMemoryId = 123;
29
30 namespace webrtc {
31
32 class ScreenCapturerTest : public ::testing::Test {
33 public:
SetUp()34 void SetUp() override {
35 capturer_ = DesktopCapturer::CreateScreenCapturer(
36 DesktopCaptureOptions::CreateDefault());
37 ASSERT_TRUE(capturer_);
38 }
39
40 protected:
41 #if defined(WEBRTC_WIN)
42 // Enable allow_directx_capturer in DesktopCaptureOptions, but let
43 // DesktopCapturer::CreateScreenCapturer to decide whether a DirectX capturer
44 // should be used.
MaybeCreateDirectxCapturer()45 void MaybeCreateDirectxCapturer() {
46 DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault());
47 options.set_allow_directx_capturer(true);
48 capturer_ = DesktopCapturer::CreateScreenCapturer(options);
49 }
50
CreateDirectxCapturer()51 bool CreateDirectxCapturer() {
52 if (!ScreenCapturerWinDirectx::IsSupported()) {
53 RTC_LOG(LS_WARNING) << "Directx capturer is not supported";
54 return false;
55 }
56
57 MaybeCreateDirectxCapturer();
58 return true;
59 }
60
CreateMagnifierCapturer()61 void CreateMagnifierCapturer() {
62 DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault());
63 options.set_allow_use_magnification_api(true);
64 capturer_ = DesktopCapturer::CreateScreenCapturer(options);
65 }
66 #endif // defined(WEBRTC_WIN)
67
68 std::unique_ptr<DesktopCapturer> capturer_;
69 MockDesktopCapturerCallback callback_;
70 };
71
72 class FakeSharedMemory : public SharedMemory {
73 public:
FakeSharedMemory(char * buffer,size_t size)74 FakeSharedMemory(char* buffer, size_t size)
75 : SharedMemory(buffer, size, 0, kTestSharedMemoryId), buffer_(buffer) {}
~FakeSharedMemory()76 ~FakeSharedMemory() override { delete[] buffer_; }
77
78 FakeSharedMemory(const FakeSharedMemory&) = delete;
79 FakeSharedMemory& operator=(const FakeSharedMemory&) = delete;
80
81 private:
82 char* buffer_;
83 };
84
85 class FakeSharedMemoryFactory : public SharedMemoryFactory {
86 public:
FakeSharedMemoryFactory()87 FakeSharedMemoryFactory() {}
~FakeSharedMemoryFactory()88 ~FakeSharedMemoryFactory() override {}
89
90 FakeSharedMemoryFactory(const FakeSharedMemoryFactory&) = delete;
91 FakeSharedMemoryFactory& operator=(const FakeSharedMemoryFactory&) = delete;
92
CreateSharedMemory(size_t size)93 std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override {
94 return std::unique_ptr<SharedMemory>(
95 new FakeSharedMemory(new char[size], size));
96 }
97 };
98
ACTION_P(SaveUniquePtrArg,dest)99 ACTION_P(SaveUniquePtrArg, dest) {
100 *dest = std::move(*arg1);
101 }
102
103 // TODO(bugs.webrtc.org/12950): Re-enable when libc++ issue is fixed.
104 #if defined(WEBRTC_LINUX) && defined(MEMORY_SANITIZER)
105 #define MAYBE_GetScreenListAndSelectScreen DISABLED_GetScreenListAndSelectScreen
106 #else
107 #define MAYBE_GetScreenListAndSelectScreen GetScreenListAndSelectScreen
108 #endif
TEST_F(ScreenCapturerTest,MAYBE_GetScreenListAndSelectScreen)109 TEST_F(ScreenCapturerTest, MAYBE_GetScreenListAndSelectScreen) {
110 webrtc::DesktopCapturer::SourceList screens;
111 EXPECT_TRUE(capturer_->GetSourceList(&screens));
112 for (const auto& screen : screens) {
113 EXPECT_TRUE(capturer_->SelectSource(screen.id));
114 }
115 }
116
117 // Flaky on Linux. See: crbug.com/webrtc/7830
118 #if defined(WEBRTC_LINUX)
119 #define MAYBE_StartCapturer DISABLED_StartCaptuerer
120 #else
121 #define MAYBE_StartCapturer StartCapturer
122 #endif
TEST_F(ScreenCapturerTest,MAYBE_StartCapturer)123 TEST_F(ScreenCapturerTest, MAYBE_StartCapturer) {
124 capturer_->Start(&callback_);
125 }
126
127 #if defined(WEBRTC_LINUX)
128 #define MAYBE_Capture DISABLED_Capture
129 #else
130 #define MAYBE_Capture Capture
131 #endif
TEST_F(ScreenCapturerTest,MAYBE_Capture)132 TEST_F(ScreenCapturerTest, MAYBE_Capture) {
133 // Assume that Start() treats the screen as invalid initially.
134 std::unique_ptr<DesktopFrame> frame;
135 EXPECT_CALL(callback_,
136 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
137 .WillOnce(SaveUniquePtrArg(&frame));
138
139 capturer_->Start(&callback_);
140 capturer_->CaptureFrame();
141
142 ASSERT_TRUE(frame);
143 EXPECT_GT(frame->size().width(), 0);
144 EXPECT_GT(frame->size().height(), 0);
145 EXPECT_GE(frame->stride(),
146 frame->size().width() * DesktopFrame::kBytesPerPixel);
147 EXPECT_TRUE(frame->shared_memory() == NULL);
148
149 // Verify that the region contains whole screen.
150 EXPECT_FALSE(frame->updated_region().is_empty());
151 DesktopRegion::Iterator it(frame->updated_region());
152 ASSERT_TRUE(!it.IsAtEnd());
153 EXPECT_TRUE(it.rect().equals(DesktopRect::MakeSize(frame->size())));
154 it.Advance();
155 EXPECT_TRUE(it.IsAtEnd());
156 }
157
158 #if defined(WEBRTC_WIN)
159
TEST_F(ScreenCapturerTest,UseSharedBuffers)160 TEST_F(ScreenCapturerTest, UseSharedBuffers) {
161 std::unique_ptr<DesktopFrame> frame;
162 EXPECT_CALL(callback_,
163 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
164 .WillOnce(SaveUniquePtrArg(&frame));
165
166 capturer_->Start(&callback_);
167 capturer_->SetSharedMemoryFactory(
168 std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory()));
169 capturer_->CaptureFrame();
170
171 ASSERT_TRUE(frame);
172 ASSERT_TRUE(frame->shared_memory());
173 EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId);
174 }
175
TEST_F(ScreenCapturerTest,UseMagnifier)176 TEST_F(ScreenCapturerTest, UseMagnifier) {
177 CreateMagnifierCapturer();
178 std::unique_ptr<DesktopFrame> frame;
179 EXPECT_CALL(callback_,
180 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
181 .WillOnce(SaveUniquePtrArg(&frame));
182
183 capturer_->Start(&callback_);
184 capturer_->CaptureFrame();
185 ASSERT_TRUE(frame);
186 }
187
TEST_F(ScreenCapturerTest,UseDirectxCapturer)188 TEST_F(ScreenCapturerTest, UseDirectxCapturer) {
189 if (!CreateDirectxCapturer()) {
190 return;
191 }
192
193 std::unique_ptr<DesktopFrame> frame;
194 EXPECT_CALL(callback_,
195 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
196 .WillOnce(SaveUniquePtrArg(&frame));
197
198 capturer_->Start(&callback_);
199 capturer_->CaptureFrame();
200 ASSERT_TRUE(frame);
201 }
202
TEST_F(ScreenCapturerTest,UseDirectxCapturerWithSharedBuffers)203 TEST_F(ScreenCapturerTest, UseDirectxCapturerWithSharedBuffers) {
204 if (!CreateDirectxCapturer()) {
205 return;
206 }
207
208 std::unique_ptr<DesktopFrame> frame;
209 EXPECT_CALL(callback_,
210 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
211 .WillOnce(SaveUniquePtrArg(&frame));
212
213 capturer_->Start(&callback_);
214 capturer_->SetSharedMemoryFactory(
215 std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory()));
216 capturer_->CaptureFrame();
217 ASSERT_TRUE(frame);
218 ASSERT_TRUE(frame->shared_memory());
219 EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId);
220 }
221
222 #endif // defined(WEBRTC_WIN)
223
224 } // namespace webrtc
225