xref: /aosp_15_r20/external/libyuv/unit_test/convert_test.cc (revision 4e366538070a3a6c5c163c31b791eab742e1657a)
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