• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2019 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 "modules/desktop_capture/desktop_frame.h"
12 
13 #include <memory>
14 
15 #include "modules/desktop_capture/desktop_region.h"
16 #include "modules/desktop_capture/test_utils.h"
17 #include "rtc_base/arraysize.h"
18 #include "test/gtest.h"
19 
20 namespace webrtc {
21 
22 namespace {
23 
CreateTestFrame(DesktopRect rect,int pixels_value)24 std::unique_ptr<DesktopFrame> CreateTestFrame(DesktopRect rect,
25                                               int pixels_value) {
26   DesktopSize size = rect.size();
27   auto frame = std::make_unique<BasicDesktopFrame>(size);
28   frame->set_top_left(rect.top_left());
29   memset(frame->data(), pixels_value, frame->stride() * size.height());
30   return frame;
31 }
32 
33 struct TestData {
34   const char* description;
35   DesktopRect dest_frame_rect;
36   DesktopRect src_frame_rect;
37   double horizontal_scale;
38   double vertical_scale;
39   DesktopRect expected_overlap_rect;
40 };
41 
RunTest(const TestData & test)42 void RunTest(const TestData& test) {
43   // Copy a source frame with all bits set into a dest frame with none set.
44   auto dest_frame = CreateTestFrame(test.dest_frame_rect, 0);
45   auto src_frame = CreateTestFrame(test.src_frame_rect, 0xff);
46 
47   dest_frame->CopyIntersectingPixelsFrom(
48       *src_frame, test.horizontal_scale, test.vertical_scale);
49 
50   // Translate the expected overlap rect to be relative to the dest frame/rect.
51   DesktopVector dest_frame_origin = test.dest_frame_rect.top_left();
52   DesktopRect relative_expected_overlap_rect = test.expected_overlap_rect;
53   relative_expected_overlap_rect.Translate(-dest_frame_origin.x(),
54                                            -dest_frame_origin.y());
55 
56   // Confirm bits are now set in the dest frame if & only if they fall in the
57   // expected range.
58   for (int y = 0; y < dest_frame->size().height(); ++y) {
59     SCOPED_TRACE(y);
60 
61     for (int x = 0; x < dest_frame->size().width(); ++x) {
62       SCOPED_TRACE(x);
63 
64       DesktopVector point(x, y);
65       uint8_t* data = dest_frame->GetFrameDataAtPos(point);
66       uint32_t pixel_value = *reinterpret_cast<uint32_t*>(data);
67       bool was_copied = pixel_value == 0xffffffff;
68       ASSERT_TRUE(was_copied || pixel_value == 0);
69 
70       bool expected_to_be_copied =
71           relative_expected_overlap_rect.Contains(point);
72 
73       ASSERT_EQ(was_copied, expected_to_be_copied);
74     }
75   }
76 }
77 
RunTests(const TestData * tests,int num_tests)78 void RunTests(const TestData* tests, int num_tests) {
79   for (int i = 0; i < num_tests; i++) {
80     const TestData& test = tests[i];
81 
82     SCOPED_TRACE(test.description);
83 
84     RunTest(test);
85   }
86 }
87 
88 }  // namespace
89 
TEST(DesktopFrameTest,CopyIntersectingPixelsMatchingRects)90 TEST(DesktopFrameTest, CopyIntersectingPixelsMatchingRects) {
91   const TestData tests[] = {
92     {"0 origin",
93      DesktopRect::MakeXYWH(0, 0, 2, 2),
94      DesktopRect::MakeXYWH(0, 0, 2, 2),
95      1.0, 1.0,
96      DesktopRect::MakeXYWH(0, 0, 2, 2)},
97 
98     {"Negative origin",
99      DesktopRect::MakeXYWH(-1, -1, 2, 2),
100      DesktopRect::MakeXYWH(-1, -1, 2, 2),
101      1.0, 1.0,
102      DesktopRect::MakeXYWH(-1, -1, 2, 2)}
103   };
104 
105   RunTests(tests, arraysize(tests));
106 }
107 
TEST(DesktopFrameTest,CopyIntersectingPixelsMatchingRectsScaled)108 TEST(DesktopFrameTest, CopyIntersectingPixelsMatchingRectsScaled) {
109   // The scale factors shouldn't affect matching rects (they're only applied
110   // to any difference between the origins)
111   const TestData tests[] = {
112     {"0 origin 2x",
113      DesktopRect::MakeXYWH(0, 0, 2, 2),
114      DesktopRect::MakeXYWH(0, 0, 2, 2),
115      2.0, 2.0,
116      DesktopRect::MakeXYWH(0, 0, 2, 2)},
117 
118     {"0 origin 0.5x",
119      DesktopRect::MakeXYWH(0, 0, 2, 2),
120      DesktopRect::MakeXYWH(0, 0, 2, 2),
121      0.5, 0.5,
122      DesktopRect::MakeXYWH(0, 0, 2, 2)},
123 
124     {"Negative origin 2x",
125      DesktopRect::MakeXYWH(-1, -1, 2, 2),
126      DesktopRect::MakeXYWH(-1, -1, 2, 2),
127      2.0, 2.0,
128      DesktopRect::MakeXYWH(-1, -1, 2, 2)},
129 
130     {"Negative origin 0.5x",
131      DesktopRect::MakeXYWH(-1, -1, 2, 2),
132      DesktopRect::MakeXYWH(-1, -1, 2, 2),
133      0.5, 0.5,
134      DesktopRect::MakeXYWH(-1, -1, 2, 2)}
135   };
136 
137   RunTests(tests, arraysize(tests));
138 }
139 
TEST(DesktopFrameTest,CopyIntersectingPixelsFullyContainedRects)140 TEST(DesktopFrameTest, CopyIntersectingPixelsFullyContainedRects) {
141   const TestData tests[] = {
142     {"0 origin top left",
143      DesktopRect::MakeXYWH(0, 0, 2, 2),
144      DesktopRect::MakeXYWH(0, 0, 1, 1),
145      1.0, 1.0,
146      DesktopRect::MakeXYWH(0, 0, 1, 1)},
147 
148     {"0 origin bottom right",
149      DesktopRect::MakeXYWH(0, 0, 2, 2),
150      DesktopRect::MakeXYWH(1, 1, 1, 1),
151      1.0, 1.0,
152      DesktopRect::MakeXYWH(1, 1, 1, 1)},
153 
154     {"Negative origin bottom left",
155      DesktopRect::MakeXYWH(-1, -1, 2, 2),
156      DesktopRect::MakeXYWH(-1, 0, 1, 1),
157      1.0, 1.0,
158      DesktopRect::MakeXYWH(-1, 0, 1, 1)}
159   };
160 
161   RunTests(tests, arraysize(tests));
162 }
163 
TEST(DesktopFrameTest,CopyIntersectingPixelsFullyContainedRectsScaled)164 TEST(DesktopFrameTest, CopyIntersectingPixelsFullyContainedRectsScaled) {
165   const TestData tests[] = {
166     {"0 origin top left 2x",
167      DesktopRect::MakeXYWH(0, 0, 2, 2),
168      DesktopRect::MakeXYWH(0, 0, 1, 1),
169      2.0, 2.0,
170      DesktopRect::MakeXYWH(0, 0, 1, 1)},
171 
172     {"0 origin top left 0.5x",
173      DesktopRect::MakeXYWH(0, 0, 2, 2),
174      DesktopRect::MakeXYWH(0, 0, 1, 1),
175      0.5, 0.5,
176      DesktopRect::MakeXYWH(0, 0, 1, 1)},
177 
178     {"0 origin bottom left 2x",
179      DesktopRect::MakeXYWH(0, 0, 4, 4),
180      DesktopRect::MakeXYWH(1, 1, 2, 2),
181      2.0, 2.0,
182      DesktopRect::MakeXYWH(2, 2, 2, 2)},
183 
184     {"0 origin bottom middle 2x/1x",
185      DesktopRect::MakeXYWH(0, 0, 4, 3),
186      DesktopRect::MakeXYWH(1, 1, 2, 2),
187      2.0, 1.0,
188      DesktopRect::MakeXYWH(2, 1, 2, 2)},
189 
190     {"0 origin middle 0.5x",
191      DesktopRect::MakeXYWH(0, 0, 3, 3),
192      DesktopRect::MakeXYWH(2, 2, 1, 1),
193      0.5, 0.5,
194      DesktopRect::MakeXYWH(1, 1, 1, 1)},
195 
196     {"Negative origin bottom left 2x",
197      DesktopRect::MakeXYWH(-1, -1, 3, 3),
198      DesktopRect::MakeXYWH(-1, 0, 1, 1),
199      2.0, 2.0,
200      DesktopRect::MakeXYWH(-1, 1, 1, 1)},
201 
202     {"Negative origin near middle 0.5x",
203      DesktopRect::MakeXYWH(-2, -2, 2, 2),
204      DesktopRect::MakeXYWH(0, 0, 1, 1),
205      0.5, 0.5,
206      DesktopRect::MakeXYWH(-1, -1, 1, 1)}
207   };
208 
209   RunTests(tests, arraysize(tests));
210 }
211 
212 
TEST(DesktopFrameTest,CopyIntersectingPixelsPartiallyContainedRects)213 TEST(DesktopFrameTest, CopyIntersectingPixelsPartiallyContainedRects) {
214   const TestData tests[] = {
215     {"Top left",
216      DesktopRect::MakeXYWH(0, 0, 2, 2),
217      DesktopRect::MakeXYWH(-1, -1, 2, 2),
218      1.0, 1.0,
219      DesktopRect::MakeXYWH(0, 0, 1, 1)},
220 
221     {"Top right",
222      DesktopRect::MakeXYWH(0, 0, 2, 2),
223      DesktopRect::MakeXYWH(1, -1, 2, 2),
224      1.0, 1.0,
225      DesktopRect::MakeXYWH(1, 0, 1, 1)},
226 
227     {"Bottom right",
228      DesktopRect::MakeXYWH(0, 0, 2, 2),
229      DesktopRect::MakeXYWH(1, 1, 2, 2),
230      1.0, 1.0,
231      DesktopRect::MakeXYWH(1, 1, 1, 1)},
232 
233     {"Bottom left",
234      DesktopRect::MakeXYWH(0, 0, 2, 2),
235      DesktopRect::MakeXYWH(-1, 1, 2, 2),
236      1.0, 1.0,
237      DesktopRect::MakeXYWH(0, 1, 1, 1)}
238   };
239 
240   RunTests(tests, arraysize(tests));
241 }
242 
TEST(DesktopFrameTest,CopyIntersectingPixelsPartiallyContainedRectsScaled)243 TEST(DesktopFrameTest, CopyIntersectingPixelsPartiallyContainedRectsScaled) {
244   const TestData tests[] = {
245     {"Top left 2x",
246      DesktopRect::MakeXYWH(0, 0, 2, 2),
247      DesktopRect::MakeXYWH(-1, -1, 3, 3),
248      2.0, 2.0,
249      DesktopRect::MakeXYWH(0, 0, 1, 1)},
250 
251     {"Top right 0.5x",
252      DesktopRect::MakeXYWH(0, 0, 2, 2),
253      DesktopRect::MakeXYWH(2, -2, 2, 2),
254      0.5, 0.5,
255      DesktopRect::MakeXYWH(1, 0, 1, 1)},
256 
257     {"Bottom right 2x",
258      DesktopRect::MakeXYWH(0, 0, 3, 3),
259      DesktopRect::MakeXYWH(-1, 1, 3, 3),
260      2.0, 2.0,
261      DesktopRect::MakeXYWH(0, 2, 1, 1)},
262 
263     {"Bottom left 0.5x",
264      DesktopRect::MakeXYWH(0, 0, 2, 2),
265      DesktopRect::MakeXYWH(-2, 2, 2, 2),
266      0.5, 0.5,
267      DesktopRect::MakeXYWH(0, 1, 1, 1)}
268   };
269 
270   RunTests(tests, arraysize(tests));
271 }
272 
273 
TEST(DesktopFrameTest,CopyIntersectingPixelsUncontainedRects)274 TEST(DesktopFrameTest, CopyIntersectingPixelsUncontainedRects) {
275   const TestData tests[] = {
276     {"Left",
277      DesktopRect::MakeXYWH(0, 0, 2, 2),
278      DesktopRect::MakeXYWH(-1, 0, 1, 2),
279      1.0, 1.0,
280      DesktopRect::MakeXYWH(0, 0, 0, 0)},
281 
282     {"Top",
283      DesktopRect::MakeXYWH(0, 0, 2, 2),
284      DesktopRect::MakeXYWH(0, -1, 2, 1),
285      1.0, 1.0,
286      DesktopRect::MakeXYWH(0, 0, 0, 0)},
287 
288     {"Right",
289      DesktopRect::MakeXYWH(0, 0, 2, 2),
290      DesktopRect::MakeXYWH(2, 0, 1, 2),
291      1.0, 1.0,
292      DesktopRect::MakeXYWH(0, 0, 0, 0)},
293 
294 
295     {"Bottom",
296      DesktopRect::MakeXYWH(0, 0, 2, 2),
297      DesktopRect::MakeXYWH(0, 2, 2, 1),
298      1.0, 1.0,
299      DesktopRect::MakeXYWH(0, 0, 0, 0)}
300   };
301 
302   RunTests(tests, arraysize(tests));
303 }
304 
TEST(DesktopFrameTest,CopyIntersectingPixelsUncontainedRectsScaled)305 TEST(DesktopFrameTest, CopyIntersectingPixelsUncontainedRectsScaled) {
306   const TestData tests[] = {
307     {"Left 2x",
308      DesktopRect::MakeXYWH(0, 0, 2, 2),
309      DesktopRect::MakeXYWH(-1, 0, 2, 2),
310      2.0, 2.0,
311      DesktopRect::MakeXYWH(0, 0, 0, 0)},
312 
313     {"Top 0.5x",
314      DesktopRect::MakeXYWH(0, 0, 2, 2),
315      DesktopRect::MakeXYWH(0, -2, 2, 1),
316      0.5, 0.5,
317      DesktopRect::MakeXYWH(0, 0, 0, 0)},
318 
319     {"Right 2x",
320      DesktopRect::MakeXYWH(0, 0, 2, 2),
321      DesktopRect::MakeXYWH(1, 0, 1, 2),
322      2.0, 2.0,
323      DesktopRect::MakeXYWH(0, 0, 0, 0)},
324 
325 
326     {"Bottom 0.5x",
327      DesktopRect::MakeXYWH(0, 0, 2, 2),
328      DesktopRect::MakeXYWH(0, 4, 2, 1),
329      0.5, 0.5,
330      DesktopRect::MakeXYWH(0, 0, 0, 0)}
331   };
332 
333   RunTests(tests, arraysize(tests));
334 }
335 
336 }  // namespace webrtc
337