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/basic_types.h"
16 #include "libyuv/compare.h"
17 #include "libyuv/convert.h"
18 #include "libyuv/convert_argb.h"
19 #include "libyuv/convert_from.h"
20 #include "libyuv/convert_from_argb.h"
21 #include "libyuv/cpu_id.h"
22 #ifdef HAVE_JPEG
23 #include "libyuv/mjpeg_decoder.h"
24 #endif
25 #include "../unit_test/unit_test.h"
26 #include "libyuv/planar_functions.h"
27 #include "libyuv/rotate.h"
28 #include "libyuv/video_common.h"
29
30 #ifdef ENABLE_ROW_TESTS
31 #include "libyuv/row.h" /* For ARGBToAR30Row_AVX2 */
32 #endif
33
34 #if defined(__riscv) && !defined(__clang__)
35 #define DISABLE_SLOW_TESTS
36 #undef ENABLE_FULL_TESTS
37 #undef ENABLE_ROW_TESTS
38 #define LEAN_TESTS
39 #endif
40
41 // Some functions fail on big endian. Enable these tests on all cpus except
42 // PowerPC, but they are not optimized so disabled by default.
43 #if !defined(DISABLE_SLOW_TESTS) && !defined(__powerpc__)
44 #define LITTLE_ENDIAN_ONLY_TEST 1
45 #endif
46 #if !defined(DISABLE_SLOW_TESTS) || defined(__x86_64__) || defined(__i386__)
47 // SLOW TESTS are those that are unoptimized C code.
48 // FULL TESTS are optimized but test many variations of the same code.
49 #define ENABLE_FULL_TESTS
50 #endif
51
52 namespace libyuv {
53
54 // Alias to copy pixels as is
55 #define AR30ToAR30 ARGBCopy
56 #define ABGRToABGR ARGBCopy
57
58 // subsample amount uses a divide.
59 #define SUBSAMPLE(v, a) ((((v) + (a)-1)) / (a))
60
61 #define ALIGNINT(V, ALIGN) (((V) + (ALIGN)-1) / (ALIGN) * (ALIGN))
62
63 // Planar test
64
65 #define TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
66 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, \
67 DST_SUBSAMP_X, DST_SUBSAMP_Y, W1280, N, NEG, OFF, \
68 SRC_DEPTH) \
69 TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) { \
70 static_assert(SRC_BPC == 1 || SRC_BPC == 2, "SRC BPC unsupported"); \
71 static_assert(DST_BPC == 1 || DST_BPC == 2, "DST BPC unsupported"); \
72 static_assert(SRC_SUBSAMP_X == 1 || SRC_SUBSAMP_X == 2, \
73 "SRC_SUBSAMP_X unsupported"); \
74 static_assert(SRC_SUBSAMP_Y == 1 || SRC_SUBSAMP_Y == 2, \
75 "SRC_SUBSAMP_Y unsupported"); \
76 static_assert(DST_SUBSAMP_X == 1 || DST_SUBSAMP_X == 2, \
77 "DST_SUBSAMP_X unsupported"); \
78 static_assert(DST_SUBSAMP_Y == 1 || DST_SUBSAMP_Y == 2, \
79 "DST_SUBSAMP_Y unsupported"); \
80 const int kWidth = W1280; \
81 const int kHeight = benchmark_height_; \
82 const int kSrcHalfWidth = SUBSAMPLE(kWidth, SRC_SUBSAMP_X); \
83 const int kSrcHalfHeight = SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); \
84 const int kDstHalfWidth = SUBSAMPLE(kWidth, DST_SUBSAMP_X); \
85 const int kDstHalfHeight = SUBSAMPLE(kHeight, DST_SUBSAMP_Y); \
86 align_buffer_page_end(src_y, kWidth* kHeight* SRC_BPC + OFF); \
87 align_buffer_page_end(src_u, \
88 kSrcHalfWidth* kSrcHalfHeight* SRC_BPC + OFF); \
89 align_buffer_page_end(src_v, \
90 kSrcHalfWidth* kSrcHalfHeight* SRC_BPC + OFF); \
91 align_buffer_page_end(dst_y_c, kWidth* kHeight* DST_BPC); \
92 align_buffer_page_end(dst_u_c, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
93 align_buffer_page_end(dst_v_c, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
94 align_buffer_page_end(dst_y_opt, kWidth* kHeight* DST_BPC); \
95 align_buffer_page_end(dst_u_opt, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
96 align_buffer_page_end(dst_v_opt, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
97 MemRandomize(src_y + OFF, kWidth * kHeight * SRC_BPC); \
98 MemRandomize(src_u + OFF, kSrcHalfWidth * kSrcHalfHeight * SRC_BPC); \
99 MemRandomize(src_v + OFF, kSrcHalfWidth * kSrcHalfHeight * SRC_BPC); \
100 SRC_T* src_y_p = reinterpret_cast<SRC_T*>(src_y + OFF); \
101 SRC_T* src_u_p = reinterpret_cast<SRC_T*>(src_u + OFF); \
102 SRC_T* src_v_p = reinterpret_cast<SRC_T*>(src_v + OFF); \
103 for (int i = 0; i < kWidth * kHeight; ++i) { \
104 src_y_p[i] = src_y_p[i] & ((1 << SRC_DEPTH) - 1); \
105 } \
106 for (int i = 0; i < kSrcHalfWidth * kSrcHalfHeight; ++i) { \
107 src_u_p[i] = src_u_p[i] & ((1 << SRC_DEPTH) - 1); \
108 src_v_p[i] = src_v_p[i] & ((1 << SRC_DEPTH) - 1); \
109 } \
110 memset(dst_y_c, 1, kWidth* kHeight* DST_BPC); \
111 memset(dst_u_c, 2, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
112 memset(dst_v_c, 3, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
113 memset(dst_y_opt, 101, kWidth* kHeight* DST_BPC); \
114 memset(dst_u_opt, 102, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
115 memset(dst_v_opt, 103, kDstHalfWidth* kDstHalfHeight* DST_BPC); \
116 MaskCpuFlags(disable_cpu_flags_); \
117 SRC_FMT_PLANAR##To##FMT_PLANAR( \
118 src_y_p, kWidth, src_u_p, kSrcHalfWidth, src_v_p, kSrcHalfWidth, \
119 reinterpret_cast<DST_T*>(dst_y_c), kWidth, \
120 reinterpret_cast<DST_T*>(dst_u_c), kDstHalfWidth, \
121 reinterpret_cast<DST_T*>(dst_v_c), kDstHalfWidth, kWidth, \
122 NEG kHeight); \
123 MaskCpuFlags(benchmark_cpu_info_); \
124 for (int i = 0; i < benchmark_iterations_; ++i) { \
125 SRC_FMT_PLANAR##To##FMT_PLANAR( \
126 src_y_p, kWidth, src_u_p, kSrcHalfWidth, src_v_p, kSrcHalfWidth, \
127 reinterpret_cast<DST_T*>(dst_y_opt), kWidth, \
128 reinterpret_cast<DST_T*>(dst_u_opt), kDstHalfWidth, \
129 reinterpret_cast<DST_T*>(dst_v_opt), kDstHalfWidth, kWidth, \
130 NEG kHeight); \
131 } \
132 for (int i = 0; i < kHeight * kWidth * DST_BPC; ++i) { \
133 EXPECT_EQ(dst_y_c[i], dst_y_opt[i]); \
134 } \
135 for (int i = 0; i < kDstHalfWidth * kDstHalfHeight * DST_BPC; ++i) { \
136 EXPECT_EQ(dst_u_c[i], dst_u_opt[i]); \
137 EXPECT_EQ(dst_v_c[i], dst_v_opt[i]); \
138 } \
139 free_aligned_buffer_page_end(dst_y_c); \
140 free_aligned_buffer_page_end(dst_u_c); \
141 free_aligned_buffer_page_end(dst_v_c); \
142 free_aligned_buffer_page_end(dst_y_opt); \
143 free_aligned_buffer_page_end(dst_u_opt); \
144 free_aligned_buffer_page_end(dst_v_opt); \
145 free_aligned_buffer_page_end(src_y); \
146 free_aligned_buffer_page_end(src_u); \
147 free_aligned_buffer_page_end(src_v); \
148 }
149
150 #if defined(ENABLE_FULL_TESTS)
151 #define TESTPLANARTOP(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
152 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, \
153 DST_SUBSAMP_X, DST_SUBSAMP_Y, SRC_DEPTH) \
154 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
155 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
156 benchmark_width_ + 1, _Any, +, 0, SRC_DEPTH) \
157 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
158 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
159 benchmark_width_, _Unaligned, +, 2, SRC_DEPTH) \
160 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
161 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
162 benchmark_width_, _Invert, -, 0, SRC_DEPTH) \
163 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
164 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
165 benchmark_width_, _Opt, +, 0, SRC_DEPTH)
166 #else
167 #define TESTPLANARTOP(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
168 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, \
169 DST_SUBSAMP_X, DST_SUBSAMP_Y, SRC_DEPTH) \
170 TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
171 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
172 benchmark_width_, _Opt, +, 0, SRC_DEPTH)
173 #endif
174
175 TESTPLANARTOP(I420, uint8_t, 1, 2, 2, I420, uint8_t, 1, 2, 2, 8)
176 TESTPLANARTOP(I422, uint8_t, 1, 2, 1, I420, uint8_t, 1, 2, 2, 8)
177 TESTPLANARTOP(I444, uint8_t, 1, 1, 1, I420, uint8_t, 1, 2, 2, 8)
178 TESTPLANARTOP(I420, uint8_t, 1, 2, 2, I422, uint8_t, 1, 2, 1, 8)
179 TESTPLANARTOP(I420, uint8_t, 1, 2, 2, I444, uint8_t, 1, 1, 1, 8)
180 TESTPLANARTOP(I420, uint8_t, 1, 2, 2, I420Mirror, uint8_t, 1, 2, 2, 8)
181 TESTPLANARTOP(I422, uint8_t, 1, 2, 1, I422, uint8_t, 1, 2, 1, 8)
182 TESTPLANARTOP(I422, uint8_t, 1, 2, 1, I444, uint8_t, 1, 1, 1, 8)
183 TESTPLANARTOP(I444, uint8_t, 1, 1, 1, I444, uint8_t, 1, 1, 1, 8)
184 TESTPLANARTOP(I010, uint16_t, 2, 2, 2, I010, uint16_t, 2, 2, 2, 10)
185 TESTPLANARTOP(I420, uint8_t, 1, 2, 2, I010, uint16_t, 2, 2, 2, 8)
186 TESTPLANARTOP(I420, uint8_t, 1, 2, 2, I012, uint16_t, 2, 2, 2, 8)
187 TESTPLANARTOP(H010, uint16_t, 2, 2, 2, H010, uint16_t, 2, 2, 2, 10)
188 TESTPLANARTOP(H010, uint16_t, 2, 2, 2, H420, uint8_t, 1, 2, 2, 10)
189 TESTPLANARTOP(H420, uint8_t, 1, 2, 2, H010, uint16_t, 2, 2, 2, 8)
190 TESTPLANARTOP(H420, uint8_t, 1, 2, 2, H012, uint16_t, 2, 2, 2, 8)
191 TESTPLANARTOP(I010, uint16_t, 2, 2, 2, I410, uint16_t, 2, 1, 1, 10)
192 TESTPLANARTOP(I210, uint16_t, 2, 2, 1, I410, uint16_t, 2, 1, 1, 10)
193 TESTPLANARTOP(I012, uint16_t, 2, 2, 2, I412, uint16_t, 2, 1, 1, 12)
194 TESTPLANARTOP(I212, uint16_t, 2, 2, 1, I412, uint16_t, 2, 1, 1, 12)
195 TESTPLANARTOP(I410, uint16_t, 2, 1, 1, I010, uint16_t, 2, 2, 2, 10)
196 TESTPLANARTOP(I210, uint16_t, 2, 2, 1, I010, uint16_t, 2, 2, 2, 10)
197 TESTPLANARTOP(I412, uint16_t, 2, 1, 1, I012, uint16_t, 2, 2, 2, 12)
198 TESTPLANARTOP(I212, uint16_t, 2, 2, 1, I012, uint16_t, 2, 2, 2, 12)
199 TESTPLANARTOP(I010, uint16_t, 2, 2, 2, I420, uint8_t, 1, 2, 2, 10)
200 TESTPLANARTOP(I210, uint16_t, 2, 2, 1, I420, uint8_t, 1, 2, 2, 10)
201 TESTPLANARTOP(I210, uint16_t, 2, 2, 1, I422, uint8_t, 1, 2, 1, 10)
202 TESTPLANARTOP(I410, uint16_t, 2, 1, 1, I420, uint8_t, 1, 2, 2, 10)
203 TESTPLANARTOP(I410, uint16_t, 2, 1, 1, I444, uint8_t, 1, 1, 1, 10)
204 TESTPLANARTOP(I012, uint16_t, 2, 2, 2, I420, uint8_t, 1, 2, 2, 12)
205 TESTPLANARTOP(I212, uint16_t, 2, 2, 1, I420, uint8_t, 1, 2, 2, 12)
206 TESTPLANARTOP(I212, uint16_t, 2, 2, 1, I422, uint8_t, 1, 2, 1, 12)
207 TESTPLANARTOP(I412, uint16_t, 2, 1, 1, I420, uint8_t, 1, 2, 2, 12)
208 TESTPLANARTOP(I412, uint16_t, 2, 1, 1, I444, uint8_t, 1, 1, 1, 12)
209
210 // Test Android 420 to I420
211 #define TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, \
212 SRC_SUBSAMP_Y, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
213 W1280, N, NEG, OFF, PN, OFF_U, OFF_V) \
214 TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##To##PN##N) { \
215 const int kWidth = W1280; \
216 const int kHeight = benchmark_height_; \
217 const int kSizeUV = \
218 SUBSAMPLE(kWidth, SRC_SUBSAMP_X) * SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); \
219 align_buffer_page_end(src_y, kWidth* kHeight + OFF); \
220 align_buffer_page_end(src_uv, \
221 kSizeUV*((PIXEL_STRIDE == 3) ? 3 : 2) + OFF); \
222 align_buffer_page_end(dst_y_c, kWidth* kHeight); \
223 align_buffer_page_end(dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X) * \
224 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
225 align_buffer_page_end(dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X) * \
226 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
227 align_buffer_page_end(dst_y_opt, kWidth* kHeight); \
228 align_buffer_page_end(dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * \
229 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
230 align_buffer_page_end(dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * \
231 SUBSAMPLE(kHeight, SUBSAMP_Y)); \
232 uint8_t* src_u = src_uv + OFF_U; \
233 uint8_t* src_v = src_uv + (PIXEL_STRIDE == 1 ? kSizeUV : OFF_V); \
234 int src_stride_uv = SUBSAMPLE(kWidth, SUBSAMP_X) * PIXEL_STRIDE; \
235 for (int i = 0; i < kHeight; ++i) \
236 for (int j = 0; j < kWidth; ++j) \
237 src_y[i * kWidth + j + OFF] = (fastrand() & 0xff); \
238 for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) { \
239 for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) { \
240 src_u[(i * src_stride_uv) + j * PIXEL_STRIDE + OFF] = \
241 (fastrand() & 0xff); \
242 src_v[(i * src_stride_uv) + j * PIXEL_STRIDE + OFF] = \
243 (fastrand() & 0xff); \
244 } \
245 } \
246 memset(dst_y_c, 1, kWidth* kHeight); \
247 memset(dst_u_c, 2, \
248 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
249 memset(dst_v_c, 3, \
250 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
251 memset(dst_y_opt, 101, kWidth* kHeight); \
252 memset(dst_u_opt, 102, \
253 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
254 memset(dst_v_opt, 103, \
255 SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
256 MaskCpuFlags(disable_cpu_flags_); \
257 SRC_FMT_PLANAR##To##FMT_PLANAR( \
258 src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \
259 src_v + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), PIXEL_STRIDE, dst_y_c, \
260 kWidth, dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X), dst_v_c, \
261 SUBSAMPLE(kWidth, SUBSAMP_X), kWidth, NEG kHeight); \
262 MaskCpuFlags(benchmark_cpu_info_); \
263 for (int i = 0; i < benchmark_iterations_; ++i) { \
264 SRC_FMT_PLANAR##To##FMT_PLANAR( \
265 src_y + OFF, kWidth, src_u + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), \
266 src_v + OFF, SUBSAMPLE(kWidth, SRC_SUBSAMP_X), PIXEL_STRIDE, \
267 dst_y_opt, kWidth, dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X), \
268 dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X), kWidth, NEG kHeight); \
269 } \
270 for (int i = 0; i < kHeight; ++i) { \
271 for (int j = 0; j < kWidth; ++j) { \
272 EXPECT_EQ(dst_y_c[i * kWidth + j], dst_y_opt[i * kWidth + j]); \
273 } \
274 } \
275 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
276 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \
277 EXPECT_EQ(dst_u_c[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j], \
278 dst_u_opt[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j]); \
279 } \
280 } \
281 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
282 for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) { \
283 EXPECT_EQ(dst_v_c[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j], \
284 dst_v_opt[i * SUBSAMPLE(kWidth, SUBSAMP_X) + j]); \
285 } \
286 } \
287 free_aligned_buffer_page_end(dst_y_c); \
288 free_aligned_buffer_page_end(dst_u_c); \
289 free_aligned_buffer_page_end(dst_v_c); \
290 free_aligned_buffer_page_end(dst_y_opt); \
291 free_aligned_buffer_page_end(dst_u_opt); \
292 free_aligned_buffer_page_end(dst_v_opt); \
293 free_aligned_buffer_page_end(src_y); \
294 free_aligned_buffer_page_end(src_uv); \
295 }
296
297 #if defined(ENABLE_FULL_TESTS)
298 #define TESTAPLANARTOP(SRC_FMT_PLANAR, PN, PIXEL_STRIDE, OFF_U, OFF_V, \
299 SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, SUBSAMP_X, \
300 SUBSAMP_Y) \
301 TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
302 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_ + 1, \
303 _Any, +, 0, PN, OFF_U, OFF_V) \
304 TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
305 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, \
306 _Unaligned, +, 2, PN, OFF_U, OFF_V) \
307 TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
308 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Invert, \
309 -, 0, PN, OFF_U, OFF_V) \
310 TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
311 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Opt, +, \
312 0, PN, OFF_U, OFF_V)
313 #else
314 #define TESTAPLANARTOP(SRC_FMT_PLANAR, PN, PIXEL_STRIDE, OFF_U, OFF_V, \
315 SRC_SUBSAMP_X, SRC_SUBSAMP_Y, FMT_PLANAR, SUBSAMP_X, \
316 SUBSAMP_Y) \
317 TESTAPLANARTOPI(SRC_FMT_PLANAR, PIXEL_STRIDE, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
318 FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, benchmark_width_, _Opt, +, \
319 0, PN, OFF_U, OFF_V)
320 #endif
321
322 TESTAPLANARTOP(Android420, I420, 1, 0, 0, 2, 2, I420, 2, 2)
323 TESTAPLANARTOP(Android420, NV12, 2, 0, 1, 2, 2, I420, 2, 2)
324 TESTAPLANARTOP(Android420, NV21, 2, 1, 0, 2, 2, I420, 2, 2)
325 #undef TESTAPLANARTOP
326 #undef TESTAPLANARTOPI
327
328 // 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)329 int I400ToNV21(const uint8_t* src_y,
330 int src_stride_y,
331 const uint8_t* /* src_u */,
332 int /* src_stride_u */,
333 const uint8_t* /* src_v */,
334 int /* src_stride_v */,
335 uint8_t* dst_y,
336 int dst_stride_y,
337 uint8_t* dst_vu,
338 int dst_stride_vu,
339 int width,
340 int height) {
341 return I400ToNV21(src_y, src_stride_y, dst_y, dst_stride_y, dst_vu,
342 dst_stride_vu, width, height);
343 }
344
345 #define TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
346 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, \
347 DST_SUBSAMP_X, DST_SUBSAMP_Y, W1280, N, NEG, OFF, \
348 SRC_DEPTH) \
349 TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) { \
350 static_assert(SRC_BPC == 1 || SRC_BPC == 2, "SRC BPC unsupported"); \
351 static_assert(DST_BPC == 1 || DST_BPC == 2, "DST BPC unsupported"); \
352 static_assert(SRC_SUBSAMP_X == 1 || SRC_SUBSAMP_X == 2, \
353 "SRC_SUBSAMP_X unsupported"); \
354 static_assert(SRC_SUBSAMP_Y == 1 || SRC_SUBSAMP_Y == 2, \
355 "SRC_SUBSAMP_Y unsupported"); \
356 static_assert(DST_SUBSAMP_X == 1 || DST_SUBSAMP_X == 2, \
357 "DST_SUBSAMP_X unsupported"); \
358 static_assert(DST_SUBSAMP_Y == 1 || DST_SUBSAMP_Y == 2, \
359 "DST_SUBSAMP_Y unsupported"); \
360 const int kWidth = W1280; \
361 const int kHeight = benchmark_height_; \
362 const int kSrcHalfWidth = SUBSAMPLE(kWidth, SRC_SUBSAMP_X); \
363 const int kSrcHalfHeight = SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); \
364 const int kDstHalfWidth = SUBSAMPLE(kWidth, DST_SUBSAMP_X); \
365 const int kDstHalfHeight = SUBSAMPLE(kHeight, DST_SUBSAMP_Y); \
366 align_buffer_page_end(src_y, kWidth* kHeight* SRC_BPC + OFF); \
367 align_buffer_page_end(src_u, \
368 kSrcHalfWidth* kSrcHalfHeight* SRC_BPC + OFF); \
369 align_buffer_page_end(src_v, \
370 kSrcHalfWidth* kSrcHalfHeight* SRC_BPC + OFF); \
371 align_buffer_page_end(dst_y_c, kWidth* kHeight* DST_BPC); \
372 align_buffer_page_end(dst_uv_c, \
373 kDstHalfWidth* kDstHalfHeight* DST_BPC * 2); \
374 align_buffer_page_end(dst_y_opt, kWidth* kHeight* DST_BPC); \
375 align_buffer_page_end(dst_uv_opt, \
376 kDstHalfWidth* kDstHalfHeight* DST_BPC * 2); \
377 MemRandomize(src_y + OFF, kWidth * kHeight * SRC_BPC); \
378 MemRandomize(src_u + OFF, kSrcHalfWidth * kSrcHalfHeight * SRC_BPC); \
379 MemRandomize(src_v + OFF, kSrcHalfWidth * kSrcHalfHeight * SRC_BPC); \
380 SRC_T* src_y_p = reinterpret_cast<SRC_T*>(src_y + OFF); \
381 SRC_T* src_u_p = reinterpret_cast<SRC_T*>(src_u + OFF); \
382 SRC_T* src_v_p = reinterpret_cast<SRC_T*>(src_v + OFF); \
383 for (int i = 0; i < kWidth * kHeight; ++i) { \
384 src_y_p[i] = src_y_p[i] & ((1 << SRC_DEPTH) - 1); \
385 } \
386 for (int i = 0; i < kSrcHalfWidth * kSrcHalfHeight; ++i) { \
387 src_u_p[i] = src_u_p[i] & ((1 << SRC_DEPTH) - 1); \
388 src_v_p[i] = src_v_p[i] & ((1 << SRC_DEPTH) - 1); \
389 } \
390 memset(dst_y_c, 1, kWidth* kHeight* DST_BPC); \
391 memset(dst_uv_c, 2, kDstHalfWidth* kDstHalfHeight* DST_BPC * 2); \
392 memset(dst_y_opt, 101, kWidth* kHeight* DST_BPC); \
393 memset(dst_uv_opt, 102, kDstHalfWidth* kDstHalfHeight* DST_BPC * 2); \
394 MaskCpuFlags(disable_cpu_flags_); \
395 SRC_FMT_PLANAR##To##FMT_PLANAR(src_y_p, kWidth, src_u_p, kSrcHalfWidth, \
396 src_v_p, kSrcHalfWidth, \
397 reinterpret_cast<DST_T*>(dst_y_c), kWidth, \
398 reinterpret_cast<DST_T*>(dst_uv_c), \
399 kDstHalfWidth * 2, kWidth, NEG kHeight); \
400 MaskCpuFlags(benchmark_cpu_info_); \
401 for (int i = 0; i < benchmark_iterations_; ++i) { \
402 SRC_FMT_PLANAR##To##FMT_PLANAR( \
403 src_y_p, kWidth, src_u_p, kSrcHalfWidth, src_v_p, kSrcHalfWidth, \
404 reinterpret_cast<DST_T*>(dst_y_opt), kWidth, \
405 reinterpret_cast<DST_T*>(dst_uv_opt), kDstHalfWidth * 2, kWidth, \
406 NEG kHeight); \
407 } \
408 for (int i = 0; i < kHeight * kWidth * DST_BPC; ++i) { \
409 EXPECT_EQ(dst_y_c[i], dst_y_opt[i]); \
410 } \
411 for (int i = 0; i < kDstHalfWidth * kDstHalfHeight * DST_BPC * 2; ++i) { \
412 EXPECT_EQ(dst_uv_c[i], dst_uv_opt[i]); \
413 } \
414 free_aligned_buffer_page_end(dst_y_c); \
415 free_aligned_buffer_page_end(dst_uv_c); \
416 free_aligned_buffer_page_end(dst_y_opt); \
417 free_aligned_buffer_page_end(dst_uv_opt); \
418 free_aligned_buffer_page_end(src_y); \
419 free_aligned_buffer_page_end(src_u); \
420 free_aligned_buffer_page_end(src_v); \
421 }
422
423 #if defined(ENABLE_FULL_TESTS)
424 #define TESTPLANARTOBP(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
425 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, \
426 DST_SUBSAMP_X, DST_SUBSAMP_Y, SRC_DEPTH) \
427 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
428 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, \
429 DST_SUBSAMP_Y, benchmark_width_ + 1, _Any, +, 0, SRC_DEPTH) \
430 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
431 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, \
432 DST_SUBSAMP_Y, benchmark_width_, _Unaligned, +, 2, \
433 SRC_DEPTH) \
434 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
435 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, \
436 DST_SUBSAMP_Y, benchmark_width_, _Invert, -, 0, SRC_DEPTH) \
437 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
438 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, \
439 DST_SUBSAMP_Y, benchmark_width_, _Opt, +, 0, SRC_DEPTH)
440 #else
441 #define TESTPLANARTOBP(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
442 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, \
443 DST_SUBSAMP_X, DST_SUBSAMP_Y, SRC_DEPTH) \
444 TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
445 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, \
446 DST_SUBSAMP_Y, benchmark_width_, _Opt, +, 0, SRC_DEPTH)
447 #endif
448
449 TESTPLANARTOBP(I420, uint8_t, 1, 2, 2, NV12, uint8_t, 1, 2, 2, 8)
450 TESTPLANARTOBP(I420, uint8_t, 1, 2, 2, NV21, uint8_t, 1, 2, 2, 8)
451 TESTPLANARTOBP(I422, uint8_t, 1, 2, 1, NV21, uint8_t, 1, 2, 2, 8)
452 TESTPLANARTOBP(I444, uint8_t, 1, 1, 1, NV12, uint8_t, 1, 2, 2, 8)
453 TESTPLANARTOBP(I444, uint8_t, 1, 1, 1, NV21, uint8_t, 1, 2, 2, 8)
454 TESTPLANARTOBP(I400, uint8_t, 1, 2, 2, NV21, uint8_t, 1, 2, 2, 8)
455 TESTPLANARTOBP(I010, uint16_t, 2, 2, 2, P010, uint16_t, 2, 2, 2, 10)
456 TESTPLANARTOBP(I210, uint16_t, 2, 2, 1, P210, uint16_t, 2, 2, 1, 10)
457 TESTPLANARTOBP(I012, uint16_t, 2, 2, 2, P012, uint16_t, 2, 2, 2, 12)
458 TESTPLANARTOBP(I212, uint16_t, 2, 2, 1, P212, uint16_t, 2, 2, 1, 12)
459
460 #define TESTBPTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
461 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, \
462 DST_SUBSAMP_Y, W1280, N, NEG, OFF, DOY, SRC_DEPTH, \
463 TILE_WIDTH, TILE_HEIGHT) \
464 TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) { \
465 static_assert(DST_BPC == 1 || DST_BPC == 2, "DST BPC unsupported"); \
466 static_assert(SRC_SUBSAMP_X == 1 || SRC_SUBSAMP_X == 2, \
467 "SRC_SUBSAMP_X unsupported"); \
468 static_assert(SRC_SUBSAMP_Y == 1 || SRC_SUBSAMP_Y == 2, \
469 "SRC_SUBSAMP_Y unsupported"); \
470 static_assert(DST_SUBSAMP_X == 1 || DST_SUBSAMP_X == 2, \
471 "DST_SUBSAMP_X unsupported"); \
472 static_assert(DST_SUBSAMP_Y == 1 || DST_SUBSAMP_Y == 2, \
473 "DST_SUBSAMP_Y unsupported"); \
474 const int kWidth = W1280; \
475 const int kHeight = benchmark_height_; \
476 const int kSrcHalfWidth = SUBSAMPLE(kWidth, SRC_SUBSAMP_X); \
477 const int kDstHalfWidth = SUBSAMPLE(kWidth, DST_SUBSAMP_X); \
478 const int kDstHalfHeight = SUBSAMPLE(kHeight, DST_SUBSAMP_Y); \
479 const int kPaddedWidth = (kWidth + (TILE_WIDTH - 1)) & ~(TILE_WIDTH - 1); \
480 const int kPaddedHeight = \
481 (kHeight + (TILE_HEIGHT - 1)) & ~(TILE_HEIGHT - 1); \
482 const int kSrcHalfPaddedWidth = SUBSAMPLE(kPaddedWidth, SRC_SUBSAMP_X); \
483 const int kSrcHalfPaddedHeight = SUBSAMPLE(kPaddedHeight, SRC_SUBSAMP_Y); \
484 align_buffer_page_end(src_y, kPaddedWidth* kPaddedHeight* SRC_BPC + OFF); \
485 align_buffer_page_end( \
486 src_uv, \
487 2 * kSrcHalfPaddedWidth * kSrcHalfPaddedHeight * SRC_BPC + OFF); \
488 align_buffer_page_end(dst_y_c, kWidth* kHeight* DST_BPC); \
489 align_buffer_page_end(dst_uv_c, \
490 2 * kDstHalfWidth * kDstHalfHeight * DST_BPC); \
491 align_buffer_page_end(dst_y_opt, kWidth* kHeight* DST_BPC); \
492 align_buffer_page_end(dst_uv_opt, \
493 2 * kDstHalfWidth * kDstHalfHeight * DST_BPC); \
494 SRC_T* src_y_p = reinterpret_cast<SRC_T*>(src_y + OFF); \
495 SRC_T* src_uv_p = reinterpret_cast<SRC_T*>(src_uv + OFF); \
496 for (int i = 0; \
497 i < kPaddedWidth * kPaddedHeight * SRC_BPC / (int)sizeof(SRC_T); \
498 ++i) { \
499 src_y_p[i] = \
500 (fastrand() & (((SRC_T)(-1)) << ((8 * SRC_BPC) - SRC_DEPTH))); \
501 } \
502 for (int i = 0; i < kSrcHalfPaddedWidth * kSrcHalfPaddedHeight * 2 * \
503 SRC_BPC / (int)sizeof(SRC_T); \
504 ++i) { \
505 src_uv_p[i] = \
506 (fastrand() & (((SRC_T)(-1)) << ((8 * SRC_BPC) - SRC_DEPTH))); \
507 } \
508 memset(dst_y_c, 1, kWidth* kHeight* DST_BPC); \
509 memset(dst_uv_c, 2, 2 * kDstHalfWidth * kDstHalfHeight * DST_BPC); \
510 memset(dst_y_opt, 101, kWidth* kHeight* DST_BPC); \
511 memset(dst_uv_opt, 102, 2 * kDstHalfWidth * kDstHalfHeight * DST_BPC); \
512 MaskCpuFlags(disable_cpu_flags_); \
513 SRC_FMT_PLANAR##To##FMT_PLANAR( \
514 src_y_p, kWidth* SRC_BPC / (int)sizeof(SRC_T), src_uv_p, \
515 2 * kSrcHalfWidth * SRC_BPC / (int)sizeof(SRC_T), \
516 DOY ? reinterpret_cast<DST_T*>(dst_y_c) : NULL, kWidth, \
517 reinterpret_cast<DST_T*>(dst_uv_c), 2 * kDstHalfWidth, kWidth, \
518 NEG kHeight); \
519 MaskCpuFlags(benchmark_cpu_info_); \
520 for (int i = 0; i < benchmark_iterations_; ++i) { \
521 SRC_FMT_PLANAR##To##FMT_PLANAR( \
522 src_y_p, kWidth* SRC_BPC / (int)sizeof(SRC_T), src_uv_p, \
523 2 * kSrcHalfWidth * SRC_BPC / (int)sizeof(SRC_T), \
524 DOY ? reinterpret_cast<DST_T*>(dst_y_opt) : NULL, kWidth, \
525 reinterpret_cast<DST_T*>(dst_uv_opt), 2 * kDstHalfWidth, kWidth, \
526 NEG kHeight); \
527 } \
528 if (DOY) { \
529 for (int i = 0; i < kHeight; ++i) { \
530 for (int j = 0; j < kWidth; ++j) { \
531 EXPECT_EQ(dst_y_c[i * kWidth + j], dst_y_opt[i * kWidth + j]); \
532 } \
533 } \
534 } \
535 for (int i = 0; i < kDstHalfHeight; ++i) { \
536 for (int j = 0; j < 2 * kDstHalfWidth; ++j) { \
537 EXPECT_EQ(dst_uv_c[i * 2 * kDstHalfWidth + j], \
538 dst_uv_opt[i * 2 * kDstHalfWidth + j]); \
539 } \
540 } \
541 free_aligned_buffer_page_end(dst_y_c); \
542 free_aligned_buffer_page_end(dst_uv_c); \
543 free_aligned_buffer_page_end(dst_y_opt); \
544 free_aligned_buffer_page_end(dst_uv_opt); \
545 free_aligned_buffer_page_end(src_y); \
546 free_aligned_buffer_page_end(src_uv); \
547 }
548
549 #if defined(ENABLE_FULL_TESTS)
550 #define TESTBPTOBP(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
551 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, \
552 DST_SUBSAMP_Y, SRC_DEPTH, TILE_WIDTH, TILE_HEIGHT) \
553 TESTBPTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
554 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
555 benchmark_width_ + 1, _Any, +, 0, 1, SRC_DEPTH, TILE_WIDTH, \
556 TILE_HEIGHT) \
557 TESTBPTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
558 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
559 benchmark_width_, _Unaligned, +, 2, 1, SRC_DEPTH, TILE_WIDTH, \
560 TILE_HEIGHT) \
561 TESTBPTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
562 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
563 benchmark_width_, _Invert, -, 0, 1, SRC_DEPTH, TILE_WIDTH, \
564 TILE_HEIGHT) \
565 TESTBPTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
566 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
567 benchmark_width_, _Opt, +, 0, 1, SRC_DEPTH, TILE_WIDTH, \
568 TILE_HEIGHT) \
569 TESTBPTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
570 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
571 benchmark_width_, _NullY, +, 0, 0, SRC_DEPTH, TILE_WIDTH, \
572 TILE_HEIGHT)
573 #else
574 #define TESTBPTOBP(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, \
575 SRC_SUBSAMP_Y, FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, \
576 DST_SUBSAMP_Y, SRC_DEPTH, TILE_WIDTH, TILE_HEIGHT) \
577 TESTBPTOBPI(SRC_FMT_PLANAR, SRC_T, SRC_BPC, SRC_SUBSAMP_X, SRC_SUBSAMP_Y, \
578 FMT_PLANAR, DST_T, DST_BPC, DST_SUBSAMP_X, DST_SUBSAMP_Y, \
579 benchmark_width_, _NullY, +, 0, 0, SRC_DEPTH, TILE_WIDTH, \
580 TILE_HEIGHT)
581 #endif
582
583 TESTBPTOBP(NV21, uint8_t, 1, 2, 2, NV12, uint8_t, 1, 2, 2, 8, 1, 1)
584 TESTBPTOBP(NV12, uint8_t, 1, 2, 2, NV12Mirror, uint8_t, 1, 2, 2, 8, 1, 1)
585 TESTBPTOBP(NV12, uint8_t, 1, 2, 2, NV24, uint8_t, 1, 1, 1, 8, 1, 1)
586 TESTBPTOBP(NV16, uint8_t, 1, 2, 1, NV24, uint8_t, 1, 1, 1, 8, 1, 1)
587 TESTBPTOBP(P010, uint16_t, 2, 2, 2, P410, uint16_t, 2, 1, 1, 10, 1, 1)
588 TESTBPTOBP(P210, uint16_t, 2, 2, 1, P410, uint16_t, 2, 1, 1, 10, 1, 1)
589 TESTBPTOBP(P012, uint16_t, 2, 2, 2, P412, uint16_t, 2, 1, 1, 10, 1, 1)
590 TESTBPTOBP(P212, uint16_t, 2, 2, 1, P412, uint16_t, 2, 1, 1, 12, 1, 1)
591 TESTBPTOBP(P016, uint16_t, 2, 2, 2, P416, uint16_t, 2, 1, 1, 12, 1, 1)
592 TESTBPTOBP(P216, uint16_t, 2, 2, 1, P416, uint16_t, 2, 1, 1, 12, 1, 1)
593 TESTBPTOBP(MM21, uint8_t, 1, 2, 2, NV12, uint8_t, 1, 2, 2, 8, 16, 32)
594 TESTBPTOBP(MT2T, uint8_t, 10 / 8, 2, 2, P010, uint16_t, 2, 2, 2, 10, 16, 32)
595
596 #define TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
597 W1280, N, NEG, OFF) \
598 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_PLANAR##N) { \
599 const int kWidth = W1280; \
600 const int kHeight = ALIGNINT(benchmark_height_, YALIGN); \
601 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
602 const int kStride = (kStrideUV * SUBSAMP_X * 8 * BPP_A + 7) / 8; \
603 align_buffer_page_end(src_argb, kStride* kHeight + OFF); \
604 align_buffer_page_end(dst_y_c, kWidth* kHeight); \
605 align_buffer_page_end(dst_uv_c, \
606 kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
607 align_buffer_page_end(dst_y_opt, kWidth* kHeight); \
608 align_buffer_page_end(dst_uv_opt, \
609 kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
610 memset(dst_y_c, 1, kWidth* kHeight); \
611 memset(dst_uv_c, 2, kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
612 memset(dst_y_opt, 101, kWidth* kHeight); \
613 memset(dst_uv_opt, 102, kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
614 for (int i = 0; i < kHeight; ++i) \
615 for (int j = 0; j < kStride; ++j) \
616 src_argb[(i * kStride) + j + OFF] = (fastrand() & 0xff); \
617 MaskCpuFlags(disable_cpu_flags_); \
618 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, dst_y_c, kWidth, dst_uv_c, \
619 kStrideUV * 2, dst_uv_c + kStrideUV, kStrideUV * 2, \
620 kWidth, NEG kHeight); \
621 MaskCpuFlags(benchmark_cpu_info_); \
622 for (int i = 0; i < benchmark_iterations_; ++i) { \
623 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, dst_y_opt, kWidth, \
624 dst_uv_opt, kStrideUV * 2, dst_uv_opt + kStrideUV, \
625 kStrideUV * 2, kWidth, NEG kHeight); \
626 } \
627 for (int i = 0; i < kHeight; ++i) { \
628 for (int j = 0; j < kWidth; ++j) { \
629 EXPECT_EQ(dst_y_c[i * kWidth + j], dst_y_opt[i * kWidth + j]); \
630 } \
631 } \
632 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y) * 2; ++i) { \
633 for (int j = 0; j < kStrideUV; ++j) { \
634 EXPECT_EQ(dst_uv_c[i * kStrideUV + j], dst_uv_opt[i * kStrideUV + j]); \
635 } \
636 } \
637 free_aligned_buffer_page_end(dst_y_c); \
638 free_aligned_buffer_page_end(dst_uv_c); \
639 free_aligned_buffer_page_end(dst_y_opt); \
640 free_aligned_buffer_page_end(dst_uv_opt); \
641 free_aligned_buffer_page_end(src_argb); \
642 }
643
644 #if defined(ENABLE_FULL_TESTS)
645 #define TESTATOPLANAR(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \
646 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
647 benchmark_width_ + 1, _Any, +, 0) \
648 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
649 benchmark_width_, _Unaligned, +, 2) \
650 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
651 benchmark_width_, _Invert, -, 0) \
652 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
653 benchmark_width_, _Opt, +, 0)
654 #else
655 #define TESTATOPLANAR(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \
656 TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
657 benchmark_width_, _Opt, +, 0)
658 #endif
659
660 TESTATOPLANAR(ABGR, 4, 1, I420, 2, 2)
661 TESTATOPLANAR(ARGB, 4, 1, I420, 2, 2)
662 TESTATOPLANAR(ARGB, 4, 1, I422, 2, 1)
663 TESTATOPLANAR(ARGB, 4, 1, I444, 1, 1)
664 TESTATOPLANAR(ARGB, 4, 1, J420, 2, 2)
665 TESTATOPLANAR(ARGB, 4, 1, J422, 2, 1)
666 TESTATOPLANAR(ABGR, 4, 1, J420, 2, 2)
667 TESTATOPLANAR(ABGR, 4, 1, J422, 2, 1)
668 #ifdef LITTLE_ENDIAN_ONLY_TEST
669 TESTATOPLANAR(ARGB4444, 2, 1, I420, 2, 2)
670 TESTATOPLANAR(RGB565, 2, 1, I420, 2, 2)
671 TESTATOPLANAR(ARGB1555, 2, 1, I420, 2, 2)
672 #endif
673 TESTATOPLANAR(BGRA, 4, 1, I420, 2, 2)
674 TESTATOPLANAR(I400, 1, 1, I420, 2, 2)
675 TESTATOPLANAR(J400, 1, 1, J420, 2, 2)
676 TESTATOPLANAR(RAW, 3, 1, I420, 2, 2)
677 TESTATOPLANAR(RAW, 3, 1, J420, 2, 2)
678 TESTATOPLANAR(RGB24, 3, 1, I420, 2, 2)
679 TESTATOPLANAR(RGB24, 3, 1, J420, 2, 2)
680 TESTATOPLANAR(RGBA, 4, 1, I420, 2, 2)
681 TESTATOPLANAR(UYVY, 2, 1, I420, 2, 2)
682 TESTATOPLANAR(UYVY, 2, 1, I422, 2, 1)
683 TESTATOPLANAR(YUY2, 2, 1, I420, 2, 2)
684 TESTATOPLANAR(YUY2, 2, 1, I422, 2, 1)
685
686 #define TESTATOPLANARAI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, \
687 SUBSAMP_Y, W1280, N, NEG, OFF) \
688 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_PLANAR##N) { \
689 const int kWidth = W1280; \
690 const int kHeight = ALIGNINT(benchmark_height_, YALIGN); \
691 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
692 const int kStride = (kStrideUV * SUBSAMP_X * 8 * BPP_A + 7) / 8; \
693 align_buffer_page_end(src_argb, kStride* kHeight + OFF); \
694 align_buffer_page_end(dst_a_c, kWidth* kHeight); \
695 align_buffer_page_end(dst_y_c, kWidth* kHeight); \
696 align_buffer_page_end(dst_uv_c, \
697 kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
698 align_buffer_page_end(dst_a_opt, kWidth* kHeight); \
699 align_buffer_page_end(dst_y_opt, kWidth* kHeight); \
700 align_buffer_page_end(dst_uv_opt, \
701 kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
702 memset(dst_a_c, 1, kWidth* kHeight); \
703 memset(dst_y_c, 2, kWidth* kHeight); \
704 memset(dst_uv_c, 3, kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
705 memset(dst_a_opt, 101, kWidth* kHeight); \
706 memset(dst_y_opt, 102, kWidth* kHeight); \
707 memset(dst_uv_opt, 103, kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
708 for (int i = 0; i < kHeight; ++i) \
709 for (int j = 0; j < kStride; ++j) \
710 src_argb[(i * kStride) + j + OFF] = (fastrand() & 0xff); \
711 MaskCpuFlags(disable_cpu_flags_); \
712 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, dst_y_c, kWidth, dst_uv_c, \
713 kStrideUV * 2, dst_uv_c + kStrideUV, kStrideUV * 2, \
714 dst_a_c, kWidth, kWidth, NEG kHeight); \
715 MaskCpuFlags(benchmark_cpu_info_); \
716 for (int i = 0; i < benchmark_iterations_; ++i) { \
717 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, dst_y_opt, kWidth, \
718 dst_uv_opt, kStrideUV * 2, dst_uv_opt + kStrideUV, \
719 kStrideUV * 2, dst_a_opt, kWidth, kWidth, \
720 NEG kHeight); \
721 } \
722 for (int i = 0; i < kHeight; ++i) { \
723 for (int j = 0; j < kWidth; ++j) { \
724 EXPECT_EQ(dst_y_c[i * kWidth + j], dst_y_opt[i * kWidth + j]); \
725 EXPECT_EQ(dst_a_c[i * kWidth + j], dst_a_opt[i * kWidth + j]); \
726 } \
727 } \
728 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y) * 2; ++i) { \
729 for (int j = 0; j < kStrideUV; ++j) { \
730 EXPECT_EQ(dst_uv_c[i * kStrideUV + j], dst_uv_opt[i * kStrideUV + j]); \
731 } \
732 } \
733 free_aligned_buffer_page_end(dst_a_c); \
734 free_aligned_buffer_page_end(dst_y_c); \
735 free_aligned_buffer_page_end(dst_uv_c); \
736 free_aligned_buffer_page_end(dst_a_opt); \
737 free_aligned_buffer_page_end(dst_y_opt); \
738 free_aligned_buffer_page_end(dst_uv_opt); \
739 free_aligned_buffer_page_end(src_argb); \
740 }
741
742 #if defined(ENABLE_FULL_TESTS)
743 #define TESTATOPLANARA(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \
744 TESTATOPLANARAI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
745 benchmark_width_ + 1, _Any, +, 0) \
746 TESTATOPLANARAI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
747 benchmark_width_, _Unaligned, +, 2) \
748 TESTATOPLANARAI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
749 benchmark_width_, _Invert, -, 0) \
750 TESTATOPLANARAI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
751 benchmark_width_, _Opt, +, 0)
752 #else
753 #define TESTATOPLANARA(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \
754 TESTATOPLANARAI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
755 benchmark_width_, _Opt, +, 0)
756 #endif
757
758 TESTATOPLANARA(ARGB, 4, 1, I420Alpha, 2, 2)
759
760 #define TESTATOBPI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
761 W1280, N, NEG, OFF) \
762 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_PLANAR##N) { \
763 const int kWidth = W1280; \
764 const int kHeight = benchmark_height_; \
765 const int kStride = SUBSAMPLE(kWidth, SUB_A) * BPP_A; \
766 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X); \
767 align_buffer_page_end(src_argb, kStride* kHeight + OFF); \
768 align_buffer_page_end(dst_y_c, kWidth* kHeight); \
769 align_buffer_page_end(dst_uv_c, \
770 kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
771 align_buffer_page_end(dst_y_opt, kWidth* kHeight); \
772 align_buffer_page_end(dst_uv_opt, \
773 kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
774 for (int i = 0; i < kHeight; ++i) \
775 for (int j = 0; j < kStride; ++j) \
776 src_argb[(i * kStride) + j + OFF] = (fastrand() & 0xff); \
777 memset(dst_y_c, 1, kWidth* kHeight); \
778 memset(dst_uv_c, 2, kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
779 memset(dst_y_opt, 101, kWidth* kHeight); \
780 memset(dst_uv_opt, 102, kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y)); \
781 MaskCpuFlags(disable_cpu_flags_); \
782 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, dst_y_c, kWidth, dst_uv_c, \
783 kStrideUV * 2, kWidth, NEG kHeight); \
784 MaskCpuFlags(benchmark_cpu_info_); \
785 for (int i = 0; i < benchmark_iterations_; ++i) { \
786 FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride, dst_y_opt, kWidth, \
787 dst_uv_opt, kStrideUV * 2, kWidth, NEG kHeight); \
788 } \
789 for (int i = 0; i < kHeight; ++i) { \
790 for (int j = 0; j < kWidth; ++j) { \
791 EXPECT_EQ(dst_y_c[i * kWidth + j], dst_y_opt[i * kWidth + j]); \
792 } \
793 } \
794 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) { \
795 for (int j = 0; j < kStrideUV * 2; ++j) { \
796 EXPECT_EQ(dst_uv_c[i * kStrideUV * 2 + j], \
797 dst_uv_opt[i * kStrideUV * 2 + j]); \
798 } \
799 } \
800 free_aligned_buffer_page_end(dst_y_c); \
801 free_aligned_buffer_page_end(dst_uv_c); \
802 free_aligned_buffer_page_end(dst_y_opt); \
803 free_aligned_buffer_page_end(dst_uv_opt); \
804 free_aligned_buffer_page_end(src_argb); \
805 }
806
807 #if defined(ENABLE_FULL_TESTS)
808 #define TESTATOBP(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \
809 TESTATOBPI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
810 benchmark_width_ + 1, _Any, +, 0) \
811 TESTATOBPI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
812 benchmark_width_, _Unaligned, +, 2) \
813 TESTATOBPI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
814 benchmark_width_, _Invert, -, 0) \
815 TESTATOBPI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
816 benchmark_width_, _Opt, +, 0)
817 #else
818 #define TESTATOBP(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \
819 TESTATOBPI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
820 benchmark_width_, _Opt, +, 0)
821 #endif
822
823 TESTATOBP(ARGB, 1, 4, NV12, 2, 2)
824 TESTATOBP(ARGB, 1, 4, NV21, 2, 2)
825 TESTATOBP(ABGR, 1, 4, NV12, 2, 2)
826 TESTATOBP(ABGR, 1, 4, NV21, 2, 2)
827 TESTATOBP(RAW, 1, 3, JNV21, 2, 2)
828 TESTATOBP(YUY2, 2, 4, NV12, 2, 2)
829 TESTATOBP(UYVY, 2, 4, NV12, 2, 2)
830 TESTATOBP(AYUV, 1, 4, NV12, 2, 2)
831 TESTATOBP(AYUV, 1, 4, NV21, 2, 2)
832
833 #if !defined(LEAN_TESTS)
834
835 #ifdef HAVE_JPEG
TEST_F(LibYUVConvertTest,ValidateJpeg)836 TEST_F(LibYUVConvertTest, ValidateJpeg) {
837 const int kOff = 10;
838 const int kMinJpeg = 64;
839 const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg
840 ? benchmark_width_ * benchmark_height_
841 : kMinJpeg;
842 const int kSize = kImageSize + kOff;
843 align_buffer_page_end(orig_pixels, kSize);
844
845 // No SOI or EOI. Expect fail.
846 memset(orig_pixels, 0, kSize);
847 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
848
849 // Test special value that matches marker start.
850 memset(orig_pixels, 0xff, kSize);
851 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
852
853 // EOI, SOI. Expect pass.
854 orig_pixels[0] = 0xff;
855 orig_pixels[1] = 0xd8; // SOI.
856 orig_pixels[2] = 0xff;
857 orig_pixels[kSize - kOff + 0] = 0xff;
858 orig_pixels[kSize - kOff + 1] = 0xd9; // EOI.
859 for (int times = 0; times < benchmark_iterations_; ++times) {
860 EXPECT_TRUE(ValidateJpeg(orig_pixels, kSize));
861 }
862 free_aligned_buffer_page_end(orig_pixels);
863 }
864
TEST_F(LibYUVConvertTest,ValidateJpegLarge)865 TEST_F(LibYUVConvertTest, ValidateJpegLarge) {
866 const int kOff = 10;
867 const int kMinJpeg = 64;
868 const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg
869 ? benchmark_width_ * benchmark_height_
870 : kMinJpeg;
871 const int kSize = kImageSize + kOff;
872 const int kMultiple = 10;
873 const int kBufSize = kImageSize * kMultiple + kOff;
874 align_buffer_page_end(orig_pixels, kBufSize);
875
876 // No SOI or EOI. Expect fail.
877 memset(orig_pixels, 0, kBufSize);
878 EXPECT_FALSE(ValidateJpeg(orig_pixels, kBufSize));
879
880 // EOI, SOI. Expect pass.
881 orig_pixels[0] = 0xff;
882 orig_pixels[1] = 0xd8; // SOI.
883 orig_pixels[2] = 0xff;
884 orig_pixels[kSize - kOff + 0] = 0xff;
885 orig_pixels[kSize - kOff + 1] = 0xd9; // EOI.
886 for (int times = 0; times < benchmark_iterations_; ++times) {
887 EXPECT_TRUE(ValidateJpeg(orig_pixels, kBufSize));
888 }
889 free_aligned_buffer_page_end(orig_pixels);
890 }
891
TEST_F(LibYUVConvertTest,InvalidateJpeg)892 TEST_F(LibYUVConvertTest, InvalidateJpeg) {
893 const int kOff = 10;
894 const int kMinJpeg = 64;
895 const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg
896 ? benchmark_width_ * benchmark_height_
897 : kMinJpeg;
898 const int kSize = kImageSize + kOff;
899 align_buffer_page_end(orig_pixels, kSize);
900
901 // NULL pointer. Expect fail.
902 EXPECT_FALSE(ValidateJpeg(NULL, kSize));
903
904 // Negative size. Expect fail.
905 EXPECT_FALSE(ValidateJpeg(orig_pixels, -1));
906
907 // Too large size. Expect fail.
908 EXPECT_FALSE(ValidateJpeg(orig_pixels, 0xfb000000ull));
909
910 // No SOI or EOI. Expect fail.
911 memset(orig_pixels, 0, kSize);
912 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
913
914 // SOI but no EOI. Expect fail.
915 orig_pixels[0] = 0xff;
916 orig_pixels[1] = 0xd8; // SOI.
917 orig_pixels[2] = 0xff;
918 for (int times = 0; times < benchmark_iterations_; ++times) {
919 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
920 }
921
922 // EOI but no SOI. Expect fail.
923 orig_pixels[0] = 0;
924 orig_pixels[1] = 0;
925 orig_pixels[kSize - kOff + 0] = 0xff;
926 orig_pixels[kSize - kOff + 1] = 0xd9; // EOI.
927 EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
928
929 free_aligned_buffer_page_end(orig_pixels);
930 }
931
TEST_F(LibYUVConvertTest,FuzzJpeg)932 TEST_F(LibYUVConvertTest, FuzzJpeg) {
933 // SOI but no EOI. Expect fail.
934 for (int times = 0; times < benchmark_iterations_; ++times) {
935 const int kSize = fastrand() % 5000 + 3;
936 align_buffer_page_end(orig_pixels, kSize);
937 MemRandomize(orig_pixels, kSize);
938
939 // Add SOI so frame will be scanned.
940 orig_pixels[0] = 0xff;
941 orig_pixels[1] = 0xd8; // SOI.
942 orig_pixels[2] = 0xff;
943 orig_pixels[kSize - 1] = 0xff;
944 ValidateJpeg(orig_pixels,
945 kSize); // Failure normally expected.
946 free_aligned_buffer_page_end(orig_pixels);
947 }
948 }
949
950 // Test data created in GIMP. In export jpeg, disable
951 // thumbnails etc, choose a subsampling, and use low quality
952 // (50) to keep size small. Generated with xxd -i test.jpg
953 // test 0 is J400
954 static const uint8_t kTest0Jpg[] = {
955 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
956 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
957 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12,
958 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23,
959 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40,
960 0x48, 0x5c, 0x4e, 0x40, 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51,
961 0x57, 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
962 0x78, 0x5c, 0x65, 0x67, 0x63, 0xff, 0xc2, 0x00, 0x0b, 0x08, 0x00, 0x10,
963 0x00, 0x20, 0x01, 0x01, 0x11, 0x00, 0xff, 0xc4, 0x00, 0x17, 0x00, 0x01,
964 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
965 0x00, 0x00, 0x00, 0x03, 0x04, 0x01, 0x02, 0xff, 0xda, 0x00, 0x08, 0x01,
966 0x01, 0x00, 0x00, 0x00, 0x01, 0x43, 0x7e, 0xa7, 0x97, 0x57, 0xff, 0xc4,
967 0x00, 0x1b, 0x10, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00,
968 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11, 0x00, 0x03,
969 0x10, 0x12, 0x13, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x05,
970 0x02, 0x3b, 0xc0, 0x6f, 0x66, 0x76, 0x56, 0x23, 0x87, 0x99, 0x0d, 0x26,
971 0x62, 0xf6, 0xbf, 0xff, 0xc4, 0x00, 0x1e, 0x10, 0x00, 0x02, 0x01, 0x03,
972 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
973 0x00, 0x11, 0x21, 0x02, 0x12, 0x32, 0x10, 0x31, 0x71, 0x81, 0xa1, 0xff,
974 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x06, 0x3f, 0x02, 0x4b, 0xb3, 0x28,
975 0x32, 0xd2, 0xed, 0xf9, 0x1d, 0x3e, 0x13, 0x51, 0x73, 0x83, 0xff, 0xc4,
976 0x00, 0x1c, 0x10, 0x01, 0x01, 0x01, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00,
977 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x21, 0x51,
978 0x31, 0x61, 0x81, 0xf0, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01,
979 0x3f, 0x21, 0x65, 0x6e, 0x31, 0x86, 0x28, 0xf9, 0x30, 0xdc, 0x27, 0xdb,
980 0xa9, 0x01, 0xf3, 0xde, 0x02, 0xa0, 0xed, 0x1e, 0x34, 0x68, 0x23, 0xf9,
981 0xc6, 0x48, 0x5d, 0x7a, 0x35, 0x02, 0xf5, 0x6f, 0xff, 0xda, 0x00, 0x08,
982 0x01, 0x01, 0x00, 0x00, 0x00, 0x10, 0x35, 0xff, 0xc4, 0x00, 0x1f, 0x10,
983 0x01, 0x00, 0x02, 0x01, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
984 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x31, 0x41, 0x61, 0x71, 0x91,
985 0x21, 0x81, 0xd1, 0xb1, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01,
986 0x3f, 0x10, 0x0b, 0x30, 0xe9, 0x58, 0xbe, 0x1a, 0xfd, 0x88, 0xab, 0x8b,
987 0x34, 0x74, 0x80, 0x4b, 0xb5, 0xd5, 0xab, 0xcd, 0x46, 0x96, 0x2e, 0xec,
988 0xbd, 0xaa, 0x78, 0x47, 0x5c, 0x47, 0xa7, 0x30, 0x49, 0xad, 0x88, 0x7c,
989 0x40, 0x74, 0x30, 0xff, 0x00, 0x23, 0x1d, 0x03, 0x0b, 0xb7, 0xd4, 0xff,
990 0xd9};
991 static const size_t kTest0JpgLen = 421;
992
993 // test 1 is J444
994 static const uint8_t kTest1Jpg[] = {
995 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
996 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
997 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12,
998 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23,
999 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40,
1000 0x48, 0x5c, 0x4e, 0x40, 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51,
1001 0x57, 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
1002 0x78, 0x5c, 0x65, 0x67, 0x63, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x11, 0x12,
1003 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
1004 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1005 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1006 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1007 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1008 0x63, 0x63, 0xff, 0xc2, 0x00, 0x11, 0x08, 0x00, 0x10, 0x00, 0x20, 0x03,
1009 0x01, 0x11, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00,
1010 0x17, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1011 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x01, 0x02, 0xff, 0xc4,
1012 0x00, 0x16, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1013 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x03, 0xff, 0xda,
1014 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x10, 0x03, 0x10, 0x00, 0x00, 0x01,
1015 0x40, 0x8f, 0x26, 0xe8, 0xf4, 0xcc, 0xf9, 0x69, 0x2b, 0x1b, 0x2a, 0xcb,
1016 0xff, 0xc4, 0x00, 0x1b, 0x10, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00,
1017 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11,
1018 0x00, 0x03, 0x10, 0x12, 0x13, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00,
1019 0x01, 0x05, 0x02, 0x3b, 0x80, 0x6f, 0x56, 0x76, 0x56, 0x23, 0x87, 0x99,
1020 0x0d, 0x26, 0x62, 0xf6, 0xbf, 0xff, 0xc4, 0x00, 0x19, 0x11, 0x01, 0x00,
1021 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1022 0x00, 0x00, 0x01, 0x00, 0x10, 0x11, 0x02, 0x12, 0xff, 0xda, 0x00, 0x08,
1023 0x01, 0x03, 0x01, 0x01, 0x3f, 0x01, 0xf1, 0x00, 0x27, 0x45, 0xbb, 0x31,
1024 0xaf, 0xff, 0xc4, 0x00, 0x1a, 0x11, 0x00, 0x02, 0x03, 0x01, 0x01, 0x00,
1025 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1026 0x02, 0x10, 0x11, 0x41, 0x12, 0xff, 0xda, 0x00, 0x08, 0x01, 0x02, 0x01,
1027 0x01, 0x3f, 0x01, 0xf6, 0x4b, 0x5f, 0x48, 0xb3, 0x69, 0x63, 0x35, 0x72,
1028 0xbf, 0xff, 0xc4, 0x00, 0x1e, 0x10, 0x00, 0x02, 0x01, 0x03, 0x05, 0x00,
1029 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11,
1030 0x21, 0x02, 0x12, 0x32, 0x10, 0x31, 0x71, 0x81, 0xa1, 0xff, 0xda, 0x00,
1031 0x08, 0x01, 0x01, 0x00, 0x06, 0x3f, 0x02, 0x4b, 0xb3, 0x28, 0x32, 0xd2,
1032 0xed, 0xf9, 0x1d, 0x3e, 0x13, 0x51, 0x73, 0x83, 0xff, 0xc4, 0x00, 0x1c,
1033 0x10, 0x01, 0x01, 0x01, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
1034 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x21, 0x51, 0x31, 0x61,
1035 0x81, 0xf0, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x3f, 0x21,
1036 0x75, 0x6e, 0x31, 0x94, 0x28, 0xf9, 0x30, 0xdc, 0x27, 0xdb, 0xa9, 0x01,
1037 0xf3, 0xde, 0x02, 0xa0, 0xed, 0x1e, 0x34, 0x68, 0x23, 0xf9, 0xc6, 0x48,
1038 0x5d, 0x7a, 0x35, 0x02, 0xf5, 0x6f, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01,
1039 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x26, 0x61, 0xd4, 0xff,
1040 0xc4, 0x00, 0x1a, 0x11, 0x00, 0x03, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00,
1041 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x21,
1042 0x31, 0x41, 0x51, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, 0x01, 0x3f,
1043 0x10, 0x54, 0xa8, 0xbf, 0x50, 0x87, 0xb0, 0x9d, 0x8b, 0xc4, 0x6a, 0x26,
1044 0x6b, 0x2a, 0x9c, 0x1f, 0xff, 0xc4, 0x00, 0x18, 0x11, 0x01, 0x01, 0x01,
1045 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1046 0x00, 0x01, 0x00, 0x11, 0x21, 0x51, 0xff, 0xda, 0x00, 0x08, 0x01, 0x02,
1047 0x01, 0x01, 0x3f, 0x10, 0x70, 0xe1, 0x3e, 0xd1, 0x8e, 0x0d, 0xe1, 0xb5,
1048 0xd5, 0x91, 0x76, 0x43, 0x82, 0x45, 0x4c, 0x7b, 0x7f, 0xff, 0xc4, 0x00,
1049 0x1f, 0x10, 0x01, 0x00, 0x02, 0x01, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00,
1050 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x31, 0x41, 0x61,
1051 0x71, 0x91, 0x21, 0x81, 0xd1, 0xb1, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01,
1052 0x00, 0x01, 0x3f, 0x10, 0x1b, 0x30, 0xe9, 0x58, 0xbe, 0x1a, 0xfd, 0x8a,
1053 0xeb, 0x8b, 0x34, 0x74, 0x80, 0x4b, 0xb5, 0xd5, 0xab, 0xcd, 0x46, 0x96,
1054 0x2e, 0xec, 0xbd, 0xaa, 0x78, 0x47, 0x5c, 0x47, 0xa7, 0x30, 0x49, 0xad,
1055 0x88, 0x7c, 0x40, 0x74, 0x30, 0xff, 0x00, 0x23, 0x1d, 0x03, 0x0b, 0xb7,
1056 0xd4, 0xff, 0xd9};
1057 static const size_t kTest1JpgLen = 735;
1058
1059 // test 2 is J420
1060 static const uint8_t kTest2Jpg[] = {
1061 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
1062 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
1063 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12,
1064 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23,
1065 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40,
1066 0x48, 0x5c, 0x4e, 0x40, 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51,
1067 0x57, 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
1068 0x78, 0x5c, 0x65, 0x67, 0x63, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x11, 0x12,
1069 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
1070 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1071 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1072 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1073 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1074 0x63, 0x63, 0xff, 0xc2, 0x00, 0x11, 0x08, 0x00, 0x10, 0x00, 0x20, 0x03,
1075 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00,
1076 0x18, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1077 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x01, 0x02, 0x04, 0xff,
1078 0xc4, 0x00, 0x16, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1079 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x02, 0xff,
1080 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x10, 0x03, 0x10, 0x00, 0x00,
1081 0x01, 0x20, 0xe7, 0x28, 0xa3, 0x0b, 0x2e, 0x2d, 0xcf, 0xff, 0xc4, 0x00,
1082 0x1b, 0x10, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
1083 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11, 0x00, 0x03, 0x10,
1084 0x12, 0x13, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x05, 0x02,
1085 0x3b, 0x80, 0x6f, 0x56, 0x76, 0x56, 0x23, 0x87, 0x99, 0x0d, 0x26, 0x62,
1086 0xf6, 0xbf, 0xff, 0xc4, 0x00, 0x17, 0x11, 0x01, 0x00, 0x03, 0x00, 0x00,
1087 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1088 0x01, 0x11, 0x21, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, 0x01, 0x3f,
1089 0x01, 0xc8, 0x53, 0xff, 0xc4, 0x00, 0x16, 0x11, 0x01, 0x01, 0x01, 0x00,
1090 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1091 0x00, 0x11, 0x32, 0xff, 0xda, 0x00, 0x08, 0x01, 0x02, 0x01, 0x01, 0x3f,
1092 0x01, 0xd2, 0xc7, 0xff, 0xc4, 0x00, 0x1e, 0x10, 0x00, 0x02, 0x01, 0x03,
1093 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1094 0x00, 0x11, 0x21, 0x02, 0x12, 0x32, 0x10, 0x31, 0x71, 0x81, 0xa1, 0xff,
1095 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x06, 0x3f, 0x02, 0x4b, 0xb3, 0x28,
1096 0x32, 0xd2, 0xed, 0xf9, 0x1d, 0x3e, 0x13, 0x51, 0x73, 0x83, 0xff, 0xc4,
1097 0x00, 0x1c, 0x10, 0x01, 0x01, 0x01, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00,
1098 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x21, 0x51,
1099 0x31, 0x61, 0x81, 0xf0, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01,
1100 0x3f, 0x21, 0x75, 0x6e, 0x31, 0x94, 0x28, 0xf9, 0x30, 0xdc, 0x27, 0xdb,
1101 0xa9, 0x01, 0xf3, 0xde, 0x02, 0xa0, 0xed, 0x1e, 0x34, 0x68, 0x23, 0xf9,
1102 0xc6, 0x48, 0x5d, 0x7a, 0x35, 0x02, 0xf5, 0x6f, 0xff, 0xda, 0x00, 0x0c,
1103 0x03, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x13, 0x5f,
1104 0xff, 0xc4, 0x00, 0x17, 0x11, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
1105 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11,
1106 0x21, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, 0x01, 0x3f, 0x10, 0x0e,
1107 0xa1, 0x3a, 0x76, 0xff, 0xc4, 0x00, 0x17, 0x11, 0x01, 0x01, 0x01, 0x01,
1108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1109 0x01, 0x00, 0x21, 0x11, 0xff, 0xda, 0x00, 0x08, 0x01, 0x02, 0x01, 0x01,
1110 0x3f, 0x10, 0x57, 0x0b, 0x08, 0x70, 0xdb, 0xff, 0xc4, 0x00, 0x1f, 0x10,
1111 0x01, 0x00, 0x02, 0x01, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1112 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x31, 0x41, 0x61, 0x71, 0x91,
1113 0x21, 0x81, 0xd1, 0xb1, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01,
1114 0x3f, 0x10, 0x1b, 0x30, 0xe9, 0x58, 0xbe, 0x1a, 0xfd, 0x8a, 0xeb, 0x8b,
1115 0x34, 0x74, 0x80, 0x4b, 0xb5, 0xd5, 0xab, 0xcd, 0x46, 0x96, 0x2e, 0xec,
1116 0xbd, 0xaa, 0x78, 0x47, 0x5c, 0x47, 0xa7, 0x30, 0x49, 0xad, 0x88, 0x7c,
1117 0x40, 0x74, 0x30, 0xff, 0x00, 0x23, 0x1d, 0x03, 0x0b, 0xb7, 0xd4, 0xff,
1118 0xd9};
1119 static const size_t kTest2JpgLen = 685;
1120
1121 // test 3 is J422
1122 static const uint8_t kTest3Jpg[] = {
1123 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
1124 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
1125 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12,
1126 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23,
1127 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40,
1128 0x48, 0x5c, 0x4e, 0x40, 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51,
1129 0x57, 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
1130 0x78, 0x5c, 0x65, 0x67, 0x63, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x11, 0x12,
1131 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
1132 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1133 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1134 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1135 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1136 0x63, 0x63, 0xff, 0xc2, 0x00, 0x11, 0x08, 0x00, 0x10, 0x00, 0x20, 0x03,
1137 0x01, 0x21, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00,
1138 0x17, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x04, 0x01, 0x02, 0xff, 0xc4,
1140 0x00, 0x17, 0x01, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0xff,
1142 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x10, 0x03, 0x10, 0x00, 0x00,
1143 0x01, 0x43, 0x8d, 0x1f, 0xa2, 0xb3, 0xca, 0x1b, 0x57, 0x0f, 0xff, 0xc4,
1144 0x00, 0x1b, 0x10, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00,
1145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11, 0x00, 0x03,
1146 0x10, 0x12, 0x13, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x05,
1147 0x02, 0x3b, 0x80, 0x6f, 0x56, 0x76, 0x56, 0x23, 0x87, 0x99, 0x0d, 0x26,
1148 0x62, 0xf6, 0xbf, 0xff, 0xc4, 0x00, 0x19, 0x11, 0x00, 0x02, 0x03, 0x01,
1149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1150 0x00, 0x01, 0x02, 0x10, 0x11, 0x21, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03,
1151 0x01, 0x01, 0x3f, 0x01, 0x51, 0xce, 0x8c, 0x75, 0xff, 0xc4, 0x00, 0x18,
1152 0x11, 0x00, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x61, 0x21, 0xff, 0xda,
1154 0x00, 0x08, 0x01, 0x02, 0x01, 0x01, 0x3f, 0x01, 0xa6, 0xd9, 0x2f, 0x84,
1155 0xe8, 0xf0, 0xff, 0xc4, 0x00, 0x1e, 0x10, 0x00, 0x02, 0x01, 0x03, 0x05,
1156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1157 0x11, 0x21, 0x02, 0x12, 0x32, 0x10, 0x31, 0x71, 0x81, 0xa1, 0xff, 0xda,
1158 0x00, 0x08, 0x01, 0x01, 0x00, 0x06, 0x3f, 0x02, 0x4b, 0xb3, 0x28, 0x32,
1159 0xd2, 0xed, 0xf9, 0x1d, 0x3e, 0x13, 0x51, 0x73, 0x83, 0xff, 0xc4, 0x00,
1160 0x1c, 0x10, 0x01, 0x01, 0x01, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00,
1161 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x21, 0x51, 0x31,
1162 0x61, 0x81, 0xf0, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x3f,
1163 0x21, 0x75, 0x6e, 0x31, 0x94, 0x28, 0xf9, 0x30, 0xdc, 0x27, 0xdb, 0xa9,
1164 0x01, 0xf3, 0xde, 0x02, 0xa0, 0xed, 0x1e, 0x34, 0x68, 0x23, 0xf9, 0xc6,
1165 0x48, 0x5d, 0x7a, 0x35, 0x02, 0xf5, 0x6f, 0xff, 0xda, 0x00, 0x0c, 0x03,
1166 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x2e, 0x45, 0xff,
1167 0xc4, 0x00, 0x18, 0x11, 0x00, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
1168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x21,
1169 0x31, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, 0x01, 0x3f, 0x10, 0x53,
1170 0x50, 0xba, 0x54, 0xc1, 0x67, 0x4f, 0xff, 0xc4, 0x00, 0x18, 0x11, 0x00,
1171 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1172 0x00, 0x00, 0x00, 0x01, 0x11, 0x21, 0x00, 0x10, 0xff, 0xda, 0x00, 0x08,
1173 0x01, 0x02, 0x01, 0x01, 0x3f, 0x10, 0x18, 0x81, 0x5c, 0x04, 0x1a, 0xca,
1174 0x91, 0xbf, 0xff, 0xc4, 0x00, 0x1f, 0x10, 0x01, 0x00, 0x02, 0x01, 0x04,
1175 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1176 0x00, 0x11, 0x31, 0x41, 0x61, 0x71, 0x91, 0x21, 0x81, 0xd1, 0xb1, 0xff,
1177 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x3f, 0x10, 0x1b, 0x30, 0xe9,
1178 0x58, 0xbe, 0x1a, 0xfd, 0x8a, 0xeb, 0x8b, 0x34, 0x74, 0x80, 0x4b, 0xb5,
1179 0xd5, 0xab, 0xcd, 0x46, 0x96, 0x2e, 0xec, 0xbd, 0xaa, 0x78, 0x47, 0x5c,
1180 0x47, 0xa7, 0x30, 0x49, 0xad, 0x88, 0x7c, 0x40, 0x74, 0x30, 0xff, 0x00,
1181 0x23, 0x1d, 0x03, 0x0b, 0xb7, 0xd4, 0xff, 0xd9};
1182 static const size_t kTest3JpgLen = 704;
1183
1184 // test 4 is J422 vertical - not supported
1185 static const uint8_t kTest4Jpg[] = {
1186 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01,
1187 0x01, 0x01, 0x00, 0x48, 0x00, 0x48, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43,
1188 0x00, 0x10, 0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d, 0x0e, 0x12,
1189 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a, 0x18, 0x16, 0x16, 0x18, 0x31, 0x23,
1190 0x25, 0x1d, 0x28, 0x3a, 0x33, 0x3d, 0x3c, 0x39, 0x33, 0x38, 0x37, 0x40,
1191 0x48, 0x5c, 0x4e, 0x40, 0x44, 0x57, 0x45, 0x37, 0x38, 0x50, 0x6d, 0x51,
1192 0x57, 0x5f, 0x62, 0x67, 0x68, 0x67, 0x3e, 0x4d, 0x71, 0x79, 0x70, 0x64,
1193 0x78, 0x5c, 0x65, 0x67, 0x63, 0xff, 0xdb, 0x00, 0x43, 0x01, 0x11, 0x12,
1194 0x12, 0x18, 0x15, 0x18, 0x2f, 0x1a, 0x1a, 0x2f, 0x63, 0x42, 0x38, 0x42,
1195 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1196 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1197 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1198 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
1199 0x63, 0x63, 0xff, 0xc2, 0x00, 0x11, 0x08, 0x00, 0x10, 0x00, 0x20, 0x03,
1200 0x01, 0x12, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xc4, 0x00,
1201 0x18, 0x00, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x01, 0x02, 0x03, 0xff,
1203 0xc4, 0x00, 0x16, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
1204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0xff,
1205 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x10, 0x03, 0x10, 0x00, 0x00,
1206 0x01, 0xd2, 0x98, 0xe9, 0x03, 0x0c, 0x00, 0x46, 0x21, 0xd9, 0xff, 0xc4,
1207 0x00, 0x1b, 0x10, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00,
1208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x11, 0x00, 0x03,
1209 0x10, 0x12, 0x13, 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x05,
1210 0x02, 0x3b, 0x80, 0x6f, 0x56, 0x76, 0x56, 0x23, 0x87, 0x99, 0x0d, 0x26,
1211 0x62, 0xf6, 0xbf, 0xff, 0xc4, 0x00, 0x17, 0x11, 0x01, 0x01, 0x01, 0x01,
1212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1213 0x00, 0x11, 0x01, 0x21, 0xff, 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, 0x01,
1214 0x3f, 0x01, 0x98, 0xb1, 0xbd, 0x47, 0xff, 0xc4, 0x00, 0x18, 0x11, 0x00,
1215 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1216 0x00, 0x00, 0x00, 0x00, 0x01, 0x12, 0x11, 0x21, 0xff, 0xda, 0x00, 0x08,
1217 0x01, 0x02, 0x01, 0x01, 0x3f, 0x01, 0xb6, 0x35, 0xa2, 0xe1, 0x47, 0xff,
1218 0xc4, 0x00, 0x1e, 0x10, 0x00, 0x02, 0x01, 0x03, 0x05, 0x00, 0x00, 0x00,
1219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x21, 0x02,
1220 0x12, 0x32, 0x10, 0x31, 0x71, 0x81, 0xa1, 0xff, 0xda, 0x00, 0x08, 0x01,
1221 0x01, 0x00, 0x06, 0x3f, 0x02, 0x4b, 0xb3, 0x28, 0x32, 0xd2, 0xed, 0xf9,
1222 0x1d, 0x3e, 0x13, 0x51, 0x73, 0x83, 0xff, 0xc4, 0x00, 0x1c, 0x10, 0x01,
1223 0x01, 0x01, 0x00, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1224 0x00, 0x00, 0x00, 0x01, 0x11, 0x00, 0x21, 0x51, 0x31, 0x61, 0x81, 0xf0,
1225 0xff, 0xda, 0x00, 0x08, 0x01, 0x01, 0x00, 0x01, 0x3f, 0x21, 0x75, 0x6e,
1226 0x31, 0x94, 0x28, 0xf9, 0x30, 0xdc, 0x27, 0xdb, 0xa9, 0x01, 0xf3, 0xde,
1227 0x02, 0xa0, 0xed, 0x1e, 0x34, 0x68, 0x23, 0xf9, 0xc6, 0x48, 0x5d, 0x7a,
1228 0x35, 0x02, 0xf5, 0x6f, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02,
1229 0x00, 0x03, 0x00, 0x00, 0x00, 0x10, 0x24, 0xaf, 0xff, 0xc4, 0x00, 0x19,
1230 0x11, 0x00, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1231 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x51, 0x21, 0x31, 0xff,
1232 0xda, 0x00, 0x08, 0x01, 0x03, 0x01, 0x01, 0x3f, 0x10, 0x59, 0x11, 0xca,
1233 0x42, 0x60, 0x9f, 0x69, 0xff, 0xc4, 0x00, 0x19, 0x11, 0x00, 0x02, 0x03,
1234 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1235 0x00, 0x00, 0x01, 0x11, 0x21, 0x31, 0x61, 0xff, 0xda, 0x00, 0x08, 0x01,
1236 0x02, 0x01, 0x01, 0x3f, 0x10, 0xb0, 0xd7, 0x27, 0x51, 0xb6, 0x41, 0xff,
1237 0xc4, 0x00, 0x1f, 0x10, 0x01, 0x00, 0x02, 0x01, 0x04, 0x03, 0x01, 0x00,
1238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x11, 0x31,
1239 0x41, 0x61, 0x71, 0x91, 0x21, 0x81, 0xd1, 0xb1, 0xff, 0xda, 0x00, 0x08,
1240 0x01, 0x01, 0x00, 0x01, 0x3f, 0x10, 0x1b, 0x30, 0xe9, 0x58, 0xbe, 0x1a,
1241 0xfd, 0x8a, 0xeb, 0x8b, 0x34, 0x74, 0x80, 0x4b, 0xb5, 0xd5, 0xab, 0xcd,
1242 0x46, 0x96, 0x2e, 0xec, 0xbd, 0xaa, 0x78, 0x47, 0x5c, 0x47, 0xa7, 0x30,
1243 0x49, 0xad, 0x88, 0x7c, 0x40, 0x74, 0x30, 0xff, 0x00, 0x23, 0x1d, 0x03,
1244 0x0b, 0xb7, 0xd4, 0xff, 0xd9};
1245 static const size_t kTest4JpgLen = 701;
1246
TEST_F(LibYUVConvertTest,TestMJPGSize)1247 TEST_F(LibYUVConvertTest, TestMJPGSize) {
1248 int width = 0;
1249 int height = 0;
1250 int ret = MJPGSize(kTest2Jpg, kTest2JpgLen, &width, &height);
1251 EXPECT_EQ(0, ret);
1252
1253 printf("test jpeg size %d x %d\n", width, height);
1254 }
1255
TEST_F(LibYUVConvertTest,TestMJPGToI420)1256 TEST_F(LibYUVConvertTest, TestMJPGToI420) {
1257 int width = 0;
1258 int height = 0;
1259 int ret = MJPGSize(kTest2Jpg, kTest2JpgLen, &width, &height);
1260 EXPECT_EQ(0, ret);
1261
1262 int half_width = (width + 1) / 2;
1263 int half_height = (height + 1) / 2;
1264 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1265 benchmark_height_ / (width * height);
1266 if (benchmark_iterations < 1) {
1267 benchmark_iterations = 1;
1268 }
1269
1270 align_buffer_page_end(dst_y, width * height);
1271 align_buffer_page_end(dst_u, half_width * half_height);
1272 align_buffer_page_end(dst_v, half_width * half_height);
1273 for (int times = 0; times < benchmark_iterations; ++times) {
1274 ret = MJPGToI420(kTest2Jpg, kTest2JpgLen, dst_y, width, dst_u, half_width,
1275 dst_v, half_width, width, height, width, height);
1276 }
1277 // Expect sucesss
1278 EXPECT_EQ(0, ret);
1279
1280 // Test result matches known hash value.
1281 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1282 uint32_t dst_u_hash = HashDjb2(dst_u, half_width * half_height, 5381);
1283 uint32_t dst_v_hash = HashDjb2(dst_v, half_width * half_height, 5381);
1284 EXPECT_EQ(dst_y_hash, 2682851208u);
1285 EXPECT_EQ(dst_u_hash, 2501859930u);
1286 EXPECT_EQ(dst_v_hash, 2126459123u);
1287
1288 free_aligned_buffer_page_end(dst_y);
1289 free_aligned_buffer_page_end(dst_u);
1290 free_aligned_buffer_page_end(dst_v);
1291 }
1292
TEST_F(LibYUVConvertTest,TestMJPGToI420_NV21)1293 TEST_F(LibYUVConvertTest, TestMJPGToI420_NV21) {
1294 int width = 0;
1295 int height = 0;
1296 int ret = MJPGSize(kTest2Jpg, kTest2JpgLen, &width, &height);
1297 EXPECT_EQ(0, ret);
1298
1299 int half_width = (width + 1) / 2;
1300 int half_height = (height + 1) / 2;
1301 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1302 benchmark_height_ / (width * height);
1303 if (benchmark_iterations < 1) {
1304 benchmark_iterations = 1;
1305 }
1306
1307 // Convert to NV21
1308 align_buffer_page_end(dst_y, width * height);
1309 align_buffer_page_end(dst_vu, half_width * half_height * 2);
1310
1311 for (int times = 0; times < benchmark_iterations; ++times) {
1312 ret = MJPGToNV21(kTest2Jpg, kTest2JpgLen, dst_y, width, dst_vu,
1313 half_width * 2, width, height, width, height);
1314 }
1315 // Expect sucesss
1316 EXPECT_EQ(0, ret);
1317
1318 // Convert to I420
1319 align_buffer_page_end(dst2_y, width * height);
1320 align_buffer_page_end(dst2_u, half_width * half_height);
1321 align_buffer_page_end(dst2_v, half_width * half_height);
1322 for (int times = 0; times < benchmark_iterations; ++times) {
1323 ret = MJPGToI420(kTest2Jpg, kTest2JpgLen, dst2_y, width, dst2_u, half_width,
1324 dst2_v, half_width, width, height, width, height);
1325 }
1326 // Expect sucesss
1327 EXPECT_EQ(0, ret);
1328
1329 // Convert I420 to NV21
1330 align_buffer_page_end(dst3_y, width * height);
1331 align_buffer_page_end(dst3_vu, half_width * half_height * 2);
1332
1333 I420ToNV21(dst2_y, width, dst2_u, half_width, dst2_v, half_width, dst3_y,
1334 width, dst3_vu, half_width * 2, width, height);
1335
1336 for (int i = 0; i < width * height; ++i) {
1337 EXPECT_EQ(dst_y[i], dst3_y[i]);
1338 }
1339 for (int i = 0; i < half_width * half_height * 2; ++i) {
1340 EXPECT_EQ(dst_vu[i], dst3_vu[i]);
1341 EXPECT_EQ(dst_vu[i], dst3_vu[i]);
1342 }
1343
1344 free_aligned_buffer_page_end(dst3_y);
1345 free_aligned_buffer_page_end(dst3_vu);
1346
1347 free_aligned_buffer_page_end(dst2_y);
1348 free_aligned_buffer_page_end(dst2_u);
1349 free_aligned_buffer_page_end(dst2_v);
1350
1351 free_aligned_buffer_page_end(dst_y);
1352 free_aligned_buffer_page_end(dst_vu);
1353 }
1354
TEST_F(LibYUVConvertTest,TestMJPGToI420_NV12)1355 TEST_F(LibYUVConvertTest, TestMJPGToI420_NV12) {
1356 int width = 0;
1357 int height = 0;
1358 int ret = MJPGSize(kTest2Jpg, kTest2JpgLen, &width, &height);
1359 EXPECT_EQ(0, ret);
1360
1361 int half_width = (width + 1) / 2;
1362 int half_height = (height + 1) / 2;
1363 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1364 benchmark_height_ / (width * height);
1365 if (benchmark_iterations < 1) {
1366 benchmark_iterations = 1;
1367 }
1368
1369 // Convert to NV12
1370 align_buffer_page_end(dst_y, width * height);
1371 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1372
1373 for (int times = 0; times < benchmark_iterations; ++times) {
1374 ret = MJPGToNV12(kTest2Jpg, kTest2JpgLen, dst_y, width, dst_uv,
1375 half_width * 2, width, height, width, height);
1376 }
1377 // Expect sucesss
1378 EXPECT_EQ(0, ret);
1379
1380 // Convert to I420
1381 align_buffer_page_end(dst2_y, width * height);
1382 align_buffer_page_end(dst2_u, half_width * half_height);
1383 align_buffer_page_end(dst2_v, half_width * half_height);
1384 for (int times = 0; times < benchmark_iterations; ++times) {
1385 ret = MJPGToI420(kTest2Jpg, kTest2JpgLen, dst2_y, width, dst2_u, half_width,
1386 dst2_v, half_width, width, height, width, height);
1387 }
1388 // Expect sucesss
1389 EXPECT_EQ(0, ret);
1390
1391 // Convert I420 to NV12
1392 align_buffer_page_end(dst3_y, width * height);
1393 align_buffer_page_end(dst3_uv, half_width * half_height * 2);
1394
1395 I420ToNV12(dst2_y, width, dst2_u, half_width, dst2_v, half_width, dst3_y,
1396 width, dst3_uv, half_width * 2, width, height);
1397
1398 for (int i = 0; i < width * height; ++i) {
1399 EXPECT_EQ(dst_y[i], dst3_y[i]);
1400 }
1401 for (int i = 0; i < half_width * half_height * 2; ++i) {
1402 EXPECT_EQ(dst_uv[i], dst3_uv[i]);
1403 EXPECT_EQ(dst_uv[i], dst3_uv[i]);
1404 }
1405
1406 free_aligned_buffer_page_end(dst3_y);
1407 free_aligned_buffer_page_end(dst3_uv);
1408
1409 free_aligned_buffer_page_end(dst2_y);
1410 free_aligned_buffer_page_end(dst2_u);
1411 free_aligned_buffer_page_end(dst2_v);
1412
1413 free_aligned_buffer_page_end(dst_y);
1414 free_aligned_buffer_page_end(dst_uv);
1415 }
1416
TEST_F(LibYUVConvertTest,TestMJPGToNV21_420)1417 TEST_F(LibYUVConvertTest, TestMJPGToNV21_420) {
1418 int width = 0;
1419 int height = 0;
1420 int ret = MJPGSize(kTest2Jpg, kTest2JpgLen, &width, &height);
1421 EXPECT_EQ(0, ret);
1422
1423 int half_width = (width + 1) / 2;
1424 int half_height = (height + 1) / 2;
1425 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1426 benchmark_height_ / (width * height);
1427 if (benchmark_iterations < 1) {
1428 benchmark_iterations = 1;
1429 }
1430
1431 align_buffer_page_end(dst_y, width * height);
1432 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1433 for (int times = 0; times < benchmark_iterations; ++times) {
1434 ret = MJPGToNV21(kTest2Jpg, kTest2JpgLen, dst_y, width, dst_uv,
1435 half_width * 2, width, height, width, height);
1436 }
1437 // Expect sucesss
1438 EXPECT_EQ(0, ret);
1439
1440 // Test result matches known hash value.
1441 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1442 uint32_t dst_uv_hash = HashDjb2(dst_uv, half_width * half_height * 2, 5381);
1443 EXPECT_EQ(dst_y_hash, 2682851208u);
1444 EXPECT_EQ(dst_uv_hash, 1069662856u);
1445
1446 free_aligned_buffer_page_end(dst_y);
1447 free_aligned_buffer_page_end(dst_uv);
1448 }
1449
TEST_F(LibYUVConvertTest,TestMJPGToNV12_420)1450 TEST_F(LibYUVConvertTest, TestMJPGToNV12_420) {
1451 int width = 0;
1452 int height = 0;
1453 int ret = MJPGSize(kTest2Jpg, kTest2JpgLen, &width, &height);
1454 EXPECT_EQ(0, ret);
1455
1456 int half_width = (width + 1) / 2;
1457 int half_height = (height + 1) / 2;
1458 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1459 benchmark_height_ / (width * height);
1460 if (benchmark_iterations < 1) {
1461 benchmark_iterations = 1;
1462 }
1463
1464 align_buffer_page_end(dst_y, width * height);
1465 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1466 for (int times = 0; times < benchmark_iterations; ++times) {
1467 ret = MJPGToNV12(kTest2Jpg, kTest2JpgLen, dst_y, width, dst_uv,
1468 half_width * 2, width, height, width, height);
1469 }
1470 // Expect sucesss
1471 EXPECT_EQ(0, ret);
1472
1473 // Test result matches known hash value. Hashes are for VU so flip the plane.
1474 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1475 align_buffer_page_end(dst_vu, half_width * half_height * 2);
1476 SwapUVPlane(dst_uv, half_width * 2, dst_vu, half_width * 2, half_width,
1477 half_height);
1478 uint32_t dst_vu_hash = HashDjb2(dst_vu, half_width * half_height * 2, 5381);
1479 EXPECT_EQ(dst_y_hash, 2682851208u);
1480 EXPECT_EQ(dst_vu_hash, 1069662856u);
1481
1482 free_aligned_buffer_page_end(dst_y);
1483 free_aligned_buffer_page_end(dst_uv);
1484 free_aligned_buffer_page_end(dst_vu);
1485 }
1486
1487 // TODO(fbarchard): Improve test to compare against I422, not checksum
TEST_F(LibYUVConvertTest,DISABLED_TestMJPGToNV21_422)1488 TEST_F(LibYUVConvertTest, DISABLED_TestMJPGToNV21_422) {
1489 int width = 0;
1490 int height = 0;
1491 int ret = MJPGSize(kTest3Jpg, kTest3JpgLen, &width, &height);
1492 EXPECT_EQ(0, ret);
1493
1494 int half_width = (width + 1) / 2;
1495 int half_height = (height + 1) / 2;
1496 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1497 benchmark_height_ / (width * height);
1498 if (benchmark_iterations < 1) {
1499 benchmark_iterations = 1;
1500 }
1501
1502 align_buffer_page_end(dst_y, width * height);
1503 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1504 for (int times = 0; times < benchmark_iterations; ++times) {
1505 ret = MJPGToNV21(kTest3Jpg, kTest3JpgLen, dst_y, width, dst_uv,
1506 half_width * 2, width, height, width, height);
1507 }
1508 // Expect sucesss
1509 EXPECT_EQ(0, ret);
1510
1511 // Test result matches known hash value.
1512 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1513 uint32_t dst_uv_hash = HashDjb2(dst_uv, half_width * half_height * 2, 5381);
1514 EXPECT_EQ(dst_y_hash, 2682851208u);
1515 EXPECT_EQ(dst_uv_hash, 493520167u);
1516
1517 free_aligned_buffer_page_end(dst_y);
1518 free_aligned_buffer_page_end(dst_uv);
1519 }
1520
TEST_F(LibYUVConvertTest,DISABLED_TestMJPGToNV12_422)1521 TEST_F(LibYUVConvertTest, DISABLED_TestMJPGToNV12_422) {
1522 int width = 0;
1523 int height = 0;
1524 int ret = MJPGSize(kTest3Jpg, kTest3JpgLen, &width, &height);
1525 EXPECT_EQ(0, ret);
1526
1527 int half_width = (width + 1) / 2;
1528 int half_height = (height + 1) / 2;
1529 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1530 benchmark_height_ / (width * height);
1531 if (benchmark_iterations < 1) {
1532 benchmark_iterations = 1;
1533 }
1534
1535 align_buffer_page_end(dst_y, width * height);
1536 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1537 for (int times = 0; times < benchmark_iterations; ++times) {
1538 ret = MJPGToNV12(kTest3Jpg, kTest3JpgLen, dst_y, width, dst_uv,
1539 half_width * 2, width, height, width, height);
1540 }
1541 // Expect sucesss
1542 EXPECT_EQ(0, ret);
1543
1544 // Test result matches known hash value. Hashes are for VU so flip the plane.
1545 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1546 align_buffer_page_end(dst_vu, half_width * half_height * 2);
1547 SwapUVPlane(dst_uv, half_width * 2, dst_vu, half_width * 2, half_width,
1548 half_height);
1549 uint32_t dst_vu_hash = HashDjb2(dst_vu, half_width * half_height * 2, 5381);
1550 EXPECT_EQ(dst_y_hash, 2682851208u);
1551 EXPECT_EQ(dst_vu_hash, 493520167u);
1552
1553 free_aligned_buffer_page_end(dst_y);
1554 free_aligned_buffer_page_end(dst_uv);
1555 free_aligned_buffer_page_end(dst_vu);
1556 }
1557
TEST_F(LibYUVConvertTest,TestMJPGToNV21_400)1558 TEST_F(LibYUVConvertTest, TestMJPGToNV21_400) {
1559 int width = 0;
1560 int height = 0;
1561 int ret = MJPGSize(kTest0Jpg, kTest0JpgLen, &width, &height);
1562 EXPECT_EQ(0, ret);
1563
1564 int half_width = (width + 1) / 2;
1565 int half_height = (height + 1) / 2;
1566 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1567 benchmark_height_ / (width * height);
1568 if (benchmark_iterations < 1) {
1569 benchmark_iterations = 1;
1570 }
1571
1572 align_buffer_page_end(dst_y, width * height);
1573 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1574 for (int times = 0; times < benchmark_iterations; ++times) {
1575 ret = MJPGToNV21(kTest0Jpg, kTest0JpgLen, dst_y, width, dst_uv,
1576 half_width * 2, width, height, width, height);
1577 }
1578 // Expect sucesss
1579 EXPECT_EQ(0, ret);
1580
1581 // Test result matches known hash value.
1582 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1583 uint32_t dst_uv_hash = HashDjb2(dst_uv, half_width * half_height * 2, 5381);
1584 EXPECT_EQ(dst_y_hash, 330644005u);
1585 EXPECT_EQ(dst_uv_hash, 135214341u);
1586
1587 free_aligned_buffer_page_end(dst_y);
1588 free_aligned_buffer_page_end(dst_uv);
1589 }
1590
TEST_F(LibYUVConvertTest,TestMJPGToNV12_400)1591 TEST_F(LibYUVConvertTest, TestMJPGToNV12_400) {
1592 int width = 0;
1593 int height = 0;
1594 int ret = MJPGSize(kTest0Jpg, kTest0JpgLen, &width, &height);
1595 EXPECT_EQ(0, ret);
1596
1597 int half_width = (width + 1) / 2;
1598 int half_height = (height + 1) / 2;
1599 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1600 benchmark_height_ / (width * height);
1601 if (benchmark_iterations < 1) {
1602 benchmark_iterations = 1;
1603 }
1604
1605 align_buffer_page_end(dst_y, width * height);
1606 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1607 for (int times = 0; times < benchmark_iterations; ++times) {
1608 ret = MJPGToNV12(kTest0Jpg, kTest0JpgLen, dst_y, width, dst_uv,
1609 half_width * 2, width, height, width, height);
1610 }
1611 // Expect sucesss
1612 EXPECT_EQ(0, ret);
1613
1614 // Test result matches known hash value. Hashes are for VU so flip the plane.
1615 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1616 align_buffer_page_end(dst_vu, half_width * half_height * 2);
1617 SwapUVPlane(dst_uv, half_width * 2, dst_vu, half_width * 2, half_width,
1618 half_height);
1619 uint32_t dst_vu_hash = HashDjb2(dst_vu, half_width * half_height * 2, 5381);
1620 EXPECT_EQ(dst_y_hash, 330644005u);
1621 EXPECT_EQ(dst_vu_hash, 135214341u);
1622
1623 free_aligned_buffer_page_end(dst_y);
1624 free_aligned_buffer_page_end(dst_uv);
1625 free_aligned_buffer_page_end(dst_vu);
1626 }
1627
TEST_F(LibYUVConvertTest,TestMJPGToNV21_444)1628 TEST_F(LibYUVConvertTest, TestMJPGToNV21_444) {
1629 int width = 0;
1630 int height = 0;
1631 int ret = MJPGSize(kTest1Jpg, kTest1JpgLen, &width, &height);
1632 EXPECT_EQ(0, ret);
1633
1634 int half_width = (width + 1) / 2;
1635 int half_height = (height + 1) / 2;
1636 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1637 benchmark_height_ / (width * height);
1638 if (benchmark_iterations < 1) {
1639 benchmark_iterations = 1;
1640 }
1641
1642 align_buffer_page_end(dst_y, width * height);
1643 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1644 for (int times = 0; times < benchmark_iterations; ++times) {
1645 ret = MJPGToNV21(kTest1Jpg, kTest1JpgLen, dst_y, width, dst_uv,
1646 half_width * 2, width, height, width, height);
1647 }
1648 // Expect sucesss
1649 EXPECT_EQ(0, ret);
1650
1651 // Test result matches known hash value.
1652 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1653 uint32_t dst_uv_hash = HashDjb2(dst_uv, half_width * half_height * 2, 5381);
1654 EXPECT_EQ(dst_y_hash, 2682851208u);
1655 EXPECT_EQ(dst_uv_hash, 506143297u);
1656
1657 free_aligned_buffer_page_end(dst_y);
1658 free_aligned_buffer_page_end(dst_uv);
1659 }
1660
TEST_F(LibYUVConvertTest,TestMJPGToNV12_444)1661 TEST_F(LibYUVConvertTest, TestMJPGToNV12_444) {
1662 int width = 0;
1663 int height = 0;
1664 int ret = MJPGSize(kTest1Jpg, kTest1JpgLen, &width, &height);
1665 EXPECT_EQ(0, ret);
1666
1667 int half_width = (width + 1) / 2;
1668 int half_height = (height + 1) / 2;
1669 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1670 benchmark_height_ / (width * height);
1671 if (benchmark_iterations < 1) {
1672 benchmark_iterations = 1;
1673 }
1674
1675 align_buffer_page_end(dst_y, width * height);
1676 align_buffer_page_end(dst_uv, half_width * half_height * 2);
1677 for (int times = 0; times < benchmark_iterations; ++times) {
1678 ret = MJPGToNV12(kTest1Jpg, kTest1JpgLen, dst_y, width, dst_uv,
1679 half_width * 2, width, height, width, height);
1680 }
1681 // Expect sucesss
1682 EXPECT_EQ(0, ret);
1683
1684 // Test result matches known hash value. Hashes are for VU so flip the plane.
1685 uint32_t dst_y_hash = HashDjb2(dst_y, width * height, 5381);
1686 align_buffer_page_end(dst_vu, half_width * half_height * 2);
1687 SwapUVPlane(dst_uv, half_width * 2, dst_vu, half_width * 2, half_width,
1688 half_height);
1689 uint32_t dst_vu_hash = HashDjb2(dst_vu, half_width * half_height * 2, 5381);
1690 EXPECT_EQ(dst_y_hash, 2682851208u);
1691 EXPECT_EQ(dst_vu_hash, 506143297u);
1692
1693 free_aligned_buffer_page_end(dst_y);
1694 free_aligned_buffer_page_end(dst_uv);
1695 free_aligned_buffer_page_end(dst_vu);
1696 }
1697
TEST_F(LibYUVConvertTest,TestMJPGToARGB)1698 TEST_F(LibYUVConvertTest, TestMJPGToARGB) {
1699 int width = 0;
1700 int height = 0;
1701 int ret = MJPGSize(kTest3Jpg, kTest3JpgLen, &width, &height);
1702 EXPECT_EQ(0, ret);
1703
1704 int benchmark_iterations = benchmark_iterations_ * benchmark_width_ *
1705 benchmark_height_ / (width * height);
1706 if (benchmark_iterations < 1) {
1707 benchmark_iterations = 1;
1708 }
1709
1710 align_buffer_page_end(dst_argb, width * height * 4);
1711 for (int times = 0; times < benchmark_iterations; ++times) {
1712 ret = MJPGToARGB(kTest3Jpg, kTest3JpgLen, dst_argb, width * 4, width,
1713 height, width, height);
1714 }
1715 // Expect sucesss
1716 EXPECT_EQ(0, ret);
1717
1718 // Test result matches known hash value.
1719 uint32_t dst_argb_hash = HashDjb2(dst_argb, width * height, 5381);
1720 #ifdef LIBYUV_UNLIMITED_DATA
1721 EXPECT_EQ(dst_argb_hash, 3900633302u);
1722 #else
1723 EXPECT_EQ(dst_argb_hash, 2355976473u);
1724 #endif
1725
1726 free_aligned_buffer_page_end(dst_argb);
1727 }
1728
ShowJPegInfo(const uint8_t * sample,size_t sample_size)1729 static int ShowJPegInfo(const uint8_t* sample, size_t sample_size) {
1730 MJpegDecoder mjpeg_decoder;
1731 LIBYUV_BOOL ret = mjpeg_decoder.LoadFrame(sample, sample_size);
1732
1733 int width = mjpeg_decoder.GetWidth();
1734 int height = mjpeg_decoder.GetHeight();
1735
1736 // YUV420
1737 if (mjpeg_decoder.GetColorSpace() == MJpegDecoder::kColorSpaceYCbCr &&
1738 mjpeg_decoder.GetNumComponents() == 3 &&
1739 mjpeg_decoder.GetVertSampFactor(0) == 2 &&
1740 mjpeg_decoder.GetHorizSampFactor(0) == 2 &&
1741 mjpeg_decoder.GetVertSampFactor(1) == 1 &&
1742 mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
1743 mjpeg_decoder.GetVertSampFactor(2) == 1 &&
1744 mjpeg_decoder.GetHorizSampFactor(2) == 1) {
1745 printf("JPeg is J420, %dx%d %d bytes\n", width, height,
1746 static_cast<int>(sample_size));
1747 // YUV422
1748 } else if (mjpeg_decoder.GetColorSpace() == MJpegDecoder::kColorSpaceYCbCr &&
1749 mjpeg_decoder.GetNumComponents() == 3 &&
1750 mjpeg_decoder.GetVertSampFactor(0) == 1 &&
1751 mjpeg_decoder.GetHorizSampFactor(0) == 2 &&
1752 mjpeg_decoder.GetVertSampFactor(1) == 1 &&
1753 mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
1754 mjpeg_decoder.GetVertSampFactor(2) == 1 &&
1755 mjpeg_decoder.GetHorizSampFactor(2) == 1) {
1756 printf("JPeg is J422, %dx%d %d bytes\n", width, height,
1757 static_cast<int>(sample_size));
1758 // YUV444
1759 } else if (mjpeg_decoder.GetColorSpace() == MJpegDecoder::kColorSpaceYCbCr &&
1760 mjpeg_decoder.GetNumComponents() == 3 &&
1761 mjpeg_decoder.GetVertSampFactor(0) == 1 &&
1762 mjpeg_decoder.GetHorizSampFactor(0) == 1 &&
1763 mjpeg_decoder.GetVertSampFactor(1) == 1 &&
1764 mjpeg_decoder.GetHorizSampFactor(1) == 1 &&
1765 mjpeg_decoder.GetVertSampFactor(2) == 1 &&
1766 mjpeg_decoder.GetHorizSampFactor(2) == 1) {
1767 printf("JPeg is J444, %dx%d %d bytes\n", width, height,
1768 static_cast<int>(sample_size));
1769 // YUV400
1770 } else if (mjpeg_decoder.GetColorSpace() ==
1771 MJpegDecoder::kColorSpaceGrayscale &&
1772 mjpeg_decoder.GetNumComponents() == 1 &&
1773 mjpeg_decoder.GetVertSampFactor(0) == 1 &&
1774 mjpeg_decoder.GetHorizSampFactor(0) == 1) {
1775 printf("JPeg is J400, %dx%d %d bytes\n", width, height,
1776 static_cast<int>(sample_size));
1777 } else {
1778 // Unknown colorspace.
1779 printf("JPeg is Unknown colorspace.\n");
1780 }
1781 mjpeg_decoder.UnloadFrame();
1782 return ret;
1783 }
1784
TEST_F(LibYUVConvertTest,TestMJPGInfo)1785 TEST_F(LibYUVConvertTest, TestMJPGInfo) {
1786 EXPECT_EQ(1, ShowJPegInfo(kTest0Jpg, kTest0JpgLen));
1787 EXPECT_EQ(1, ShowJPegInfo(kTest1Jpg, kTest1JpgLen));
1788 EXPECT_EQ(1, ShowJPegInfo(kTest2Jpg, kTest2JpgLen));
1789 EXPECT_EQ(1, ShowJPegInfo(kTest3Jpg, kTest3JpgLen));
1790 EXPECT_EQ(1, ShowJPegInfo(kTest4Jpg,
1791 kTest4JpgLen)); // Valid but unsupported.
1792 }
1793 #endif // HAVE_JPEG
1794
TEST_F(LibYUVConvertTest,NV12Crop)1795 TEST_F(LibYUVConvertTest, NV12Crop) {
1796 const int SUBSAMP_X = 2;
1797 const int SUBSAMP_Y = 2;
1798 const int kWidth = benchmark_width_;
1799 const int kHeight = benchmark_height_;
1800 const int crop_y =
1801 ((benchmark_height_ - (benchmark_height_ * 360 / 480)) / 2 + 1) & ~1;
1802 const int kDestWidth = benchmark_width_;
1803 const int kDestHeight = benchmark_height_ - crop_y * 2;
1804 const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X);
1805 const int sample_size =
1806 kWidth * kHeight + kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y) * 2;
1807 align_buffer_page_end(src_y, sample_size);
1808 uint8_t* src_uv = src_y + kWidth * kHeight;
1809
1810 align_buffer_page_end(dst_y, kDestWidth * kDestHeight);
1811 align_buffer_page_end(dst_u, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1812 SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1813 align_buffer_page_end(dst_v, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1814 SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1815
1816 align_buffer_page_end(dst_y_2, kDestWidth * kDestHeight);
1817 align_buffer_page_end(dst_u_2, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1818 SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1819 align_buffer_page_end(dst_v_2, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1820 SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1821
1822 for (int i = 0; i < kHeight * kWidth; ++i) {
1823 src_y[i] = (fastrand() & 0xff);
1824 }
1825 for (int i = 0; i < (SUBSAMPLE(kHeight, SUBSAMP_Y) * kStrideUV) * 2; ++i) {
1826 src_uv[i] = (fastrand() & 0xff);
1827 }
1828 memset(dst_y, 1, kDestWidth * kDestHeight);
1829 memset(dst_u, 2,
1830 SUBSAMPLE(kDestWidth, SUBSAMP_X) * SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1831 memset(dst_v, 3,
1832 SUBSAMPLE(kDestWidth, SUBSAMP_X) * SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1833 memset(dst_y_2, 1, kDestWidth * kDestHeight);
1834 memset(dst_u_2, 2,
1835 SUBSAMPLE(kDestWidth, SUBSAMP_X) * SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1836 memset(dst_v_2, 3,
1837 SUBSAMPLE(kDestWidth, SUBSAMP_X) * SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1838
1839 ConvertToI420(src_y, sample_size, dst_y_2, kDestWidth, dst_u_2,
1840 SUBSAMPLE(kDestWidth, SUBSAMP_X), dst_v_2,
1841 SUBSAMPLE(kDestWidth, SUBSAMP_X), 0, crop_y, kWidth, kHeight,
1842 kDestWidth, kDestHeight, libyuv::kRotate0, libyuv::FOURCC_NV12);
1843
1844 NV12ToI420(src_y + crop_y * kWidth, kWidth,
1845 src_uv + (crop_y / 2) * kStrideUV * 2, kStrideUV * 2, dst_y,
1846 kDestWidth, dst_u, SUBSAMPLE(kDestWidth, SUBSAMP_X), dst_v,
1847 SUBSAMPLE(kDestWidth, SUBSAMP_X), kDestWidth, kDestHeight);
1848
1849 for (int i = 0; i < kDestHeight; ++i) {
1850 for (int j = 0; j < kDestWidth; ++j) {
1851 EXPECT_EQ(dst_y[i * kWidth + j], dst_y_2[i * kWidth + j]);
1852 }
1853 }
1854 for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) {
1855 for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) {
1856 EXPECT_EQ(dst_u[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j],
1857 dst_u_2[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]);
1858 }
1859 }
1860 for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) {
1861 for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) {
1862 EXPECT_EQ(dst_v[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j],
1863 dst_v_2[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]);
1864 }
1865 }
1866 free_aligned_buffer_page_end(dst_y);
1867 free_aligned_buffer_page_end(dst_u);
1868 free_aligned_buffer_page_end(dst_v);
1869 free_aligned_buffer_page_end(dst_y_2);
1870 free_aligned_buffer_page_end(dst_u_2);
1871 free_aligned_buffer_page_end(dst_v_2);
1872 free_aligned_buffer_page_end(src_y);
1873 }
1874
TEST_F(LibYUVConvertTest,I420CropOddY)1875 TEST_F(LibYUVConvertTest, I420CropOddY) {
1876 const int SUBSAMP_X = 2;
1877 const int SUBSAMP_Y = 2;
1878 const int kWidth = benchmark_width_;
1879 const int kHeight = benchmark_height_;
1880 const int crop_y = benchmark_height_ > 1 ? 1 : 0;
1881 const int kDestWidth = benchmark_width_;
1882 const int kDestHeight = benchmark_height_ - crop_y * 2;
1883 const int kStrideU = SUBSAMPLE(kWidth, SUBSAMP_X);
1884 const int kStrideV = SUBSAMPLE(kWidth, SUBSAMP_X);
1885 const int sample_size = kWidth * kHeight +
1886 kStrideU * SUBSAMPLE(kHeight, SUBSAMP_Y) +
1887 kStrideV * SUBSAMPLE(kHeight, SUBSAMP_Y);
1888 align_buffer_page_end(src_y, sample_size);
1889 uint8_t* src_u = src_y + kWidth * kHeight;
1890 uint8_t* src_v = src_u + kStrideU * SUBSAMPLE(kHeight, SUBSAMP_Y);
1891
1892 align_buffer_page_end(dst_y, kDestWidth * kDestHeight);
1893 align_buffer_page_end(dst_u, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1894 SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1895 align_buffer_page_end(dst_v, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1896 SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1897
1898 for (int i = 0; i < kHeight * kWidth; ++i) {
1899 src_y[i] = (fastrand() & 0xff);
1900 }
1901 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y) * kStrideU; ++i) {
1902 src_u[i] = (fastrand() & 0xff);
1903 }
1904 for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y) * kStrideV; ++i) {
1905 src_v[i] = (fastrand() & 0xff);
1906 }
1907 memset(dst_y, 1, kDestWidth * kDestHeight);
1908 memset(dst_u, 2,
1909 SUBSAMPLE(kDestWidth, SUBSAMP_X) * SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1910 memset(dst_v, 3,
1911 SUBSAMPLE(kDestWidth, SUBSAMP_X) * SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1912
1913 MaskCpuFlags(benchmark_cpu_info_);
1914 for (int i = 0; i < benchmark_iterations_; ++i) {
1915 ConvertToI420(src_y, sample_size, dst_y, kDestWidth, dst_u,
1916 SUBSAMPLE(kDestWidth, SUBSAMP_X), dst_v,
1917 SUBSAMPLE(kDestWidth, SUBSAMP_X), 0, crop_y, kWidth, kHeight,
1918 kDestWidth, kDestHeight, libyuv::kRotate0,
1919 libyuv::FOURCC_I420);
1920 }
1921
1922 for (int i = 0; i < kDestHeight; ++i) {
1923 for (int j = 0; j < kDestWidth; ++j) {
1924 EXPECT_EQ(src_y[crop_y * kWidth + i * kWidth + j],
1925 dst_y[i * kDestWidth + j]);
1926 }
1927 }
1928 for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) {
1929 for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) {
1930 EXPECT_EQ(src_u[(crop_y / 2 + i) * kStrideU + j],
1931 dst_u[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]);
1932 }
1933 }
1934 for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) {
1935 for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) {
1936 EXPECT_EQ(src_v[(crop_y / 2 + i) * kStrideV + j],
1937 dst_v[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]);
1938 }
1939 }
1940
1941 free_aligned_buffer_page_end(dst_y);
1942 free_aligned_buffer_page_end(dst_u);
1943 free_aligned_buffer_page_end(dst_v);
1944 free_aligned_buffer_page_end(src_y);
1945 }
1946
1947 #define TESTPTOB(NAME, UYVYTOI420, UYVYTONV12) \
1948 TEST_F(LibYUVConvertTest, NAME) { \
1949 const int kWidth = benchmark_width_; \
1950 const int kHeight = benchmark_height_; \
1951 \
1952 align_buffer_page_end(orig_uyvy, 4 * SUBSAMPLE(kWidth, 2) * kHeight); \
1953 align_buffer_page_end(orig_y, kWidth* kHeight); \
1954 align_buffer_page_end(orig_u, \
1955 SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2)); \
1956 align_buffer_page_end(orig_v, \
1957 SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2)); \
1958 \
1959 align_buffer_page_end(dst_y_orig, kWidth* kHeight); \
1960 align_buffer_page_end(dst_uv_orig, \
1961 2 * SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2)); \
1962 \
1963 align_buffer_page_end(dst_y, kWidth* kHeight); \
1964 align_buffer_page_end(dst_uv, \
1965 2 * SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2)); \
1966 \
1967 MemRandomize(orig_uyvy, 4 * SUBSAMPLE(kWidth, 2) * kHeight); \
1968 \
1969 /* Convert UYVY to NV12 in 2 steps for reference */ \
1970 libyuv::UYVYTOI420(orig_uyvy, 4 * SUBSAMPLE(kWidth, 2), orig_y, kWidth, \
1971 orig_u, SUBSAMPLE(kWidth, 2), orig_v, \
1972 SUBSAMPLE(kWidth, 2), kWidth, kHeight); \
1973 libyuv::I420ToNV12(orig_y, kWidth, orig_u, SUBSAMPLE(kWidth, 2), orig_v, \
1974 SUBSAMPLE(kWidth, 2), dst_y_orig, kWidth, dst_uv_orig, \
1975 2 * SUBSAMPLE(kWidth, 2), kWidth, kHeight); \
1976 \
1977 /* Convert to NV12 */ \
1978 for (int i = 0; i < benchmark_iterations_; ++i) { \
1979 libyuv::UYVYTONV12(orig_uyvy, 4 * SUBSAMPLE(kWidth, 2), dst_y, kWidth, \
1980 dst_uv, 2 * SUBSAMPLE(kWidth, 2), kWidth, kHeight); \
1981 } \
1982 \
1983 for (int i = 0; i < kWidth * kHeight; ++i) { \
1984 EXPECT_EQ(orig_y[i], dst_y[i]); \
1985 } \
1986 for (int i = 0; i < kWidth * kHeight; ++i) { \
1987 EXPECT_EQ(dst_y_orig[i], dst_y[i]); \
1988 } \
1989 for (int i = 0; i < 2 * SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2); \
1990 ++i) { \
1991 EXPECT_EQ(dst_uv_orig[i], dst_uv[i]); \
1992 } \
1993 \
1994 free_aligned_buffer_page_end(orig_uyvy); \
1995 free_aligned_buffer_page_end(orig_y); \
1996 free_aligned_buffer_page_end(orig_u); \
1997 free_aligned_buffer_page_end(orig_v); \
1998 free_aligned_buffer_page_end(dst_y_orig); \
1999 free_aligned_buffer_page_end(dst_uv_orig); \
2000 free_aligned_buffer_page_end(dst_y); \
2001 free_aligned_buffer_page_end(dst_uv); \
2002 }
2003
TESTPTOB(TestYUY2ToNV12,YUY2ToI420,YUY2ToNV12)2004 TESTPTOB(TestYUY2ToNV12, YUY2ToI420, YUY2ToNV12)
2005 TESTPTOB(TestUYVYToNV12, UYVYToI420, UYVYToNV12)
2006
2007 TEST_F(LibYUVConvertTest, MM21ToYUY2) {
2008 const int kWidth = (benchmark_width_ + 15) & (~15);
2009 const int kHeight = (benchmark_height_ + 31) & (~31);
2010
2011 align_buffer_page_end(orig_y, kWidth * kHeight);
2012 align_buffer_page_end(orig_uv,
2013 2 * SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2));
2014
2015 align_buffer_page_end(tmp_y, kWidth * kHeight);
2016 align_buffer_page_end(tmp_u, SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2));
2017 align_buffer_page_end(tmp_v, SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2));
2018
2019 align_buffer_page_end(dst_yuyv, 4 * SUBSAMPLE(kWidth, 2) * kHeight);
2020 align_buffer_page_end(golden_yuyv, 4 * SUBSAMPLE(kWidth, 2) * kHeight);
2021
2022 MemRandomize(orig_y, kWidth * kHeight);
2023 MemRandomize(orig_uv, 2 * SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2));
2024
2025 /* Convert MM21 to YUY2 in 2 steps for reference */
2026 libyuv::MM21ToI420(orig_y, kWidth, orig_uv, 2 * SUBSAMPLE(kWidth, 2), tmp_y,
2027 kWidth, tmp_u, SUBSAMPLE(kWidth, 2), tmp_v,
2028 SUBSAMPLE(kWidth, 2), kWidth, kHeight);
2029 libyuv::I420ToYUY2(tmp_y, kWidth, tmp_u, SUBSAMPLE(kWidth, 2), tmp_v,
2030 SUBSAMPLE(kWidth, 2), golden_yuyv,
2031 4 * SUBSAMPLE(kWidth, 2), kWidth, kHeight);
2032
2033 /* Convert to NV12 */
2034 for (int i = 0; i < benchmark_iterations_; ++i) {
2035 libyuv::MM21ToYUY2(orig_y, kWidth, orig_uv, 2 * SUBSAMPLE(kWidth, 2),
2036 dst_yuyv, 4 * SUBSAMPLE(kWidth, 2), kWidth, kHeight);
2037 }
2038
2039 for (int i = 0; i < 4 * SUBSAMPLE(kWidth, 2) * kHeight; ++i) {
2040 EXPECT_EQ(dst_yuyv[i], golden_yuyv[i]);
2041 }
2042
2043 free_aligned_buffer_page_end(orig_y);
2044 free_aligned_buffer_page_end(orig_uv);
2045 free_aligned_buffer_page_end(tmp_y);
2046 free_aligned_buffer_page_end(tmp_u);
2047 free_aligned_buffer_page_end(tmp_v);
2048 free_aligned_buffer_page_end(dst_yuyv);
2049 free_aligned_buffer_page_end(golden_yuyv);
2050 }
2051
2052 // Test RGB24 to J420 is exact
2053 #if defined(LIBYUV_BIT_EXACT)
TEST_F(LibYUVConvertTest,TestRGB24ToJ420)2054 TEST_F(LibYUVConvertTest, TestRGB24ToJ420) {
2055 const int kSize = 256;
2056 align_buffer_page_end(orig_rgb24, kSize * 3 * 2); // 2 rows of RGB24
2057 align_buffer_page_end(dest_j420, kSize * 3 / 2 * 2);
2058 int iterations256 = (benchmark_width_ * benchmark_height_ + (kSize * 2 - 1)) /
2059 (kSize * 2) * benchmark_iterations_;
2060
2061 for (int i = 0; i < kSize * 3 * 2; ++i) {
2062 orig_rgb24[i] = i;
2063 }
2064
2065 for (int i = 0; i < iterations256; ++i) {
2066 RGB24ToJ420(orig_rgb24, kSize * 3, dest_j420, kSize, // Y plane
2067 dest_j420 + kSize * 2, kSize / 2, // U plane
2068 dest_j420 + kSize * 5 / 2, kSize / 2, // V plane
2069 kSize, 2);
2070 }
2071
2072 uint32_t checksum = HashDjb2(dest_j420, kSize * 3 / 2 * 2, 5381);
2073 EXPECT_EQ(2755440272u, checksum);
2074
2075 free_aligned_buffer_page_end(orig_rgb24);
2076 free_aligned_buffer_page_end(dest_j420);
2077 }
2078 #endif
2079
2080 // Test RGB24 to I420 is exact
2081 #if defined(LIBYUV_BIT_EXACT)
TEST_F(LibYUVConvertTest,TestRGB24ToI420)2082 TEST_F(LibYUVConvertTest, TestRGB24ToI420) {
2083 const int kSize = 256;
2084 align_buffer_page_end(orig_rgb24, kSize * 3 * 2); // 2 rows of RGB24
2085 align_buffer_page_end(dest_i420, kSize * 3 / 2 * 2);
2086 int iterations256 = (benchmark_width_ * benchmark_height_ + (kSize * 2 - 1)) /
2087 (kSize * 2) * benchmark_iterations_;
2088
2089 for (int i = 0; i < kSize * 3 * 2; ++i) {
2090 orig_rgb24[i] = i;
2091 }
2092
2093 for (int i = 0; i < iterations256; ++i) {
2094 RGB24ToI420(orig_rgb24, kSize * 3, dest_i420, kSize, // Y plane
2095 dest_i420 + kSize * 2, kSize / 2, // U plane
2096 dest_i420 + kSize * 5 / 2, kSize / 2, // V plane
2097 kSize, 2);
2098 }
2099
2100 uint32_t checksum = HashDjb2(dest_i420, kSize * 3 / 2 * 2, 5381);
2101 EXPECT_EQ(1526656597u, checksum);
2102
2103 free_aligned_buffer_page_end(orig_rgb24);
2104 free_aligned_buffer_page_end(dest_i420);
2105 }
2106 #endif
2107
2108 #endif // !defined(LEAN_TESTS)
2109
2110 } // namespace libyuv
2111