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