Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Side by Side Diff: webrtc/modules/desktop_capture/screen_capturer_unittest.cc

Issue 2444583002: Move ScreenCapturer 'real' tests out of screen_capturer_unittest.cc. (Closed)
Patch Set: Resolve review comments Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include <string.h>
12
13 #include <algorithm>
14 #include <initializer_list>
15 #include <memory> 11 #include <memory>
16 #include <utility>
17 12
18 #include "webrtc/modules/desktop_capture/screen_capturer.h" 13 #include "webrtc/modules/desktop_capture/screen_capturer.h"
19 14
20 #include "webrtc/test/gmock.h" 15 #include "webrtc/test/gmock.h"
21 #include "webrtc/test/gtest.h" 16 #include "webrtc/test/gtest.h"
22 #include "webrtc/base/checks.h"
23 #include "webrtc/base/constructormagic.h" 17 #include "webrtc/base/constructormagic.h"
24 #include "webrtc/base/logging.h" 18 #include "webrtc/base/logging.h"
25 #include "webrtc/modules/desktop_capture/rgba_color.h"
26 #include "webrtc/modules/desktop_capture/desktop_capture_options.h" 19 #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
27 #include "webrtc/modules/desktop_capture/desktop_frame.h" 20 #include "webrtc/modules/desktop_capture/desktop_frame.h"
28 #include "webrtc/modules/desktop_capture/desktop_region.h" 21 #include "webrtc/modules/desktop_capture/desktop_region.h"
29 #include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h" 22 #include "webrtc/modules/desktop_capture/screen_capturer_mock_objects.h"
30 #include "webrtc/modules/desktop_capture/screen_drawer.h"
31 #include "webrtc/system_wrappers/include/sleep.h"
32 23
33 #if defined(WEBRTC_WIN) 24 #if defined(WEBRTC_WIN)
34 #include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h" 25 #include "webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
35 #endif // defined(WEBRTC_WIN) 26 #endif // defined(WEBRTC_WIN)
36 27
37 using ::testing::_; 28 using ::testing::_;
38 using ::testing::AnyNumber;
39 using ::testing::Return;
40 29
41 const int kTestSharedMemoryId = 123; 30 const int kTestSharedMemoryId = 123;
42 31
43 namespace webrtc { 32 namespace webrtc {
44 33
45 namespace {
46
47 ACTION_P(SaveUniquePtrArg, dest) {
48 *dest = std::move(*arg1);
49 }
50
51 // Returns true if color in |rect| of |frame| is |color|.
52 bool ArePixelsColoredBy(const DesktopFrame& frame,
53 DesktopRect rect,
54 RgbaColor color,
55 bool may_partially_draw) {
56 if (!may_partially_draw) {
57 // updated_region() should cover the painted area.
58 DesktopRegion updated_region(frame.updated_region());
59 updated_region.IntersectWith(rect);
60 if (!updated_region.Equals(DesktopRegion(rect))) {
61 return false;
62 }
63 }
64
65 // Color in the |rect| should be |color|.
66 uint8_t* row = frame.GetFrameDataAtPos(rect.top_left());
67 for (int i = 0; i < rect.height(); i++) {
68 uint8_t* column = row;
69 for (int j = 0; j < rect.width(); j++) {
70 if (color != RgbaColor(column)) {
71 return false;
72 }
73 column += DesktopFrame::kBytesPerPixel;
74 }
75 row += frame.stride();
76 }
77 return true;
78 }
79
80 } // namespace
81
82 class ScreenCapturerTest : public testing::Test { 34 class ScreenCapturerTest : public testing::Test {
83 public: 35 public:
84 void SetUp() override { 36 void SetUp() override {
85 capturer_.reset( 37 capturer_.reset(
86 ScreenCapturer::Create(DesktopCaptureOptions::CreateDefault())); 38 ScreenCapturer::Create(DesktopCaptureOptions::CreateDefault()));
87 } 39 }
88 40
89 protected: 41 protected:
90 void TestCaptureUpdatedRegion(
91 std::initializer_list<ScreenCapturer*> capturers) {
92 RTC_DCHECK(capturers.size() > 0);
93 // A large enough area for the tests, which should be able to fulfill by
94 // most of systems.
95 const int kTestArea = 512;
96 const int kRectSize = 32;
97 std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create();
98 if (!drawer || drawer->DrawableRegion().is_empty()) {
99 LOG(LS_WARNING) << "No ScreenDrawer implementation for current platform.";
100 return;
101 }
102 if (drawer->DrawableRegion().width() < kTestArea ||
103 drawer->DrawableRegion().height() < kTestArea) {
104 LOG(LS_WARNING) << "ScreenDrawer::DrawableRegion() is too small for the "
105 "CaptureUpdatedRegion tests.";
106 return;
107 }
108
109 for (ScreenCapturer* capturer : capturers) {
110 capturer->Start(&callback_);
111 }
112
113 // Draw a set of |kRectSize| by |kRectSize| rectangles at (|i|, |i|), or
114 // |i| by |i| rectangles at (|kRectSize|, |kRectSize|). One of (controlled
115 // by |c|) its primary colors is |i|, and the other two are 0x7f. So we
116 // won't draw a black or white rectangle.
117 for (int c = 0; c < 3; c++) {
118 // A fixed size rectangle.
119 for (int i = 0; i < kTestArea - kRectSize; i += 16) {
120 DesktopRect rect = DesktopRect::MakeXYWH(i, i, kRectSize, kRectSize);
121 rect.Translate(drawer->DrawableRegion().top_left());
122 RgbaColor color((c == 0 ? (i & 0xff) : 0x7f),
123 (c == 1 ? (i & 0xff) : 0x7f),
124 (c == 2 ? (i & 0xff) : 0x7f));
125 TestCaptureOneFrame(capturers, drawer.get(), rect, color);
126 }
127
128 // A variable-size rectangle.
129 for (int i = 0; i < kTestArea - kRectSize; i += 16) {
130 DesktopRect rect = DesktopRect::MakeXYWH(kRectSize, kRectSize, i, i);
131 rect.Translate(drawer->DrawableRegion().top_left());
132 RgbaColor color((c == 0 ? (i & 0xff) : 0x7f),
133 (c == 1 ? (i & 0xff) : 0x7f),
134 (c == 2 ? (i & 0xff) : 0x7f));
135 TestCaptureOneFrame(capturers, drawer.get(), rect, color);
136 }
137 }
138 }
139
140 void TestCaptureUpdatedRegion() {
141 TestCaptureUpdatedRegion({capturer_.get()});
142 }
143
144 #if defined(WEBRTC_WIN) 42 #if defined(WEBRTC_WIN)
145 // Enable allow_directx_capturer in DesktopCaptureOptions, but let 43 // Enable allow_directx_capturer in DesktopCaptureOptions, but let
146 // ScreenCapturer::Create to decide whether a DirectX capturer should be used. 44 // ScreenCapturer::Create to decide whether a DirectX capturer should be used.
147 void MaybeCreateDirectxCapturer() { 45 void MaybeCreateDirectxCapturer() {
148 DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault()); 46 DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault());
149 options.set_allow_directx_capturer(true); 47 options.set_allow_directx_capturer(true);
150 capturer_.reset(ScreenCapturer::Create(options)); 48 capturer_.reset(ScreenCapturer::Create(options));
151 } 49 }
152 50
153 bool CreateDirectxCapturer() { 51 bool CreateDirectxCapturer() {
154 if (!ScreenCapturerWinDirectx::IsSupported()) { 52 if (!ScreenCapturerWinDirectx::IsSupported()) {
155 LOG(LS_WARNING) << "Directx capturer is not supported"; 53 LOG(LS_WARNING) << "Directx capturer is not supported";
156 return false; 54 return false;
157 } 55 }
158 56
159 MaybeCreateDirectxCapturer(); 57 MaybeCreateDirectxCapturer();
160 return true; 58 return true;
161 } 59 }
162 60
163 void CreateMagnifierCapturer() { 61 void CreateMagnifierCapturer() {
164 DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault()); 62 DesktopCaptureOptions options(DesktopCaptureOptions::CreateDefault());
165 options.set_allow_use_magnification_api(true); 63 options.set_allow_use_magnification_api(true);
166 capturer_.reset(ScreenCapturer::Create(options)); 64 capturer_.reset(ScreenCapturer::Create(options));
167 } 65 }
168 #endif // defined(WEBRTC_WIN) 66 #endif // defined(WEBRTC_WIN)
169 67
170 std::unique_ptr<ScreenCapturer> capturer_; 68 std::unique_ptr<ScreenCapturer> capturer_;
171 MockScreenCapturerCallback callback_; 69 MockScreenCapturerCallback callback_;
172
173 private:
174 // Repeats capturing the frame by using |capturers| one-by-one for 600 times,
175 // typically 30 seconds, until they succeeded captured a |color| rectangle at
176 // |rect|. This function uses |drawer|->WaitForPendingDraws() between two
177 // attempts to wait for the screen to update.
178 void TestCaptureOneFrame(std::vector<ScreenCapturer*> capturers,
179 ScreenDrawer* drawer,
180 DesktopRect rect,
181 RgbaColor color) {
182 const int wait_capture_round = 600;
183 drawer->Clear();
184 size_t succeeded_capturers = 0;
185 for (int i = 0; i < wait_capture_round; i++) {
186 drawer->DrawRectangle(rect, color);
187 drawer->WaitForPendingDraws();
188 for (size_t j = 0; j < capturers.size(); j++) {
189 if (capturers[j] == nullptr) {
190 // ScreenCapturer should return an empty updated_region() if no
191 // update detected. So we won't test it again if it has captured
192 // the rectangle we drew.
193 continue;
194 }
195 std::unique_ptr<DesktopFrame> frame = CaptureFrame(capturers[j]);
196 if (!frame) {
197 // CaptureFrame() has triggered an assertion failure already, we
198 // only need to return here.
199 return;
200 }
201
202 if (ArePixelsColoredBy(
203 *frame, rect, color, drawer->MayDrawIncompleteShapes())) {
204 capturers[j] = nullptr;
205 succeeded_capturers++;
206 }
207 }
208
209 if (succeeded_capturers == capturers.size()) {
210 break;
211 }
212 }
213
214 ASSERT_EQ(succeeded_capturers, capturers.size());
215 }
216
217 // Expects |capturer| to successfully capture a frame, and returns it.
218 std::unique_ptr<DesktopFrame> CaptureFrame(ScreenCapturer* capturer) {
219 std::unique_ptr<DesktopFrame> frame;
220 EXPECT_CALL(callback_,
221 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
222 .WillOnce(SaveUniquePtrArg(&frame));
223 capturer->CaptureFrame();
224 EXPECT_TRUE(frame);
225 return frame;
226 }
227 }; 70 };
228 71
229 class FakeSharedMemory : public SharedMemory { 72 class FakeSharedMemory : public SharedMemory {
230 public: 73 public:
231 FakeSharedMemory(char* buffer, size_t size) 74 FakeSharedMemory(char* buffer, size_t size)
232 : SharedMemory(buffer, size, 0, kTestSharedMemoryId), 75 : SharedMemory(buffer, size, 0, kTestSharedMemoryId),
233 buffer_(buffer) { 76 buffer_(buffer) {
234 } 77 }
235 virtual ~FakeSharedMemory() { 78 virtual ~FakeSharedMemory() {
236 delete[] buffer_; 79 delete[] buffer_;
(...skipping 10 matching lines...) Expand all
247 90
248 std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override { 91 std::unique_ptr<SharedMemory> CreateSharedMemory(size_t size) override {
249 return std::unique_ptr<SharedMemory>( 92 return std::unique_ptr<SharedMemory>(
250 new FakeSharedMemory(new char[size], size)); 93 new FakeSharedMemory(new char[size], size));
251 } 94 }
252 95
253 private: 96 private:
254 RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemoryFactory); 97 RTC_DISALLOW_COPY_AND_ASSIGN(FakeSharedMemoryFactory);
255 }; 98 };
256 99
100 ACTION_P(SaveUniquePtrArg, dest) {
101 *dest = std::move(*arg1);
102 }
103
257 TEST_F(ScreenCapturerTest, GetScreenListAndSelectScreen) { 104 TEST_F(ScreenCapturerTest, GetScreenListAndSelectScreen) {
258 webrtc::ScreenCapturer::ScreenList screens; 105 webrtc::ScreenCapturer::ScreenList screens;
259 EXPECT_TRUE(capturer_->GetScreenList(&screens)); 106 EXPECT_TRUE(capturer_->GetScreenList(&screens));
260 for (webrtc::ScreenCapturer::ScreenList::iterator it = screens.begin(); 107 for (webrtc::ScreenCapturer::ScreenList::iterator it = screens.begin();
261 it != screens.end(); ++it) { 108 it != screens.end(); ++it) {
262 EXPECT_TRUE(capturer_->SelectScreen(it->id)); 109 EXPECT_TRUE(capturer_->SelectScreen(it->id));
263 } 110 }
264 } 111 }
265 112
266 TEST_F(ScreenCapturerTest, StartCapturer) { 113 TEST_F(ScreenCapturerTest, StartCapturer) {
267 capturer_->Start(&callback_); 114 capturer_->Start(&callback_);
268 } 115 }
269 116
270 TEST_F(ScreenCapturerTest, Capture) { 117 TEST_F(ScreenCapturerTest, Capture) {
271 // Assume that Start() treats the screen as invalid initially. 118 // Assume that Start() treats the screen as invalid initially.
(...skipping 14 matching lines...) Expand all
286 133
287 // Verify that the region contains whole screen. 134 // Verify that the region contains whole screen.
288 EXPECT_FALSE(frame->updated_region().is_empty()); 135 EXPECT_FALSE(frame->updated_region().is_empty());
289 DesktopRegion::Iterator it(frame->updated_region()); 136 DesktopRegion::Iterator it(frame->updated_region());
290 ASSERT_TRUE(!it.IsAtEnd()); 137 ASSERT_TRUE(!it.IsAtEnd());
291 EXPECT_TRUE(it.rect().equals(DesktopRect::MakeSize(frame->size()))); 138 EXPECT_TRUE(it.rect().equals(DesktopRect::MakeSize(frame->size())));
292 it.Advance(); 139 it.Advance();
293 EXPECT_TRUE(it.IsAtEnd()); 140 EXPECT_TRUE(it.IsAtEnd());
294 } 141 }
295 142
296 // Disabled due to being flaky due to the fact that it uses rendering / UI, see
297 // webrtc/6366.
298 TEST_F(ScreenCapturerTest, DISABLED_CaptureUpdatedRegion) {
299 TestCaptureUpdatedRegion();
300 }
301
302 // Disabled due to being flaky due to the fact that it uses rendering / UI, see
303 // webrtc/6366.
304 TEST_F(ScreenCapturerTest, DISABLED_TwoCapturers) {
305 std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
306 SetUp();
307 TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
308 }
309
310 #if defined(WEBRTC_WIN) 143 #if defined(WEBRTC_WIN)
311 144
312 TEST_F(ScreenCapturerTest, UseSharedBuffers) { 145 TEST_F(ScreenCapturerTest, UseSharedBuffers) {
313 std::unique_ptr<DesktopFrame> frame; 146 std::unique_ptr<DesktopFrame> frame;
314 EXPECT_CALL(callback_, 147 EXPECT_CALL(callback_,
315 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) 148 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
316 .WillOnce(SaveUniquePtrArg(&frame)); 149 .WillOnce(SaveUniquePtrArg(&frame));
317 150
318 capturer_->Start(&callback_); 151 capturer_->Start(&callback_);
319 capturer_->SetSharedMemoryFactory( 152 capturer_->SetSharedMemoryFactory(
320 std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory())); 153 std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory()));
321 capturer_->CaptureFrame(); 154 capturer_->CaptureFrame();
322 155
323 ASSERT_TRUE(frame); 156 ASSERT_TRUE(frame);
324 ASSERT_TRUE(frame->shared_memory()); 157 ASSERT_TRUE(frame->shared_memory());
325 EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId); 158 EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId);
326 } 159 }
327 160
328 TEST_F(ScreenCapturerTest, UseMagnifier) { 161 TEST_F(ScreenCapturerTest, UseMagnifier) {
329 CreateMagnifierCapturer(); 162 CreateMagnifierCapturer();
330
331 std::unique_ptr<DesktopFrame> frame; 163 std::unique_ptr<DesktopFrame> frame;
332 EXPECT_CALL(callback_, 164 EXPECT_CALL(callback_,
333 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _)) 165 OnCaptureResultPtr(DesktopCapturer::Result::SUCCESS, _))
334 .WillOnce(SaveUniquePtrArg(&frame)); 166 .WillOnce(SaveUniquePtrArg(&frame));
335 167
336 capturer_->Start(&callback_); 168 capturer_->Start(&callback_);
337 capturer_->CaptureFrame(); 169 capturer_->CaptureFrame();
338 ASSERT_TRUE(frame); 170 ASSERT_TRUE(frame);
339 } 171 }
340 172
(...skipping 24 matching lines...) Expand all
365 197
366 capturer_->Start(&callback_); 198 capturer_->Start(&callback_);
367 capturer_->SetSharedMemoryFactory( 199 capturer_->SetSharedMemoryFactory(
368 std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory())); 200 std::unique_ptr<SharedMemoryFactory>(new FakeSharedMemoryFactory()));
369 capturer_->CaptureFrame(); 201 capturer_->CaptureFrame();
370 ASSERT_TRUE(frame); 202 ASSERT_TRUE(frame);
371 ASSERT_TRUE(frame->shared_memory()); 203 ASSERT_TRUE(frame->shared_memory());
372 EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId); 204 EXPECT_EQ(frame->shared_memory()->id(), kTestSharedMemoryId);
373 } 205 }
374 206
375 // Disabled due to being flaky due to the fact that it uses rendering / UI, see
376 // webrtc/6366.
377 TEST_F(ScreenCapturerTest, DISABLED_CaptureUpdatedRegionWithDirectxCapturer) {
378 if (!CreateDirectxCapturer()) {
379 return;
380 }
381
382 TestCaptureUpdatedRegion();
383 }
384
385 // Disabled due to being flaky due to the fact that it uses rendering / UI, see
386 // webrtc/6366.
387 TEST_F(ScreenCapturerTest, DISABLED_TwoDirectxCapturers) {
388 if (!CreateDirectxCapturer()) {
389 return;
390 }
391
392 std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
393 RTC_CHECK(CreateDirectxCapturer());
394 TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
395 }
396
397 // Disabled due to being flaky due to the fact that it uses rendering / UI, see
398 // webrtc/6366.
399 TEST_F(ScreenCapturerTest, DISABLED_CaptureUpdatedRegionWithMagnifierCapturer) {
400 CreateMagnifierCapturer();
401 TestCaptureUpdatedRegion();
402 }
403
404 // Disabled due to being flaky due to the fact that it uses rendering / UI, see
405 // webrtc/6366.
406 TEST_F(ScreenCapturerTest, DISABLED_TwoMagnifierCapturers) {
407 CreateMagnifierCapturer();
408 std::unique_ptr<ScreenCapturer> capturer2 = std::move(capturer_);
409 CreateMagnifierCapturer();
410 TestCaptureUpdatedRegion({capturer_.get(), capturer2.get()});
411 }
412
413 // Disabled due to being flaky due to the fact that it uses rendering / UI, see
414 // webrtc/6366.
415 TEST_F(ScreenCapturerTest,
416 DISABLED_MaybeCaptureUpdatedRegionWithDirectxCapturer) {
417 // Even DirectX capturer is not supported in current system, we should be able
418 // to select a usable capturer.
419 MaybeCreateDirectxCapturer();
420 TestCaptureUpdatedRegion();
421 }
422
423 #endif // defined(WEBRTC_WIN) 207 #endif // defined(WEBRTC_WIN)
424 208
425 } // namespace webrtc 209 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698