1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "remoting/base/util.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "third_party/libyuv/include/libyuv/convert_from_argb.h"
10 #include "third_party/webrtc/modules/desktop_capture/desktop_geometry.h"
12 static const int kWidth
= 32 ;
13 static const int kHeight
= 24 ;
14 static const int kBytesPerPixel
= 4;
15 static const int kYStride
= kWidth
;
16 static const int kUvStride
= kWidth
/ 2;
17 static const int kRgbStride
= kWidth
* kBytesPerPixel
;
18 static const uint32 kFillColor
= 0xffffff;
22 class YuvToRgbTester
{
25 yuv_buffer_size_
= (kYStride
+ kUvStride
) * kHeight
;
26 yuv_buffer_
.reset(new uint8
[yuv_buffer_size_
]);
27 yplane_
= yuv_buffer_
.get();
28 uplane_
= yplane_
+ (kYStride
* kHeight
);
29 vplane_
= uplane_
+ (kUvStride
* kHeight
/ 2);
31 rgb_buffer_size_
= kWidth
* kHeight
* kBytesPerPixel
;
32 rgb_buffer_
.reset(new uint8
[rgb_buffer_size_
]);
40 void ResetYuvBuffer() {
41 memset(yuv_buffer_
.get(), 0, yuv_buffer_size_
);
44 void ResetRgbBuffer() {
45 memset(rgb_buffer_
.get(), 0, rgb_buffer_size_
);
48 void FillRgbBuffer(const webrtc::DesktopRect
& rect
) {
49 uint32
* ptr
= reinterpret_cast<uint32
*>(
50 rgb_buffer_
.get() + (rect
.top() * kRgbStride
) +
51 (rect
.left() * kBytesPerPixel
));
52 int width
= rect
.width();
53 for (int height
= rect
.height(); height
> 0; --height
) {
54 std::fill(ptr
, ptr
+ width
, kFillColor
);
55 ptr
+= kRgbStride
/ kBytesPerPixel
;
59 // Check the the desination buffer is filled within expected bounds.
60 void CheckRgbBuffer(const webrtc::DesktopRect
& rect
) {
61 uint32
* ptr
= reinterpret_cast<uint32
*>(rgb_buffer_
.get());
62 for (int y
= 0; y
< kHeight
; ++y
) {
63 if (y
< rect
.top() || rect
.bottom() <= y
) {
64 // The whole line should be intact.
65 EXPECT_EQ((ptrdiff_t)kWidth
,
66 std::count(ptr
, ptr
+ kWidth
, 0u));
68 // The space before the painted rectangle should be intact.
69 EXPECT_EQ((ptrdiff_t)rect
.left(),
70 std::count(ptr
, ptr
+ rect
.left(), 0u));
72 // All pixels of the target rectangle should be touched.
73 EXPECT_EQ(ptr
+ rect
.right(),
74 std::find(ptr
+ rect
.left(), ptr
+ rect
.right(), 0u));
76 // The space after the painted rectangle should be intact.
77 EXPECT_EQ((ptrdiff_t)kWidth
- rect
.right(),
78 std::count(ptr
+ rect
.right(), ptr
+ kWidth
, 0u));
80 ptr
+= kRgbStride
/ kBytesPerPixel
;
84 void RunTest(const webrtc::DesktopSize dest_size
,
85 const webrtc::DesktopRect
& rect
) {
87 DoesRectContain(webrtc::DesktopRect::MakeSize(dest_size
), rect
));
95 libyuv::ARGBToI420(rgb_buffer_
.get(),
106 // Reset RGB buffer and do opposite conversion.
108 ConvertAndScaleYUVToRGB32Rect(yplane_
,
113 webrtc::DesktopSize(kWidth
, kHeight
),
114 webrtc::DesktopRect::MakeWH(kWidth
, kHeight
),
118 webrtc::DesktopRect::MakeSize(dest_size
),
121 // Check if it worked out.
122 CheckRgbBuffer(rect
);
125 void TestBasicConversion() {
127 RunTest(webrtc::DesktopSize(kWidth
, kHeight
),
128 webrtc::DesktopRect::MakeWH(kWidth
, kHeight
));
132 size_t yuv_buffer_size_
;
133 scoped_ptr
<uint8
[]> yuv_buffer_
;
138 size_t rgb_buffer_size_
;
139 scoped_ptr
<uint8
[]> rgb_buffer_
;
141 DISALLOW_COPY_AND_ASSIGN(YuvToRgbTester
);
144 TEST(YuvToRgbTest
, BasicConversion
) {
145 YuvToRgbTester tester
;
146 tester
.TestBasicConversion();
149 TEST(YuvToRgbTest
, Clipping
) {
150 YuvToRgbTester tester
;
152 webrtc::DesktopSize dest_size
= webrtc::DesktopSize(kWidth
, kHeight
);
153 webrtc::DesktopRect rect
=
154 webrtc::DesktopRect::MakeLTRB(0, 0, kWidth
- 1, kHeight
- 1);
155 // TODO(fbarchard): Allow top/left clipping to odd boundary.
156 for (int i
= 0; i
< 16; ++i
) {
157 webrtc::DesktopRect dest_rect
= webrtc::DesktopRect::MakeLTRB(
158 rect
.left() + ((i
& 1) ? 2 : 0),
159 rect
.top() + ((i
& 2) ? 2 : 0),
160 rect
.right() - ((i
& 4) ? 1 : 0),
161 rect
.bottom() - ((i
& 8) ? 1 : 0));
163 tester
.RunTest(dest_size
, dest_rect
);
167 TEST(YuvToRgbTest
, ClippingAndScaling
) {
168 YuvToRgbTester tester
;
170 webrtc::DesktopSize dest_size
=
171 webrtc::DesktopSize(kWidth
- 10, kHeight
- 10);
172 webrtc::DesktopRect rect
=
173 webrtc::DesktopRect::MakeLTRB(6, 6, kWidth
- 11, kHeight
- 11);
174 for (int i
= 0; i
< 16; ++i
) {
175 webrtc::DesktopRect dest_rect
= webrtc::DesktopRect::MakeLTRB(
176 rect
.left() + ((i
& 1) ? 2 : 0),
177 rect
.top() + ((i
& 2) ? 2 : 0),
178 rect
.right() - ((i
& 4) ? 1 : 0),
179 rect
.bottom() - ((i
& 8) ? 1 : 0));
181 tester
.RunTest(dest_size
, dest_rect
);
185 TEST(ReplaceLfByCrLfTest
, Basic
) {
186 EXPECT_EQ("ab", ReplaceLfByCrLf("ab"));
187 EXPECT_EQ("\r\nab", ReplaceLfByCrLf("\nab"));
188 EXPECT_EQ("\r\nab\r\n", ReplaceLfByCrLf("\nab\n"));
189 EXPECT_EQ("\r\nab\r\ncd", ReplaceLfByCrLf("\nab\ncd"));
190 EXPECT_EQ("\r\nab\r\ncd\r\n", ReplaceLfByCrLf("\nab\ncd\n"));
191 EXPECT_EQ("\r\n\r\nab\r\n\r\ncd\r\n\r\n",
192 ReplaceLfByCrLf("\n\nab\n\ncd\n\n"));
195 TEST(ReplaceLfByCrLfTest
, Speed
) {
197 std::string
line(kLineSize
, 'a');
198 line
[kLineSize
- 1] = '\n';
199 // Make a 10M string.
200 int kLineNum
= 10 * 1024 * 1024 / kLineSize
;
202 buffer
.resize(kLineNum
* kLineSize
);
203 for (int i
= 0; i
< kLineNum
; ++i
) {
204 memcpy(&buffer
[i
* kLineSize
], &line
[0], kLineSize
);
206 // Convert the string.
207 buffer
= ReplaceLfByCrLf(buffer
);
208 // Check the converted string.
209 EXPECT_EQ(static_cast<size_t>((kLineSize
+ 1) * kLineNum
), buffer
.size());
210 const char* p
= &buffer
[0];
211 for (int i
= 0; i
< kLineNum
; ++i
) {
212 EXPECT_EQ(0, memcmp(&line
[0], p
, kLineSize
- 1));
214 EXPECT_EQ('\r', *p
++);
215 EXPECT_EQ('\n', *p
++);
219 TEST(ReplaceCrLfByLfTest
, Basic
) {
220 EXPECT_EQ("ab", ReplaceCrLfByLf("ab"));
221 EXPECT_EQ("\nab", ReplaceCrLfByLf("\r\nab"));
222 EXPECT_EQ("\nab\n", ReplaceCrLfByLf("\r\nab\r\n"));
223 EXPECT_EQ("\nab\ncd", ReplaceCrLfByLf("\r\nab\r\ncd"));
224 EXPECT_EQ("\nab\ncd\n", ReplaceCrLfByLf("\r\nab\r\ncd\n"));
225 EXPECT_EQ("\n\nab\n\ncd\n\n",
226 ReplaceCrLfByLf("\r\n\r\nab\r\n\r\ncd\r\n\r\n"));
227 EXPECT_EQ("\rab\rcd\r", ReplaceCrLfByLf("\rab\rcd\r"));
230 TEST(ReplaceCrLfByLfTest
, Speed
) {
232 std::string
line(kLineSize
, 'a');
233 line
[kLineSize
- 2] = '\r';
234 line
[kLineSize
- 1] = '\n';
235 // Make a 10M string.
236 int kLineNum
= 10 * 1024 * 1024 / kLineSize
;
238 buffer
.resize(kLineNum
* kLineSize
);
239 for (int i
= 0; i
< kLineNum
; ++i
) {
240 memcpy(&buffer
[i
* kLineSize
], &line
[0], kLineSize
);
242 // Convert the string.
243 buffer
= ReplaceCrLfByLf(buffer
);
244 // Check the converted string.
245 EXPECT_EQ(static_cast<size_t>((kLineSize
- 1) * kLineNum
), buffer
.size());
246 const char* p
= &buffer
[0];
247 for (int i
= 0; i
< kLineNum
; ++i
) {
248 EXPECT_EQ(0, memcmp(&line
[0], p
, kLineSize
- 2));
250 EXPECT_EQ('\n', *p
++);
254 TEST(StringIsUtf8Test
, Basic
) {
255 EXPECT_TRUE(StringIsUtf8("", 0));
256 EXPECT_TRUE(StringIsUtf8("\0", 1));
257 EXPECT_TRUE(StringIsUtf8("abc", 3));
258 EXPECT_TRUE(StringIsUtf8("\xc0\x80", 2));
259 EXPECT_TRUE(StringIsUtf8("\xe0\x80\x80", 3));
260 EXPECT_TRUE(StringIsUtf8("\xf0\x80\x80\x80", 4));
261 EXPECT_TRUE(StringIsUtf8("\xf8\x80\x80\x80\x80", 5));
262 EXPECT_TRUE(StringIsUtf8("\xfc\x80\x80\x80\x80\x80", 6));
264 // Not enough continuation characters
265 EXPECT_FALSE(StringIsUtf8("\xc0", 1));
266 EXPECT_FALSE(StringIsUtf8("\xe0\x80", 2));
267 EXPECT_FALSE(StringIsUtf8("\xf0\x80\x80", 3));
268 EXPECT_FALSE(StringIsUtf8("\xf8\x80\x80\x80", 4));
269 EXPECT_FALSE(StringIsUtf8("\xfc\x80\x80\x80\x80", 5));
271 // One more continuation character than needed
272 EXPECT_FALSE(StringIsUtf8("\xc0\x80\x80", 3));
273 EXPECT_FALSE(StringIsUtf8("\xe0\x80\x80\x80", 4));
274 EXPECT_FALSE(StringIsUtf8("\xf0\x80\x80\x80\x80", 5));
275 EXPECT_FALSE(StringIsUtf8("\xf8\x80\x80\x80\x80\x80", 6));
276 EXPECT_FALSE(StringIsUtf8("\xfc\x80\x80\x80\x80\x80\x80", 7));
278 // Invalid first byte
279 EXPECT_FALSE(StringIsUtf8("\xfe\x80\x80\x80\x80\x80\x80", 7));
280 EXPECT_FALSE(StringIsUtf8("\xff\x80\x80\x80\x80\x80\x80", 7));
282 // Invalid continuation byte
283 EXPECT_FALSE(StringIsUtf8("\xc0\x00", 2));
284 EXPECT_FALSE(StringIsUtf8("\xc0\x40", 2));
285 EXPECT_FALSE(StringIsUtf8("\xc0\xc0", 2));
288 } // namespace remoting