1 /*
2 * Copyright 2011 The LibYuv 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 <assert.h>
12 #include <stdlib.h>
13 #include <time.h>
14
15 #include "libyuv/row.h" /* For ARGBToAR30Row_AVX2 */
16
17 #include "libyuv/basic_types.h"
18 #include "libyuv/compare.h"
19 #include "libyuv/convert.h"
20 #include "libyuv/convert_argb.h"
21 #include "libyuv/convert_from.h"
22 #include "libyuv/convert_from_argb.h"
23 #include "libyuv/cpu_id.h"
24 #ifdef HAVE_JPEG
25 #include "libyuv/mjpeg_decoder.h"
26 #endif
27 #include "../unit_test/unit_test.h"
28 #include "libyuv/planar_functions.h"
29 #include "libyuv/rotate.h"
30 #include "libyuv/video_common.h"
31
32 #if defined(__arm__) || defined(__aarch64__)
33 // arm version subsamples by summing 4 pixels then multiplying by matrix with
34 // 4x smaller coefficients which are rounded to nearest integer.
35 #define ARM_YUV_ERROR 4
36 #else
37 #define ARM_YUV_ERROR 0
38 #endif
39
40 namespace libyuv {
41
42 // Alias to copy pixels as is
43 #define AR30ToAR30 ARGBCopy
44 #define ABGRToABGR ARGBCopy
45
46 #define SUBSAMPLE(v, a) ((((v) + (a)-1)) / (a))
47
48 // Planar test
49
50 #define TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
51 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, \
52 DST_SUBSAMP_X, DST_SUBSAMP_Y, W1280, N, NEG, OFF) \
53 TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) { \
54 static_assert(SRC_BPC == 1 || SRC_BPC == 2, "SRC BPC unsupported"); \
55 static_assert(DST_BPC == 1 || DST_BPC == 2, "DST BPC unsupported"); \
56 static_assert(SRC_SUBSAMP_X == 1 || SRC_SUBSAMP_X == 2, \
57 "DST SRC_SUBSAMP_X unsupported"); \
58 static_assert(SRC_SUBSAMP_Y == 1 || SRC_SUBSAMP_Y == 2, \
59 "DST SRC_SUBSAMP_Y unsupported"); \
60 static_assert(DST_SUBSAMP_X == 1 || DST_SUBSAMP_X == 2, \
61 "DST DST_SUBSAMP_X unsupported"); \
62 static_assert(DST_SUBSAMP_Y == 1 || DST_SUBSAMP_Y == 2, \
63 "DST DST_SUBSAMP_Y unsupported"); \
64 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
65 const int kHeight = benchmark_height_; \
66 const int kSrcHalfWidth = SUBSAMPLE(kWidth, SRC_SUBSAMP_X); \
67 const int kSrcHalfHeight = SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); \
68 const int kDstHalfWidth = SUBSAMPLE(kWidth, DST_SUBSAMP_X); \
69 const int kDstHalfHeight = SUBSAMPLE(kHeight, DST_SUBSAMP_Y); \
70 align_buffer_page_end(src_y, kWidth* kHeight* SRC_BPC + OFF); \
71 align_buffer_page_end(src_u, \
72 kSrcHalfWidth* kSrcHalfHeight* SRC_BPC + OFF); \
73 align_buffer_page_end(src_v, \
74 kSrcHalfWidth* kSrcHalfHeight* SRC_BPC + OFF); \
75 align_buffer_page_end(dst_y_c, kWidth* kHeight* DST_BPC); \
76 align_buffer_page_end(dst_u_c, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
77 align_buffer_page_end(dst_v_c, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
78 align_buffer_page_end(dst_y_opt, kWidth* kHeight* DST_BPC); \
79 align_buffer_page_end(dst_u_opt, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
80 align_buffer_page_end(dst_v_opt, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
81 MemRandomize(src_y + OFF, kWidth * kHeight * SRC_BPC); \
82 MemRandomize(src_u + OFF, kSrcHalfWidth * kSrcHalfHeight * SRC_BPC); \
83 MemRandomize(src_v + OFF, kSrcHalfWidth * kSrcHalfHeight * SRC_BPC); \
84 memset(dst_y_c, 1, kWidth* kHeight* DST_BPC); \
85 memset(dst_u_c, 2, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
86 memset(dst_v_c, 3, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
87 memset(dst_y_opt, 101, kWidth* kHeight* DST_BPC); \
88 memset(dst_u_opt, 102, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
89 memset(dst_v_opt, 103, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
90 MaskCpuFlags(disable_cpu_flags_); \
91 SRC_FMT_PLANAR##To##FMT_PLANAR( \
92 reinterpret_cast<SRC_T*>(src_y + OFF), kWidth, \
93 reinterpret_cast<SRC_T*>(src_u + OFF), kSrcHalfWidth, \
94 reinterpret_cast<SRC_T*>(src_v + OFF), kSrcHalfWidth, \
95 reinterpret_cast<DST_T*>(dst_y_c), kWidth, \
96 reinterpret_cast<DST_T*>(dst_u_c), kDstHalfWidth, \
97 reinterpret_cast<DST_T*>(dst_v_c), kDstHalfWidth, kWidth, \
98 NEG kHeight); \
99 MaskCpuFlags(benchmark_cpu_info_); \
100 for (int i = 0; i < benchmark_iterations_; ++i) { \
101 SRC_FMT_PLANAR##To##FMT_PLANAR( \
102 reinterpret_cast<SRC_T*>(src_y + OFF), kWidth, \
103 reinterpret_cast<SRC_T*>(src_u + OFF), kSrcHalfWidth, \
104 reinterpret_cast<SRC_T*>(src_v + OFF), kSrcHalfWidth, \
105 reinterpret_cast<DST_T*>(dst_y_opt), kWidth, \
106 reinterpret_cast<DST_T*>(dst_u_opt), kDstHalfWidth, \
107 reinterpret_cast<DST_T*>(dst_v_opt), kDstHalfWidth, kWidth, \
108 NEG kHeight); \
109 } \
110 for (int i = 0; i < kHeight * kWidth * DST_BPC; ++i) { \
111 EXPECT_EQ(dst_y_c[i], dst_y_opt[i]); \
112 } \
113 for (int i = 0; i < kDstHalfWidth * kDstHalfHeight * DST_BPC; ++i) { \
114 EXPECT_EQ(dst_u_c[i], dst_u_opt[i]); \
115 EXPECT_EQ(dst_v_c[i], dst_v_opt[i]); \
116 } \
117 free_aligned_buffer_page_end(dst_y_c); \
118 free_aligned_buffer_page_end(dst_u_c); \
119 free_aligned_buffer_page_end(dst_v_c); \
120 free_aligned_buffer_page_end(dst_y_opt); \
121 free_aligned_buffer_page_end(dst_u_opt); \
122 free_aligned_buffer_page_end(dst_v_opt); \
123 free_aligned_buffer_page_end(src_y); \
124 free_aligned_buffer_page_end(src_u); \
125 free_aligned_buffer_page_end(src_v); \
126 }
127
128 #define TESTPLANARTOP(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
129 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, \
130 DST_SUBSAMP_X, DST_SUBSAMP_Y) \
131 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
132 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
133 benchmark_width_ - 4, _Any, +, 0) \
134 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
135 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
136 benchmark_width_, _Unaligned, +, 1) \
137 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
138 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
139 benchmark_width_, _Invert, -, 0) \
140 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
141 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
142 benchmark_width_, _Opt, +, 0)
143
144 TESTPLANARTOP(I420, uint8_t, 1, 2, 2, I420, uint8_t, 1, 2, 2)
145 TESTPLANARTOP(I422, uint8_t, 1, 2, 1, I420, uint8_t, 1, 2, 2)
146 TESTPLANARTOP(I444, uint8_t, 1, 1, 1, I420, uint8_t, 1, 2, 2)
147 TESTPLANARTOP(I420, uint8_t, 1, 2, 2, I422, uint8_t, 1, 2, 1)
148 TESTPLANARTOP(I420, uint8_t, 1, 2, 2, I444, uint8_t, 1, 1, 1)
149 TESTPLANARTOP(I420, uint8_t, 1, 2, 2, I420Mirror, uint8_t, 1, 2, 2)
150 TESTPLANARTOP(I422, uint8_t, 1, 2, 1, I422, uint8_t, 1, 2, 1)
151 TESTPLANARTOP(I444, uint8_t, 1, 1, 1, I444, uint8_t, 1, 1, 1)
152 TESTPLANARTOP(I010, uint16_t, 2, 2, 2, I010, uint16_t, 2, 2, 2)
153 TESTPLANARTOP(I010, uint16_t, 2, 2, 2, I420, uint8_t, 1, 2, 2)
154 TESTPLANARTOP(I420, uint8_t, 1, 2, 2, I010, uint16_t, 2, 2, 2)
155 TESTPLANARTOP(H010, uint16_t, 2, 2, 2, H010, uint16_t, 2, 2, 2)
156 TESTPLANARTOP(H010, uint16_t, 2, 2, 2, H420, uint8_t, 1, 2, 2)
157 TESTPLANARTOP(H420, uint8_t, 1, 2, 2, H010, uint16_t, 2, 2, 2)
158
159 // Test Android 420 to I420
160 #define TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, \
161 SRC_SUBSAMP_Y, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
162 W1280, N, NEG, OFF, PN, OFF_U, OFF_V) \
163 TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##_##PN##N) { \
164 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
165 const int kHeight = benchmark_height_; \
166 const int kSizeUV = \
167 SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); \
168 align_buffer_page_end(src_y, kWidth* kHeight + OFF); \
169 align_buffer_page_end(src_uv, \
170 kSizeUV*((PIXEL_STRIDE == 3) ? 3 : 2) + OFF); \
171 align_buffer_page_end(dst_y_c, kWidth* kHeight); \
172 align_buffer_page_end(dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X) * \
173 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
174 align_buffer_page_end(dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X) * \
175 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
176 align_buffer_page_end(dst_y_opt, kWidth* kHeight); \
177 align_buffer_page_end(dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * \
178 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
179 align_buffer_page_end(dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * \
180 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
181 uint8_t* src_u = src_uv + OFF_U; \
182 uint8_t* src_v = src_uv + (PIXEL_STRIDE == 1 ? kSizeUV : OFF_V); \
183 int src_stride_uv = SUBSAMPLE(kWidth, SUBSAMP_X) * PIXEL_STRIDE; \
184 for (int i = 0; i < kHeight; ++i) \
185 for (int j = 0; j < kWidth; ++j) \
186 src_y[i * kWidth + j + OFF] = (fastrand() & 0xff); \
187 for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) { \
188 for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) { \
189 src_u[(i * src_stride_uv) + j * PIXEL_STRIDE + OFF] = \
190 (fastrand() & 0xff); \
191 src_v[(i * src_stride_uv) + j * PIXEL_STRIDE + OFF] = \
192 (fastrand() & 0xff); \
193 } \
194 } \
195 memset(dst_y_c, 1, kWidth* kHeight); \
196 memset(dst_u_c, 2, \
197 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
198 memset(dst_v_c, 3, \
199 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
200 memset(dst_y_opt, 101, kWidth* kHeight); \
201 memset(dst_u_opt, 102, \
202 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
203 memset(dst_v_opt, 103, \
204 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
205 MaskCpuFlags(disable_cpu_flags_); \
206 SRC_FMT_PLANAR##To##FMT_PLANAR( \
207 src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \
208 src_v + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), PIXEL_STRIDE, dst_y_c, \
209 kWidth, dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X), dst_v_c, \
210 SUBSAMPLE(kWidth, SUBSAMP_X), kWidth, NEG kHeight); \
211 MaskCpuFlags(benchmark_cpu_info_); \
212 for (int i = 0; i < benchmark_iterations_; ++i) { \
213 SRC_FMT_PLANAR##To##FMT_PLANAR( \
214 src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \
215 src_v + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), PIXEL_STRIDE, \
216 dst_y_opt, kWidth, dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X), \
217 dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X), kWidth, NEG kHeight); \
218 } \
219 int max_diff = 0; \
220 for (int i = 0; i < kHeight; ++i) { \
221 for (int j = 0; j < kWidth; ++j) { \
222 int abs_diff = abs(static_cast<int>(dst_y_c[i * kWidth + j]) - \
223 static_cast<int>(dst_y_opt[i * kWidth + j])); \
224 if (abs_diff > max_diff) { \
225 max_diff = abs_diff; \
226 } \
227 } \
228 } \
229 EXPECT_EQ(0, max_diff); \
230 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
231 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \
232 int abs_diff = abs( \
233 static_cast<int>(dst_u_c[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j]) - \
234 static_cast<int>( \
235 dst_u_opt[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j])); \
236 if (abs_diff > max_diff) { \
237 max_diff = abs_diff; \
238 } \
239 } \
240 } \
241 EXPECT_LE(max_diff, 3); \
242 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
243 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \
244 int abs_diff = abs( \
245 static_cast<int>(dst_v_c[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j]) - \
246 static_cast<int>( \
247 dst_v_opt[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j])); \
248 if (abs_diff > max_diff) { \
249 max_diff = abs_diff; \
250 } \
251 } \
252 } \
253 EXPECT_LE(max_diff, 3); \
254 free_aligned_buffer_page_end(dst_y_c); \
255 free_aligned_buffer_page_end(dst_u_c); \
256 free_aligned_buffer_page_end(dst_v_c); \
257 free_aligned_buffer_page_end(dst_y_opt); \
258 free_aligned_buffer_page_end(dst_u_opt); \
259 free_aligned_buffer_page_end(dst_v_opt); \
260 free_aligned_buffer_page_end(src_y); \
261 free_aligned_buffer_page_end(src_uv); \
262 }
263
264 #define TESTAPLANARTOP(SRC_FMT_PLANAR, PN, PIXEL_STRIDE, OFF_U, OFF_V, \
265 SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, SUBSAMP_X, \
266 SUBSAMP_Y) \
267 TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
268 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_ - 4, \
269 _Any, +, 0, PN, OFF_U, OFF_V) \
270 TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
271 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, \
272 _Unaligned, +, 1, PN, OFF_U, OFF_V) \
273 TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
274 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Invert, \
275 -, 0, PN, OFF_U, OFF_V) \
276 TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
277 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Opt, +, \
278 0, PN, OFF_U, OFF_V)
279
280 TESTAPLANARTOP(Android420, I420, 1, 0, 0, 2, 2, I420, 2, 2)
281 TESTAPLANARTOP(Android420, NV12, 2, 0, 1, 2, 2, I420, 2, 2)
282 TESTAPLANARTOP(Android420, NV21, 2, 1, 0, 2, 2, I420, 2, 2)
283
284 // wrapper to keep API the same
I400ToNV21(const uint8_t * src_y,int src_stride_y,const uint8_t *,int,const uint8_t *,int,uint8_t * dst_y,int dst_stride_y,uint8_t * dst_vu,int dst_stride_vu,int width,int height)285 int I400ToNV21(const uint8_t* src_y,
286 int src_stride_y,
287 const uint8_t* /* src_u */,
288 int /* src_stride_u */,
289 const uint8_t* /* src_v */,
290 int /* src_stride_v */,
291 uint8_t* dst_y,
292 int dst_stride_y,
293 uint8_t* dst_vu,
294 int dst_stride_vu,
295 int width,
296 int height) {
297 return I400ToNV21(src_y, src_stride_y, dst_y, dst_stride_y, dst_vu,
298 dst_stride_vu, width, height);
299 }
300
301 #define TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
302 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF) \
303 TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) { \
304 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
305 const int kHeight = benchmark_height_; \
306 align_buffer_page_end(src_y, kWidth* kHeight + OFF); \
307 align_buffer_page_end(src_u, SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * \
308 SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + \
309 OFF); \
310 align_buffer_page_end(src_v, SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * \
311 SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + \
312 OFF); \
313 align_buffer_page_end(dst_y_c, kWidth* kHeight); \
314 align_buffer_page_end(dst_uv_c, SUBSAMPLE(kWidth, SUBSAMP_X) * 2 * \
315 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
316 align_buffer_page_end(dst_y_opt, kWidth* kHeight); \
317 align_buffer_page_end(dst_uv_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * 2 * \
318 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
319 for (int i = 0; i < kHeight; ++i) \
320 for (int j = 0; j < kWidth; ++j) \
321 src_y[i * kWidth + j + OFF] = (fastrand() & 0xff); \
322 for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) { \
323 for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) { \
324 src_u[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] = \
325 (fastrand() & 0xff); \
326 src_v[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] = \
327 (fastrand() & 0xff); \
328 } \
329 } \
330 memset(dst_y_c, 1, kWidth* kHeight); \
331 memset(dst_uv_c, 2, \
332 SUBSAMPLE(kWidth, SUBSAMP_X) * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
333 memset(dst_y_opt, 101, kWidth* kHeight); \
334 memset(dst_uv_opt, 102, \
335 SUBSAMPLE(kWidth, SUBSAMP_X) * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
336 MaskCpuFlags(disable_cpu_flags_); \
337 SRC_FMT_PLANAR##To##FMT_PLANAR( \
338 src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \
339 src_v + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), dst_y_c, kWidth, \
340 dst_uv_c, SUBSAMPLE(kWidth, SUBSAMP_X) * 2, kWidth, NEG kHeight); \
341 MaskCpuFlags(benchmark_cpu_info_); \
342 for (int i = 0; i < benchmark_iterations_; ++i) { \
343 SRC_FMT_PLANAR##To##FMT_PLANAR( \
344 src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \
345 src_v + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), dst_y_opt, kWidth, \
346 dst_uv_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * 2, kWidth, NEG kHeight); \
347 } \
348 int max_diff = 0; \
349 for (int i = 0; i < kHeight; ++i) { \
350 for (int j = 0; j < kWidth; ++j) { \
351 int abs_diff = abs(static_cast<int>(dst_y_c[i * kWidth + j]) - \
352 static_cast<int>(dst_y_opt[i * kWidth + j])); \
353 if (abs_diff > max_diff) { \
354 max_diff = abs_diff; \
355 } \
356 } \
357 } \
358 EXPECT_LE(max_diff, 1); \
359 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
360 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X) * 2; ++j) { \
361 int abs_diff = \
362 abs(static_cast<int>( \
363 dst_uv_c[i * SUBSAMPLE(kWidth, SUBSAMP_X) * 2 + j]) - \
364 static_cast<int>( \
365 dst_uv_opt[i * SUBSAMPLE(kWidth, SUBSAMP_X) * 2 + j])); \
366 if (abs_diff > max_diff) { \
367 max_diff = abs_diff; \
368 } \
369 } \
370 } \
371 EXPECT_LE(max_diff, 1); \
372 free_aligned_buffer_page_end(dst_y_c); \
373 free_aligned_buffer_page_end(dst_uv_c); \
374 free_aligned_buffer_page_end(dst_y_opt); \
375 free_aligned_buffer_page_end(dst_uv_opt); \
376 free_aligned_buffer_page_end(src_y); \
377 free_aligned_buffer_page_end(src_u); \
378 free_aligned_buffer_page_end(src_v); \
379 }
380
381 #define TESTPLANARTOBP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
382 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \
383 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
384 SUBSAMP_X, SUBSAMP_Y, benchmark_width_ - 4, _Any, +, 0) \
385 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
386 SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Unaligned, +, 1) \
387 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
388 SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Invert, -, 0) \
389 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
390 SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Opt, +, 0)
391
392 TESTPLANARTOBP(I420, 2, 2, NV12, 2, 2)
393 TESTPLANARTOBP(I420, 2, 2, NV21, 2, 2)
394 TESTPLANARTOBP(I422, 2, 1, NV21, 2, 2)
395 TESTPLANARTOBP(I444, 1, 1, NV21, 2, 2)
396 TESTPLANARTOBP(I400, 2, 2, NV21, 2, 2)
397
398 #define TESTBIPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
399 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, \
400 OFF) \
401 TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) { \
402 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
403 const int kHeight = benchmark_height_; \
404 align_buffer_page_end(src_y, kWidth* kHeight + OFF); \
405 align_buffer_page_end(src_uv, SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * 2 * \
406 SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + \
407 OFF); \
408 align_buffer_page_end(dst_y_c, kWidth* kHeight); \
409 align_buffer_page_end(dst_uv_c, SUBSAMPLE(kWidth, SUBSAMP_X) * 2 * \
410 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
411 align_buffer_page_end(dst_y_opt, kWidth* kHeight); \
412 align_buffer_page_end(dst_uv_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * 2 * \
413 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
414 for (int i = 0; i < kHeight; ++i) \
415 for (int j = 0; j < kWidth; ++j) \
416 src_y[i * kWidth + j + OFF] = (fastrand() & 0xff); \
417 for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) { \
418 for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) { \
419 src_uv[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) * 2 + j + 0 + OFF] = \
420 (fastrand() & 0xff); \
421 src_uv[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) * 2 + j + 1 + OFF] = \
422 (fastrand() & 0xff); \
423 } \
424 } \
425 memset(dst_y_c, 1, kWidth* kHeight); \
426 memset(dst_uv_c, 2, \
427 SUBSAMPLE(kWidth, SUBSAMP_X) * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
428 memset(dst_y_opt, 101, kWidth* kHeight); \
429 memset(dst_uv_opt, 102, \
430 SUBSAMPLE(kWidth, SUBSAMP_X) * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
431 MaskCpuFlags(disable_cpu_flags_); \
432 SRC_FMT_PLANAR##To##FMT_PLANAR( \
433 src_y + OFF, kWidth, src_uv + OFF, \
434 SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * 2, dst_y_c, kWidth, dst_uv_c, \
435 SUBSAMPLE(kWidth, SUBSAMP_X) * 2, kWidth, NEG kHeight); \
436 MaskCpuFlags(benchmark_cpu_info_); \
437 for (int i = 0; i < benchmark_iterations_; ++i) { \
438 SRC_FMT_PLANAR##To##FMT_PLANAR( \
439 src_y + OFF, kWidth, src_uv + OFF, \
440 SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * 2, dst_y_opt, kWidth, dst_uv_opt, \
441 SUBSAMPLE(kWidth, SUBSAMP_X) * 2, kWidth, NEG kHeight); \
442 } \
443 int max_diff = 0; \
444 for (int i = 0; i < kHeight; ++i) { \
445 for (int j = 0; j < kWidth; ++j) { \
446 int abs_diff = abs(static_cast<int>(dst_y_c[i * kWidth + j]) - \
447 static_cast<int>(dst_y_opt[i * kWidth + j])); \
448 if (abs_diff > max_diff) { \
449 max_diff = abs_diff; \
450 } \
451 } \
452 } \
453 EXPECT_LE(max_diff, 1); \
454 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
455 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X) * 2; ++j) { \
456 int abs_diff = \
457 abs(static_cast<int>( \
458 dst_uv_c[i * SUBSAMPLE(kWidth, SUBSAMP_X) * 2 + j]) - \
459 static_cast<int>( \
460 dst_uv_opt[i * SUBSAMPLE(kWidth, SUBSAMP_X) * 2 + j])); \
461 if (abs_diff > max_diff) { \
462 max_diff = abs_diff; \
463 } \
464 } \
465 } \
466 EXPECT_LE(max_diff, 1); \
467 free_aligned_buffer_page_end(dst_y_c); \
468 free_aligned_buffer_page_end(dst_uv_c); \
469 free_aligned_buffer_page_end(dst_y_opt); \
470 free_aligned_buffer_page_end(dst_uv_opt); \
471 free_aligned_buffer_page_end(src_y); \
472 free_aligned_buffer_page_end(src_uv); \
473 }
474
475 #define TESTBIPLANARTOBP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
476 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \
477 TESTBIPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
478 SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Opt, +, 0) \
479 TESTBIPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
480 SUBSAMP_X, SUBSAMP_Y, benchmark_width_ - 4, _Any, +, 0) \
481 TESTBIPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
482 SUBSAMP_X, SUBSAMP_Y, benchmark_width, _Unaligned, +, 1) \
483 TESTBIPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
484 SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Invert, -, 0) \
485 TESTBIPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
486 SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Opt, +, 0)
487
488 // TODO(fbarchard): Fix msan on this unittest
489 // TESTBIPLANARTOBP(NV21, 2, 2, NV12, 2, 2)
490
491 #define TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
492 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF, \
493 DOY) \
494 TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) { \
495 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
496 const int kHeight = benchmark_height_; \
497 align_buffer_page_end(src_y, kWidth* kHeight + OFF); \
498 align_buffer_page_end(src_uv, 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * \
499 SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + \
500 OFF); \
501 align_buffer_page_end(dst_y_c, kWidth* kHeight); \
502 align_buffer_page_end(dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X) * \
503 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
504 align_buffer_page_end(dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X) * \
505 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
506 align_buffer_page_end(dst_y_opt, kWidth* kHeight); \
507 align_buffer_page_end(dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * \
508 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
509 align_buffer_page_end(dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * \
510 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
511 for (int i = 0; i < kHeight; ++i) \
512 for (int j = 0; j < kWidth; ++j) \
513 src_y[i * kWidth + j + OFF] = (fastrand() & 0xff); \
514 for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) { \
515 for (int j = 0; j < 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) { \
516 src_uv[(i * 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] = \
517 (fastrand() & 0xff); \
518 } \
519 } \
520 memset(dst_y_c, 1, kWidth* kHeight); \
521 memset(dst_u_c, 2, \
522 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
523 memset(dst_v_c, 3, \
524 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
525 memset(dst_y_opt, 101, kWidth* kHeight); \
526 memset(dst_u_opt, 102, \
527 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
528 memset(dst_v_opt, 103, \
529 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
530 MaskCpuFlags(disable_cpu_flags_); \
531 SRC_FMT_PLANAR##To##FMT_PLANAR( \
532 src_y + OFF, kWidth, src_uv + OFF, \
533 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X), DOY ? dst_y_c : NULL, kWidth, \
534 dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X), dst_v_c, \
535 SUBSAMPLE(kWidth, SUBSAMP_X), kWidth, NEG kHeight); \
536 MaskCpuFlags(benchmark_cpu_info_); \
537 for (int i = 0; i < benchmark_iterations_; ++i) { \
538 SRC_FMT_PLANAR##To##FMT_PLANAR( \
539 src_y + OFF, kWidth, src_uv + OFF, \
540 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X), DOY ? dst_y_opt : NULL, \
541 kWidth, dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X), dst_v_opt, \
542 SUBSAMPLE(kWidth, SUBSAMP_X), kWidth, NEG kHeight); \
543 } \
544 int max_diff = 0; \
545 if (DOY) { \
546 for (int i = 0; i < kHeight; ++i) { \
547 for (int j = 0; j < kWidth; ++j) { \
548 int abs_diff = abs(static_cast<int>(dst_y_c[i * kWidth + j]) - \
549 static_cast<int>(dst_y_opt[i * kWidth + j])); \
550 if (abs_diff > max_diff) { \
551 max_diff = abs_diff; \
552 } \
553 } \
554 } \
555 EXPECT_LE(max_diff, 1); \
556 } \
557 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
558 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \
559 int abs_diff = abs( \
560 static_cast<int>(dst_u_c[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j]) - \
561 static_cast<int>( \
562 dst_u_opt[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j])); \
563 if (abs_diff > max_diff) { \
564 max_diff = abs_diff; \
565 } \
566 } \
567 } \
568 EXPECT_LE(max_diff, 1); \
569 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
570 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \
571 int abs_diff = abs( \
572 static_cast<int>(dst_v_c[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j]) - \
573 static_cast<int>( \
574 dst_v_opt[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j])); \
575 if (abs_diff > max_diff) { \
576 max_diff = abs_diff; \
577 } \
578 } \
579 } \
580 EXPECT_LE(max_diff, 1); \
581 free_aligned_buffer_page_end(dst_y_c); \
582 free_aligned_buffer_page_end(dst_u_c); \
583 free_aligned_buffer_page_end(dst_v_c); \
584 free_aligned_buffer_page_end(dst_y_opt); \
585 free_aligned_buffer_page_end(dst_u_opt); \
586 free_aligned_buffer_page_end(dst_v_opt); \
587 free_aligned_buffer_page_end(src_y); \
588 free_aligned_buffer_page_end(src_uv); \
589 }
590
591 #define TESTBIPLANARTOP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
592 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \
593 TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
594 SUBSAMP_X, SUBSAMP_Y, benchmark_width_ - 4, _Any, +, 0, 1) \
595 TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
596 SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Unaligned, +, 1, \
597 1) \
598 TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
599 SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Invert, -, 0, 1) \
600 TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
601 SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Opt, +, 0, 1) \
602 TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, \
603 SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _NullY, +, 0, 0)
604
605 TESTBIPLANARTOP(NV12, 2, 2, I420, 2, 2)
606 TESTBIPLANARTOP(NV21, 2, 2, I420, 2, 2)
607
608 #define ALIGNINT(V, ALIGN) (((V) + (ALIGN)-1) / (ALIGN) * (ALIGN))
609
610 #define TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
611 YALIGN, W1280, N, NEG, OFF) \
612 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##N) { \
613 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
614 const int kHeight = ALIGNINT(benchmark_height_, YALIGN); \
615 const int kStrideB = ALIGNINT(kWidth * BPP_B, ALIGN); \
616 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
617 const int kSizeUV = kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y); \
618 align_buffer_page_end(src_y, kWidth* kHeight + OFF); \
619 align_buffer_page_end(src_u, kSizeUV + OFF); \
620 align_buffer_page_end(src_v, kSizeUV + OFF); \
621 align_buffer_page_end(dst_argb_c, kStrideB* kHeight + OFF); \
622 align_buffer_page_end(dst_argb_opt, kStrideB* kHeight + OFF); \
623 for (int i = 0; i < kWidth * kHeight; ++i) { \
624 src_y[i + OFF] = (fastrand() & 0xff); \
625 } \
626 for (int i = 0; i < kSizeUV; ++i) { \
627 src_u[i + OFF] = (fastrand() & 0xff); \
628 src_v[i + OFF] = (fastrand() & 0xff); \
629 } \
630 memset(dst_argb_c + OFF, 1, kStrideB * kHeight); \
631 memset(dst_argb_opt + OFF, 101, kStrideB * kHeight); \
632 MaskCpuFlags(disable_cpu_flags_); \
633 double time0 = get_time(); \
634 FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, src_u + OFF, kStrideUV, \
635 src_v + OFF, kStrideUV, dst_argb_c + OFF, kStrideB, \
636 kWidth, NEG kHeight); \
637 double time1 = get_time(); \
638 MaskCpuFlags(benchmark_cpu_info_); \
639 for (int i = 0; i < benchmark_iterations_; ++i) { \
640 FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, src_u + OFF, kStrideUV, \
641 src_v + OFF, kStrideUV, dst_argb_opt + OFF, \
642 kStrideB, kWidth, NEG kHeight); \
643 } \
644 double time2 = get_time(); \
645 printf(" %8d us C - %8d us OPT\n", \
646 static_cast<int>((time1 - time0) * 1e6), \
647 static_cast<int>((time2 - time1) * 1e6 / benchmark_iterations_)); \
648 for (int i = 0; i < kWidth * BPP_B * kHeight; ++i) { \
649 EXPECT_EQ(dst_argb_c[i + OFF], dst_argb_opt[i + OFF]); \
650 } \
651 free_aligned_buffer_page_end(src_y); \
652 free_aligned_buffer_page_end(src_u); \
653 free_aligned_buffer_page_end(src_v); \
654 free_aligned_buffer_page_end(dst_argb_c); \
655 free_aligned_buffer_page_end(dst_argb_opt); \
656 }
657
658 #define TESTPLANARTOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
659 YALIGN) \
660 TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
661 YALIGN, benchmark_width_ - 4, _Any, +, 0) \
662 TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
663 YALIGN, benchmark_width_, _Unaligned, +, 1) \
664 TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
665 YALIGN, benchmark_width_, _Invert, -, 0) \
666 TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
667 YALIGN, benchmark_width_, _Opt, +, 0)
668
669 TESTPLANARTOB(I420, 2, 2, ARGB, 4, 4, 1)
670 TESTPLANARTOB(J420, 2, 2, ARGB, 4, 4, 1)
671 TESTPLANARTOB(J420, 2, 2, ABGR, 4, 4, 1)
672 TESTPLANARTOB(H420, 2, 2, ARGB, 4, 4, 1)
673 TESTPLANARTOB(H420, 2, 2, ABGR, 4, 4, 1)
674 TESTPLANARTOB(I420, 2, 2, BGRA, 4, 4, 1)
675 TESTPLANARTOB(I420, 2, 2, ABGR, 4, 4, 1)
676 TESTPLANARTOB(I420, 2, 2, RGBA, 4, 4, 1)
677 TESTPLANARTOB(I420, 2, 2, RAW, 3, 3, 1)
678 TESTPLANARTOB(I420, 2, 2, RGB24, 3, 3, 1)
679 TESTPLANARTOB(H420, 2, 2, RAW, 3, 3, 1)
680 TESTPLANARTOB(H420, 2, 2, RGB24, 3, 3, 1)
681 TESTPLANARTOB(I420, 2, 2, RGB565, 2, 2, 1)
682 TESTPLANARTOB(J420, 2, 2, RGB565, 2, 2, 1)
683 TESTPLANARTOB(H420, 2, 2, RGB565, 2, 2, 1)
684 TESTPLANARTOB(I420, 2, 2, ARGB1555, 2, 2, 1)
685 TESTPLANARTOB(I420, 2, 2, ARGB4444, 2, 2, 1)
686 TESTPLANARTOB(I422, 2, 1, ARGB, 4, 4, 1)
687 TESTPLANARTOB(I422, 2, 1, RGB565, 2, 2, 1)
688 TESTPLANARTOB(J422, 2, 1, ARGB, 4, 4, 1)
689 TESTPLANARTOB(J422, 2, 1, ABGR, 4, 4, 1)
690 TESTPLANARTOB(H422, 2, 1, ARGB, 4, 4, 1)
691 TESTPLANARTOB(H422, 2, 1, ABGR, 4, 4, 1)
692 TESTPLANARTOB(I422, 2, 1, BGRA, 4, 4, 1)
693 TESTPLANARTOB(I422, 2, 1, ABGR, 4, 4, 1)
694 TESTPLANARTOB(I422, 2, 1, RGBA, 4, 4, 1)
695 TESTPLANARTOB(I444, 1, 1, ARGB, 4, 4, 1)
696 TESTPLANARTOB(J444, 1, 1, ARGB, 4, 4, 1)
697 TESTPLANARTOB(I444, 1, 1, ABGR, 4, 4, 1)
698 TESTPLANARTOB(I420, 2, 2, YUY2, 2, 4, 1)
699 TESTPLANARTOB(I420, 2, 2, UYVY, 2, 4, 1)
700 TESTPLANARTOB(I422, 2, 1, YUY2, 2, 4, 1)
701 TESTPLANARTOB(I422, 2, 1, UYVY, 2, 4, 1)
702 TESTPLANARTOB(I420, 2, 2, I400, 1, 1, 1)
703 TESTPLANARTOB(J420, 2, 2, J400, 1, 1, 1)
704 TESTPLANARTOB(I420, 2, 2, AR30, 4, 4, 1)
705 TESTPLANARTOB(H420, 2, 2, AR30, 4, 4, 1)
706
707 #define TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
708 YALIGN, W1280, DIFF, N, NEG, OFF, ATTEN) \
709 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##N) { \
710 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
711 const int kHeight = ALIGNINT(benchmark_height_, YALIGN); \
712 const int kStrideB = ALIGNINT(kWidth * BPP_B, ALIGN); \
713 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
714 const int kSizeUV = kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y); \
715 align_buffer_page_end(src_y, kWidth* kHeight + OFF); \
716 align_buffer_page_end(src_u, kSizeUV + OFF); \
717 align_buffer_page_end(src_v, kSizeUV + OFF); \
718 align_buffer_page_end(src_a, kWidth* kHeight + OFF); \
719 align_buffer_page_end(dst_argb_c, kStrideB* kHeight + OFF); \
720 align_buffer_page_end(dst_argb_opt, kStrideB* kHeight + OFF); \
721 for (int i = 0; i < kWidth * kHeight; ++i) { \
722 src_y[i + OFF] = (fastrand() & 0xff); \
723 src_a[i + OFF] = (fastrand() & 0xff); \
724 } \
725 for (int i = 0; i < kSizeUV; ++i) { \
726 src_u[i + OFF] = (fastrand() & 0xff); \
727 src_v[i + OFF] = (fastrand() & 0xff); \
728 } \
729 memset(dst_argb_c + OFF, 1, kStrideB * kHeight); \
730 memset(dst_argb_opt + OFF, 101, kStrideB * kHeight); \
731 MaskCpuFlags(disable_cpu_flags_); \
732 FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, src_u + OFF, kStrideUV, \
733 src_v + OFF, kStrideUV, src_a + OFF, kWidth, \
734 dst_argb_c + OFF, kStrideB, kWidth, NEG kHeight, \
735 ATTEN); \
736 MaskCpuFlags(benchmark_cpu_info_); \
737 for (int i = 0; i < benchmark_iterations_; ++i) { \
738 FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, src_u + OFF, kStrideUV, \
739 src_v + OFF, kStrideUV, src_a + OFF, kWidth, \
740 dst_argb_opt + OFF, kStrideB, kWidth, NEG kHeight, \
741 ATTEN); \
742 } \
743 int max_diff = 0; \
744 for (int i = 0; i < kWidth * BPP_B * kHeight; ++i) { \
745 int abs_diff = abs(static_cast<int>(dst_argb_c[i + OFF]) - \
746 static_cast<int>(dst_argb_opt[i + OFF])); \
747 if (abs_diff > max_diff) { \
748 max_diff = abs_diff; \
749 } \
750 } \
751 EXPECT_LE(max_diff, DIFF); \
752 free_aligned_buffer_page_end(src_y); \
753 free_aligned_buffer_page_end(src_u); \
754 free_aligned_buffer_page_end(src_v); \
755 free_aligned_buffer_page_end(src_a); \
756 free_aligned_buffer_page_end(dst_argb_c); \
757 free_aligned_buffer_page_end(dst_argb_opt); \
758 }
759
760 #define TESTQPLANARTOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
761 YALIGN, DIFF) \
762 TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
763 YALIGN, benchmark_width_ - 4, DIFF, _Any, +, 0, 0) \
764 TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
765 YALIGN, benchmark_width_, DIFF, _Unaligned, +, 1, 0) \
766 TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
767 YALIGN, benchmark_width_, DIFF, _Invert, -, 0, 0) \
768 TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
769 YALIGN, benchmark_width_, DIFF, _Opt, +, 0, 0) \
770 TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
771 YALIGN, benchmark_width_, DIFF, _Premult, +, 0, 1)
772
773 TESTQPLANARTOB(I420Alpha, 2, 2, ARGB, 4, 4, 1, 2)
774 TESTQPLANARTOB(I420Alpha, 2, 2, ABGR, 4, 4, 1, 2)
775
776 #define TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, FMT_C, \
777 BPP_B, W1280, DIFF, N, NEG, OFF) \
778 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##N) { \
779 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
780 const int kHeight = benchmark_height_; \
781 const int kStrideB = kWidth * BPP_B; \
782 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
783 align_buffer_page_end(src_y, kWidth* kHeight + OFF); \
784 align_buffer_page_end(src_uv, \
785 kStrideUV* SUBSAMPLE(kHeight, SUBSAMP_Y) * 2 + OFF); \
786 align_buffer_page_end(dst_argb_c, kStrideB* kHeight); \
787 align_buffer_page_end(dst_argb_opt, kStrideB* kHeight); \
788 for (int i = 0; i < kHeight; ++i) \
789 for (int j = 0; j < kWidth; ++j) \
790 src_y[i * kWidth + j + OFF] = (fastrand() & 0xff); \
791 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
792 for (int j = 0; j < kStrideUV * 2; ++j) { \
793 src_uv[i * kStrideUV * 2 + j + OFF] = (fastrand() & 0xff); \
794 } \
795 } \
796 memset(dst_argb_c, 1, kStrideB* kHeight); \
797 memset(dst_argb_opt, 101, kStrideB* kHeight); \
798 MaskCpuFlags(disable_cpu_flags_); \
799 FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, src_uv + OFF, kStrideUV * 2, \
800 dst_argb_c, kWidth * BPP_B, kWidth, NEG kHeight); \
801 MaskCpuFlags(benchmark_cpu_info_); \
802 for (int i = 0; i < benchmark_iterations_; ++i) { \
803 FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, src_uv + OFF, kStrideUV * 2, \
804 dst_argb_opt, kWidth * BPP_B, kWidth, \
805 NEG kHeight); \
806 } \
807 /* Convert to ARGB so 565 is expanded to bytes that can be compared. */ \
808 align_buffer_page_end(dst_argb32_c, kWidth * 4 * kHeight); \
809 align_buffer_page_end(dst_argb32_opt, kWidth * 4 * kHeight); \
810 memset(dst_argb32_c, 2, kWidth * 4 * kHeight); \
811 memset(dst_argb32_opt, 102, kWidth * 4 * kHeight); \
812 FMT_C##ToARGB(dst_argb_c, kStrideB, dst_argb32_c, kWidth * 4, kWidth, \
813 kHeight); \
814 FMT_C##ToARGB(dst_argb_opt, kStrideB, dst_argb32_opt, kWidth * 4, kWidth, \
815 kHeight); \
816 int max_diff = 0; \
817 for (int i = 0; i < kHeight; ++i) { \
818 for (int j = 0; j < kWidth * 4; ++j) { \
819 int abs_diff = \
820 abs(static_cast<int>(dst_argb32_c[i * kWidth * 4 + j]) - \
821 static_cast<int>(dst_argb32_opt[i * kWidth * 4 + j])); \
822 if (abs_diff > max_diff) { \
823 max_diff = abs_diff; \
824 } \
825 } \
826 } \
827 EXPECT_LE(max_diff, DIFF); \
828 free_aligned_buffer_page_end(src_y); \
829 free_aligned_buffer_page_end(src_uv); \
830 free_aligned_buffer_page_end(dst_argb_c); \
831 free_aligned_buffer_page_end(dst_argb_opt); \
832 free_aligned_buffer_page_end(dst_argb32_c); \
833 free_aligned_buffer_page_end(dst_argb32_opt); \
834 }
835
836 #define TESTBIPLANARTOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, FMT_C, BPP_B, \
837 DIFF) \
838 TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, FMT_C, BPP_B, \
839 benchmark_width_ - 4, DIFF, _Any, +, 0) \
840 TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, FMT_C, BPP_B, \
841 benchmark_width_, DIFF, _Unaligned, +, 1) \
842 TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, FMT_C, BPP_B, \
843 benchmark_width_, DIFF, _Invert, -, 0) \
844 TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, FMT_C, BPP_B, \
845 benchmark_width_, DIFF, _Opt, +, 0)
846
847 TESTBIPLANARTOB(NV12, 2, 2, ARGB, ARGB, 4, 2)
848 TESTBIPLANARTOB(NV21, 2, 2, ARGB, ARGB, 4, 2)
849 TESTBIPLANARTOB(NV12, 2, 2, ABGR, ABGR, 4, 2)
850 TESTBIPLANARTOB(NV21, 2, 2, ABGR, ABGR, 4, 2)
851 TESTBIPLANARTOB(NV12, 2, 2, RGB24, RGB24, 3, 2)
852 TESTBIPLANARTOB(NV21, 2, 2, RGB24, RGB24, 3, 2)
853 TESTBIPLANARTOB(NV12, 2, 2, RAW, RAW, 3, 2)
854 TESTBIPLANARTOB(NV21, 2, 2, RAW, RAW, 3, 2)
855 TESTBIPLANARTOB(NV12, 2, 2, RGB565, RGB565, 2, 9)
856 TESTBIPLANARTOB(NV21, 2, 2, YUV24, RAW, 3, 2)
857
858 #ifdef DO_THREE_PLANES
859 // Do 3 allocations for yuv. conventional but slower.
860 #define TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
861 W1280, DIFF, N, NEG, OFF) \
862 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_PLANAR##N) { \
863 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
864 const int kHeight = ALIGNINT(benchmark_height_, YALIGN); \
865 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
866 const int kStride = (kStrideUV * SUBSAMP_X * 8 * BPP_A + 7) / 8; \
867 align_buffer_page_end(src_argb, kStride* kHeight + OFF); \
868 align_buffer_page_end(dst_y_c, kWidth* kHeight); \
869 align_buffer_page_end(dst_u_c, kStrideUV* SUBSAMPLE(kHeight, SUBSAMP_Y)); \
870 align_buffer_page_end(dst_v_c, kStrideUV* SUBSAMPLE(kHeight, SUBSAMP_Y)); \
871 align_buffer_page_end(dst_y_opt, kWidth* kHeight); \
872 align_buffer_page_end(dst_u_opt, \
873 kStrideUV* SUBSAMPLE(kHeight, SUBSAMP_Y)); \
874 align_buffer_page_end(dst_v_opt, \
875 kStrideUV* SUBSAMPLE(kHeight, SUBSAMP_Y)); \
876 memset(dst_y_c, 1, kWidth* kHeight); \
877 memset(dst_u_c, 2, kStrideUV* SUBSAMPLE(kHeight, SUBSAMP_Y)); \
878 memset(dst_v_c, 3, kStrideUV* SUBSAMPLE(kHeight, SUBSAMP_Y)); \
879 memset(dst_y_opt, 101, kWidth* kHeight); \
880 memset(dst_u_opt, 102, kStrideUV* SUBSAMPLE(kHeight, SUBSAMP_Y)); \
881 memset(dst_v_opt, 103, kStrideUV* SUBSAMPLE(kHeight, SUBSAMP_Y)); \
882 for (int i = 0; i < kHeight; ++i) \
883 for (int j = 0; j < kStride; ++j) \
884 src_argb[(i * kStride) + j + OFF] = (fastrand() & 0xff); \
885 MaskCpuFlags(disable_cpu_flags_); \
886 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, dst_y_c, kWidth, dst_u_c, \
887 kStrideUV, dst_v_c, kStrideUV, kWidth, NEG kHeight); \
888 MaskCpuFlags(benchmark_cpu_info_); \
889 for (int i = 0; i < benchmark_iterations_; ++i) { \
890 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, dst_y_opt, kWidth, \
891 dst_u_opt, kStrideUV, dst_v_opt, kStrideUV, \
892 kWidth, NEG kHeight); \
893 } \
894 for (int i = 0; i < kHeight; ++i) { \
895 for (int j = 0; j < kWidth; ++j) { \
896 EXPECT_NEAR(static_cast<int>(dst_y_c[i * kWidth + j]), \
897 static_cast<int>(dst_y_opt[i * kWidth + j]), DIFF); \
898 } \
899 } \
900 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
901 for (int j = 0; j < kStrideUV; ++j) { \
902 EXPECT_NEAR(static_cast<int>(dst_u_c[i * kStrideUV + j]), \
903 static_cast<int>(dst_u_opt[i * kStrideUV + j]), DIFF); \
904 } \
905 } \
906 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
907 for (int j = 0; j < kStrideUV; ++j) { \
908 EXPECT_NEAR(static_cast<int>(dst_v_c[i * kStrideUV + j]), \
909 static_cast<int>(dst_v_opt[i * kStrideUV + j]), DIFF); \
910 } \
911 } \
912 free_aligned_buffer_page_end(dst_y_c); \
913 free_aligned_buffer_page_end(dst_u_c); \
914 free_aligned_buffer_page_end(dst_v_c); \
915 free_aligned_buffer_page_end(dst_y_opt); \
916 free_aligned_buffer_page_end(dst_u_opt); \
917 free_aligned_buffer_page_end(dst_v_opt); \
918 free_aligned_buffer_page_end(src_argb); \
919 }
920 #else
921 #define TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
922 W1280, DIFF, N, NEG, OFF) \
923 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_PLANAR##N) { \
924 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
925 const int kHeight = ALIGNINT(benchmark_height_, YALIGN); \
926 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
927 const int kStride = (kStrideUV * SUBSAMP_X * 8 * BPP_A + 7) / 8; \
928 align_buffer_page_end(src_argb, kStride* kHeight + OFF); \
929 align_buffer_page_end(dst_y_c, kWidth* kHeight); \
930 align_buffer_page_end(dst_uv_c, \
931 kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
932 align_buffer_page_end(dst_y_opt, kWidth* kHeight); \
933 align_buffer_page_end(dst_uv_opt, \
934 kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
935 memset(dst_y_c, 1, kWidth* kHeight); \
936 memset(dst_uv_c, 2, kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
937 memset(dst_y_opt, 101, kWidth* kHeight); \
938 memset(dst_uv_opt, 102, kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
939 for (int i = 0; i < kHeight; ++i) \
940 for (int j = 0; j < kStride; ++j) \
941 src_argb[(i * kStride) + j + OFF] = (fastrand() & 0xff); \
942 MaskCpuFlags(disable_cpu_flags_); \
943 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, dst_y_c, kWidth, dst_uv_c, \
944 kStrideUV * 2, dst_uv_c + kStrideUV, kStrideUV * 2, \
945 kWidth, NEG kHeight); \
946 MaskCpuFlags(benchmark_cpu_info_); \
947 for (int i = 0; i < benchmark_iterations_; ++i) { \
948 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, dst_y_opt, kWidth, \
949 dst_uv_opt, kStrideUV * 2, dst_uv_opt + kStrideUV, \
950 kStrideUV * 2, kWidth, NEG kHeight); \
951 } \
952 for (int i = 0; i < kHeight; ++i) { \
953 for (int j = 0; j < kWidth; ++j) { \
954 EXPECT_NEAR(static_cast<int>(dst_y_c[i * kWidth + j]), \
955 static_cast<int>(dst_y_opt[i * kWidth + j]), DIFF); \
956 } \
957 } \
958 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y) * 2; ++i) { \
959 for (int j = 0; j < kStrideUV; ++j) { \
960 EXPECT_NEAR(static_cast<int>(dst_uv_c[i * kStrideUV + j]), \
961 static_cast<int>(dst_uv_opt[i * kStrideUV + j]), DIFF); \
962 } \
963 } \
964 free_aligned_buffer_page_end(dst_y_c); \
965 free_aligned_buffer_page_end(dst_uv_c); \
966 free_aligned_buffer_page_end(dst_y_opt); \
967 free_aligned_buffer_page_end(dst_uv_opt); \
968 free_aligned_buffer_page_end(src_argb); \
969 }
970 #endif
971
972 #define TESTATOPLANAR(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
973 DIFF) \
974 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
975 benchmark_width_ - 4, DIFF, _Any, +, 0) \
976 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
977 benchmark_width_, DIFF, _Unaligned, +, 1) \
978 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
979 benchmark_width_, DIFF, _Invert, -, 0) \
980 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
981 benchmark_width_, DIFF, _Opt, +, 0)
982
983 TESTATOPLANAR(ABGR, 4, 1, I420, 2, 2, 4)
984 TESTATOPLANAR(ARGB, 4, 1, I420, 2, 2, 4)
985 TESTATOPLANAR(ARGB, 4, 1, I422, 2, 1, 2)
986 TESTATOPLANAR(ARGB, 4, 1, I444, 1, 1, 2)
987 TESTATOPLANAR(ARGB, 4, 1, J420, 2, 2, ARM_YUV_ERROR)
988 TESTATOPLANAR(ARGB, 4, 1, J422, 2, 1, ARM_YUV_ERROR)
989 TESTATOPLANAR(ARGB1555, 2, 1, I420, 2, 2, 15)
990 TESTATOPLANAR(ARGB4444, 2, 1, I420, 2, 2, 17)
991 TESTATOPLANAR(BGRA, 4, 1, I420, 2, 2, 4)
992 TESTATOPLANAR(I400, 1, 1, I420, 2, 2, 2)
993 TESTATOPLANAR(J400, 1, 1, J420, 2, 2, 2)
994 TESTATOPLANAR(RAW, 3, 1, I420, 2, 2, 4)
995 TESTATOPLANAR(RGB24, 3, 1, I420, 2, 2, 4)
996 // TODO(fbarchard): Investigate J420 error of 11 on Windows.
997 TESTATOPLANAR(RGB24, 3, 1, J420, 2, 2, 11)
998 TESTATOPLANAR(RGB565, 2, 1, I420, 2, 2, 5)
999 TESTATOPLANAR(RGBA, 4, 1, I420, 2, 2, 4)
1000 TESTATOPLANAR(UYVY, 2, 1, I420, 2, 2, 2)
1001 TESTATOPLANAR(UYVY, 2, 1, I422, 2, 1, 2)
1002 TESTATOPLANAR(YUY2, 2, 1, I420, 2, 2, 2)
1003 TESTATOPLANAR(YUY2, 2, 1, I422, 2, 1, 2)
1004
1005 #define TESTATOBIPLANARI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, \
1006 SUBSAMP_Y, W1280, N, NEG, OFF) \
1007 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_PLANAR##N) { \
1008 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
1009 const int kHeight = benchmark_height_; \
1010 const int kStride = SUBSAMPLE(kWidth, SUB_A) * BPP_A; \
1011 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
1012 align_buffer_page_end(src_argb, kStride* kHeight + OFF); \
1013 align_buffer_page_end(dst_y_c, kWidth* kHeight); \
1014 align_buffer_page_end(dst_uv_c, \
1015 kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
1016 align_buffer_page_end(dst_y_opt, kWidth* kHeight); \
1017 align_buffer_page_end(dst_uv_opt, \
1018 kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
1019 for (int i = 0; i < kHeight; ++i) \
1020 for (int j = 0; j < kStride; ++j) \
1021 src_argb[(i * kStride) + j + OFF] = (fastrand() & 0xff); \
1022 memset(dst_y_c, 1, kWidth* kHeight); \
1023 memset(dst_uv_c, 2, kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
1024 memset(dst_y_opt, 101, kWidth* kHeight); \
1025 memset(dst_uv_opt, 102, kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
1026 MaskCpuFlags(disable_cpu_flags_); \
1027 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, dst_y_c, kWidth, dst_uv_c, \
1028 kStrideUV * 2, kWidth, NEG kHeight); \
1029 MaskCpuFlags(benchmark_cpu_info_); \
1030 for (int i = 0; i < benchmark_iterations_; ++i) { \
1031 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, dst_y_opt, kWidth, \
1032 dst_uv_opt, kStrideUV * 2, kWidth, NEG kHeight); \
1033 } \
1034 int max_diff = 0; \
1035 for (int i = 0; i < kHeight; ++i) { \
1036 for (int j = 0; j < kWidth; ++j) { \
1037 int abs_diff = abs(static_cast<int>(dst_y_c[i * kWidth + j]) - \
1038 static_cast<int>(dst_y_opt[i * kWidth + j])); \
1039 if (abs_diff > max_diff) { \
1040 max_diff = abs_diff; \
1041 } \
1042 } \
1043 } \
1044 EXPECT_LE(max_diff, 4); \
1045 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
1046 for (int j = 0; j < kStrideUV * 2; ++j) { \
1047 int abs_diff = \
1048 abs(static_cast<int>(dst_uv_c[i * kStrideUV * 2 + j]) - \
1049 static_cast<int>(dst_uv_opt[i * kStrideUV * 2 + j])); \
1050 if (abs_diff > max_diff) { \
1051 max_diff = abs_diff; \
1052 } \
1053 } \
1054 } \
1055 EXPECT_LE(max_diff, 4); \
1056 free_aligned_buffer_page_end(dst_y_c); \
1057 free_aligned_buffer_page_end(dst_uv_c); \
1058 free_aligned_buffer_page_end(dst_y_opt); \
1059 free_aligned_buffer_page_end(dst_uv_opt); \
1060 free_aligned_buffer_page_end(src_argb); \
1061 }
1062
1063 #define TESTATOBIPLANAR(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \
1064 TESTATOBIPLANARI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
1065 benchmark_width_ - 4, _Any, +, 0) \
1066 TESTATOBIPLANARI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
1067 benchmark_width_, _Unaligned, +, 1) \
1068 TESTATOBIPLANARI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
1069 benchmark_width_, _Invert, -, 0) \
1070 TESTATOBIPLANARI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
1071 benchmark_width_, _Opt, +, 0)
1072
1073 TESTATOBIPLANAR(ARGB, 1, 4, NV12, 2, 2)
1074 TESTATOBIPLANAR(ARGB, 1, 4, NV21, 2, 2)
1075 TESTATOBIPLANAR(YUY2, 2, 4, NV12, 2, 2)
1076 TESTATOBIPLANAR(UYVY, 2, 4, NV12, 2, 2)
1077 TESTATOBIPLANAR(AYUV, 1, 4, NV12, 2, 2)
1078 TESTATOBIPLANAR(AYUV, 1, 4, NV21, 2, 2)
1079
1080 #define TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1081 HEIGHT_B, W1280, DIFF, N, NEG, OFF) \
1082 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_B##N) { \
1083 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
1084 const int kHeight = benchmark_height_; \
1085 const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A; \
1086 const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B; \
1087 const int kStrideA = \
1088 (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A; \
1089 const int kStrideB = \
1090 (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B; \
1091 align_buffer_page_end(src_argb, kStrideA* kHeightA + OFF); \
1092 align_buffer_page_end(dst_argb_c, kStrideB* kHeightB); \
1093 align_buffer_page_end(dst_argb_opt, kStrideB* kHeightB); \
1094 for (int i = 0; i < kStrideA * kHeightA; ++i) { \
1095 src_argb[i + OFF] = (fastrand() & 0xff); \
1096 } \
1097 memset(dst_argb_c, 1, kStrideB* kHeightB); \
1098 memset(dst_argb_opt, 101, kStrideB* kHeightB); \
1099 MaskCpuFlags(disable_cpu_flags_); \
1100 FMT_A##To##FMT_B(src_argb + OFF, kStrideA, dst_argb_c, kStrideB, kWidth, \
1101 NEG kHeight); \
1102 MaskCpuFlags(benchmark_cpu_info_); \
1103 for (int i = 0; i < benchmark_iterations_; ++i) { \
1104 FMT_A##To##FMT_B(src_argb + OFF, kStrideA, dst_argb_opt, kStrideB, \
1105 kWidth, NEG kHeight); \
1106 } \
1107 int max_diff = 0; \
1108 for (int i = 0; i < kStrideB * kHeightB; ++i) { \
1109 int abs_diff = abs(static_cast<int>(dst_argb_c[i]) - \
1110 static_cast<int>(dst_argb_opt[i])); \
1111 if (abs_diff > max_diff) { \
1112 max_diff = abs_diff; \
1113 } \
1114 } \
1115 EXPECT_LE(max_diff, DIFF); \
1116 free_aligned_buffer_page_end(src_argb); \
1117 free_aligned_buffer_page_end(dst_argb_c); \
1118 free_aligned_buffer_page_end(dst_argb_opt); \
1119 }
1120
1121 #define TESTATOBRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, \
1122 STRIDE_B, HEIGHT_B, DIFF) \
1123 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_B##_Random) { \
1124 for (int times = 0; times < benchmark_iterations_; ++times) { \
1125 const int kWidth = (fastrand() & 63) + 1; \
1126 const int kHeight = (fastrand() & 31) + 1; \
1127 const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A; \
1128 const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B; \
1129 const int kStrideA = \
1130 (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A; \
1131 const int kStrideB = \
1132 (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B; \
1133 align_buffer_page_end(src_argb, kStrideA* kHeightA); \
1134 align_buffer_page_end(dst_argb_c, kStrideB* kHeightB); \
1135 align_buffer_page_end(dst_argb_opt, kStrideB* kHeightB); \
1136 for (int i = 0; i < kStrideA * kHeightA; ++i) { \
1137 src_argb[i] = (fastrand() & 0xff); \
1138 } \
1139 memset(dst_argb_c, 123, kStrideB* kHeightB); \
1140 memset(dst_argb_opt, 123, kStrideB* kHeightB); \
1141 MaskCpuFlags(disable_cpu_flags_); \
1142 FMT_A##To##FMT_B(src_argb, kStrideA, dst_argb_c, kStrideB, kWidth, \
1143 kHeight); \
1144 MaskCpuFlags(benchmark_cpu_info_); \
1145 FMT_A##To##FMT_B(src_argb, kStrideA, dst_argb_opt, kStrideB, kWidth, \
1146 kHeight); \
1147 for (int i = 0; i < kStrideB * kHeightB; ++i) { \
1148 EXPECT_NEAR(dst_argb_c[i], dst_argb_opt[i], DIFF); \
1149 } \
1150 free_aligned_buffer_page_end(src_argb); \
1151 free_aligned_buffer_page_end(dst_argb_c); \
1152 free_aligned_buffer_page_end(dst_argb_opt); \
1153 } \
1154 }
1155
1156 #define TESTATOB(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1157 HEIGHT_B, DIFF) \
1158 TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1159 HEIGHT_B, benchmark_width_ - 4, DIFF, _Any, +, 0) \
1160 TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1161 HEIGHT_B, benchmark_width_, DIFF, _Unaligned, +, 1) \
1162 TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1163 HEIGHT_B, benchmark_width_, DIFF, _Invert, -, 0) \
1164 TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1165 HEIGHT_B, benchmark_width_, DIFF, _Opt, +, 0) \
1166 TESTATOBRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1167 HEIGHT_B, DIFF)
1168
1169 // TODO(fbarchard): make ARM version of C code that matches NEON.
1170 TESTATOB(AB30, 4, 4, 1, ABGR, 4, 4, 1, 0)
1171 TESTATOB(AB30, 4, 4, 1, ARGB, 4, 4, 1, 0)
1172 TESTATOB(ABGR, 4, 4, 1, AR30, 4, 4, 1, 0)
1173 TESTATOB(ABGR, 4, 4, 1, ARGB, 4, 4, 1, 0)
1174 TESTATOB(AR30, 4, 4, 1, AB30, 4, 4, 1, 0)
1175 TESTATOB(AR30, 4, 4, 1, ABGR, 4, 4, 1, 0)
1176 TESTATOB(AR30, 4, 4, 1, AR30, 4, 4, 1, 0)
1177 TESTATOB(AR30, 4, 4, 1, ARGB, 4, 4, 1, 0)
1178 TESTATOB(ARGB, 4, 4, 1, ABGR, 4, 4, 1, 0)
1179 TESTATOB(ARGB, 4, 4, 1, AR30, 4, 4, 1, 0)
1180 TESTATOB(ARGB, 4, 4, 1, ARGB, 4, 4, 1, 0)
1181 TESTATOB(ARGB, 4, 4, 1, ARGB1555, 2, 2, 1, 0)
1182 TESTATOB(ARGB, 4, 4, 1, ARGB4444, 2, 2, 1, 0)
1183 TESTATOB(ARGB, 4, 4, 1, ARGBMirror, 4, 4, 1, 0)
1184 TESTATOB(ARGB, 4, 4, 1, BGRA, 4, 4, 1, 0)
1185 TESTATOB(ARGB, 4, 4, 1, I400, 1, 1, 1, 2)
1186 TESTATOB(ARGB, 4, 4, 1, J400, 1, 1, 1, 2)
1187 TESTATOB(ARGB, 4, 4, 1, RAW, 3, 3, 1, 0)
1188 TESTATOB(ARGB, 4, 4, 1, RGB24, 3, 3, 1, 0)
1189 TESTATOB(ARGB, 4, 4, 1, RGB565, 2, 2, 1, 0)
1190 TESTATOB(ARGB, 4, 4, 1, RGBA, 4, 4, 1, 0)
1191 TESTATOB(ARGB, 4, 4, 1, UYVY, 2, 4, 1, 4)
1192 TESTATOB(ARGB, 4, 4, 1, YUY2, 2, 4, 1, 4)
1193 TESTATOB(ARGB1555, 2, 2, 1, ARGB, 4, 4, 1, 0)
1194 TESTATOB(ARGB4444, 2, 2, 1, ARGB, 4, 4, 1, 0)
1195 TESTATOB(BGRA, 4, 4, 1, ARGB, 4, 4, 1, 0)
1196 TESTATOB(I400, 1, 1, 1, ARGB, 4, 4, 1, 0)
1197 TESTATOB(I400, 1, 1, 1, I400, 1, 1, 1, 0)
1198 TESTATOB(I400, 1, 1, 1, I400Mirror, 1, 1, 1, 0)
1199 TESTATOB(J400, 1, 1, 1, ARGB, 4, 4, 1, 0)
1200 TESTATOB(J400, 1, 1, 1, J400, 1, 1, 1, 0)
1201 TESTATOB(RAW, 3, 3, 1, ARGB, 4, 4, 1, 0)
1202 TESTATOB(RAW, 3, 3, 1, RGB24, 3, 3, 1, 0)
1203 TESTATOB(RGB24, 3, 3, 1, ARGB, 4, 4, 1, 0)
1204 TESTATOB(RGB24, 3, 3, 1, J400, 1, 1, 1, 0)
1205 TESTATOB(RGB565, 2, 2, 1, ARGB, 4, 4, 1, 0)
1206 TESTATOB(RGBA, 4, 4, 1, ARGB, 4, 4, 1, 0)
1207 TESTATOB(UYVY, 2, 4, 1, ARGB, 4, 4, 1, ARM_YUV_ERROR)
1208 TESTATOB(YUY2, 2, 4, 1, ARGB, 4, 4, 1, ARM_YUV_ERROR)
1209 TESTATOB(YUY2, 2, 4, 1, Y, 1, 1, 1, 0)
1210
1211 #define TESTATOBDI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1212 HEIGHT_B, W1280, DIFF, N, NEG, OFF) \
1213 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_B##Dither##N) { \
1214 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
1215 const int kHeight = benchmark_height_; \
1216 const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A; \
1217 const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B; \
1218 const int kStrideA = \
1219 (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A; \
1220 const int kStrideB = \
1221 (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B; \
1222 align_buffer_page_end(src_argb, kStrideA* kHeightA + OFF); \
1223 align_buffer_page_end(dst_argb_c, kStrideB* kHeightB); \
1224 align_buffer_page_end(dst_argb_opt, kStrideB* kHeightB); \
1225 for (int i = 0; i < kStrideA * kHeightA; ++i) { \
1226 src_argb[i + OFF] = (fastrand() & 0xff); \
1227 } \
1228 memset(dst_argb_c, 1, kStrideB* kHeightB); \
1229 memset(dst_argb_opt, 101, kStrideB* kHeightB); \
1230 MaskCpuFlags(disable_cpu_flags_); \
1231 FMT_A##To##FMT_B##Dither(src_argb + OFF, kStrideA, dst_argb_c, kStrideB, \
1232 NULL, kWidth, NEG kHeight); \
1233 MaskCpuFlags(benchmark_cpu_info_); \
1234 for (int i = 0; i < benchmark_iterations_; ++i) { \
1235 FMT_A##To##FMT_B##Dither(src_argb + OFF, kStrideA, dst_argb_opt, \
1236 kStrideB, NULL, kWidth, NEG kHeight); \
1237 } \
1238 int max_diff = 0; \
1239 for (int i = 0; i < kStrideB * kHeightB; ++i) { \
1240 int abs_diff = abs(static_cast<int>(dst_argb_c[i]) - \
1241 static_cast<int>(dst_argb_opt[i])); \
1242 if (abs_diff > max_diff) { \
1243 max_diff = abs_diff; \
1244 } \
1245 } \
1246 EXPECT_LE(max_diff, DIFF); \
1247 free_aligned_buffer_page_end(src_argb); \
1248 free_aligned_buffer_page_end(dst_argb_c); \
1249 free_aligned_buffer_page_end(dst_argb_opt); \
1250 }
1251
1252 #define TESTATOBDRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, \
1253 STRIDE_B, HEIGHT_B, DIFF) \
1254 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_B##Dither_Random) { \
1255 for (int times = 0; times < benchmark_iterations_; ++times) { \
1256 const int kWidth = (fastrand() & 63) + 1; \
1257 const int kHeight = (fastrand() & 31) + 1; \
1258 const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A; \
1259 const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B; \
1260 const int kStrideA = \
1261 (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A; \
1262 const int kStrideB = \
1263 (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B; \
1264 align_buffer_page_end(src_argb, kStrideA* kHeightA); \
1265 align_buffer_page_end(dst_argb_c, kStrideB* kHeightB); \
1266 align_buffer_page_end(dst_argb_opt, kStrideB* kHeightB); \
1267 for (int i = 0; i < kStrideA * kHeightA; ++i) { \
1268 src_argb[i] = (fastrand() & 0xff); \
1269 } \
1270 memset(dst_argb_c, 123, kStrideB* kHeightB); \
1271 memset(dst_argb_opt, 123, kStrideB* kHeightB); \
1272 MaskCpuFlags(disable_cpu_flags_); \
1273 FMT_A##To##FMT_B##Dither(src_argb, kStrideA, dst_argb_c, kStrideB, NULL, \
1274 kWidth, kHeight); \
1275 MaskCpuFlags(benchmark_cpu_info_); \
1276 FMT_A##To##FMT_B##Dither(src_argb, kStrideA, dst_argb_opt, kStrideB, \
1277 NULL, kWidth, kHeight); \
1278 int max_diff = 0; \
1279 for (int i = 0; i < kStrideB * kHeightB; ++i) { \
1280 int abs_diff = abs(static_cast<int>(dst_argb_c[i]) - \
1281 static_cast<int>(dst_argb_opt[i])); \
1282 if (abs_diff > max_diff) { \
1283 max_diff = abs_diff; \
1284 } \
1285 } \
1286 EXPECT_LE(max_diff, DIFF); \
1287 free_aligned_buffer_page_end(src_argb); \
1288 free_aligned_buffer_page_end(dst_argb_c); \
1289 free_aligned_buffer_page_end(dst_argb_opt); \
1290 } \
1291 }
1292
1293 #define TESTATOBD(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1294 HEIGHT_B, DIFF) \
1295 TESTATOBDI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1296 HEIGHT_B, benchmark_width_ - 4, DIFF, _Any, +, 0) \
1297 TESTATOBDI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1298 HEIGHT_B, benchmark_width_, DIFF, _Unaligned, +, 1) \
1299 TESTATOBDI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1300 HEIGHT_B, benchmark_width_, DIFF, _Invert, -, 0) \
1301 TESTATOBDI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1302 HEIGHT_B, benchmark_width_, DIFF, _Opt, +, 0) \
1303 TESTATOBDRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A, FMT_B, BPP_B, STRIDE_B, \
1304 HEIGHT_B, DIFF)
1305
1306 TESTATOBD(ARGB, 4, 4, 1, RGB565, 2, 2, 1, 0)
1307
1308 #define TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A, W1280, N, NEG, OFF) \
1309 TEST_F(LibYUVConvertTest, FMT_ATOB##_Symetric##N) { \
1310 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
1311 const int kHeight = benchmark_height_; \
1312 const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A; \
1313 const int kStrideA = \
1314 (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A; \
1315 align_buffer_page_end(src_argb, kStrideA* kHeightA + OFF); \
1316 align_buffer_page_end(dst_argb_c, kStrideA* kHeightA); \
1317 align_buffer_page_end(dst_argb_opt, kStrideA* kHeightA); \
1318 for (int i = 0; i < kStrideA * kHeightA; ++i) { \
1319 src_argb[i + OFF] = (fastrand() & 0xff); \
1320 } \
1321 memset(dst_argb_c, 1, kStrideA* kHeightA); \
1322 memset(dst_argb_opt, 101, kStrideA* kHeightA); \
1323 MaskCpuFlags(disable_cpu_flags_); \
1324 FMT_ATOB(src_argb + OFF, kStrideA, dst_argb_c, kStrideA, kWidth, \
1325 NEG kHeight); \
1326 MaskCpuFlags(benchmark_cpu_info_); \
1327 for (int i = 0; i < benchmark_iterations_; ++i) { \
1328 FMT_ATOB(src_argb + OFF, kStrideA, dst_argb_opt, kStrideA, kWidth, \
1329 NEG kHeight); \
1330 } \
1331 MaskCpuFlags(disable_cpu_flags_); \
1332 FMT_ATOB(dst_argb_c, kStrideA, dst_argb_c, kStrideA, kWidth, NEG kHeight); \
1333 MaskCpuFlags(benchmark_cpu_info_); \
1334 FMT_ATOB(dst_argb_opt, kStrideA, dst_argb_opt, kStrideA, kWidth, \
1335 NEG kHeight); \
1336 for (int i = 0; i < kStrideA * kHeightA; ++i) { \
1337 EXPECT_EQ(src_argb[i + OFF], dst_argb_opt[i]); \
1338 EXPECT_EQ(dst_argb_c[i], dst_argb_opt[i]); \
1339 } \
1340 free_aligned_buffer_page_end(src_argb); \
1341 free_aligned_buffer_page_end(dst_argb_c); \
1342 free_aligned_buffer_page_end(dst_argb_opt); \
1343 }
1344
1345 #define TESTSYM(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A) \
1346 TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A, benchmark_width_ - 4, _Any, +, \
1347 0) \
1348 TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A, benchmark_width_, _Unaligned, \
1349 +, 1) \
1350 TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A, benchmark_width_, _Opt, +, 0)
1351
1352 TESTSYM(ARGBToARGB, 4, 4, 1)
1353 TESTSYM(ARGBToBGRA, 4, 4, 1)
1354 TESTSYM(ARGBToABGR, 4, 4, 1)
1355 TESTSYM(BGRAToARGB, 4, 4, 1)
1356 TESTSYM(ABGRToARGB, 4, 4, 1)
1357
TEST_F(LibYUVConvertTest,Test565)1358 TEST_F(LibYUVConvertTest, Test565) {
1359 SIMD_ALIGNED(uint8_t orig_pixels[256][4]);
1360 SIMD_ALIGNED(uint8_t pixels565[256][2]);
1361
1362 for (int i = 0; i < 256; ++i) {
1363 for (int j = 0; j < 4; ++j) {
1364 orig_pixels[i][j] = i;
1365 }
1366 }
1367 ARGBToRGB565(&orig_pixels[0][0], 0, &pixels565[0][0], 0, 256, 1);
1368 uint32_t checksum = HashDjb2(&pixels565[0][0], sizeof(pixels565), 5381);
1369 EXPECT_EQ(610919429u, checksum);
1370 }
1371
1372 #ifdef HAVE_JPEG
TEST_F(LibYUVConvertTest,ValidateJpeg)1373 TEST_F(LibYUVConvertTest, ValidateJpeg) {
1374 const int kOff = 10;
1375 const int kMinJpeg = 64;
1376 const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg
1377 ? benchmark_width_ * benchmark_height_
1378 : kMinJpeg;
1379 const int kSize = kImageSize + kOff;
1380 align_buffer_page_end(orig_pixels, kSize);
1381
1382 // No SOI or EOI. Expect fail.
1383 memset(orig_pixels, 0, kSize);
1384 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
1385
1386 // Test special value that matches marker start.
1387 memset(orig_pixels, 0xff, kSize);
1388 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
1389
1390 // EOI, SOI. Expect pass.
1391 orig_pixels[0] = 0xff;
1392 orig_pixels[1] = 0xd8; // SOI.
1393 orig_pixels[2] = 0xff;
1394 orig_pixels[kSize - kOff + 0] = 0xff;
1395 orig_pixels[kSize - kOff + 1] = 0xd9; // EOI.
1396 for (int times = 0; times < benchmark_iterations_; ++times) {
1397 EXPECT_TRUE(ValidateJpeg(orig_pixels, kSize));
1398 }
1399 free_aligned_buffer_page_end(orig_pixels);
1400 }
1401
TEST_F(LibYUVConvertTest,ValidateJpegLarge)1402 TEST_F(LibYUVConvertTest, ValidateJpegLarge) {
1403 const int kOff = 10;
1404 const int kMinJpeg = 64;
1405 const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg
1406 ? benchmark_width_ * benchmark_height_
1407 : kMinJpeg;
1408 const int kSize = kImageSize + kOff;
1409 const int kMultiple = 10;
1410 const int kBufSize = kImageSize * kMultiple + kOff;
1411 align_buffer_page_end(orig_pixels, kBufSize);
1412
1413 // No SOI or EOI. Expect fail.
1414 memset(orig_pixels, 0, kBufSize);
1415 EXPECT_FALSE(ValidateJpeg(orig_pixels, kBufSize));
1416
1417 // EOI, SOI. Expect pass.
1418 orig_pixels[0] = 0xff;
1419 orig_pixels[1] = 0xd8; // SOI.
1420 orig_pixels[2] = 0xff;
1421 orig_pixels[kSize - kOff + 0] = 0xff;
1422 orig_pixels[kSize - kOff + 1] = 0xd9; // EOI.
1423 for (int times = 0; times < benchmark_iterations_; ++times) {
1424 EXPECT_TRUE(ValidateJpeg(orig_pixels, kBufSize));
1425 }
1426 free_aligned_buffer_page_end(orig_pixels);
1427 }
1428
TEST_F(LibYUVConvertTest,InvalidateJpeg)1429 TEST_F(LibYUVConvertTest, InvalidateJpeg) {
1430 const int kOff = 10;
1431 const int kMinJpeg = 64;
1432 const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg
1433 ? benchmark_width_ * benchmark_height_
1434 : kMinJpeg;
1435 const int kSize = kImageSize + kOff;
1436 align_buffer_page_end(orig_pixels, kSize);
1437
1438 // NULL pointer. Expect fail.
1439 EXPECT_FALSE(ValidateJpeg(NULL, kSize));
1440
1441 // Negative size. Expect fail.
1442 EXPECT_FALSE(ValidateJpeg(orig_pixels, -1));
1443
1444 // Too large size. Expect fail.
1445 EXPECT_FALSE(ValidateJpeg(orig_pixels, 0xfb000000ull));
1446
1447 // No SOI or EOI. Expect fail.
1448 memset(orig_pixels, 0, kSize);
1449 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
1450
1451 // SOI but no EOI. Expect fail.
1452 orig_pixels[0] = 0xff;
1453 orig_pixels[1] = 0xd8; // SOI.
1454 orig_pixels[2] = 0xff;
1455 for (int times = 0; times < benchmark_iterations_; ++times) {
1456 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
1457 }
1458
1459 // EOI but no SOI. Expect fail.
1460 orig_pixels[0] = 0;
1461 orig_pixels[1] = 0;
1462 orig_pixels[kSize - kOff + 0] = 0xff;
1463 orig_pixels[kSize - kOff + 1] = 0xd9; // EOI.
1464 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
1465
1466 free_aligned_buffer_page_end(orig_pixels);
1467 }
1468
TEST_F(LibYUVConvertTest,FuzzJpeg)1469 TEST_F(LibYUVConvertTest, FuzzJpeg) {
1470 // SOI but no EOI. Expect fail.
1471 for (int times = 0; times < benchmark_iterations_; ++times) {
1472 const int kSize = fastrand() % 5000 + 3;
1473 align_buffer_page_end(orig_pixels, kSize);
1474 MemRandomize(orig_pixels, kSize);
1475
1476 // Add SOI so frame will be scanned.
1477 orig_pixels[0] = 0xff;
1478 orig_pixels[1] = 0xd8; // SOI.
1479 orig_pixels[2] = 0xff;
1480 orig_pixels[kSize - 1] = 0xff;
1481 ValidateJpeg(orig_pixels,
1482 kSize); // Failure normally expected.
1483 free_aligned_buffer_page_end(orig_pixels);
1484 }
1485 }
1486
1487 // Test data created in GIMP. In export jpeg, disable
1488 // thumbnails etc, choose a subsampling, and use low quality
1489 // (50) to keep size small. Generated with xxd -i test.jpg
1490 // test 0 is J400
1491 static const uint8_t kTest0Jpg[] = {
1492 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
1493 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
1494 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12,
1495 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23,
1496 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40,
1497 0x48, 0x5c, 0x4e, 0x40, 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51,
1498 0x57, 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
1499 0x78, 0x5c, 0x65, 0x67, 0x63, 0xff, 0xc2, 0x00, 0x0b, 0x08, 0x00, 0x10,
1500 0x00, 0x20, 0x01, 0x01, 0x11, 0x00, 0xff, 0xc4, 0x00, 0x17, 0x00, 0x01,
1501 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1502 0x00, 0x00, 0x00, 0x03, 0x04, 0x01, 0x02, 0xff, 0xda, 0x00, 0x08, 0x01,
1503 0x01, 0x00, 0x00, 0x00, 0x01, 0x43, 0x7e, 0xa7, 0x97, 0x57, 0xff, 0xc4,
1504 0x00, 0x1b, 0x10, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00,
1505 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11, 0x00, 0x03,
1506 0x10, 0x12, 0x13, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x05,
1507 0x02, 0x3b, 0xc0, 0x6f, 0x66, 0x76, 0x56, 0x23, 0x87, 0x99, 0x0d, 0x26,
1508 0x62, 0xf6, 0xbf, 0xff, 0xc4, 0x00, 0x1e, 0x10, 0x00, 0x02, 0x01, 0x03,
1509 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1510 0x00, 0x11, 0x21, 0x02, 0x12, 0x32, 0x10, 0x31, 0x71, 0x81, 0xa1, 0xff,
1511 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x06, 0x3f, 0x02, 0x4b, 0xb3, 0x28,
1512 0x32, 0xd2, 0xed, 0xf9, 0x1d, 0x3e, 0x13, 0x51, 0x73, 0x83, 0xff, 0xc4,
1513 0x00, 0x1c, 0x10, 0x01, 0x01, 0x01, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00,
1514 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x21, 0x51,
1515 0x31, 0x61, 0x81, 0xf0, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01,
1516 0x3f, 0x21, 0x65, 0x6e, 0x31, 0x86, 0x28, 0xf9, 0x30, 0xdc, 0x27, 0xdb,
1517 0xa9, 0x01, 0xf3, 0xde, 0x02, 0xa0, 0xed, 0x1e, 0x34, 0x68, 0x23, 0xf9,
1518 0xc6, 0x48, 0x5d, 0x7a, 0x35, 0x02, 0xf5, 0x6f, 0xff, 0xda, 0x00, 0x08,
1519 0x01, 0x01, 0x00, 0x00, 0x00, 0x10, 0x35, 0xff, 0xc4, 0x00, 0x1f, 0x10,
1520 0x01, 0x00, 0x02, 0x01, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1521 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x31, 0x41, 0x61, 0x71, 0x91,
1522 0x21, 0x81, 0xd1, 0xb1, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01,
1523 0x3f, 0x10, 0x0b, 0x30, 0xe9, 0x58, 0xbe, 0x1a, 0xfd, 0x88, 0xab, 0x8b,
1524 0x34, 0x74, 0x80, 0x4b, 0xb5, 0xd5, 0xab, 0xcd, 0x46, 0x96, 0x2e, 0xec,
1525 0xbd, 0xaa, 0x78, 0x47, 0x5c, 0x47, 0xa7, 0x30, 0x49, 0xad, 0x88, 0x7c,
1526 0x40, 0x74, 0x30, 0xff, 0x00, 0x23, 0x1d, 0x03, 0x0b, 0xb7, 0xd4, 0xff,
1527 0xd9};
1528 static const size_t kTest0JpgLen = 421;
1529
1530 // test 1 is J444
1531 static const uint8_t kTest1Jpg[] = {
1532 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
1533 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
1534 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12,
1535 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23,
1536 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40,
1537 0x48, 0x5c, 0x4e, 0x40, 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51,
1538 0x57, 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
1539 0x78, 0x5c, 0x65, 0x67, 0x63, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x11, 0x12,
1540 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
1541 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1542 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1543 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1544 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1545 0x63, 0x63, 0xff, 0xc2, 0x00, 0x11, 0x08, 0x00, 0x10, 0x00, 0x20, 0x03,
1546 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00,
1547 0x17, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1548 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x01, 0x02, 0xff, 0xc4,
1549 0x00, 0x16, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1550 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0xff, 0xda,
1551 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x10, 0x03, 0x10, 0x00, 0x00, 0x01,
1552 0x40, 0x8f, 0x26, 0xe8, 0xf4, 0xcc, 0xf9, 0x69, 0x2b, 0x1b, 0x2a, 0xcb,
1553 0xff, 0xc4, 0x00, 0x1b, 0x10, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00,
1554 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11,
1555 0x00, 0x03, 0x10, 0x12, 0x13, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00,
1556 0x01, 0x05, 0x02, 0x3b, 0x80, 0x6f, 0x56, 0x76, 0x56, 0x23, 0x87, 0x99,
1557 0x0d, 0x26, 0x62, 0xf6, 0xbf, 0xff, 0xc4, 0x00, 0x19, 0x11, 0x01, 0x00,
1558 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1559 0x00, 0x00, 0x01, 0x00, 0x10, 0x11, 0x02, 0x12, 0xff, 0xda, 0x00, 0x08,
1560 0x01, 0x03, 0x01, 0x01, 0x3f, 0x01, 0xf1, 0x00, 0x27, 0x45, 0xbb, 0x31,
1561 0xaf, 0xff, 0xc4, 0x00, 0x1a, 0x11, 0x00, 0x02, 0x03, 0x01, 0x01, 0x00,
1562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1563 0x02, 0x10, 0x11, 0x41, 0x12, 0xff, 0xda, 0x00, 0x08, 0x01, 0x02, 0x01,
1564 0x01, 0x3f, 0x01, 0xf6, 0x4b, 0x5f, 0x48, 0xb3, 0x69, 0x63, 0x35, 0x72,
1565 0xbf, 0xff, 0xc4, 0x00, 0x1e, 0x10, 0x00, 0x02, 0x01, 0x03, 0x05, 0x00,
1566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
1567 0x21, 0x02, 0x12, 0x32, 0x10, 0x31, 0x71, 0x81, 0xa1, 0xff, 0xda, 0x00,
1568 0x08, 0x01, 0x01, 0x00, 0x06, 0x3f, 0x02, 0x4b, 0xb3, 0x28, 0x32, 0xd2,
1569 0xed, 0xf9, 0x1d, 0x3e, 0x13, 0x51, 0x73, 0x83, 0xff, 0xc4, 0x00, 0x1c,
1570 0x10, 0x01, 0x01, 0x01, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
1571 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x21, 0x51, 0x31, 0x61,
1572 0x81, 0xf0, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x3f, 0x21,
1573 0x75, 0x6e, 0x31, 0x94, 0x28, 0xf9, 0x30, 0xdc, 0x27, 0xdb, 0xa9, 0x01,
1574 0xf3, 0xde, 0x02, 0xa0, 0xed, 0x1e, 0x34, 0x68, 0x23, 0xf9, 0xc6, 0x48,
1575 0x5d, 0x7a, 0x35, 0x02, 0xf5, 0x6f, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01,
1576 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x26, 0x61, 0xd4, 0xff,
1577 0xc4, 0x00, 0x1a, 0x11, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00,
1578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x21,
1579 0x31, 0x41, 0x51, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, 0x01, 0x3f,
1580 0x10, 0x54, 0xa8, 0xbf, 0x50, 0x87, 0xb0, 0x9d, 0x8b, 0xc4, 0x6a, 0x26,
1581 0x6b, 0x2a, 0x9c, 0x1f, 0xff, 0xc4, 0x00, 0x18, 0x11, 0x01, 0x01, 0x01,
1582 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1583 0x00, 0x01, 0x00, 0x11, 0x21, 0x51, 0xff, 0xda, 0x00, 0x08, 0x01, 0x02,
1584 0x01, 0x01, 0x3f, 0x10, 0x70, 0xe1, 0x3e, 0xd1, 0x8e, 0x0d, 0xe1, 0xb5,
1585 0xd5, 0x91, 0x76, 0x43, 0x82, 0x45, 0x4c, 0x7b, 0x7f, 0xff, 0xc4, 0x00,
1586 0x1f, 0x10, 0x01, 0x00, 0x02, 0x01, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00,
1587 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x31, 0x41, 0x61,
1588 0x71, 0x91, 0x21, 0x81, 0xd1, 0xb1, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01,
1589 0x00, 0x01, 0x3f, 0x10, 0x1b, 0x30, 0xe9, 0x58, 0xbe, 0x1a, 0xfd, 0x8a,
1590 0xeb, 0x8b, 0x34, 0x74, 0x80, 0x4b, 0xb5, 0xd5, 0xab, 0xcd, 0x46, 0x96,
1591 0x2e, 0xec, 0xbd, 0xaa, 0x78, 0x47, 0x5c, 0x47, 0xa7, 0x30, 0x49, 0xad,
1592 0x88, 0x7c, 0x40, 0x74, 0x30, 0xff, 0x00, 0x23, 0x1d, 0x03, 0x0b, 0xb7,
1593 0xd4, 0xff, 0xd9};
1594 static const size_t kTest1JpgLen = 735;
1595
1596 // test 2 is J420
1597 static const uint8_t kTest2Jpg[] = {
1598 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
1599 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
1600 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12,
1601 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23,
1602 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40,
1603 0x48, 0x5c, 0x4e, 0x40, 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51,
1604 0x57, 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
1605 0x78, 0x5c, 0x65, 0x67, 0x63, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x11, 0x12,
1606 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
1607 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1608 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1609 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1610 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1611 0x63, 0x63, 0xff, 0xc2, 0x00, 0x11, 0x08, 0x00, 0x10, 0x00, 0x20, 0x03,
1612 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00,
1613 0x18, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1614 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x01, 0x02, 0x04, 0xff,
1615 0xc4, 0x00, 0x16, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1616 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x02, 0xff,
1617 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x10, 0x03, 0x10, 0x00, 0x00,
1618 0x01, 0x20, 0xe7, 0x28, 0xa3, 0x0b, 0x2e, 0x2d, 0xcf, 0xff, 0xc4, 0x00,
1619 0x1b, 0x10, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1620 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11, 0x00, 0x03, 0x10,
1621 0x12, 0x13, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x05, 0x02,
1622 0x3b, 0x80, 0x6f, 0x56, 0x76, 0x56, 0x23, 0x87, 0x99, 0x0d, 0x26, 0x62,
1623 0xf6, 0xbf, 0xff, 0xc4, 0x00, 0x17, 0x11, 0x01, 0x00, 0x03, 0x00, 0x00,
1624 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1625 0x01, 0x11, 0x21, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, 0x01, 0x3f,
1626 0x01, 0xc8, 0x53, 0xff, 0xc4, 0x00, 0x16, 0x11, 0x01, 0x01, 0x01, 0x00,
1627 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1628 0x00, 0x11, 0x32, 0xff, 0xda, 0x00, 0x08, 0x01, 0x02, 0x01, 0x01, 0x3f,
1629 0x01, 0xd2, 0xc7, 0xff, 0xc4, 0x00, 0x1e, 0x10, 0x00, 0x02, 0x01, 0x03,
1630 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1631 0x00, 0x11, 0x21, 0x02, 0x12, 0x32, 0x10, 0x31, 0x71, 0x81, 0xa1, 0xff,
1632 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x06, 0x3f, 0x02, 0x4b, 0xb3, 0x28,
1633 0x32, 0xd2, 0xed, 0xf9, 0x1d, 0x3e, 0x13, 0x51, 0x73, 0x83, 0xff, 0xc4,
1634 0x00, 0x1c, 0x10, 0x01, 0x01, 0x01, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00,
1635 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x21, 0x51,
1636 0x31, 0x61, 0x81, 0xf0, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01,
1637 0x3f, 0x21, 0x75, 0x6e, 0x31, 0x94, 0x28, 0xf9, 0x30, 0xdc, 0x27, 0xdb,
1638 0xa9, 0x01, 0xf3, 0xde, 0x02, 0xa0, 0xed, 0x1e, 0x34, 0x68, 0x23, 0xf9,
1639 0xc6, 0x48, 0x5d, 0x7a, 0x35, 0x02, 0xf5, 0x6f, 0xff, 0xda, 0x00, 0x0c,
1640 0x03, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x13, 0x5f,
1641 0xff, 0xc4, 0x00, 0x17, 0x11, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
1642 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11,
1643 0x21, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, 0x01, 0x3f, 0x10, 0x0e,
1644 0xa1, 0x3a, 0x76, 0xff, 0xc4, 0x00, 0x17, 0x11, 0x01, 0x01, 0x01, 0x01,
1645 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1646 0x01, 0x00, 0x21, 0x11, 0xff, 0xda, 0x00, 0x08, 0x01, 0x02, 0x01, 0x01,
1647 0x3f, 0x10, 0x57, 0x0b, 0x08, 0x70, 0xdb, 0xff, 0xc4, 0x00, 0x1f, 0x10,
1648 0x01, 0x00, 0x02, 0x01, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1649 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x31, 0x41, 0x61, 0x71, 0x91,
1650 0x21, 0x81, 0xd1, 0xb1, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01,
1651 0x3f, 0x10, 0x1b, 0x30, 0xe9, 0x58, 0xbe, 0x1a, 0xfd, 0x8a, 0xeb, 0x8b,
1652 0x34, 0x74, 0x80, 0x4b, 0xb5, 0xd5, 0xab, 0xcd, 0x46, 0x96, 0x2e, 0xec,
1653 0xbd, 0xaa, 0x78, 0x47, 0x5c, 0x47, 0xa7, 0x30, 0x49, 0xad, 0x88, 0x7c,
1654 0x40, 0x74, 0x30, 0xff, 0x00, 0x23, 0x1d, 0x03, 0x0b, 0xb7, 0xd4, 0xff,
1655 0xd9};
1656 static const size_t kTest2JpgLen = 685;
1657
1658 // test 3 is J422
1659 static const uint8_t kTest3Jpg[] = {
1660 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
1661 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
1662 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12,
1663 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23,
1664 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40,
1665 0x48, 0x5c, 0x4e, 0x40, 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51,
1666 0x57, 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
1667 0x78, 0x5c, 0x65, 0x67, 0x63, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x11, 0x12,
1668 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
1669 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1670 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1671 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1672 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1673 0x63, 0x63, 0xff, 0xc2, 0x00, 0x11, 0x08, 0x00, 0x10, 0x00, 0x20, 0x03,
1674 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00,
1675 0x17, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x01, 0x02, 0xff, 0xc4,
1677 0x00, 0x17, 0x01, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0xff,
1679 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x10, 0x03, 0x10, 0x00, 0x00,
1680 0x01, 0x43, 0x8d, 0x1f, 0xa2, 0xb3, 0xca, 0x1b, 0x57, 0x0f, 0xff, 0xc4,
1681 0x00, 0x1b, 0x10, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00,
1682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11, 0x00, 0x03,
1683 0x10, 0x12, 0x13, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x05,
1684 0x02, 0x3b, 0x80, 0x6f, 0x56, 0x76, 0x56, 0x23, 0x87, 0x99, 0x0d, 0x26,
1685 0x62, 0xf6, 0xbf, 0xff, 0xc4, 0x00, 0x19, 0x11, 0x00, 0x02, 0x03, 0x01,
1686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1687 0x00, 0x01, 0x02, 0x10, 0x11, 0x21, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03,
1688 0x01, 0x01, 0x3f, 0x01, 0x51, 0xce, 0x8c, 0x75, 0xff, 0xc4, 0x00, 0x18,
1689 0x11, 0x00, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1690 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x61, 0x21, 0xff, 0xda,
1691 0x00, 0x08, 0x01, 0x02, 0x01, 0x01, 0x3f, 0x01, 0xa6, 0xd9, 0x2f, 0x84,
1692 0xe8, 0xf0, 0xff, 0xc4, 0x00, 0x1e, 0x10, 0x00, 0x02, 0x01, 0x03, 0x05,
1693 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1694 0x11, 0x21, 0x02, 0x12, 0x32, 0x10, 0x31, 0x71, 0x81, 0xa1, 0xff, 0xda,
1695 0x00, 0x08, 0x01, 0x01, 0x00, 0x06, 0x3f, 0x02, 0x4b, 0xb3, 0x28, 0x32,
1696 0xd2, 0xed, 0xf9, 0x1d, 0x3e, 0x13, 0x51, 0x73, 0x83, 0xff, 0xc4, 0x00,
1697 0x1c, 0x10, 0x01, 0x01, 0x01, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00,
1698 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x21, 0x51, 0x31,
1699 0x61, 0x81, 0xf0, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x3f,
1700 0x21, 0x75, 0x6e, 0x31, 0x94, 0x28, 0xf9, 0x30, 0xdc, 0x27, 0xdb, 0xa9,
1701 0x01, 0xf3, 0xde, 0x02, 0xa0, 0xed, 0x1e, 0x34, 0x68, 0x23, 0xf9, 0xc6,
1702 0x48, 0x5d, 0x7a, 0x35, 0x02, 0xf5, 0x6f, 0xff, 0xda, 0x00, 0x0c, 0x03,
1703 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x2e, 0x45, 0xff,
1704 0xc4, 0x00, 0x18, 0x11, 0x00, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
1705 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x21,
1706 0x31, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, 0x01, 0x3f, 0x10, 0x53,
1707 0x50, 0xba, 0x54, 0xc1, 0x67, 0x4f, 0xff, 0xc4, 0x00, 0x18, 0x11, 0x00,
1708 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1709 0x00, 0x00, 0x00, 0x01, 0x11, 0x21, 0x00, 0x10, 0xff, 0xda, 0x00, 0x08,
1710 0x01, 0x02, 0x01, 0x01, 0x3f, 0x10, 0x18, 0x81, 0x5c, 0x04, 0x1a, 0xca,
1711 0x91, 0xbf, 0xff, 0xc4, 0x00, 0x1f, 0x10, 0x01, 0x00, 0x02, 0x01, 0x04,
1712 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1713 0x00, 0x11, 0x31, 0x41, 0x61, 0x71, 0x91, 0x21, 0x81, 0xd1, 0xb1, 0xff,
1714 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x3f, 0x10, 0x1b, 0x30, 0xe9,
1715 0x58, 0xbe, 0x1a, 0xfd, 0x8a, 0xeb, 0x8b, 0x34, 0x74, 0x80, 0x4b, 0xb5,
1716 0xd5, 0xab, 0xcd, 0x46, 0x96, 0x2e, 0xec, 0xbd, 0xaa, 0x78, 0x47, 0x5c,
1717 0x47, 0xa7, 0x30, 0x49, 0xad, 0x88, 0x7c, 0x40, 0x74, 0x30, 0xff, 0x00,
1718 0x23, 0x1d, 0x03, 0x0b, 0xb7, 0xd4, 0xff, 0xd9};
1719 static const size_t kTest3JpgLen = 704;
1720
1721 // test 4 is J422 vertical - not supported
1722 static const uint8_t kTest4Jpg[] = {
1723 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
1724 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
1725 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12,
1726 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23,
1727 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40,
1728 0x48, 0x5c, 0x4e, 0x40, 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51,
1729 0x57, 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
1730 0x78, 0x5c, 0x65, 0x67, 0x63, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x11, 0x12,
1731 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
1732 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1733 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1734 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1735 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1736 0x63, 0x63, 0xff, 0xc2, 0x00, 0x11, 0x08, 0x00, 0x10, 0x00, 0x20, 0x03,
1737 0x01, 0x12, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00,
1738 0x18, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1739 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x01, 0x02, 0x03, 0xff,
1740 0xc4, 0x00, 0x16, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1741 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0xff,
1742 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x10, 0x03, 0x10, 0x00, 0x00,
1743 0x01, 0xd2, 0x98, 0xe9, 0x03, 0x0c, 0x00, 0x46, 0x21, 0xd9, 0xff, 0xc4,
1744 0x00, 0x1b, 0x10, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00,
1745 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11, 0x00, 0x03,
1746 0x10, 0x12, 0x13, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x05,
1747 0x02, 0x3b, 0x80, 0x6f, 0x56, 0x76, 0x56, 0x23, 0x87, 0x99, 0x0d, 0x26,
1748 0x62, 0xf6, 0xbf, 0xff, 0xc4, 0x00, 0x17, 0x11, 0x01, 0x01, 0x01, 0x01,
1749 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1750 0x00, 0x11, 0x01, 0x21, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, 0x01,
1751 0x3f, 0x01, 0x98, 0xb1, 0xbd, 0x47, 0xff, 0xc4, 0x00, 0x18, 0x11, 0x00,
1752 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1753 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x11, 0x21, 0xff, 0xda, 0x00, 0x08,
1754 0x01, 0x02, 0x01, 0x01, 0x3f, 0x01, 0xb6, 0x35, 0xa2, 0xe1, 0x47, 0xff,
1755 0xc4, 0x00, 0x1e, 0x10, 0x00, 0x02, 0x01, 0x03, 0x05, 0x00, 0x00, 0x00,
1756 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x21, 0x02,
1757 0x12, 0x32, 0x10, 0x31, 0x71, 0x81, 0xa1, 0xff, 0xda, 0x00, 0x08, 0x01,
1758 0x01, 0x00, 0x06, 0x3f, 0x02, 0x4b, 0xb3, 0x28, 0x32, 0xd2, 0xed, 0xf9,
1759 0x1d, 0x3e, 0x13, 0x51, 0x73, 0x83, 0xff, 0xc4, 0x00, 0x1c, 0x10, 0x01,
1760 0x01, 0x01, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1761 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x21, 0x51, 0x31, 0x61, 0x81, 0xf0,
1762 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x3f, 0x21, 0x75, 0x6e,
1763 0x31, 0x94, 0x28, 0xf9, 0x30, 0xdc, 0x27, 0xdb, 0xa9, 0x01, 0xf3, 0xde,
1764 0x02, 0xa0, 0xed, 0x1e, 0x34, 0x68, 0x23, 0xf9, 0xc6, 0x48, 0x5d, 0x7a,
1765 0x35, 0x02, 0xf5, 0x6f, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
1766 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x24, 0xaf, 0xff, 0xc4, 0x00, 0x19,
1767 0x11, 0x00, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1768 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x51, 0x21, 0x31, 0xff,
1769 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, 0x01, 0x3f, 0x10, 0x59, 0x11, 0xca,
1770 0x42, 0x60, 0x9f, 0x69, 0xff, 0xc4, 0x00, 0x19, 0x11, 0x00, 0x02, 0x03,
1771 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1772 0x00, 0x00, 0x01, 0x11, 0x21, 0x31, 0x61, 0xff, 0xda, 0x00, 0x08, 0x01,
1773 0x02, 0x01, 0x01, 0x3f, 0x10, 0xb0, 0xd7, 0x27, 0x51, 0xb6, 0x41, 0xff,
1774 0xc4, 0x00, 0x1f, 0x10, 0x01, 0x00, 0x02, 0x01, 0x04, 0x03, 0x01, 0x00,
1775 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x31,
1776 0x41, 0x61, 0x71, 0x91, 0x21, 0x81, 0xd1, 0xb1, 0xff, 0xda, 0x00, 0x08,
1777 0x01, 0x01, 0x00, 0x01, 0x3f, 0x10, 0x1b, 0x30, 0xe9, 0x58, 0xbe, 0x1a,
1778 0xfd, 0x8a, 0xeb, 0x8b, 0x34, 0x74, 0x80, 0x4b, 0xb5, 0xd5, 0xab, 0xcd,
1779 0x46, 0x96, 0x2e, 0xec, 0xbd, 0xaa, 0x78, 0x47, 0x5c, 0x47, 0xa7, 0x30,
1780 0x49, 0xad, 0x88, 0x7c, 0x40, 0x74, 0x30, 0xff, 0x00, 0x23, 0x1d, 0x03,
1781 0x0b, 0xb7, 0xd4, 0xff, 0xd9};
1782 static const size_t kTest4JpgLen = 701;
1783
TEST_F(LibYUVConvertTest,TestMJPGSize)1784 TEST_F(LibYUVConvertTest, TestMJPGSize) {
1785 int width = 0;
1786 int height = 0;
1787 int ret = MJPGSize(kTest2Jpg, kTest2JpgLen, &width, &height);
1788 EXPECT_EQ(0, ret);
1789
1790 printf("test jpeg size %d x %d\n", width, height);
1791 }
1792
TEST_F(LibYUVConvertTest,TestMJPGToI420)1793 TEST_F(LibYUVConvertTest, TestMJPGToI420) {
1794 int width = 0;
1795 int height = 0;
1796 int ret = MJPGSize(kTest2Jpg, kTest2JpgLen, &width, &height);
1797 EXPECT_EQ(0, ret);
1798
1799 int half_width = (width + 1) / 2;
1800 int half_height = (height + 1) / 2;
1801 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1802 benchmark_height_ / (width * height);
1803
1804 align_buffer_page_end(dst_y, width * height);
1805 align_buffer_page_end(dst_u, half_width * half_height);
1806 align_buffer_page_end(dst_v, half_width * half_height);
1807 for (int times = 0; times < benchmark_iterations; ++times) {
1808 ret = MJPGToI420(kTest2Jpg, kTest2JpgLen, dst_y, width, dst_u, half_width,
1809 dst_v, half_width, width, height, width, height);
1810 }
1811 // Expect sucesss
1812 EXPECT_EQ(0, ret);
1813
1814 // Test result matches known hash value.
1815 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1816 uint32_t dst_u_hash = HashDjb2(dst_u, half_width * half_height, 5381);
1817 uint32_t dst_v_hash = HashDjb2(dst_v, half_width * half_height, 5381);
1818 EXPECT_EQ(dst_y_hash, 2682851208u);
1819 EXPECT_EQ(dst_u_hash, 2501859930u);
1820 EXPECT_EQ(dst_v_hash, 2126459123u);
1821
1822 free_aligned_buffer_page_end(dst_y);
1823 free_aligned_buffer_page_end(dst_u);
1824 free_aligned_buffer_page_end(dst_v);
1825 }
1826
TEST_F(LibYUVConvertTest,TestMJPGToI420_NV21)1827 TEST_F(LibYUVConvertTest, TestMJPGToI420_NV21) {
1828 int width = 0;
1829 int height = 0;
1830 int ret = MJPGSize(kTest2Jpg, kTest2JpgLen, &width, &height);
1831 EXPECT_EQ(0, ret);
1832
1833 int half_width = (width + 1) / 2;
1834 int half_height = (height + 1) / 2;
1835 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1836 benchmark_height_ / (width * height);
1837
1838 // Convert to NV21
1839 align_buffer_page_end(dst_y, width * height);
1840 align_buffer_page_end(dst_vu, half_width * half_height * 2);
1841
1842 for (int times = 0; times < benchmark_iterations; ++times) {
1843 ret = MJPGToNV21(kTest2Jpg, kTest2JpgLen, dst_y, width, dst_vu,
1844 half_width * 2, width, height, width, height);
1845 }
1846 // Expect sucesss
1847 EXPECT_EQ(0, ret);
1848
1849 // Convert to I420
1850 align_buffer_page_end(dst2_y, width * height);
1851 align_buffer_page_end(dst2_u, half_width * half_height);
1852 align_buffer_page_end(dst2_v, half_width * half_height);
1853 for (int times = 0; times < benchmark_iterations; ++times) {
1854 ret = MJPGToI420(kTest2Jpg, kTest2JpgLen, dst2_y, width, dst2_u, half_width,
1855 dst2_v, half_width, width, height, width, height);
1856 }
1857 // Expect sucesss
1858 EXPECT_EQ(0, ret);
1859
1860 // Convert I420 to NV21
1861 align_buffer_page_end(dst3_y, width * height);
1862 align_buffer_page_end(dst3_vu, half_width * half_height * 2);
1863
1864 I420ToNV21(dst2_y, width, dst2_u, half_width, dst2_v, half_width, dst3_y,
1865 width, dst3_vu, half_width * 2, width, height);
1866
1867 for (int i = 0; i < width * height; ++i) {
1868 EXPECT_EQ(dst_y[i], dst3_y[i]);
1869 }
1870 for (int i = 0; i < half_width * half_height * 2; ++i) {
1871 EXPECT_EQ(dst_vu[i], dst3_vu[i]);
1872 EXPECT_EQ(dst_vu[i], dst3_vu[i]);
1873 }
1874
1875 free_aligned_buffer_page_end(dst3_y);
1876 free_aligned_buffer_page_end(dst3_vu);
1877
1878 free_aligned_buffer_page_end(dst2_y);
1879 free_aligned_buffer_page_end(dst2_u);
1880 free_aligned_buffer_page_end(dst2_v);
1881
1882 free_aligned_buffer_page_end(dst_y);
1883 free_aligned_buffer_page_end(dst_vu);
1884 }
1885
TEST_F(LibYUVConvertTest,TestMJPGToNV21_420)1886 TEST_F(LibYUVConvertTest, TestMJPGToNV21_420) {
1887 int width = 0;
1888 int height = 0;
1889 int ret = MJPGSize(kTest2Jpg, kTest2JpgLen, &width, &height);
1890 EXPECT_EQ(0, ret);
1891
1892 int half_width = (width + 1) / 2;
1893 int half_height = (height + 1) / 2;
1894 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1895 benchmark_height_ / (width * height);
1896
1897 align_buffer_page_end(dst_y, width * height);
1898 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1899 for (int times = 0; times < benchmark_iterations; ++times) {
1900 ret = MJPGToNV21(kTest2Jpg, kTest2JpgLen, dst_y, width, dst_uv,
1901 half_width * 2, width, height, width, height);
1902 }
1903 // Expect sucesss
1904 EXPECT_EQ(0, ret);
1905
1906 // Test result matches known hash value.
1907 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1908 uint32_t dst_uv_hash = HashDjb2(dst_uv, half_width * half_height * 2, 5381);
1909 EXPECT_EQ(dst_y_hash, 2682851208u);
1910 EXPECT_EQ(dst_uv_hash, 1069662856u);
1911
1912 free_aligned_buffer_page_end(dst_y);
1913 free_aligned_buffer_page_end(dst_uv);
1914 }
1915
TEST_F(LibYUVConvertTest,TestMJPGToNV21_422)1916 TEST_F(LibYUVConvertTest, TestMJPGToNV21_422) {
1917 int width = 0;
1918 int height = 0;
1919 int ret = MJPGSize(kTest3Jpg, kTest3JpgLen, &width, &height);
1920 EXPECT_EQ(0, ret);
1921
1922 int half_width = (width + 1) / 2;
1923 int half_height = (height + 1) / 2;
1924 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1925 benchmark_height_ / (width * height);
1926
1927 align_buffer_page_end(dst_y, width * height);
1928 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1929 for (int times = 0; times < benchmark_iterations; ++times) {
1930 ret = MJPGToNV21(kTest3Jpg, kTest3JpgLen, dst_y, width, dst_uv,
1931 half_width * 2, width, height, width, height);
1932 }
1933 // Expect sucesss
1934 EXPECT_EQ(0, ret);
1935
1936 // Test result matches known hash value.
1937 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1938 uint32_t dst_uv_hash = HashDjb2(dst_uv, half_width * half_height * 2, 5381);
1939 EXPECT_EQ(dst_y_hash, 2682851208u);
1940 EXPECT_EQ(dst_uv_hash, 3543430771u);
1941
1942 free_aligned_buffer_page_end(dst_y);
1943 free_aligned_buffer_page_end(dst_uv);
1944 }
1945
TEST_F(LibYUVConvertTest,TestMJPGToNV21_400)1946 TEST_F(LibYUVConvertTest, TestMJPGToNV21_400) {
1947 int width = 0;
1948 int height = 0;
1949 int ret = MJPGSize(kTest0Jpg, kTest0JpgLen, &width, &height);
1950 EXPECT_EQ(0, ret);
1951
1952 int half_width = (width + 1) / 2;
1953 int half_height = (height + 1) / 2;
1954 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1955 benchmark_height_ / (width * height);
1956
1957 align_buffer_page_end(dst_y, width * height);
1958 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1959 for (int times = 0; times < benchmark_iterations; ++times) {
1960 ret = MJPGToNV21(kTest0Jpg, kTest0JpgLen, dst_y, width, dst_uv,
1961 half_width * 2, width, height, width, height);
1962 }
1963 // Expect sucesss
1964 EXPECT_EQ(0, ret);
1965
1966 // Test result matches known hash value.
1967 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1968 uint32_t dst_uv_hash = HashDjb2(dst_uv, half_width * half_height * 2, 5381);
1969 EXPECT_EQ(dst_y_hash, 330644005u);
1970 EXPECT_EQ(dst_uv_hash, 135214341u);
1971
1972 free_aligned_buffer_page_end(dst_y);
1973 free_aligned_buffer_page_end(dst_uv);
1974 }
1975
TEST_F(LibYUVConvertTest,TestMJPGToNV21_444)1976 TEST_F(LibYUVConvertTest, TestMJPGToNV21_444) {
1977 int width = 0;
1978 int height = 0;
1979 int ret = MJPGSize(kTest1Jpg, kTest1JpgLen, &width, &height);
1980 EXPECT_EQ(0, ret);
1981
1982 int half_width = (width + 1) / 2;
1983 int half_height = (height + 1) / 2;
1984 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1985 benchmark_height_ / (width * height);
1986
1987 align_buffer_page_end(dst_y, width * height);
1988 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1989 for (int times = 0; times < benchmark_iterations; ++times) {
1990 ret = MJPGToNV21(kTest1Jpg, kTest1JpgLen, dst_y, width, dst_uv,
1991 half_width * 2, width, height, width, height);
1992 }
1993 // Expect sucesss
1994 EXPECT_EQ(0, ret);
1995
1996 // Test result matches known hash value.
1997 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1998 uint32_t dst_uv_hash = HashDjb2(dst_uv, half_width * half_height * 2, 5381);
1999 EXPECT_EQ(dst_y_hash, 2682851208u);
2000 EXPECT_EQ(dst_uv_hash, 506143297u);
2001
2002 free_aligned_buffer_page_end(dst_y);
2003 free_aligned_buffer_page_end(dst_uv);
2004 }
2005
TEST_F(LibYUVConvertTest,TestMJPGToARGB)2006 TEST_F(LibYUVConvertTest, TestMJPGToARGB) {
2007 int width = 0;
2008 int height = 0;
2009 int ret = MJPGSize(kTest3Jpg, kTest3JpgLen, &width, &height);
2010 EXPECT_EQ(0, ret);
2011
2012 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
2013 benchmark_height_ / (width * height);
2014
2015 align_buffer_page_end(dst_argb, width * height * 4);
2016 for (int times = 0; times < benchmark_iterations; ++times) {
2017 ret = MJPGToARGB(kTest3Jpg, kTest3JpgLen, dst_argb, width * 4, width,
2018 height, width, height);
2019 }
2020 // Expect sucesss
2021 EXPECT_EQ(0, ret);
2022
2023 // Test result matches known hash value.
2024 uint32_t dst_argb_hash = HashDjb2(dst_argb, width * height, 5381);
2025 EXPECT_EQ(dst_argb_hash, 2355976473u);
2026
2027 free_aligned_buffer_page_end(dst_argb);
2028 }
2029
ShowJPegInfo(const uint8_t * sample,size_t sample_size)2030 static int ShowJPegInfo(const uint8_t* sample, size_t sample_size) {
2031 MJpegDecoder mjpeg_decoder;
2032 LIBYUV_BOOL ret = mjpeg_decoder.LoadFrame(sample, sample_size);
2033
2034 int width = mjpeg_decoder.GetWidth();
2035 int height = mjpeg_decoder.GetHeight();
2036
2037 // YUV420
2038 if (mjpeg_decoder.GetColorSpace() == MJpegDecoder::kColorSpaceYCbCr &&
2039 mjpeg_decoder.GetNumComponents() == 3 &&
2040 mjpeg_decoder.GetVertSampFactor(0) == 2 &&
2041 mjpeg_decoder.GetHorizSampFactor(0) == 2 &&
2042 mjpeg_decoder.GetVertSampFactor(1) == 1 &&
2043 mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
2044 mjpeg_decoder.GetVertSampFactor(2) == 1 &&
2045 mjpeg_decoder.GetHorizSampFactor(2) == 1) {
2046 printf("JPeg is J420, %dx%d %d bytes\n", width, height,
2047 static_cast<int>(sample_size));
2048 // YUV422
2049 } else if (mjpeg_decoder.GetColorSpace() == MJpegDecoder::kColorSpaceYCbCr &&
2050 mjpeg_decoder.GetNumComponents() == 3 &&
2051 mjpeg_decoder.GetVertSampFactor(0) == 1 &&
2052 mjpeg_decoder.GetHorizSampFactor(0) == 2 &&
2053 mjpeg_decoder.GetVertSampFactor(1) == 1 &&
2054 mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
2055 mjpeg_decoder.GetVertSampFactor(2) == 1 &&
2056 mjpeg_decoder.GetHorizSampFactor(2) == 1) {
2057 printf("JPeg is J422, %dx%d %d bytes\n", width, height,
2058 static_cast<int>(sample_size));
2059 // YUV444
2060 } else if (mjpeg_decoder.GetColorSpace() == MJpegDecoder::kColorSpaceYCbCr &&
2061 mjpeg_decoder.GetNumComponents() == 3 &&
2062 mjpeg_decoder.GetVertSampFactor(0) == 1 &&
2063 mjpeg_decoder.GetHorizSampFactor(0) == 1 &&
2064 mjpeg_decoder.GetVertSampFactor(1) == 1 &&
2065 mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
2066 mjpeg_decoder.GetVertSampFactor(2) == 1 &&
2067 mjpeg_decoder.GetHorizSampFactor(2) == 1) {
2068 printf("JPeg is J444, %dx%d %d bytes\n", width, height,
2069 static_cast<int>(sample_size));
2070 // YUV400
2071 } else if (mjpeg_decoder.GetColorSpace() ==
2072 MJpegDecoder::kColorSpaceGrayscale &&
2073 mjpeg_decoder.GetNumComponents() == 1 &&
2074 mjpeg_decoder.GetVertSampFactor(0) == 1 &&
2075 mjpeg_decoder.GetHorizSampFactor(0) == 1) {
2076 printf("JPeg is J400, %dx%d %d bytes\n", width, height,
2077 static_cast<int>(sample_size));
2078 } else {
2079 // Unknown colorspace.
2080 printf("JPeg is Unknown colorspace.\n");
2081 }
2082 mjpeg_decoder.UnloadFrame();
2083 return ret;
2084 }
2085
TEST_F(LibYUVConvertTest,TestMJPGInfo)2086 TEST_F(LibYUVConvertTest, TestMJPGInfo) {
2087 EXPECT_EQ(1, ShowJPegInfo(kTest0Jpg, kTest0JpgLen));
2088 EXPECT_EQ(1, ShowJPegInfo(kTest1Jpg, kTest1JpgLen));
2089 EXPECT_EQ(1, ShowJPegInfo(kTest2Jpg, kTest2JpgLen));
2090 EXPECT_EQ(1, ShowJPegInfo(kTest3Jpg, kTest3JpgLen));
2091 EXPECT_EQ(1, ShowJPegInfo(kTest4Jpg,
2092 kTest4JpgLen)); // Valid but unsupported.
2093 }
2094 #endif // HAVE_JPEG
2095
TEST_F(LibYUVConvertTest,NV12Crop)2096 TEST_F(LibYUVConvertTest, NV12Crop) {
2097 const int SUBSAMP_X = 2;
2098 const int SUBSAMP_Y = 2;
2099 const int kWidth = benchmark_width_;
2100 const int kHeight = benchmark_height_;
2101 const int crop_y =
2102 ((benchmark_height_ - (benchmark_height_ * 360 / 480)) / 2 + 1) & ~1;
2103 const int kDestWidth = benchmark_width_;
2104 const int kDestHeight = benchmark_height_ - crop_y * 2;
2105 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X);
2106 const int sample_size =
2107 kWidth * kHeight + kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y) * 2;
2108 align_buffer_page_end(src_y, sample_size);
2109 uint8_t* src_uv = src_y + kWidth * kHeight;
2110
2111 align_buffer_page_end(dst_y, kDestWidth * kDestHeight);
2112 align_buffer_page_end(dst_u, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
2113 SUBSAMPLE(kDestHeight, SUBSAMP_Y));
2114 align_buffer_page_end(dst_v, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
2115 SUBSAMPLE(kDestHeight, SUBSAMP_Y));
2116
2117 align_buffer_page_end(dst_y_2, kDestWidth * kDestHeight);
2118 align_buffer_page_end(dst_u_2, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
2119 SUBSAMPLE(kDestHeight, SUBSAMP_Y));
2120 align_buffer_page_end(dst_v_2, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
2121 SUBSAMPLE(kDestHeight, SUBSAMP_Y));
2122
2123 for (int i = 0; i < kHeight * kWidth; ++i) {
2124 src_y[i] = (fastrand() & 0xff);
2125 }
2126 for (int i = 0; i < (SUBSAMPLE(kHeight, SUBSAMP_Y) * kStrideUV) * 2; ++i) {
2127 src_uv[i] = (fastrand() & 0xff);
2128 }
2129 memset(dst_y, 1, kDestWidth * kDestHeight);
2130 memset(dst_u, 2,
2131 SUBSAMPLE(kDestWidth, SUBSAMP_X) * SUBSAMPLE(kDestHeight, SUBSAMP_Y));
2132 memset(dst_v, 3,
2133 SUBSAMPLE(kDestWidth, SUBSAMP_X) * SUBSAMPLE(kDestHeight, SUBSAMP_Y));
2134 memset(dst_y_2, 1, kDestWidth * kDestHeight);
2135 memset(dst_u_2, 2,
2136 SUBSAMPLE(kDestWidth, SUBSAMP_X) * SUBSAMPLE(kDestHeight, SUBSAMP_Y));
2137 memset(dst_v_2, 3,
2138 SUBSAMPLE(kDestWidth, SUBSAMP_X) * SUBSAMPLE(kDestHeight, SUBSAMP_Y));
2139
2140 ConvertToI420(src_y, sample_size, dst_y_2, kDestWidth, dst_u_2,
2141 SUBSAMPLE(kDestWidth, SUBSAMP_X), dst_v_2,
2142 SUBSAMPLE(kDestWidth, SUBSAMP_X), 0, crop_y, kWidth, kHeight,
2143 kDestWidth, kDestHeight, libyuv::kRotate0, libyuv::FOURCC_NV12);
2144
2145 NV12ToI420(src_y + crop_y * kWidth, kWidth,
2146 src_uv + (crop_y / 2) * kStrideUV * 2, kStrideUV * 2, dst_y,
2147 kDestWidth, dst_u, SUBSAMPLE(kDestWidth, SUBSAMP_X), dst_v,
2148 SUBSAMPLE(kDestWidth, SUBSAMP_X), kDestWidth, kDestHeight);
2149
2150 for (int i = 0; i < kDestHeight; ++i) {
2151 for (int j = 0; j < kDestWidth; ++j) {
2152 EXPECT_EQ(dst_y[i * kWidth + j], dst_y_2[i * kWidth + j]);
2153 }
2154 }
2155 for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) {
2156 for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) {
2157 EXPECT_EQ(dst_u[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j],
2158 dst_u_2[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]);
2159 }
2160 }
2161 for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) {
2162 for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) {
2163 EXPECT_EQ(dst_v[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j],
2164 dst_v_2[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]);
2165 }
2166 }
2167 free_aligned_buffer_page_end(dst_y);
2168 free_aligned_buffer_page_end(dst_u);
2169 free_aligned_buffer_page_end(dst_v);
2170 free_aligned_buffer_page_end(dst_y_2);
2171 free_aligned_buffer_page_end(dst_u_2);
2172 free_aligned_buffer_page_end(dst_v_2);
2173 free_aligned_buffer_page_end(src_y);
2174 }
2175
TEST_F(LibYUVConvertTest,I420CropOddY)2176 TEST_F(LibYUVConvertTest, I420CropOddY) {
2177 const int SUBSAMP_X = 2;
2178 const int SUBSAMP_Y = 2;
2179 const int kWidth = benchmark_width_;
2180 const int kHeight = benchmark_height_;
2181 const int crop_y = 1;
2182 const int kDestWidth = benchmark_width_;
2183 const int kDestHeight = benchmark_height_ - crop_y * 2;
2184 const int kStrideU = SUBSAMPLE(kWidth, SUBSAMP_X);
2185 const int kStrideV = SUBSAMPLE(kWidth, SUBSAMP_X);
2186 const int sample_size = kWidth * kHeight +
2187 kStrideU * SUBSAMPLE(kHeight, SUBSAMP_Y) +
2188 kStrideV * SUBSAMPLE(kHeight, SUBSAMP_Y);
2189 align_buffer_page_end(src_y, sample_size);
2190 uint8_t* src_u = src_y + kWidth * kHeight;
2191 uint8_t* src_v = src_u + kStrideU * SUBSAMPLE(kHeight, SUBSAMP_Y);
2192
2193 align_buffer_page_end(dst_y, kDestWidth * kDestHeight);
2194 align_buffer_page_end(dst_u, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
2195 SUBSAMPLE(kDestHeight, SUBSAMP_Y));
2196 align_buffer_page_end(dst_v, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
2197 SUBSAMPLE(kDestHeight, SUBSAMP_Y));
2198
2199 for (int i = 0; i < kHeight * kWidth; ++i) {
2200 src_y[i] = (fastrand() & 0xff);
2201 }
2202 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y) * kStrideU; ++i) {
2203 src_u[i] = (fastrand() & 0xff);
2204 }
2205 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y) * kStrideV; ++i) {
2206 src_v[i] = (fastrand() & 0xff);
2207 }
2208 memset(dst_y, 1, kDestWidth * kDestHeight);
2209 memset(dst_u, 2,
2210 SUBSAMPLE(kDestWidth, SUBSAMP_X) * SUBSAMPLE(kDestHeight, SUBSAMP_Y));
2211 memset(dst_v, 3,
2212 SUBSAMPLE(kDestWidth, SUBSAMP_X) * SUBSAMPLE(kDestHeight, SUBSAMP_Y));
2213
2214 MaskCpuFlags(benchmark_cpu_info_);
2215 for (int i = 0; i < benchmark_iterations_; ++i) {
2216 ConvertToI420(src_y, sample_size, dst_y, kDestWidth, dst_u,
2217 SUBSAMPLE(kDestWidth, SUBSAMP_X), dst_v,
2218 SUBSAMPLE(kDestWidth, SUBSAMP_X), 0, crop_y, kWidth, kHeight,
2219 kDestWidth, kDestHeight, libyuv::kRotate0,
2220 libyuv::FOURCC_I420);
2221 }
2222
2223 for (int i = 0; i < kDestHeight; ++i) {
2224 for (int j = 0; j < kDestWidth; ++j) {
2225 EXPECT_EQ(src_y[crop_y * kWidth + i * kWidth + j],
2226 dst_y[i * kDestWidth + j]);
2227 }
2228 }
2229 for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) {
2230 for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) {
2231 EXPECT_EQ(src_u[(crop_y / 2 + i) * kStrideU + j],
2232 dst_u[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]);
2233 }
2234 }
2235 for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) {
2236 for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) {
2237 EXPECT_EQ(src_v[(crop_y / 2 + i) * kStrideV + j],
2238 dst_v[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]);
2239 }
2240 }
2241
2242 free_aligned_buffer_page_end(dst_y);
2243 free_aligned_buffer_page_end(dst_u);
2244 free_aligned_buffer_page_end(dst_v);
2245 free_aligned_buffer_page_end(src_y);
2246 }
2247
TEST_F(LibYUVConvertTest,TestYToARGB)2248 TEST_F(LibYUVConvertTest, TestYToARGB) {
2249 uint8_t y[32];
2250 uint8_t expectedg[32];
2251 for (int i = 0; i < 32; ++i) {
2252 y[i] = i * 5 + 17;
2253 expectedg[i] = static_cast<int>((y[i] - 16) * 1.164f + 0.5f);
2254 }
2255 uint8_t argb[32 * 4];
2256 YToARGB(y, 0, argb, 0, 32, 1);
2257
2258 for (int i = 0; i < 32; ++i) {
2259 printf("%2d %d: %d <-> %d,%d,%d,%d\n", i, y[i], expectedg[i],
2260 argb[i * 4 + 0], argb[i * 4 + 1], argb[i * 4 + 2], argb[i * 4 + 3]);
2261 }
2262 for (int i = 0; i < 32; ++i) {
2263 EXPECT_EQ(expectedg[i], argb[i * 4 + 0]);
2264 }
2265 }
2266
2267 static const uint8_t kNoDither4x4[16] = {
2268 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
2269 };
2270
TEST_F(LibYUVConvertTest,TestNoDither)2271 TEST_F(LibYUVConvertTest, TestNoDither) {
2272 align_buffer_page_end(src_argb, benchmark_width_ * benchmark_height_ * 4);
2273 align_buffer_page_end(dst_rgb565, benchmark_width_ * benchmark_height_ * 2);
2274 align_buffer_page_end(dst_rgb565dither,
2275 benchmark_width_ * benchmark_height_ * 2);
2276 MemRandomize(src_argb, benchmark_width_ * benchmark_height_ * 4);
2277 MemRandomize(dst_rgb565, benchmark_width_ * benchmark_height_ * 2);
2278 MemRandomize(dst_rgb565dither, benchmark_width_ * benchmark_height_ * 2);
2279 ARGBToRGB565(src_argb, benchmark_width_ * 4, dst_rgb565, benchmark_width_ * 2,
2280 benchmark_width_, benchmark_height_);
2281 ARGBToRGB565Dither(src_argb, benchmark_width_ * 4, dst_rgb565dither,
2282 benchmark_width_ * 2, kNoDither4x4, benchmark_width_,
2283 benchmark_height_);
2284 for (int i = 0; i < benchmark_width_ * benchmark_height_ * 2; ++i) {
2285 EXPECT_EQ(dst_rgb565[i], dst_rgb565dither[i]);
2286 }
2287
2288 free_aligned_buffer_page_end(src_argb);
2289 free_aligned_buffer_page_end(dst_rgb565);
2290 free_aligned_buffer_page_end(dst_rgb565dither);
2291 }
2292
2293 // Ordered 4x4 dither for 888 to 565. Values from 0 to 7.
2294 static const uint8_t kDither565_4x4[16] = {
2295 0, 4, 1, 5, 6, 2, 7, 3, 1, 5, 0, 4, 7, 3, 6, 2,
2296 };
2297
TEST_F(LibYUVConvertTest,TestDither)2298 TEST_F(LibYUVConvertTest, TestDither) {
2299 align_buffer_page_end(src_argb, benchmark_width_ * benchmark_height_ * 4);
2300 align_buffer_page_end(dst_rgb565, benchmark_width_ * benchmark_height_ * 2);
2301 align_buffer_page_end(dst_rgb565dither,
2302 benchmark_width_ * benchmark_height_ * 2);
2303 align_buffer_page_end(dst_argb, benchmark_width_ * benchmark_height_ * 4);
2304 align_buffer_page_end(dst_argbdither,
2305 benchmark_width_ * benchmark_height_ * 4);
2306 MemRandomize(src_argb, benchmark_width_ * benchmark_height_ * 4);
2307 MemRandomize(dst_rgb565, benchmark_width_ * benchmark_height_ * 2);
2308 MemRandomize(dst_rgb565dither, benchmark_width_ * benchmark_height_ * 2);
2309 MemRandomize(dst_argb, benchmark_width_ * benchmark_height_ * 4);
2310 MemRandomize(dst_argbdither, benchmark_width_ * benchmark_height_ * 4);
2311 ARGBToRGB565(src_argb, benchmark_width_ * 4, dst_rgb565, benchmark_width_ * 2,
2312 benchmark_width_, benchmark_height_);
2313 ARGBToRGB565Dither(src_argb, benchmark_width_ * 4, dst_rgb565dither,
2314 benchmark_width_ * 2, kDither565_4x4, benchmark_width_,
2315 benchmark_height_);
2316 RGB565ToARGB(dst_rgb565, benchmark_width_ * 2, dst_argb, benchmark_width_ * 4,
2317 benchmark_width_, benchmark_height_);
2318 RGB565ToARGB(dst_rgb565dither, benchmark_width_ * 2, dst_argbdither,
2319 benchmark_width_ * 4, benchmark_width_, benchmark_height_);
2320
2321 for (int i = 0; i < benchmark_width_ * benchmark_height_ * 4; ++i) {
2322 EXPECT_NEAR(dst_argb[i], dst_argbdither[i], 9);
2323 }
2324 free_aligned_buffer_page_end(src_argb);
2325 free_aligned_buffer_page_end(dst_rgb565);
2326 free_aligned_buffer_page_end(dst_rgb565dither);
2327 free_aligned_buffer_page_end(dst_argb);
2328 free_aligned_buffer_page_end(dst_argbdither);
2329 }
2330
2331 #define TESTPLANARTOBID(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
2332 YALIGN, W1280, DIFF, N, NEG, OFF, FMT_C, BPP_C) \
2333 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##Dither##N) { \
2334 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
2335 const int kHeight = ALIGNINT(benchmark_height_, YALIGN); \
2336 const int kStrideB = ALIGNINT(kWidth * BPP_B, ALIGN); \
2337 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
2338 const int kSizeUV = kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y); \
2339 align_buffer_page_end(src_y, kWidth* kHeight + OFF); \
2340 align_buffer_page_end(src_u, kSizeUV + OFF); \
2341 align_buffer_page_end(src_v, kSizeUV + OFF); \
2342 align_buffer_page_end(dst_argb_c, kStrideB* kHeight + OFF); \
2343 align_buffer_page_end(dst_argb_opt, kStrideB* kHeight + OFF); \
2344 for (int i = 0; i < kWidth * kHeight; ++i) { \
2345 src_y[i + OFF] = (fastrand() & 0xff); \
2346 } \
2347 for (int i = 0; i < kSizeUV; ++i) { \
2348 src_u[i + OFF] = (fastrand() & 0xff); \
2349 src_v[i + OFF] = (fastrand() & 0xff); \
2350 } \
2351 memset(dst_argb_c + OFF, 1, kStrideB * kHeight); \
2352 memset(dst_argb_opt + OFF, 101, kStrideB * kHeight); \
2353 MaskCpuFlags(disable_cpu_flags_); \
2354 FMT_PLANAR##To##FMT_B##Dither(src_y + OFF, kWidth, src_u + OFF, kStrideUV, \
2355 src_v + OFF, kStrideUV, dst_argb_c + OFF, \
2356 kStrideB, NULL, kWidth, NEG kHeight); \
2357 MaskCpuFlags(benchmark_cpu_info_); \
2358 for (int i = 0; i < benchmark_iterations_; ++i) { \
2359 FMT_PLANAR##To##FMT_B##Dither( \
2360 src_y + OFF, kWidth, src_u + OFF, kStrideUV, src_v + OFF, kStrideUV, \
2361 dst_argb_opt + OFF, kStrideB, NULL, kWidth, NEG kHeight); \
2362 } \
2363 int max_diff = 0; \
2364 /* Convert to ARGB so 565 is expanded to bytes that can be compared. */ \
2365 align_buffer_page_end(dst_argb32_c, kWidth* BPP_C* kHeight); \
2366 align_buffer_page_end(dst_argb32_opt, kWidth* BPP_C* kHeight); \
2367 memset(dst_argb32_c, 2, kWidth* BPP_C* kHeight); \
2368 memset(dst_argb32_opt, 102, kWidth* BPP_C* kHeight); \
2369 FMT_B##To##FMT_C(dst_argb_c + OFF, kStrideB, dst_argb32_c, kWidth * BPP_C, \
2370 kWidth, kHeight); \
2371 FMT_B##To##FMT_C(dst_argb_opt + OFF, kStrideB, dst_argb32_opt, \
2372 kWidth * BPP_C, kWidth, kHeight); \
2373 for (int i = 0; i < kWidth * BPP_C * kHeight; ++i) { \
2374 int abs_diff = abs(static_cast<int>(dst_argb32_c[i]) - \
2375 static_cast<int>(dst_argb32_opt[i])); \
2376 if (abs_diff > max_diff) { \
2377 max_diff = abs_diff; \
2378 } \
2379 } \
2380 EXPECT_LE(max_diff, DIFF); \
2381 free_aligned_buffer_page_end(src_y); \
2382 free_aligned_buffer_page_end(src_u); \
2383 free_aligned_buffer_page_end(src_v); \
2384 free_aligned_buffer_page_end(dst_argb_c); \
2385 free_aligned_buffer_page_end(dst_argb_opt); \
2386 free_aligned_buffer_page_end(dst_argb32_c); \
2387 free_aligned_buffer_page_end(dst_argb32_opt); \
2388 }
2389
2390 #define TESTPLANARTOBD(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
2391 YALIGN, DIFF, FMT_C, BPP_C) \
2392 TESTPLANARTOBID(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
2393 YALIGN, benchmark_width_ - 4, DIFF, _Any, +, 0, FMT_C, \
2394 BPP_C) \
2395 TESTPLANARTOBID(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
2396 YALIGN, benchmark_width_, DIFF, _Unaligned, +, 1, FMT_C, \
2397 BPP_C) \
2398 TESTPLANARTOBID(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
2399 YALIGN, benchmark_width_, DIFF, _Invert, -, 0, FMT_C, BPP_C) \
2400 TESTPLANARTOBID(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
2401 YALIGN, benchmark_width_, DIFF, _Opt, +, 0, FMT_C, BPP_C)
2402
2403 TESTPLANARTOBD(I420, 2, 2, RGB565, 2, 2, 1, 9, ARGB, 4)
2404
2405 #define TESTPTOB(NAME, UYVYTOI420, UYVYTONV12) \
2406 TEST_F(LibYUVConvertTest, NAME) { \
2407 const int kWidth = benchmark_width_; \
2408 const int kHeight = benchmark_height_; \
2409 \
2410 align_buffer_page_end(orig_uyvy, 4 * SUBSAMPLE(kWidth, 2) * kHeight); \
2411 align_buffer_page_end(orig_y, kWidth* kHeight); \
2412 align_buffer_page_end(orig_u, \
2413 SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2)); \
2414 align_buffer_page_end(orig_v, \
2415 SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2)); \
2416 \
2417 align_buffer_page_end(dst_y_orig, kWidth* kHeight); \
2418 align_buffer_page_end(dst_uv_orig, \
2419 2 * SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2)); \
2420 \
2421 align_buffer_page_end(dst_y, kWidth* kHeight); \
2422 align_buffer_page_end(dst_uv, \
2423 2 * SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2)); \
2424 \
2425 MemRandomize(orig_uyvy, 4 * SUBSAMPLE(kWidth, 2) * kHeight); \
2426 \
2427 /* Convert UYVY to NV12 in 2 steps for reference */ \
2428 libyuv::UYVYTOI420(orig_uyvy, 4 * SUBSAMPLE(kWidth, 2), orig_y, kWidth, \
2429 orig_u, SUBSAMPLE(kWidth, 2), orig_v, \
2430 SUBSAMPLE(kWidth, 2), kWidth, kHeight); \
2431 libyuv::I420ToNV12(orig_y, kWidth, orig_u, SUBSAMPLE(kWidth, 2), orig_v, \
2432 SUBSAMPLE(kWidth, 2), dst_y_orig, kWidth, dst_uv_orig, \
2433 2 * SUBSAMPLE(kWidth, 2), kWidth, kHeight); \
2434 \
2435 /* Convert to NV12 */ \
2436 for (int i = 0; i < benchmark_iterations_; ++i) { \
2437 libyuv::UYVYTONV12(orig_uyvy, 4 * SUBSAMPLE(kWidth, 2), dst_y, kWidth, \
2438 dst_uv, 2 * SUBSAMPLE(kWidth, 2), kWidth, kHeight); \
2439 } \
2440 \
2441 for (int i = 0; i < kWidth * kHeight; ++i) { \
2442 EXPECT_EQ(orig_y[i], dst_y[i]); \
2443 } \
2444 for (int i = 0; i < kWidth * kHeight; ++i) { \
2445 EXPECT_EQ(dst_y_orig[i], dst_y[i]); \
2446 } \
2447 for (int i = 0; i < 2 * SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2); \
2448 ++i) { \
2449 EXPECT_EQ(dst_uv_orig[i], dst_uv[i]); \
2450 } \
2451 \
2452 free_aligned_buffer_page_end(orig_uyvy); \
2453 free_aligned_buffer_page_end(orig_y); \
2454 free_aligned_buffer_page_end(orig_u); \
2455 free_aligned_buffer_page_end(orig_v); \
2456 free_aligned_buffer_page_end(dst_y_orig); \
2457 free_aligned_buffer_page_end(dst_uv_orig); \
2458 free_aligned_buffer_page_end(dst_y); \
2459 free_aligned_buffer_page_end(dst_uv); \
2460 }
2461
TESTPTOB(TestYUY2ToNV12,YUY2ToI420,YUY2ToNV12)2462 TESTPTOB(TestYUY2ToNV12, YUY2ToI420, YUY2ToNV12)
2463 TESTPTOB(TestUYVYToNV12, UYVYToI420, UYVYToNV12)
2464
2465 // Transitive tests. A to B to C is same as A to C.
2466
2467 #define TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2468 W1280, N, NEG, OFF, FMT_C, BPP_C) \
2469 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##_##FMT_C##N) { \
2470 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
2471 const int kHeight = benchmark_height_; \
2472 const int kStrideB = SUBSAMPLE(kWidth, SUB_B) * BPP_B; \
2473 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
2474 const int kSizeUV = kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y); \
2475 align_buffer_page_end(src_y, kWidth* kHeight + OFF); \
2476 align_buffer_page_end(src_u, kSizeUV + OFF); \
2477 align_buffer_page_end(src_v, kSizeUV + OFF); \
2478 align_buffer_page_end(dst_argb_b, kStrideB* kHeight + OFF); \
2479 for (int i = 0; i < kWidth * kHeight; ++i) { \
2480 src_y[i + OFF] = (fastrand() & 0xff); \
2481 } \
2482 for (int i = 0; i < kSizeUV; ++i) { \
2483 src_u[i + OFF] = (fastrand() & 0xff); \
2484 src_v[i + OFF] = (fastrand() & 0xff); \
2485 } \
2486 memset(dst_argb_b + OFF, 1, kStrideB * kHeight); \
2487 for (int i = 0; i < benchmark_iterations_; ++i) { \
2488 FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth, src_u + OFF, kStrideUV, \
2489 src_v + OFF, kStrideUV, dst_argb_b + OFF, \
2490 kStrideB, kWidth, NEG kHeight); \
2491 } \
2492 /* Convert to a 3rd format in 1 step and 2 steps and compare */ \
2493 const int kStrideC = kWidth * BPP_C; \
2494 align_buffer_page_end(dst_argb_c, kStrideC* kHeight + OFF); \
2495 align_buffer_page_end(dst_argb_bc, kStrideC* kHeight + OFF); \
2496 memset(dst_argb_c + OFF, 2, kStrideC * kHeight); \
2497 memset(dst_argb_bc + OFF, 3, kStrideC * kHeight); \
2498 FMT_PLANAR##To##FMT_C(src_y + OFF, kWidth, src_u + OFF, kStrideUV, \
2499 src_v + OFF, kStrideUV, dst_argb_c + OFF, kStrideC, \
2500 kWidth, NEG kHeight); \
2501 /* Convert B to C */ \
2502 FMT_B##To##FMT_C(dst_argb_b + OFF, kStrideB, dst_argb_bc + OFF, kStrideC, \
2503 kWidth, kHeight); \
2504 for (int i = 0; i < kStrideC * kHeight; ++i) { \
2505 EXPECT_EQ(dst_argb_c[i + OFF], dst_argb_bc[i + OFF]); \
2506 } \
2507 free_aligned_buffer_page_end(src_y); \
2508 free_aligned_buffer_page_end(src_u); \
2509 free_aligned_buffer_page_end(src_v); \
2510 free_aligned_buffer_page_end(dst_argb_b); \
2511 free_aligned_buffer_page_end(dst_argb_c); \
2512 free_aligned_buffer_page_end(dst_argb_bc); \
2513 }
2514
2515 #define TESTPLANARTOE(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2516 FMT_C, BPP_C) \
2517 TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2518 benchmark_width_ - 4, _Any, +, 0, FMT_C, BPP_C) \
2519 TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2520 benchmark_width_, _Unaligned, +, 1, FMT_C, BPP_C) \
2521 TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2522 benchmark_width_, _Invert, -, 0, FMT_C, BPP_C) \
2523 TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2524 benchmark_width_, _Opt, +, 0, FMT_C, BPP_C)
2525
2526 TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, ABGR, 4)
2527 TESTPLANARTOE(J420, 2, 2, ARGB, 1, 4, ARGB, 4)
2528 TESTPLANARTOE(J420, 2, 2, ABGR, 1, 4, ARGB, 4)
2529 TESTPLANARTOE(H420, 2, 2, ARGB, 1, 4, ARGB, 4)
2530 TESTPLANARTOE(H420, 2, 2, ABGR, 1, 4, ARGB, 4)
2531 TESTPLANARTOE(I420, 2, 2, BGRA, 1, 4, ARGB, 4)
2532 TESTPLANARTOE(I420, 2, 2, ABGR, 1, 4, ARGB, 4)
2533 TESTPLANARTOE(I420, 2, 2, RGBA, 1, 4, ARGB, 4)
2534 TESTPLANARTOE(I420, 2, 2, RGB24, 1, 3, ARGB, 4)
2535 TESTPLANARTOE(I420, 2, 2, RAW, 1, 3, RGB24, 3)
2536 TESTPLANARTOE(I420, 2, 2, RGB24, 1, 3, RAW, 3)
2537 TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, RAW, 3)
2538 TESTPLANARTOE(I420, 2, 2, RAW, 1, 3, ARGB, 4)
2539 TESTPLANARTOE(H420, 2, 2, RGB24, 1, 3, ARGB, 4)
2540 TESTPLANARTOE(H420, 2, 2, RAW, 1, 3, RGB24, 3)
2541 TESTPLANARTOE(H420, 2, 2, RGB24, 1, 3, RAW, 3)
2542 TESTPLANARTOE(H420, 2, 2, ARGB, 1, 4, RAW, 3)
2543 TESTPLANARTOE(H420, 2, 2, RAW, 1, 3, ARGB, 4)
2544 TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, RGB565, 2)
2545 TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, ARGB1555, 2)
2546 TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, ARGB4444, 2)
2547 TESTPLANARTOE(I422, 2, 1, ARGB, 1, 4, RGB565, 2)
2548 TESTPLANARTOE(J422, 2, 1, ARGB, 1, 4, ARGB, 4)
2549 TESTPLANARTOE(J422, 2, 1, ABGR, 1, 4, ARGB, 4)
2550 TESTPLANARTOE(H422, 2, 1, ARGB, 1, 4, ARGB, 4)
2551 TESTPLANARTOE(H422, 2, 1, ABGR, 1, 4, ARGB, 4)
2552 TESTPLANARTOE(I422, 2, 1, BGRA, 1, 4, ARGB, 4)
2553 TESTPLANARTOE(I422, 2, 1, ABGR, 1, 4, ARGB, 4)
2554 TESTPLANARTOE(I422, 2, 1, RGBA, 1, 4, ARGB, 4)
2555 TESTPLANARTOE(I444, 1, 1, ARGB, 1, 4, ARGB, 4)
2556 TESTPLANARTOE(J444, 1, 1, ARGB, 1, 4, ARGB, 4)
2557 TESTPLANARTOE(I444, 1, 1, ABGR, 1, 4, ARGB, 4)
2558 TESTPLANARTOE(I420, 2, 2, YUY2, 2, 4, ARGB, 4)
2559 TESTPLANARTOE(I420, 2, 2, UYVY, 2, 4, ARGB, 4)
2560 TESTPLANARTOE(I422, 2, 1, YUY2, 2, 4, ARGB, 4)
2561 TESTPLANARTOE(I422, 2, 1, UYVY, 2, 4, ARGB, 4)
2562
2563 #define TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2564 W1280, N, NEG, OFF, FMT_C, BPP_C, ATTEN) \
2565 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##_##FMT_C##N) { \
2566 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
2567 const int kHeight = benchmark_height_; \
2568 const int kStrideB = SUBSAMPLE(kWidth, SUB_B) * BPP_B; \
2569 const int kSizeUV = \
2570 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y); \
2571 align_buffer_page_end(src_y, kWidth* kHeight + OFF); \
2572 align_buffer_page_end(src_u, kSizeUV + OFF); \
2573 align_buffer_page_end(src_v, kSizeUV + OFF); \
2574 align_buffer_page_end(src_a, kWidth* kHeight + OFF); \
2575 align_buffer_page_end(dst_argb_b, kStrideB* kHeight + OFF); \
2576 for (int i = 0; i < kWidth * kHeight; ++i) { \
2577 src_y[i + OFF] = (fastrand() & 0xff); \
2578 src_a[i + OFF] = (fastrand() & 0xff); \
2579 } \
2580 for (int i = 0; i < kSizeUV; ++i) { \
2581 src_u[i + OFF] = (fastrand() & 0xff); \
2582 src_v[i + OFF] = (fastrand() & 0xff); \
2583 } \
2584 memset(dst_argb_b + OFF, 1, kStrideB * kHeight); \
2585 for (int i = 0; i < benchmark_iterations_; ++i) { \
2586 FMT_PLANAR##To##FMT_B( \
2587 src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), \
2588 src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), src_a + OFF, kWidth, \
2589 dst_argb_b + OFF, kStrideB, kWidth, NEG kHeight, ATTEN); \
2590 } \
2591 /* Convert to a 3rd format in 1 step and 2 steps and compare */ \
2592 const int kStrideC = kWidth * BPP_C; \
2593 align_buffer_page_end(dst_argb_c, kStrideC* kHeight + OFF); \
2594 align_buffer_page_end(dst_argb_bc, kStrideC* kHeight + OFF); \
2595 memset(dst_argb_c + OFF, 2, kStrideC * kHeight); \
2596 memset(dst_argb_bc + OFF, 3, kStrideC * kHeight); \
2597 FMT_PLANAR##To##FMT_C( \
2598 src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), \
2599 src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X), src_a + OFF, kWidth, \
2600 dst_argb_c + OFF, kStrideC, kWidth, NEG kHeight, ATTEN); \
2601 /* Convert B to C */ \
2602 FMT_B##To##FMT_C(dst_argb_b + OFF, kStrideB, dst_argb_bc + OFF, kStrideC, \
2603 kWidth, kHeight); \
2604 for (int i = 0; i < kStrideC * kHeight; ++i) { \
2605 EXPECT_EQ(dst_argb_c[i + OFF], dst_argb_bc[i + OFF]); \
2606 } \
2607 free_aligned_buffer_page_end(src_y); \
2608 free_aligned_buffer_page_end(src_u); \
2609 free_aligned_buffer_page_end(src_v); \
2610 free_aligned_buffer_page_end(src_a); \
2611 free_aligned_buffer_page_end(dst_argb_b); \
2612 free_aligned_buffer_page_end(dst_argb_c); \
2613 free_aligned_buffer_page_end(dst_argb_bc); \
2614 }
2615
2616 #define TESTQPLANARTOE(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2617 FMT_C, BPP_C) \
2618 TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2619 benchmark_width_ - 4, _Any, +, 0, FMT_C, BPP_C, 0) \
2620 TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2621 benchmark_width_, _Unaligned, +, 1, FMT_C, BPP_C, 0) \
2622 TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2623 benchmark_width_, _Invert, -, 0, FMT_C, BPP_C, 0) \
2624 TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2625 benchmark_width_, _Opt, +, 0, FMT_C, BPP_C, 0) \
2626 TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
2627 benchmark_width_, _Premult, +, 0, FMT_C, BPP_C, 1)
2628
2629 TESTQPLANARTOE(I420Alpha, 2, 2, ARGB, 1, 4, ABGR, 4)
2630 TESTQPLANARTOE(I420Alpha, 2, 2, ABGR, 1, 4, ARGB, 4)
2631
2632 #define TESTPLANETOEI(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, W1280, N, NEG, \
2633 OFF, FMT_C, BPP_C) \
2634 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_B##_##FMT_C##N) { \
2635 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
2636 const int kHeight = benchmark_height_; \
2637 const int kStrideA = SUBSAMPLE(kWidth, SUB_A) * BPP_A; \
2638 const int kStrideB = SUBSAMPLE(kWidth, SUB_B) * BPP_B; \
2639 align_buffer_page_end(src_argb_a, kStrideA* kHeight + OFF); \
2640 align_buffer_page_end(dst_argb_b, kStrideB* kHeight + OFF); \
2641 MemRandomize(src_argb_a + OFF, kStrideA * kHeight); \
2642 memset(dst_argb_b + OFF, 1, kStrideB * kHeight); \
2643 for (int i = 0; i < benchmark_iterations_; ++i) { \
2644 FMT_A##To##FMT_B(src_argb_a + OFF, kStrideA, dst_argb_b + OFF, kStrideB, \
2645 kWidth, NEG kHeight); \
2646 } \
2647 /* Convert to a 3rd format in 1 step and 2 steps and compare */ \
2648 const int kStrideC = kWidth * BPP_C; \
2649 align_buffer_page_end(dst_argb_c, kStrideC* kHeight + OFF); \
2650 align_buffer_page_end(dst_argb_bc, kStrideC* kHeight + OFF); \
2651 memset(dst_argb_c + OFF, 2, kStrideC * kHeight); \
2652 memset(dst_argb_bc + OFF, 3, kStrideC * kHeight); \
2653 FMT_A##To##FMT_C(src_argb_a + OFF, kStrideA, dst_argb_c + OFF, kStrideC, \
2654 kWidth, NEG kHeight); \
2655 /* Convert B to C */ \
2656 FMT_B##To##FMT_C(dst_argb_b + OFF, kStrideB, dst_argb_bc + OFF, kStrideC, \
2657 kWidth, kHeight); \
2658 for (int i = 0; i < kStrideC * kHeight; i += 4) { \
2659 EXPECT_EQ(dst_argb_c[i + OFF + 0], dst_argb_bc[i + OFF + 0]); \
2660 EXPECT_EQ(dst_argb_c[i + OFF + 1], dst_argb_bc[i + OFF + 1]); \
2661 EXPECT_EQ(dst_argb_c[i + OFF + 2], dst_argb_bc[i + OFF + 2]); \
2662 EXPECT_NEAR(dst_argb_c[i + OFF + 3], dst_argb_bc[i + OFF + 3], 64); \
2663 } \
2664 free_aligned_buffer_page_end(src_argb_a); \
2665 free_aligned_buffer_page_end(dst_argb_b); \
2666 free_aligned_buffer_page_end(dst_argb_c); \
2667 free_aligned_buffer_page_end(dst_argb_bc); \
2668 }
2669
2670 #define TESTPLANETOE(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, FMT_C, BPP_C) \
2671 TESTPLANETOEI(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, \
2672 benchmark_width_ - 4, _Any, +, 0, FMT_C, BPP_C) \
2673 TESTPLANETOEI(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, benchmark_width_, \
2674 _Unaligned, +, 1, FMT_C, BPP_C) \
2675 TESTPLANETOEI(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, benchmark_width_, \
2676 _Invert, -, 0, FMT_C, BPP_C) \
2677 TESTPLANETOEI(FMT_A, SUB_A, BPP_A, FMT_B, SUB_B, BPP_B, benchmark_width_, \
2678 _Opt, +, 0, FMT_C, BPP_C)
2679
2680 // Caveat: Destination needs to be 4 bytes
2681 TESTPLANETOE(ARGB, 1, 4, AR30, 1, 4, ARGB, 4)
2682 TESTPLANETOE(ABGR, 1, 4, AR30, 1, 4, ABGR, 4)
2683 TESTPLANETOE(AR30, 1, 4, ARGB, 1, 4, ABGR, 4)
2684 TESTPLANETOE(AR30, 1, 4, ABGR, 1, 4, ARGB, 4)
2685 TESTPLANETOE(ARGB, 1, 4, AB30, 1, 4, ARGB, 4)
2686 TESTPLANETOE(ABGR, 1, 4, AB30, 1, 4, ABGR, 4)
2687 TESTPLANETOE(AB30, 1, 4, ARGB, 1, 4, ABGR, 4)
2688 TESTPLANETOE(AB30, 1, 4, ABGR, 1, 4, ARGB, 4)
2689
2690 TEST_F(LibYUVConvertTest, RotateWithARGBSource) {
2691 // 2x2 frames
2692 uint32_t src[4];
2693 uint32_t dst[4];
2694 // some random input
2695 src[0] = 0x11000000;
2696 src[1] = 0x00450000;
2697 src[2] = 0x00009f00;
2698 src[3] = 0x000000ff;
2699 // zeros on destination
2700 dst[0] = 0x00000000;
2701 dst[1] = 0x00000000;
2702 dst[2] = 0x00000000;
2703 dst[3] = 0x00000000;
2704
2705 int r = ConvertToARGB(reinterpret_cast<uint8_t*>(src),
2706 16, // input size
2707 reinterpret_cast<uint8_t*>(dst),
2708 8, // destination stride
2709 0, // crop_x
2710 0, // crop_y
2711 2, // width
2712 2, // height
2713 2, // crop width
2714 2, // crop height
2715 kRotate90, FOURCC_ARGB);
2716
2717 EXPECT_EQ(r, 0);
2718 // 90 degrees rotation, no conversion
2719 EXPECT_EQ(dst[0], src[2]);
2720 EXPECT_EQ(dst[1], src[0]);
2721 EXPECT_EQ(dst[2], src[3]);
2722 EXPECT_EQ(dst[3], src[1]);
2723 }
2724
2725 #ifdef HAS_ARGBTOAR30ROW_AVX2
TEST_F(LibYUVConvertTest,ARGBToAR30Row_Opt)2726 TEST_F(LibYUVConvertTest, ARGBToAR30Row_Opt) {
2727 // ARGBToAR30Row_AVX2 expects a multiple of 8 pixels.
2728 const int kPixels = (benchmark_width_ * benchmark_height_ + 7) & ~7;
2729 align_buffer_page_end(src, kPixels * 4);
2730 align_buffer_page_end(dst_opt, kPixels * 4);
2731 align_buffer_page_end(dst_c, kPixels * 4);
2732 MemRandomize(src, kPixels * 4);
2733 memset(dst_opt, 0, kPixels * 4);
2734 memset(dst_c, 1, kPixels * 4);
2735
2736 ARGBToAR30Row_C(src, dst_c, kPixels);
2737
2738 int has_avx2 = TestCpuFlag(kCpuHasAVX2);
2739 int has_ssse3 = TestCpuFlag(kCpuHasSSSE3);
2740 for (int i = 0; i < benchmark_iterations_; ++i) {
2741 if (has_avx2) {
2742 ARGBToAR30Row_AVX2(src, dst_opt, kPixels);
2743 } else if (has_ssse3) {
2744 ARGBToAR30Row_SSSE3(src, dst_opt, kPixels);
2745 } else {
2746 ARGBToAR30Row_C(src, dst_opt, kPixels);
2747 }
2748 }
2749 for (int i = 0; i < kPixels * 4; ++i) {
2750 EXPECT_EQ(dst_opt[i], dst_c[i]);
2751 }
2752
2753 free_aligned_buffer_page_end(src);
2754 free_aligned_buffer_page_end(dst_opt);
2755 free_aligned_buffer_page_end(dst_c);
2756 }
2757 #endif // HAS_ARGBTOAR30ROW_AVX2
2758
2759 #ifdef HAS_ABGRTOAR30ROW_AVX2
TEST_F(LibYUVConvertTest,ABGRToAR30Row_Opt)2760 TEST_F(LibYUVConvertTest, ABGRToAR30Row_Opt) {
2761 // ABGRToAR30Row_AVX2 expects a multiple of 8 pixels.
2762 const int kPixels = (benchmark_width_ * benchmark_height_ + 7) & ~7;
2763 align_buffer_page_end(src, kPixels * 4);
2764 align_buffer_page_end(dst_opt, kPixels * 4);
2765 align_buffer_page_end(dst_c, kPixels * 4);
2766 MemRandomize(src, kPixels * 4);
2767 memset(dst_opt, 0, kPixels * 4);
2768 memset(dst_c, 1, kPixels * 4);
2769
2770 ABGRToAR30Row_C(src, dst_c, kPixels);
2771
2772 int has_avx2 = TestCpuFlag(kCpuHasAVX2);
2773 int has_ssse3 = TestCpuFlag(kCpuHasSSSE3);
2774 for (int i = 0; i < benchmark_iterations_; ++i) {
2775 if (has_avx2) {
2776 ABGRToAR30Row_AVX2(src, dst_opt, kPixels);
2777 } else if (has_ssse3) {
2778 ABGRToAR30Row_SSSE3(src, dst_opt, kPixels);
2779 } else {
2780 ABGRToAR30Row_C(src, dst_opt, kPixels);
2781 }
2782 }
2783 for (int i = 0; i < kPixels * 4; ++i) {
2784 EXPECT_EQ(dst_opt[i], dst_c[i]);
2785 }
2786
2787 free_aligned_buffer_page_end(src);
2788 free_aligned_buffer_page_end(dst_opt);
2789 free_aligned_buffer_page_end(dst_c);
2790 }
2791 #endif // HAS_ABGRTOAR30ROW_AVX2
2792
2793 // TODO(fbarchard): Fix clamping issue affected by U channel.
2794 #define TESTPLANAR16TOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, \
2795 ALIGN, YALIGN, W1280, DIFF, N, NEG, SOFF, DOFF) \
2796 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##N) { \
2797 const int kWidth = ((W1280) > 0) ? (W1280) : 1; \
2798 const int kHeight = ALIGNINT(benchmark_height_, YALIGN); \
2799 const int kStrideB = ALIGNINT(kWidth * BPP_B, ALIGN); \
2800 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
2801 const int kSizeUV = kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y); \
2802 const int kBpc = 2; \
2803 align_buffer_page_end(src_y, kWidth* kHeight* kBpc + SOFF); \
2804 align_buffer_page_end(src_u, kSizeUV* kBpc + SOFF); \
2805 align_buffer_page_end(src_v, kSizeUV* kBpc + SOFF); \
2806 align_buffer_page_end(dst_argb_c, kStrideB* kHeight + DOFF); \
2807 align_buffer_page_end(dst_argb_opt, kStrideB* kHeight + DOFF); \
2808 for (int i = 0; i < kWidth * kHeight; ++i) { \
2809 reinterpret_cast<uint16_t*>(src_y + SOFF)[i] = (fastrand() & 0x3ff); \
2810 } \
2811 for (int i = 0; i < kSizeUV; ++i) { \
2812 reinterpret_cast<uint16_t*>(src_u + SOFF)[i] = (fastrand() & 0x3ff); \
2813 reinterpret_cast<uint16_t*>(src_v + SOFF)[i] = (fastrand() & 0x3ff); \
2814 } \
2815 memset(dst_argb_c + DOFF, 1, kStrideB * kHeight); \
2816 memset(dst_argb_opt + DOFF, 101, kStrideB * kHeight); \
2817 MaskCpuFlags(disable_cpu_flags_); \
2818 FMT_PLANAR##To##FMT_B( \
2819 reinterpret_cast<uint16_t*>(src_y + SOFF), kWidth, \
2820 reinterpret_cast<uint16_t*>(src_u + SOFF), kStrideUV, \
2821 reinterpret_cast<uint16_t*>(src_v + SOFF), kStrideUV, \
2822 dst_argb_c + DOFF, kStrideB, kWidth, NEG kHeight); \
2823 MaskCpuFlags(benchmark_cpu_info_); \
2824 for (int i = 0; i < benchmark_iterations_; ++i) { \
2825 FMT_PLANAR##To##FMT_B( \
2826 reinterpret_cast<uint16_t*>(src_y + SOFF), kWidth, \
2827 reinterpret_cast<uint16_t*>(src_u + SOFF), kStrideUV, \
2828 reinterpret_cast<uint16_t*>(src_v + SOFF), kStrideUV, \
2829 dst_argb_opt + DOFF, kStrideB, kWidth, NEG kHeight); \
2830 } \
2831 int max_diff = 0; \
2832 for (int i = 0; i < kWidth * BPP_B * kHeight; ++i) { \
2833 int abs_diff = abs(static_cast<int>(dst_argb_c[i + DOFF]) - \
2834 static_cast<int>(dst_argb_opt[i + DOFF])); \
2835 if (abs_diff > max_diff) { \
2836 max_diff = abs_diff; \
2837 } \
2838 } \
2839 EXPECT_LE(max_diff, DIFF); \
2840 free_aligned_buffer_page_end(src_y); \
2841 free_aligned_buffer_page_end(src_u); \
2842 free_aligned_buffer_page_end(src_v); \
2843 free_aligned_buffer_page_end(dst_argb_c); \
2844 free_aligned_buffer_page_end(dst_argb_opt); \
2845 }
2846
2847 #define TESTPLANAR16TOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
2848 YALIGN, DIFF) \
2849 TESTPLANAR16TOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
2850 YALIGN, benchmark_width_ - 4, DIFF, _Any, +, 0, 0) \
2851 TESTPLANAR16TOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
2852 YALIGN, benchmark_width_, DIFF, _Unaligned, +, 1, 1) \
2853 TESTPLANAR16TOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
2854 YALIGN, benchmark_width_, DIFF, _Invert, -, 0, 0) \
2855 TESTPLANAR16TOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
2856 YALIGN, benchmark_width_, DIFF, _Opt, +, 0, 0)
2857
2858 TESTPLANAR16TOB(I010, 2, 2, ARGB, 4, 4, 1, 2)
2859 TESTPLANAR16TOB(I010, 2, 2, ABGR, 4, 4, 1, 2)
2860 TESTPLANAR16TOB(I010, 2, 2, AR30, 4, 4, 1, 2)
2861 TESTPLANAR16TOB(I010, 2, 2, AB30, 4, 4, 1, 2)
2862 TESTPLANAR16TOB(H010, 2, 2, ARGB, 4, 4, 1, 2)
2863 TESTPLANAR16TOB(H010, 2, 2, ABGR, 4, 4, 1, 2)
2864 TESTPLANAR16TOB(H010, 2, 2, AR30, 4, 4, 1, 2)
2865 TESTPLANAR16TOB(H010, 2, 2, AB30, 4, 4, 1, 2)
2866
Clamp(int y)2867 static int Clamp(int y) {
2868 if (y < 0) {
2869 y = 0;
2870 }
2871 if (y > 255) {
2872 y = 255;
2873 }
2874 return y;
2875 }
2876
Clamp10(int y)2877 static int Clamp10(int y) {
2878 if (y < 0) {
2879 y = 0;
2880 }
2881 if (y > 1023) {
2882 y = 1023;
2883 }
2884 return y;
2885 }
2886
2887 // Test 8 bit YUV to 8 bit RGB
TEST_F(LibYUVConvertTest,TestH420ToARGB)2888 TEST_F(LibYUVConvertTest, TestH420ToARGB) {
2889 const int kSize = 256;
2890 int histogram_b[256];
2891 int histogram_g[256];
2892 int histogram_r[256];
2893 memset(histogram_b, 0, sizeof(histogram_b));
2894 memset(histogram_g, 0, sizeof(histogram_g));
2895 memset(histogram_r, 0, sizeof(histogram_r));
2896 align_buffer_page_end(orig_yuv, kSize + kSize / 2 * 2);
2897 align_buffer_page_end(argb_pixels, kSize * 4);
2898 uint8_t* orig_y = orig_yuv;
2899 uint8_t* orig_u = orig_y + kSize;
2900 uint8_t* orig_v = orig_u + kSize / 2;
2901
2902 // Test grey scale
2903 for (int i = 0; i < kSize; ++i) {
2904 orig_y[i] = i;
2905 }
2906 for (int i = 0; i < kSize / 2; ++i) {
2907 orig_u[i] = 128; // 128 is 0.
2908 orig_v[i] = 128;
2909 }
2910
2911 H420ToARGB(orig_y, 0, orig_u, 0, orig_v, 0, argb_pixels, 0, kSize, 1);
2912
2913 for (int i = 0; i < kSize; ++i) {
2914 int b = argb_pixels[i * 4 + 0];
2915 int g = argb_pixels[i * 4 + 1];
2916 int r = argb_pixels[i * 4 + 2];
2917 int a = argb_pixels[i * 4 + 3];
2918 ++histogram_b[b];
2919 ++histogram_g[g];
2920 ++histogram_r[r];
2921 int expected_y = Clamp(static_cast<int>((i - 16) * 1.164f));
2922 EXPECT_NEAR(b, expected_y, 1);
2923 EXPECT_NEAR(g, expected_y, 1);
2924 EXPECT_NEAR(r, expected_y, 1);
2925 EXPECT_EQ(a, 255);
2926 }
2927
2928 int count_b = 0;
2929 int count_g = 0;
2930 int count_r = 0;
2931 for (int i = 0; i < kSize; ++i) {
2932 if (histogram_b[i]) {
2933 ++count_b;
2934 }
2935 if (histogram_g[i]) {
2936 ++count_g;
2937 }
2938 if (histogram_r[i]) {
2939 ++count_r;
2940 }
2941 }
2942 printf("uniques: B %d, G, %d, R %d\n", count_b, count_g, count_r);
2943
2944 free_aligned_buffer_page_end(orig_yuv);
2945 free_aligned_buffer_page_end(argb_pixels);
2946 }
2947
2948 // Test 10 bit YUV to 8 bit RGB
TEST_F(LibYUVConvertTest,TestH010ToARGB)2949 TEST_F(LibYUVConvertTest, TestH010ToARGB) {
2950 const int kSize = 1024;
2951 int histogram_b[1024];
2952 int histogram_g[1024];
2953 int histogram_r[1024];
2954 memset(histogram_b, 0, sizeof(histogram_b));
2955 memset(histogram_g, 0, sizeof(histogram_g));
2956 memset(histogram_r, 0, sizeof(histogram_r));
2957 align_buffer_page_end(orig_yuv, kSize * 2 + kSize / 2 * 2 * 2);
2958 align_buffer_page_end(argb_pixels, kSize * 4);
2959 uint16_t* orig_y = reinterpret_cast<uint16_t*>(orig_yuv);
2960 uint16_t* orig_u = orig_y + kSize;
2961 uint16_t* orig_v = orig_u + kSize / 2;
2962
2963 // Test grey scale
2964 for (int i = 0; i < kSize; ++i) {
2965 orig_y[i] = i;
2966 }
2967 for (int i = 0; i < kSize / 2; ++i) {
2968 orig_u[i] = 512; // 512 is 0.
2969 orig_v[i] = 512;
2970 }
2971
2972 H010ToARGB(orig_y, 0, orig_u, 0, orig_v, 0, argb_pixels, 0, kSize, 1);
2973
2974 for (int i = 0; i < kSize; ++i) {
2975 int b = argb_pixels[i * 4 + 0];
2976 int g = argb_pixels[i * 4 + 1];
2977 int r = argb_pixels[i * 4 + 2];
2978 int a = argb_pixels[i * 4 + 3];
2979 ++histogram_b[b];
2980 ++histogram_g[g];
2981 ++histogram_r[r];
2982 int expected_y = Clamp(static_cast<int>((i - 64) * 1.164f / 4));
2983 EXPECT_NEAR(b, expected_y, 1);
2984 EXPECT_NEAR(g, expected_y, 1);
2985 EXPECT_NEAR(r, expected_y, 1);
2986 EXPECT_EQ(a, 255);
2987 }
2988
2989 int count_b = 0;
2990 int count_g = 0;
2991 int count_r = 0;
2992 for (int i = 0; i < kSize; ++i) {
2993 if (histogram_b[i]) {
2994 ++count_b;
2995 }
2996 if (histogram_g[i]) {
2997 ++count_g;
2998 }
2999 if (histogram_r[i]) {
3000 ++count_r;
3001 }
3002 }
3003 printf("uniques: B %d, G, %d, R %d\n", count_b, count_g, count_r);
3004
3005 free_aligned_buffer_page_end(orig_yuv);
3006 free_aligned_buffer_page_end(argb_pixels);
3007 }
3008
3009 // Test 10 bit YUV to 10 bit RGB
3010 // Caveat: Result is near due to float rounding in expected
3011 // result.
TEST_F(LibYUVConvertTest,TestH010ToAR30)3012 TEST_F(LibYUVConvertTest, TestH010ToAR30) {
3013 const int kSize = 1024;
3014 int histogram_b[1024];
3015 int histogram_g[1024];
3016 int histogram_r[1024];
3017 memset(histogram_b, 0, sizeof(histogram_b));
3018 memset(histogram_g, 0, sizeof(histogram_g));
3019 memset(histogram_r, 0, sizeof(histogram_r));
3020
3021 align_buffer_page_end(orig_yuv, kSize * 2 + kSize / 2 * 2 * 2);
3022 align_buffer_page_end(ar30_pixels, kSize * 4);
3023 uint16_t* orig_y = reinterpret_cast<uint16_t*>(orig_yuv);
3024 uint16_t* orig_u = orig_y + kSize;
3025 uint16_t* orig_v = orig_u + kSize / 2;
3026
3027 // Test grey scale
3028 for (int i = 0; i < kSize; ++i) {
3029 orig_y[i] = i;
3030 }
3031 for (int i = 0; i < kSize / 2; ++i) {
3032 orig_u[i] = 512; // 512 is 0.
3033 orig_v[i] = 512;
3034 }
3035
3036 H010ToAR30(orig_y, 0, orig_u, 0, orig_v, 0, ar30_pixels, 0, kSize, 1);
3037
3038 for (int i = 0; i < kSize; ++i) {
3039 int b10 = reinterpret_cast<uint32_t*>(ar30_pixels)[i] & 1023;
3040 int g10 = (reinterpret_cast<uint32_t*>(ar30_pixels)[i] >> 10) & 1023;
3041 int r10 = (reinterpret_cast<uint32_t*>(ar30_pixels)[i] >> 20) & 1023;
3042 int a2 = (reinterpret_cast<uint32_t*>(ar30_pixels)[i] >> 30) & 3;
3043 ++histogram_b[b10];
3044 ++histogram_g[g10];
3045 ++histogram_r[r10];
3046 int expected_y = Clamp10(static_cast<int>((i - 64) * 1.164f));
3047 EXPECT_NEAR(b10, expected_y, 4);
3048 EXPECT_NEAR(g10, expected_y, 4);
3049 EXPECT_NEAR(r10, expected_y, 4);
3050 EXPECT_EQ(a2, 3);
3051 }
3052
3053 int count_b = 0;
3054 int count_g = 0;
3055 int count_r = 0;
3056 for (int i = 0; i < kSize; ++i) {
3057 if (histogram_b[i]) {
3058 ++count_b;
3059 }
3060 if (histogram_g[i]) {
3061 ++count_g;
3062 }
3063 if (histogram_r[i]) {
3064 ++count_r;
3065 }
3066 }
3067 printf("uniques: B %d, G, %d, R %d\n", count_b, count_g, count_r);
3068
3069 free_aligned_buffer_page_end(orig_yuv);
3070 free_aligned_buffer_page_end(ar30_pixels);
3071 }
3072
3073 // Test 10 bit YUV to 10 bit RGB
3074 // Caveat: Result is near due to float rounding in expected
3075 // result.
TEST_F(LibYUVConvertTest,TestH010ToAB30)3076 TEST_F(LibYUVConvertTest, TestH010ToAB30) {
3077 const int kSize = 1024;
3078 int histogram_b[1024];
3079 int histogram_g[1024];
3080 int histogram_r[1024];
3081 memset(histogram_b, 0, sizeof(histogram_b));
3082 memset(histogram_g, 0, sizeof(histogram_g));
3083 memset(histogram_r, 0, sizeof(histogram_r));
3084
3085 align_buffer_page_end(orig_yuv, kSize * 2 + kSize / 2 * 2 * 2);
3086 align_buffer_page_end(ab30_pixels, kSize * 4);
3087 uint16_t* orig_y = reinterpret_cast<uint16_t*>(orig_yuv);
3088 uint16_t* orig_u = orig_y + kSize;
3089 uint16_t* orig_v = orig_u + kSize / 2;
3090
3091 // Test grey scale
3092 for (int i = 0; i < kSize; ++i) {
3093 orig_y[i] = i;
3094 }
3095 for (int i = 0; i < kSize / 2; ++i) {
3096 orig_u[i] = 512; // 512 is 0.
3097 orig_v[i] = 512;
3098 }
3099
3100 H010ToAB30(orig_y, 0, orig_u, 0, orig_v, 0, ab30_pixels, 0, kSize, 1);
3101
3102 for (int i = 0; i < kSize; ++i) {
3103 int r10 = reinterpret_cast<uint32_t*>(ab30_pixels)[i] & 1023;
3104 int g10 = (reinterpret_cast<uint32_t*>(ab30_pixels)[i] >> 10) & 1023;
3105 int b10 = (reinterpret_cast<uint32_t*>(ab30_pixels)[i] >> 20) & 1023;
3106 int a2 = (reinterpret_cast<uint32_t*>(ab30_pixels)[i] >> 30) & 3;
3107 ++histogram_b[b10];
3108 ++histogram_g[g10];
3109 ++histogram_r[r10];
3110 int expected_y = Clamp10(static_cast<int>((i - 64) * 1.164f));
3111 EXPECT_NEAR(b10, expected_y, 4);
3112 EXPECT_NEAR(g10, expected_y, 4);
3113 EXPECT_NEAR(r10, expected_y, 4);
3114 EXPECT_EQ(a2, 3);
3115 }
3116
3117 int count_b = 0;
3118 int count_g = 0;
3119 int count_r = 0;
3120 for (int i = 0; i < kSize; ++i) {
3121 if (histogram_b[i]) {
3122 ++count_b;
3123 }
3124 if (histogram_g[i]) {
3125 ++count_g;
3126 }
3127 if (histogram_r[i]) {
3128 ++count_r;
3129 }
3130 }
3131 printf("uniques: B %d, G, %d, R %d\n", count_b, count_g, count_r);
3132
3133 free_aligned_buffer_page_end(orig_yuv);
3134 free_aligned_buffer_page_end(ab30_pixels);
3135 }
3136
3137 // Test 8 bit YUV to 10 bit RGB
TEST_F(LibYUVConvertTest,TestH420ToAR30)3138 TEST_F(LibYUVConvertTest, TestH420ToAR30) {
3139 const int kSize = 256;
3140 const int kHistSize = 1024;
3141 int histogram_b[kHistSize];
3142 int histogram_g[kHistSize];
3143 int histogram_r[kHistSize];
3144 memset(histogram_b, 0, sizeof(histogram_b));
3145 memset(histogram_g, 0, sizeof(histogram_g));
3146 memset(histogram_r, 0, sizeof(histogram_r));
3147 align_buffer_page_end(orig_yuv, kSize + kSize / 2 * 2);
3148 align_buffer_page_end(ar30_pixels, kSize * 4);
3149 uint8_t* orig_y = orig_yuv;
3150 uint8_t* orig_u = orig_y + kSize;
3151 uint8_t* orig_v = orig_u + kSize / 2;
3152
3153 // Test grey scale
3154 for (int i = 0; i < kSize; ++i) {
3155 orig_y[i] = i;
3156 }
3157 for (int i = 0; i < kSize / 2; ++i) {
3158 orig_u[i] = 128; // 128 is 0.
3159 orig_v[i] = 128;
3160 }
3161
3162 H420ToAR30(orig_y, 0, orig_u, 0, orig_v, 0, ar30_pixels, 0, kSize, 1);
3163
3164 for (int i = 0; i < kSize; ++i) {
3165 int b10 = reinterpret_cast<uint32_t*>(ar30_pixels)[i] & 1023;
3166 int g10 = (reinterpret_cast<uint32_t*>(ar30_pixels)[i] >> 10) & 1023;
3167 int r10 = (reinterpret_cast<uint32_t*>(ar30_pixels)[i] >> 20) & 1023;
3168 int a2 = (reinterpret_cast<uint32_t*>(ar30_pixels)[i] >> 30) & 3;
3169 ++histogram_b[b10];
3170 ++histogram_g[g10];
3171 ++histogram_r[r10];
3172 int expected_y = Clamp10(static_cast<int>((i - 16) * 1.164f * 4.f));
3173 EXPECT_NEAR(b10, expected_y, 4);
3174 EXPECT_NEAR(g10, expected_y, 4);
3175 EXPECT_NEAR(r10, expected_y, 4);
3176 EXPECT_EQ(a2, 3);
3177 }
3178
3179 int count_b = 0;
3180 int count_g = 0;
3181 int count_r = 0;
3182 for (int i = 0; i < kHistSize; ++i) {
3183 if (histogram_b[i]) {
3184 ++count_b;
3185 }
3186 if (histogram_g[i]) {
3187 ++count_g;
3188 }
3189 if (histogram_r[i]) {
3190 ++count_r;
3191 }
3192 }
3193 printf("uniques: B %d, G, %d, R %d\n", count_b, count_g, count_r);
3194
3195 free_aligned_buffer_page_end(orig_yuv);
3196 free_aligned_buffer_page_end(ar30_pixels);
3197 }
3198
3199 // Test RGB24 to ARGB and back to RGB24
TEST_F(LibYUVConvertTest,TestARGBToRGB24)3200 TEST_F(LibYUVConvertTest, TestARGBToRGB24) {
3201 const int kSize = 256;
3202 align_buffer_page_end(orig_rgb24, kSize * 3);
3203 align_buffer_page_end(argb_pixels, kSize * 4);
3204 align_buffer_page_end(dest_rgb24, kSize * 3);
3205
3206 // Test grey scale
3207 for (int i = 0; i < kSize * 3; ++i) {
3208 orig_rgb24[i] = i;
3209 }
3210
3211 RGB24ToARGB(orig_rgb24, 0, argb_pixels, 0, kSize, 1);
3212 ARGBToRGB24(argb_pixels, 0, dest_rgb24, 0, kSize, 1);
3213
3214 for (int i = 0; i < kSize * 3; ++i) {
3215 EXPECT_EQ(orig_rgb24[i], dest_rgb24[i]);
3216 }
3217
3218 free_aligned_buffer_page_end(orig_rgb24);
3219 free_aligned_buffer_page_end(argb_pixels);
3220 free_aligned_buffer_page_end(dest_rgb24);
3221 }
3222
3223 } // namespace libyuv
3224