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 <stdlib.h>
12#include <time.h>
13
14#include "libyuv/compare.h"
15#include "libyuv/convert.h"
16#include "libyuv/convert_argb.h"
17#include "libyuv/convert_from.h"
18#include "libyuv/convert_from_argb.h"
19#include "libyuv/cpu_id.h"
20#include "libyuv/format_conversion.h"
21#ifdef HAVE_JPEG
22#include "libyuv/mjpeg_decoder.h"
23#endif
24#include "libyuv/planar_functions.h"
25#include "libyuv/rotate.h"
26#include "libyuv/row.h"
27#include "libyuv/video_common.h"
28#include "../unit_test/unit_test.h"
29
30#if defined(_MSC_VER)
31#define SIMD_ALIGNED(var) __declspec(align(16)) var
32#else  // __GNUC__
33#define SIMD_ALIGNED(var) var __attribute__((aligned(16)))
34#endif
35
36namespace libyuv {
37
38#define SUBSAMPLE(v, a) ((((v) + (a) - 1)) / (a))
39
40#define TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,           \
41                       FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF)   \
42TEST_F(libyuvTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) {                        \
43  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
44  const int kHeight = benchmark_height_;                                       \
45  align_buffer_64(src_y, kWidth * kHeight + OFF);                              \
46  align_buffer_64(src_u,                                                       \
47                  SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                           \
48                  SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);                    \
49  align_buffer_64(src_v,                                                       \
50                  SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                           \
51                  SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);                    \
52  align_buffer_64(dst_y_c, kWidth * kHeight);                                  \
53  align_buffer_64(dst_u_c,                                                     \
54                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
55                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
56  align_buffer_64(dst_v_c,                                                     \
57                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
58                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
59  align_buffer_64(dst_y_opt, kWidth * kHeight);                                \
60  align_buffer_64(dst_u_opt,                                                   \
61                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
62                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
63  align_buffer_64(dst_v_opt,                                                   \
64                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
65                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
66  srandom(time(NULL));                                                         \
67  for (int i = 0; i < kHeight; ++i)                                            \
68    for (int j = 0; j < kWidth; ++j)                                           \
69      src_y[(i * kWidth) + j + OFF] = (random() & 0xff);                       \
70  for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) {                \
71    for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) {               \
72      src_u[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \
73          (random() & 0xff);                                                   \
74      src_v[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \
75          (random() & 0xff);                                                   \
76    }                                                                          \
77  }                                                                            \
78  memset(dst_y_c, 1, kWidth * kHeight);                                        \
79  memset(dst_u_c, 2, SUBSAMPLE(kWidth, SUBSAMP_X) *                            \
80                     SUBSAMPLE(kHeight, SUBSAMP_Y));                           \
81  memset(dst_v_c, 3, SUBSAMPLE(kWidth, SUBSAMP_X) *                            \
82                     SUBSAMPLE(kHeight, SUBSAMP_Y));                           \
83  memset(dst_y_opt, 101, kWidth * kHeight);                                    \
84  memset(dst_u_opt, 102, SUBSAMPLE(kWidth, SUBSAMP_X) *                        \
85                         SUBSAMPLE(kHeight, SUBSAMP_Y));                       \
86  memset(dst_v_opt, 103, SUBSAMPLE(kWidth, SUBSAMP_X) *                        \
87                         SUBSAMPLE(kHeight, SUBSAMP_Y));                       \
88  MaskCpuFlags(0);                                                             \
89  SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                          \
90                                 src_u + OFF,                                  \
91                                 SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \
92                                 src_v + OFF,                                  \
93                                 SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \
94                                 dst_y_c, kWidth,                              \
95                                 dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \
96                                 dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \
97                                 kWidth, NEG kHeight);                         \
98  MaskCpuFlags(-1);                                                            \
99  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
100    SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                        \
101                                   src_u + OFF,                                \
102                                       SUBSAMPLE(kWidth, SRC_SUBSAMP_X),       \
103                                   src_v + OFF,                                \
104                                       SUBSAMPLE(kWidth, SRC_SUBSAMP_X),       \
105                                   dst_y_opt, kWidth,                          \
106                                   dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \
107                                   dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \
108                                   kWidth, NEG kHeight);                       \
109  }                                                                            \
110  int max_diff = 0;                                                            \
111  for (int i = 0; i < kHeight; ++i) {                                          \
112    for (int j = 0; j < kWidth; ++j) {                                         \
113      int abs_diff =                                                           \
114          abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
115              static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
116      if (abs_diff > max_diff) {                                               \
117        max_diff = abs_diff;                                                   \
118      }                                                                        \
119    }                                                                          \
120  }                                                                            \
121  EXPECT_EQ(0, max_diff);                                                      \
122  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
123    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
124      int abs_diff =                                                           \
125          abs(static_cast<int>(dst_u_c[i *                                     \
126                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
127              static_cast<int>(dst_u_opt[i *                                   \
128                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
129      if (abs_diff > max_diff) {                                               \
130        max_diff = abs_diff;                                                   \
131      }                                                                        \
132    }                                                                          \
133  }                                                                            \
134  EXPECT_LE(max_diff, 3);                                                      \
135  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
136    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
137      int abs_diff =                                                           \
138          abs(static_cast<int>(dst_v_c[i *                                     \
139                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
140              static_cast<int>(dst_v_opt[i *                                   \
141                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
142      if (abs_diff > max_diff) {                                               \
143        max_diff = abs_diff;                                                   \
144      }                                                                        \
145    }                                                                          \
146  }                                                                            \
147  EXPECT_LE(max_diff, 3);                                                      \
148  free_aligned_buffer_64(dst_y_c);                                             \
149  free_aligned_buffer_64(dst_u_c);                                             \
150  free_aligned_buffer_64(dst_v_c);                                             \
151  free_aligned_buffer_64(dst_y_opt);                                           \
152  free_aligned_buffer_64(dst_u_opt);                                           \
153  free_aligned_buffer_64(dst_v_opt);                                           \
154  free_aligned_buffer_64(src_y);                                               \
155  free_aligned_buffer_64(src_u);                                               \
156  free_aligned_buffer_64(src_v);                                               \
157}
158
159#define TESTPLANARTOP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,            \
160                      FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y)                        \
161    TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,               \
162                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                           \
163                   benchmark_width_ - 4, _Any, +, 0)                           \
164    TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,               \
165                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                           \
166                   benchmark_width_, _Unaligned, +, 1)                         \
167    TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,               \
168                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                           \
169                   benchmark_width_, _Invert, -, 0)                            \
170    TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,               \
171                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                           \
172                   benchmark_width_, _Opt, +, 0)
173
174TESTPLANARTOP(I420, 2, 2, I420, 2, 2)
175TESTPLANARTOP(I422, 2, 1, I420, 2, 2)
176TESTPLANARTOP(I444, 1, 1, I420, 2, 2)
177TESTPLANARTOP(I411, 4, 1, I420, 2, 2)
178TESTPLANARTOP(I420, 2, 2, I422, 2, 1)
179TESTPLANARTOP(I420, 2, 2, I444, 1, 1)
180TESTPLANARTOP(I420, 2, 2, I411, 4, 1)
181TESTPLANARTOP(I420, 2, 2, I420Mirror, 2, 2)
182TESTPLANARTOP(I422, 2, 1, I422, 2, 1)
183TESTPLANARTOP(I444, 1, 1, I444, 1, 1)
184
185#define TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,          \
186                       FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF)   \
187TEST_F(libyuvTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) {                        \
188  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
189  const int kHeight = benchmark_height_;                                       \
190  align_buffer_64(src_y, kWidth * kHeight + OFF);                              \
191  align_buffer_64(src_u,                                                       \
192                  SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                           \
193                  SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);                    \
194  align_buffer_64(src_v,                                                       \
195                  SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                           \
196                  SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);                    \
197  align_buffer_64(dst_y_c, kWidth * kHeight);                                  \
198  align_buffer_64(dst_uv_c, SUBSAMPLE(kWidth * 2, SUBSAMP_X) *                 \
199                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
200  align_buffer_64(dst_y_opt, kWidth * kHeight);                                \
201  align_buffer_64(dst_uv_opt, SUBSAMPLE(kWidth * 2, SUBSAMP_X) *               \
202                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
203  srandom(time(NULL));                                                         \
204  for (int i = 0; i < kHeight; ++i)                                            \
205    for (int j = 0; j < kWidth; ++j)                                           \
206      src_y[(i * kWidth) + j + OFF] = (random() & 0xff);                       \
207  for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) {                \
208    for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) {               \
209      src_u[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \
210          (random() & 0xff);                                                   \
211      src_v[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \
212          (random() & 0xff);                                                   \
213    }                                                                          \
214  }                                                                            \
215  memset(dst_y_c, 1, kWidth * kHeight);                                        \
216  memset(dst_uv_c, 2, SUBSAMPLE(kWidth * 2, SUBSAMP_X) *                       \
217                      SUBSAMPLE(kHeight, SUBSAMP_Y));                          \
218  memset(dst_y_opt, 101, kWidth * kHeight);                                    \
219  memset(dst_uv_opt, 102, SUBSAMPLE(kWidth * 2, SUBSAMP_X) *                   \
220                          SUBSAMPLE(kHeight, SUBSAMP_Y));                      \
221  MaskCpuFlags(0);                                                             \
222  SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                          \
223                                 src_u + OFF,                                  \
224                                 SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \
225                                 src_v + OFF,                                  \
226                                 SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \
227                                 dst_y_c, kWidth,                              \
228                                 dst_uv_c, SUBSAMPLE(kWidth * 2, SUBSAMP_X),   \
229                                 kWidth, NEG kHeight);                         \
230  MaskCpuFlags(-1);                                                            \
231  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
232    SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                        \
233                                   src_u + OFF,                                \
234                                   SUBSAMPLE(kWidth, SRC_SUBSAMP_X),           \
235                                   src_v + OFF,                                \
236                                   SUBSAMPLE(kWidth, SRC_SUBSAMP_X),           \
237                                   dst_y_opt, kWidth,                          \
238                                   dst_uv_opt,                                 \
239                                   SUBSAMPLE(kWidth * 2, SUBSAMP_X),           \
240                                   kWidth, NEG kHeight);                       \
241  }                                                                            \
242  int max_diff = 0;                                                            \
243  for (int i = 0; i < kHeight; ++i) {                                          \
244    for (int j = 0; j < kWidth; ++j) {                                         \
245      int abs_diff =                                                           \
246          abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
247              static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
248      if (abs_diff > max_diff) {                                               \
249        max_diff = abs_diff;                                                   \
250      }                                                                        \
251    }                                                                          \
252  }                                                                            \
253  EXPECT_LE(max_diff, 1);                                                      \
254  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
255    for (int j = 0; j < SUBSAMPLE(kWidth * 2, SUBSAMP_X); ++j) {               \
256      int abs_diff =                                                           \
257          abs(static_cast<int>(dst_uv_c[i *                                    \
258                               SUBSAMPLE(kWidth * 2, SUBSAMP_X) + j]) -        \
259              static_cast<int>(dst_uv_opt[i *                                  \
260                               SUBSAMPLE(kWidth * 2, SUBSAMP_X) + j]));        \
261      if (abs_diff > max_diff) {                                               \
262        max_diff = abs_diff;                                                   \
263      }                                                                        \
264    }                                                                          \
265  }                                                                            \
266  EXPECT_LE(max_diff, 1);                                                      \
267  free_aligned_buffer_64(dst_y_c);                                             \
268  free_aligned_buffer_64(dst_uv_c);                                            \
269  free_aligned_buffer_64(dst_y_opt);                                           \
270  free_aligned_buffer_64(dst_uv_opt);                                          \
271  free_aligned_buffer_64(src_y);                                               \
272  free_aligned_buffer_64(src_u);                                               \
273  free_aligned_buffer_64(src_v);                                               \
274}
275
276#define TESTPLANARTOBP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,           \
277                       FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y)                       \
278    TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \
279                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \
280                    benchmark_width_ - 4, _Any, +, 0)                          \
281    TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \
282                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \
283                    benchmark_width_, _Unaligned, +, 1)                        \
284    TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \
285                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \
286                    benchmark_width_, _Invert, -, 0)                           \
287    TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \
288                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \
289                    benchmark_width_, _Opt, +, 0)
290
291TESTPLANARTOBP(I420, 2, 2, NV12, 2, 2)
292TESTPLANARTOBP(I420, 2, 2, NV21, 2, 2)
293
294#define TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,         \
295                         FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF) \
296TEST_F(libyuvTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) {                        \
297  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
298  const int kHeight = benchmark_height_;                                       \
299  align_buffer_64(src_y, kWidth * kHeight + OFF);                              \
300  align_buffer_64(src_uv, 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *               \
301                  SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);                    \
302  align_buffer_64(dst_y_c, kWidth * kHeight);                                  \
303  align_buffer_64(dst_u_c,                                                     \
304                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
305                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
306  align_buffer_64(dst_v_c,                                                     \
307                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
308                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
309  align_buffer_64(dst_y_opt, kWidth * kHeight);                                \
310  align_buffer_64(dst_u_opt,                                                   \
311                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
312                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
313  align_buffer_64(dst_v_opt,                                                   \
314                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
315                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
316  srandom(time(NULL));                                                         \
317  for (int i = 0; i < kHeight; ++i)                                            \
318    for (int j = 0; j < kWidth; ++j)                                           \
319      src_y[(i * kWidth) + j + OFF] = (random() & 0xff);                       \
320  for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) {                \
321    for (int j = 0; j < 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) {           \
322      src_uv[(i * 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =           \
323          (random() & 0xff);                                                   \
324    }                                                                          \
325  }                                                                            \
326  memset(dst_y_c, 1, kWidth * kHeight);                                        \
327  memset(dst_u_c, 2, SUBSAMPLE(kWidth, SUBSAMP_X) *                            \
328                     SUBSAMPLE(kHeight, SUBSAMP_Y));                           \
329  memset(dst_v_c, 3, SUBSAMPLE(kWidth, SUBSAMP_X) *                            \
330                     SUBSAMPLE(kHeight, SUBSAMP_Y));                           \
331  memset(dst_y_opt, 101, kWidth * kHeight);                                    \
332  memset(dst_u_opt, 102, SUBSAMPLE(kWidth, SUBSAMP_X) *                        \
333                         SUBSAMPLE(kHeight, SUBSAMP_Y));                       \
334  memset(dst_v_opt, 103, SUBSAMPLE(kWidth, SUBSAMP_X) *                        \
335                         SUBSAMPLE(kHeight, SUBSAMP_Y));                       \
336  MaskCpuFlags(0);                                                             \
337  SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                          \
338                                 src_uv + OFF,                                 \
339                                 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X),         \
340                                 dst_y_c, kWidth,                              \
341                                 dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \
342                                 dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \
343                                 kWidth, NEG kHeight);                         \
344  MaskCpuFlags(-1);                                                            \
345  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
346    SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                        \
347                                   src_uv + OFF,                               \
348                                   2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X),       \
349                                   dst_y_opt, kWidth,                          \
350                                   dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \
351                                   dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \
352                                   kWidth, NEG kHeight);                       \
353  }                                                                            \
354  int max_diff = 0;                                                            \
355  for (int i = 0; i < kHeight; ++i) {                                          \
356    for (int j = 0; j < kWidth; ++j) {                                         \
357      int abs_diff =                                                           \
358          abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
359              static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
360      if (abs_diff > max_diff) {                                               \
361        max_diff = abs_diff;                                                   \
362      }                                                                        \
363    }                                                                          \
364  }                                                                            \
365  EXPECT_LE(max_diff, 1);                                                      \
366  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
367    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
368      int abs_diff =                                                           \
369          abs(static_cast<int>(dst_u_c[i *                                     \
370                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
371              static_cast<int>(dst_u_opt[i *                                   \
372                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
373      if (abs_diff > max_diff) {                                               \
374        max_diff = abs_diff;                                                   \
375      }                                                                        \
376    }                                                                          \
377  }                                                                            \
378  EXPECT_LE(max_diff, 1);                                                      \
379  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
380    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
381      int abs_diff =                                                           \
382          abs(static_cast<int>(dst_v_c[i *                                     \
383                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
384              static_cast<int>(dst_v_opt[i *                                   \
385                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
386      if (abs_diff > max_diff) {                                               \
387        max_diff = abs_diff;                                                   \
388      }                                                                        \
389    }                                                                          \
390  }                                                                            \
391  EXPECT_LE(max_diff, 1);                                                      \
392  free_aligned_buffer_64(dst_y_c);                                             \
393  free_aligned_buffer_64(dst_u_c);                                             \
394  free_aligned_buffer_64(dst_v_c);                                             \
395  free_aligned_buffer_64(dst_y_opt);                                           \
396  free_aligned_buffer_64(dst_u_opt);                                           \
397  free_aligned_buffer_64(dst_v_opt);                                           \
398  free_aligned_buffer_64(src_y);                                               \
399  free_aligned_buffer_64(src_uv);                                              \
400}
401
402#define TESTBIPLANARTOP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,          \
403                        FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y)                      \
404    TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,             \
405                     FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                         \
406                     benchmark_width_ - 4, _Any, +, 0)                         \
407    TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,             \
408                     FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                         \
409                     benchmark_width_, _Unaligned, +, 1)                       \
410    TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,             \
411                     FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                         \
412                     benchmark_width_, _Invert, -, 0)                          \
413    TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,             \
414                     FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                         \
415                     benchmark_width_, _Opt, +, 0)
416
417TESTBIPLANARTOP(NV12, 2, 2, I420, 2, 2)
418TESTBIPLANARTOP(NV21, 2, 2, I420, 2, 2)
419
420#define ALIGNINT(V, ALIGN) (((V) + (ALIGN) - 1) / (ALIGN) * (ALIGN))
421
422#define TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,  \
423                       YALIGN, W1280, DIFF, N, NEG, OFF, FMT_C, BPP_C)         \
424TEST_F(libyuvTest, FMT_PLANAR##To##FMT_B##N) {                                 \
425  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
426  const int kHeight = ALIGNINT(benchmark_height_, YALIGN);                     \
427  const int kStrideB = ALIGNINT(kWidth * BPP_B, ALIGN);                        \
428  const int kSizeUV =                                                          \
429    SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y);              \
430  align_buffer_64(src_y, kWidth * kHeight + OFF);                              \
431  align_buffer_64(src_u, kSizeUV + OFF);                                       \
432  align_buffer_64(src_v, kSizeUV + OFF);                                       \
433  align_buffer_64(dst_argb_c, kStrideB * kHeight);                             \
434  align_buffer_64(dst_argb_opt, kStrideB * kHeight);                           \
435  srandom(time(NULL));                                                         \
436  for (int i = 0; i < kWidth * kHeight; ++i) {                                 \
437    src_y[i + OFF] = (random() & 0xff);                                        \
438  }                                                                            \
439  for (int i = 0; i < kSizeUV; ++i) {                                          \
440    src_u[i + OFF] = (random() & 0xff);                                        \
441    src_v[i + OFF] = (random() & 0xff);                                        \
442  }                                                                            \
443  memset(dst_argb_c, 1, kStrideB * kHeight);                                   \
444  memset(dst_argb_opt, 101, kStrideB * kHeight);                               \
445  MaskCpuFlags(0);                                                             \
446  FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                   \
447                        src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X),             \
448                        src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X),             \
449                        dst_argb_c, kStrideB,                                  \
450                        kWidth, NEG kHeight);                                  \
451  MaskCpuFlags(-1);                                                            \
452  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
453    FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                 \
454                          src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X),           \
455                          src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X),           \
456                          dst_argb_opt, kStrideB,                              \
457                          kWidth, NEG kHeight);                                \
458  }                                                                            \
459  int max_diff = 0;                                                            \
460  /* Convert to ARGB so 565 is expanded to bytes that can be compared. */      \
461  align_buffer_64(dst_argb32_c, kWidth * BPP_C  * kHeight);                    \
462  align_buffer_64(dst_argb32_opt, kWidth * BPP_C  * kHeight);                  \
463  memset(dst_argb32_c, 2, kWidth * BPP_C  * kHeight);                          \
464  memset(dst_argb32_opt, 102, kWidth * BPP_C  * kHeight);                      \
465  FMT_B##To##FMT_C(dst_argb_c, kStrideB,                                       \
466                   dst_argb32_c, kWidth * BPP_C ,                              \
467                   kWidth, kHeight);                                           \
468  FMT_B##To##FMT_C(dst_argb_opt, kStrideB,                                     \
469                   dst_argb32_opt, kWidth * BPP_C ,                            \
470                   kWidth, kHeight);                                           \
471  for (int i = 0; i < kWidth * BPP_C * kHeight; ++i) {                         \
472    int abs_diff =                                                             \
473        abs(static_cast<int>(dst_argb32_c[i]) -                                \
474            static_cast<int>(dst_argb32_opt[i]));                              \
475    if (abs_diff > max_diff) {                                                 \
476      max_diff = abs_diff;                                                     \
477    }                                                                          \
478  }                                                                            \
479  EXPECT_LE(max_diff, DIFF);                                                   \
480  free_aligned_buffer_64(src_y);                                               \
481  free_aligned_buffer_64(src_u);                                               \
482  free_aligned_buffer_64(src_v);                                               \
483  free_aligned_buffer_64(dst_argb_c);                                          \
484  free_aligned_buffer_64(dst_argb_opt);                                        \
485  free_aligned_buffer_64(dst_argb32_c);                                        \
486  free_aligned_buffer_64(dst_argb32_opt);                                      \
487}
488
489#define TESTPLANARTOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,   \
490                      YALIGN, DIFF, FMT_C, BPP_C)                              \
491    TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,      \
492        YALIGN, benchmark_width_ - 4, DIFF, _Any, +, 0, FMT_C, BPP_C)          \
493    TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,      \
494        YALIGN, benchmark_width_, DIFF, _Unaligned, +, 1, FMT_C, BPP_C)        \
495    TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,      \
496        YALIGN, benchmark_width_, DIFF, _Invert, -, 0, FMT_C, BPP_C)           \
497    TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,      \
498        YALIGN, benchmark_width_, DIFF, _Opt, +, 0, FMT_C, BPP_C)
499
500// TODO(fbarchard): Make vertical alignment unnecessary on bayer.
501TESTPLANARTOB(I420, 2, 2, ARGB, 4, 4, 1, 2, ARGB, 4)
502TESTPLANARTOB(I420, 2, 2, BGRA, 4, 4, 1, 2, ARGB, 4)
503TESTPLANARTOB(I420, 2, 2, ABGR, 4, 4, 1, 2, ARGB, 4)
504TESTPLANARTOB(I420, 2, 2, RGBA, 4, 4, 1, 2, ARGB, 4)
505TESTPLANARTOB(I420, 2, 2, RAW, 3, 3, 1, 2, ARGB, 4)
506TESTPLANARTOB(I420, 2, 2, RGB24, 3, 3, 1, 2, ARGB, 4)
507TESTPLANARTOB(I420, 2, 2, RGB565, 2, 2, 1, 9, ARGB, 4)
508TESTPLANARTOB(I420, 2, 2, ARGB1555, 2, 2, 1, 9, ARGB, 4)
509TESTPLANARTOB(I420, 2, 2, ARGB4444, 2, 2, 1, 17, ARGB, 4)
510TESTPLANARTOB(I422, 2, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
511TESTPLANARTOB(I422, 2, 1, BGRA, 4, 4, 1, 2, ARGB, 4)
512TESTPLANARTOB(I422, 2, 1, ABGR, 4, 4, 1, 2, ARGB, 4)
513TESTPLANARTOB(I422, 2, 1, RGBA, 4, 4, 1, 2, ARGB, 4)
514TESTPLANARTOB(I411, 4, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
515TESTPLANARTOB(I444, 1, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
516TESTPLANARTOB(I420, 2, 2, YUY2, 2, 4, 1, 1, ARGB, 4)
517TESTPLANARTOB(I420, 2, 2, UYVY, 2, 4, 1, 1, ARGB, 4)
518TESTPLANARTOB(I422, 2, 1, YUY2, 2, 4, 1, 0, ARGB, 4)
519TESTPLANARTOB(I422, 2, 1, UYVY, 2, 4, 1, 0, ARGB, 4)
520TESTPLANARTOB(I420, 2, 2, I400, 1, 1, 1, 0, ARGB, 4)
521TESTPLANARTOB(I420, 2, 2, BayerBGGR, 1, 2, 2, 2, ARGB, 4)
522TESTPLANARTOB(I420, 2, 2, BayerRGGB, 1, 2, 2, 2, ARGB, 4)
523TESTPLANARTOB(I420, 2, 2, BayerGBRG, 1, 2, 2, 2, ARGB, 4)
524TESTPLANARTOB(I420, 2, 2, BayerGRBG, 1, 2, 2, 2, ARGB, 4)
525
526#define TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,       \
527                         W1280, DIFF, N, NEG, OFF)                             \
528TEST_F(libyuvTest, FMT_PLANAR##To##FMT_B##N) {                                 \
529  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
530  const int kHeight = benchmark_height_;                                       \
531  const int kStrideB = kWidth * BPP_B;                                         \
532  align_buffer_64(src_y, kWidth * kHeight + OFF);                              \
533  align_buffer_64(src_uv,                                                      \
534                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
535                  SUBSAMPLE(kHeight, SUBSAMP_Y) * 2 + OFF);                    \
536  align_buffer_64(dst_argb_c, kStrideB * kHeight);                             \
537  align_buffer_64(dst_argb_opt, kStrideB * kHeight);                           \
538  srandom(time(NULL));                                                         \
539  for (int i = 0; i < kHeight; ++i)                                            \
540    for (int j = 0; j < kWidth; ++j)                                           \
541      src_y[(i * kWidth) + j + OFF] = (random() & 0xff);                       \
542  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
543    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X) * 2; ++j) {               \
544      src_uv[(i * SUBSAMPLE(kWidth, SUBSAMP_X)) * 2 + j + OFF] =               \
545          (random() & 0xff);                                                   \
546    }                                                                          \
547  }                                                                            \
548  memset(dst_argb_c, 1, kStrideB * kHeight);                                   \
549  memset(dst_argb_opt, 101, kStrideB * kHeight);                               \
550  MaskCpuFlags(0);                                                             \
551  FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                   \
552                        src_uv + OFF, SUBSAMPLE(kWidth, SUBSAMP_X) * 2,        \
553                        dst_argb_c, kWidth * BPP_B,                            \
554                        kWidth, NEG kHeight);                                  \
555  MaskCpuFlags(-1);                                                            \
556  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
557    FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                 \
558                          src_uv + OFF, SUBSAMPLE(kWidth, SUBSAMP_X) * 2,      \
559                          dst_argb_opt, kWidth * BPP_B,                        \
560                          kWidth, NEG kHeight);                                \
561  }                                                                            \
562  /* Convert to ARGB so 565 is expanded to bytes that can be compared. */      \
563  align_buffer_64(dst_argb32_c, kWidth * 4 * kHeight);                         \
564  align_buffer_64(dst_argb32_opt, kWidth * 4 * kHeight);                       \
565  memset(dst_argb32_c, 2, kWidth * 4 * kHeight);                               \
566  memset(dst_argb32_opt, 102, kWidth * 4 * kHeight);                           \
567  FMT_B##ToARGB(dst_argb_c, kStrideB,                                          \
568                dst_argb32_c, kWidth * 4,                                      \
569                kWidth, kHeight);                                              \
570  FMT_B##ToARGB(dst_argb_opt, kStrideB,                                        \
571                dst_argb32_opt, kWidth * 4,                                    \
572                kWidth, kHeight);                                              \
573  int max_diff = 0;                                                            \
574  for (int i = 0; i < kHeight; ++i) {                                          \
575    for (int j = 0; j < kWidth * 4; ++j) {                                     \
576      int abs_diff =                                                           \
577          abs(static_cast<int>(dst_argb32_c[i * kWidth * 4 + j]) -             \
578              static_cast<int>(dst_argb32_opt[i * kWidth * 4 + j]));           \
579      if (abs_diff > max_diff) {                                               \
580        max_diff = abs_diff;                                                   \
581      }                                                                        \
582    }                                                                          \
583  }                                                                            \
584  EXPECT_LE(max_diff, DIFF);                                                   \
585  free_aligned_buffer_64(src_y);                                               \
586  free_aligned_buffer_64(src_uv);                                              \
587  free_aligned_buffer_64(dst_argb_c);                                          \
588  free_aligned_buffer_64(dst_argb_opt);                                        \
589  free_aligned_buffer_64(dst_argb32_c);                                        \
590  free_aligned_buffer_64(dst_argb32_opt);                                      \
591}
592
593#define TESTBIPLANARTOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, DIFF)  \
594    TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,           \
595                     benchmark_width_ - 4, DIFF, _Any, +, 0)                   \
596    TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,           \
597                     benchmark_width_, DIFF, _Unaligned, +, 1)                 \
598    TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,           \
599                     benchmark_width_, DIFF, _Invert, -, 0)                    \
600    TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,           \
601                     benchmark_width_, DIFF, _Opt, +, 0)
602
603TESTBIPLANARTOB(NV12, 2, 2, ARGB, 4, 2)
604TESTBIPLANARTOB(NV21, 2, 2, ARGB, 4, 2)
605TESTBIPLANARTOB(NV12, 2, 2, RGB565, 2, 9)
606TESTBIPLANARTOB(NV21, 2, 2, RGB565, 2, 9)
607
608#define TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
609                       W1280, DIFF, N, NEG, OFF)                               \
610TEST_F(libyuvTest, FMT_A##To##FMT_PLANAR##N) {                                 \
611  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
612  const int kHeight = ALIGNINT(benchmark_height_, YALIGN);                     \
613  const int kStride =                                                          \
614      (SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMP_X * 8 * BPP_A + 7) / 8;          \
615  align_buffer_64(src_argb, kStride * kHeight + OFF);                          \
616  align_buffer_64(dst_y_c, kWidth * kHeight);                                  \
617  align_buffer_64(dst_u_c,                                                     \
618                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
619                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
620  align_buffer_64(dst_v_c,                                                     \
621                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
622                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
623  align_buffer_64(dst_y_opt, kWidth * kHeight);                                \
624  align_buffer_64(dst_u_opt,                                                   \
625                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
626                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
627  align_buffer_64(dst_v_opt,                                                   \
628                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
629                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
630  memset(dst_y_c, 1, kWidth * kHeight);                                        \
631  memset(dst_u_c, 2,                                                           \
632         SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y));        \
633  memset(dst_v_c, 3,                                                           \
634         SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y));        \
635  memset(dst_y_opt, 101, kWidth * kHeight);                                    \
636  memset(dst_u_opt, 102,                                                       \
637         SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y));        \
638  memset(dst_v_opt, 103,                                                       \
639         SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y));        \
640  srandom(time(NULL));                                                         \
641  for (int i = 0; i < kHeight; ++i)                                            \
642    for (int j = 0; j < kStride; ++j)                                          \
643      src_argb[(i * kStride) + j + OFF] = (random() & 0xff);                   \
644  MaskCpuFlags(0);                                                             \
645  FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride,                               \
646                        dst_y_c, kWidth,                                       \
647                        dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X),                 \
648                        dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X),                 \
649                        kWidth, NEG kHeight);                                  \
650  MaskCpuFlags(-1);                                                            \
651  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
652    FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride,                             \
653                          dst_y_opt, kWidth,                                   \
654                          dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X),             \
655                          dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X),             \
656                          kWidth, NEG kHeight);                                \
657  }                                                                            \
658  int max_diff = 0;                                                            \
659  for (int i = 0; i < kHeight; ++i) {                                          \
660    for (int j = 0; j < kWidth; ++j) {                                         \
661      int abs_diff =                                                           \
662          abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
663              static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
664      if (abs_diff > max_diff) {                                               \
665        max_diff = abs_diff;                                                   \
666      }                                                                        \
667    }                                                                          \
668  }                                                                            \
669  EXPECT_LE(max_diff, DIFF);                                                   \
670  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
671    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
672      int abs_diff =                                                           \
673          abs(static_cast<int>(dst_u_c[i *                                     \
674                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
675              static_cast<int>(dst_u_opt[i *                                   \
676                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
677      if (abs_diff > max_diff) {                                               \
678        max_diff = abs_diff;                                                   \
679      }                                                                        \
680    }                                                                          \
681  }                                                                            \
682  EXPECT_LE(max_diff, DIFF);                                                   \
683  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
684    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
685      int abs_diff =                                                           \
686          abs(static_cast<int>(dst_v_c[i *                                     \
687                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
688              static_cast<int>(dst_v_opt[i *                                   \
689                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
690      if (abs_diff > max_diff) {                                               \
691        max_diff = abs_diff;                                                   \
692      }                                                                        \
693    }                                                                          \
694  }                                                                            \
695  EXPECT_LE(max_diff, DIFF);                                                   \
696  free_aligned_buffer_64(dst_y_c);                                             \
697  free_aligned_buffer_64(dst_u_c);                                             \
698  free_aligned_buffer_64(dst_v_c);                                             \
699  free_aligned_buffer_64(dst_y_opt);                                           \
700  free_aligned_buffer_64(dst_u_opt);                                           \
701  free_aligned_buffer_64(dst_v_opt);                                           \
702  free_aligned_buffer_64(src_argb);                                            \
703}
704
705#define TESTATOPLANAR(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,  \
706                      DIFF)                                                    \
707    TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,     \
708                   benchmark_width_ - 4, DIFF, _Any, +, 0)                     \
709    TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,     \
710                   benchmark_width_, DIFF, _Unaligned, +, 1)                   \
711    TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,     \
712                   benchmark_width_, DIFF, _Invert, -, 0)                      \
713    TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,     \
714                   benchmark_width_, DIFF, _Opt, +, 0)
715
716TESTATOPLANAR(ARGB, 4, 1, I420, 2, 2, 4)
717#ifdef __arm__
718TESTATOPLANAR(ARGB, 4, 1, J420, 2, 2, 4)
719#else
720TESTATOPLANAR(ARGB, 4, 1, J420, 2, 2, 0)
721#endif
722TESTATOPLANAR(BGRA, 4, 1, I420, 2, 2, 4)
723TESTATOPLANAR(ABGR, 4, 1, I420, 2, 2, 4)
724TESTATOPLANAR(RGBA, 4, 1, I420, 2, 2, 4)
725TESTATOPLANAR(RAW, 3, 1, I420, 2, 2, 4)
726TESTATOPLANAR(RGB24, 3, 1, I420, 2, 2, 4)
727TESTATOPLANAR(RGB565, 2, 1, I420, 2, 2, 5)
728// TODO(fbarchard): Make 1555 neon work same as C code, reduce to diff 9.
729TESTATOPLANAR(ARGB1555, 2, 1, I420, 2, 2, 15)
730TESTATOPLANAR(ARGB4444, 2, 1, I420, 2, 2, 17)
731TESTATOPLANAR(ARGB, 4, 1, I411, 4, 1, 4)
732TESTATOPLANAR(ARGB, 4, 1, I422, 2, 1, 2)
733TESTATOPLANAR(ARGB, 4, 1, I444, 1, 1, 2)
734TESTATOPLANAR(YUY2, 2, 1, I420, 2, 2, 2)
735TESTATOPLANAR(UYVY, 2, 1, I420, 2, 2, 2)
736TESTATOPLANAR(YUY2, 2, 1, I422, 2, 1, 2)
737TESTATOPLANAR(UYVY, 2, 1, I422, 2, 1, 2)
738TESTATOPLANAR(I400, 1, 1, I420, 2, 2, 2)
739TESTATOPLANAR(BayerBGGR, 1, 2, I420, 2, 2, 4)
740TESTATOPLANAR(BayerRGGB, 1, 2, I420, 2, 2, 4)
741TESTATOPLANAR(BayerGBRG, 1, 2, I420, 2, 2, 4)
742TESTATOPLANAR(BayerGRBG, 1, 2, I420, 2, 2, 4)
743
744#define TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,       \
745                       W1280, N, NEG, OFF)                                     \
746TEST_F(libyuvTest, FMT_A##To##FMT_PLANAR##N) {                                 \
747  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
748  const int kHeight = benchmark_height_;                                       \
749  const int kStride = (kWidth * 8 * BPP_A + 7) / 8;                            \
750  align_buffer_64(src_argb, kStride * kHeight + OFF);                          \
751  align_buffer_64(dst_y_c, kWidth * kHeight);                                  \
752  align_buffer_64(dst_uv_c,                                                    \
753                  SUBSAMPLE(kWidth, SUBSAMP_X) * 2 *                           \
754                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
755  align_buffer_64(dst_y_opt, kWidth * kHeight);                                \
756  align_buffer_64(dst_uv_opt,                                                  \
757                  SUBSAMPLE(kWidth, SUBSAMP_X) * 2 *                           \
758                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
759  srandom(time(NULL));                                                         \
760  for (int i = 0; i < kHeight; ++i)                                            \
761    for (int j = 0; j < kStride; ++j)                                          \
762      src_argb[(i * kStride) + j + OFF] = (random() & 0xff);                   \
763  memset(dst_y_c, 1, kWidth * kHeight);                                        \
764  memset(dst_uv_c, 2, SUBSAMPLE(kWidth, SUBSAMP_X) * 2 *                       \
765                      SUBSAMPLE(kHeight, SUBSAMP_Y));                          \
766  memset(dst_y_opt, 101, kWidth * kHeight);                                    \
767  memset(dst_uv_opt, 102, SUBSAMPLE(kWidth, SUBSAMP_X) * 2 *                   \
768                        SUBSAMPLE(kHeight, SUBSAMP_Y));                        \
769  MaskCpuFlags(0);                                                             \
770  FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride,                               \
771                        dst_y_c, kWidth,                                       \
772                        dst_uv_c, SUBSAMPLE(kWidth, SUBSAMP_X) * 2,            \
773                        kWidth, NEG kHeight);                                  \
774  MaskCpuFlags(-1);                                                            \
775  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
776    FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride,                             \
777                          dst_y_opt, kWidth,                                   \
778                          dst_uv_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * 2,        \
779                          kWidth, NEG kHeight);                                \
780  }                                                                            \
781  int max_diff = 0;                                                            \
782  for (int i = 0; i < kHeight; ++i) {                                          \
783    for (int j = 0; j < kWidth; ++j) {                                         \
784      int abs_diff =                                                           \
785          abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
786              static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
787      if (abs_diff > max_diff) {                                               \
788        max_diff = abs_diff;                                                   \
789      }                                                                        \
790    }                                                                          \
791  }                                                                            \
792  EXPECT_LE(max_diff, 4);                                                      \
793  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
794    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X) * 2; ++j) {               \
795      int abs_diff =                                                           \
796          abs(static_cast<int>(dst_uv_c[i *                                    \
797                               SUBSAMPLE(kWidth, SUBSAMP_X) * 2 + j]) -        \
798              static_cast<int>(dst_uv_opt[i *                                  \
799                               SUBSAMPLE(kWidth, SUBSAMP_X) * 2 + j]));        \
800      if (abs_diff > max_diff) {                                               \
801        max_diff = abs_diff;                                                   \
802      }                                                                        \
803    }                                                                          \
804  }                                                                            \
805  EXPECT_LE(max_diff, 4);                                                      \
806  free_aligned_buffer_64(dst_y_c);                                             \
807  free_aligned_buffer_64(dst_uv_c);                                            \
808  free_aligned_buffer_64(dst_y_opt);                                           \
809  free_aligned_buffer_64(dst_uv_opt);                                          \
810  free_aligned_buffer_64(src_argb);                                            \
811}
812
813#define TESTATOBIPLANAR(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y)        \
814    TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,           \
815                     benchmark_width_ - 4, _Any, +, 0)                         \
816    TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,           \
817                     benchmark_width_, _Unaligned, +, 1)                       \
818    TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,           \
819                     benchmark_width_, _Invert, -, 0)                          \
820    TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,           \
821                     benchmark_width_, _Opt, +, 0)
822
823TESTATOBIPLANAR(ARGB, 4, NV12, 2, 2)
824TESTATOBIPLANAR(ARGB, 4, NV21, 2, 2)
825
826#define TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                            \
827                  FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                            \
828                  W1280, DIFF, N, NEG, OFF)                                    \
829TEST_F(libyuvTest, FMT_A##To##FMT_B##N) {                                      \
830  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
831  const int kHeight = benchmark_height_;                                       \
832  const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A;         \
833  const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B;         \
834  const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;  \
835  const int kStrideB = (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B;  \
836  align_buffer_64(src_argb, kStrideA * kHeightA + OFF);                        \
837  align_buffer_64(dst_argb_c, kStrideB * kHeightB);                            \
838  align_buffer_64(dst_argb_opt, kStrideB * kHeightB);                          \
839  srandom(time(NULL));                                                         \
840  for (int i = 0; i < kStrideA * kHeightA; ++i) {                              \
841    src_argb[i + OFF] = (random() & 0xff);                                     \
842  }                                                                            \
843  memset(dst_argb_c, 1, kStrideB * kHeightB);                                  \
844  memset(dst_argb_opt, 101, kStrideB * kHeightB);                              \
845  MaskCpuFlags(0);                                                             \
846  FMT_A##To##FMT_B(src_argb + OFF, kStrideA,                                   \
847                   dst_argb_c, kStrideB,                                       \
848                   kWidth, NEG kHeight);                                       \
849  MaskCpuFlags(-1);                                                            \
850  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
851    FMT_A##To##FMT_B(src_argb + OFF, kStrideA,                                 \
852                     dst_argb_opt, kStrideB,                                   \
853                     kWidth, NEG kHeight);                                     \
854  }                                                                            \
855  int max_diff = 0;                                                            \
856  for (int i = 0; i < kStrideB * kHeightB; ++i) {                              \
857    int abs_diff =                                                             \
858        abs(static_cast<int>(dst_argb_c[i]) -                                  \
859            static_cast<int>(dst_argb_opt[i]));                                \
860    if (abs_diff > max_diff) {                                                 \
861      max_diff = abs_diff;                                                     \
862    }                                                                          \
863  }                                                                            \
864  EXPECT_LE(max_diff, DIFF);                                                   \
865  free_aligned_buffer_64(src_argb);                                            \
866  free_aligned_buffer_64(dst_argb_c);                                          \
867  free_aligned_buffer_64(dst_argb_opt);                                        \
868}
869
870#define TESTATOBRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                       \
871                       FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF)                 \
872TEST_F(libyuvTest, FMT_A##To##FMT_B##_Random) {                                \
873  srandom(time(NULL));                                                         \
874  for (int times = 0; times < benchmark_iterations_; ++times) {                \
875    const int kWidth = (random() & 63) + 1;                                    \
876    const int kHeight = (random() & 31) + 1;                                   \
877    const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A;       \
878    const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B;       \
879    const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;\
880    const int kStrideB = (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B;\
881    align_buffer_page_end(src_argb, kStrideA * kHeightA);                      \
882    align_buffer_page_end(dst_argb_c, kStrideB * kHeightB);                    \
883    align_buffer_page_end(dst_argb_opt, kStrideB * kHeightB);                  \
884    for (int i = 0; i < kStrideA * kHeightA; ++i) {                            \
885      src_argb[i] = (random() & 0xff);                                         \
886    }                                                                          \
887    memset(dst_argb_c, 123, kStrideB * kHeightB);                              \
888    memset(dst_argb_opt, 123, kStrideB * kHeightB);                            \
889    MaskCpuFlags(0);                                                           \
890    FMT_A##To##FMT_B(src_argb, kStrideA,                                       \
891                     dst_argb_c, kStrideB,                                     \
892                     kWidth, kHeight);                                         \
893    MaskCpuFlags(-1);                                                          \
894    FMT_A##To##FMT_B(src_argb, kStrideA,                                       \
895                     dst_argb_opt, kStrideB,                                   \
896                     kWidth, kHeight);                                         \
897    int max_diff = 0;                                                          \
898    for (int i = 0; i < kStrideB * kHeightB; ++i) {                            \
899      int abs_diff =                                                           \
900          abs(static_cast<int>(dst_argb_c[i]) -                                \
901              static_cast<int>(dst_argb_opt[i]));                              \
902      if (abs_diff > max_diff) {                                               \
903        max_diff = abs_diff;                                                   \
904      }                                                                        \
905    }                                                                          \
906    EXPECT_LE(max_diff, DIFF);                                                 \
907    free_aligned_buffer_page_end(src_argb);                                    \
908    free_aligned_buffer_page_end(dst_argb_c);                                  \
909    free_aligned_buffer_page_end(dst_argb_opt);                                \
910  }                                                                            \
911}
912
913#define TESTATOB(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                             \
914                 FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF)                       \
915    TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                                \
916              FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                                \
917              benchmark_width_ - 4, DIFF, _Any, +, 0)                          \
918    TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                                \
919              FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                                \
920              benchmark_width_, DIFF, _Unaligned, +, 1)                        \
921    TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                                \
922              FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                                \
923              benchmark_width_, DIFF, _Invert, -, 0)                           \
924    TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                                \
925              FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                                \
926              benchmark_width_, DIFF, _Opt, +, 0)                              \
927    TESTATOBRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                           \
928                   FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF)
929
930TESTATOB(ARGB, 4, 4, 1, ARGB, 4, 4, 1, 0)
931TESTATOB(ARGB, 4, 4, 1, BGRA, 4, 4, 1, 0)
932TESTATOB(ARGB, 4, 4, 1, ABGR, 4, 4, 1, 0)
933TESTATOB(ARGB, 4, 4, 1, RGBA, 4, 4, 1, 0)
934TESTATOB(ARGB, 4, 4, 1, RAW, 3, 3, 1, 0)
935TESTATOB(ARGB, 4, 4, 1, RGB24, 3, 3, 1, 0)
936TESTATOB(ARGB, 4, 4, 1, RGB565, 2, 2, 1, 0)
937TESTATOB(ARGB, 4, 4, 1, ARGB1555, 2, 2, 1, 0)
938TESTATOB(ARGB, 4, 4, 1, ARGB4444, 2, 2, 1, 0)
939TESTATOB(ARGB, 4, 4, 1, BayerBGGR, 1, 1, 1, 0)
940TESTATOB(ARGB, 4, 4, 1, BayerRGGB, 1, 1, 1, 0)
941TESTATOB(ARGB, 4, 4, 1, BayerGBRG, 1, 1, 1, 0)
942TESTATOB(ARGB, 4, 4, 1, BayerGRBG, 1, 1, 1, 0)
943TESTATOB(ARGB, 4, 4, 1, YUY2, 2, 4, 1, 4)
944TESTATOB(ARGB, 4, 4, 1, UYVY, 2, 4, 1, 4)
945TESTATOB(ARGB, 4, 4, 1, I400, 1, 1, 1, 2)
946TESTATOB(ARGB, 4, 4, 1, J400, 1, 1, 1, 2)
947TESTATOB(BGRA, 4, 4, 1, ARGB, 4, 4, 1, 0)
948TESTATOB(ABGR, 4, 4, 1, ARGB, 4, 4, 1, 0)
949TESTATOB(RGBA, 4, 4, 1, ARGB, 4, 4, 1, 0)
950TESTATOB(RAW, 3, 3, 1, ARGB, 4, 4, 1, 0)
951TESTATOB(RGB24, 3, 3, 1, ARGB, 4, 4, 1, 0)
952TESTATOB(RGB565, 2, 2, 1, ARGB, 4, 4, 1, 0)
953TESTATOB(ARGB1555, 2, 2, 1, ARGB, 4, 4, 1, 0)
954TESTATOB(ARGB4444, 2, 2, 1, ARGB, 4, 4, 1, 0)
955TESTATOB(YUY2, 2, 4, 1, ARGB, 4, 4, 1, 4)
956TESTATOB(UYVY, 2, 4, 1, ARGB, 4, 4, 1, 4)
957TESTATOB(BayerBGGR, 1, 2, 2, ARGB, 4, 4, 1, 0)
958TESTATOB(BayerRGGB, 1, 2, 2, ARGB, 4, 4, 1, 0)
959TESTATOB(BayerGBRG, 1, 2, 2, ARGB, 4, 4, 1, 0)
960TESTATOB(BayerGRBG, 1, 2, 2, ARGB, 4, 4, 1, 0)
961TESTATOB(I400, 1, 1, 1, ARGB, 4, 4, 1, 0)
962TESTATOB(I400, 1, 1, 1, I400, 1, 1, 1, 0)
963TESTATOB(I400, 1, 1, 1, I400Mirror, 1, 1, 1, 0)
964TESTATOB(Y, 1, 1, 1, ARGB, 4, 4, 1, 0)
965TESTATOB(ARGB, 4, 4, 1, ARGBMirror, 4, 4, 1, 0)
966
967#define TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A,                          \
968                 W1280, N, NEG, OFF)                                           \
969TEST_F(libyuvTest, FMT_ATOB##_Symetric##N) {                                   \
970  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
971  const int kHeight = benchmark_height_;                                       \
972  const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A;         \
973  const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;  \
974  align_buffer_64(src_argb, kStrideA * kHeightA + OFF);                        \
975  align_buffer_64(dst_argb_c, kStrideA * kHeightA);                            \
976  align_buffer_64(dst_argb_opt, kStrideA * kHeightA);                          \
977  srandom(time(NULL));                                                         \
978  for (int i = 0; i < kStrideA * kHeightA; ++i) {                              \
979    src_argb[i + OFF] = (random() & 0xff);                                     \
980  }                                                                            \
981  memset(dst_argb_c, 1, kStrideA * kHeightA);                                  \
982  memset(dst_argb_opt, 101, kStrideA * kHeightA);                              \
983  MaskCpuFlags(0);                                                             \
984  FMT_ATOB(src_argb + OFF, kStrideA,                                           \
985           dst_argb_c, kStrideA,                                               \
986           kWidth, NEG kHeight);                                               \
987  MaskCpuFlags(-1);                                                            \
988  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
989    FMT_ATOB(src_argb + OFF, kStrideA,                                         \
990             dst_argb_opt, kStrideA,                                           \
991             kWidth, NEG kHeight);                                             \
992  }                                                                            \
993  MaskCpuFlags(0);                                                             \
994  FMT_ATOB(dst_argb_c, kStrideA,                                               \
995           dst_argb_c, kStrideA,                                               \
996           kWidth, NEG kHeight);                                               \
997  MaskCpuFlags(-1);                                                            \
998  FMT_ATOB(dst_argb_opt, kStrideA,                                             \
999           dst_argb_opt, kStrideA,                                             \
1000           kWidth, NEG kHeight);                                               \
1001  for (int i = 0; i < kStrideA * kHeightA; ++i) {                              \
1002    EXPECT_EQ(src_argb[i + OFF], dst_argb_opt[i]);                             \
1003    EXPECT_EQ(dst_argb_c[i], dst_argb_opt[i]);                                 \
1004  }                                                                            \
1005  free_aligned_buffer_64(src_argb);                                            \
1006  free_aligned_buffer_64(dst_argb_c);                                          \
1007  free_aligned_buffer_64(dst_argb_opt);                                        \
1008}
1009
1010#define TESTSYM(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A)                           \
1011    TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A,                              \
1012             benchmark_width_ - 4, _Any, +, 0)                                 \
1013    TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A,                              \
1014             benchmark_width_, _Unaligned, +, 1)                               \
1015    TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A,                              \
1016             benchmark_width_, _Opt, +, 0)
1017
1018TESTSYM(ARGBToARGB, 4, 4, 1)
1019TESTSYM(ARGBToBGRA, 4, 4, 1)
1020TESTSYM(ARGBToABGR, 4, 4, 1)
1021TESTSYM(BGRAToARGB, 4, 4, 1)
1022TESTSYM(ABGRToARGB, 4, 4, 1)
1023
1024TEST_F(libyuvTest, Test565) {
1025  SIMD_ALIGNED(uint8 orig_pixels[256][4]);
1026  SIMD_ALIGNED(uint8 pixels565[256][2]);
1027
1028  for (int i = 0; i < 256; ++i) {
1029    for (int j = 0; j < 4; ++j) {
1030      orig_pixels[i][j] = i;
1031    }
1032  }
1033  ARGBToRGB565(&orig_pixels[0][0], 0, &pixels565[0][0], 0, 256, 1);
1034  uint32 checksum = HashDjb2(&pixels565[0][0], sizeof(pixels565), 5381);
1035  EXPECT_EQ(610919429u, checksum);
1036}
1037
1038#ifdef HAVE_JPEG
1039TEST_F(libyuvTest, ValidateJpeg) {
1040  const int kOff = 10;
1041  const int kMinJpeg = 64;
1042  const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ?
1043    benchmark_width_ * benchmark_height_ : kMinJpeg;
1044  const int kSize = kImageSize + kOff;
1045  align_buffer_64(orig_pixels, kSize);
1046
1047  // No SOI or EOI. Expect fail.
1048  memset(orig_pixels, 0, kSize);
1049  EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
1050
1051  // EOI, SOI. Expect pass.
1052  orig_pixels[0] = 0xff;
1053  orig_pixels[1] = 0xd8;  // SOI.
1054  orig_pixels[kSize - kOff + 0] = 0xff;
1055  orig_pixels[kSize - kOff + 1] = 0xd9;  // EOI.
1056  for (int times = 0; times < benchmark_iterations_; ++times) {
1057    EXPECT_TRUE(ValidateJpeg(orig_pixels, kSize));
1058  }
1059  free_aligned_buffer_page_end(orig_pixels);
1060}
1061
1062TEST_F(libyuvTest, InvalidateJpeg) {
1063  const int kOff = 10;
1064  const int kMinJpeg = 64;
1065  const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ?
1066    benchmark_width_ * benchmark_height_ : kMinJpeg;
1067  const int kSize = kImageSize + kOff;
1068  align_buffer_64(orig_pixels, kSize);
1069
1070  // No SOI or EOI. Expect fail.
1071  memset(orig_pixels, 0, kSize);
1072  EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
1073
1074  // SOI but no EOI. Expect fail.
1075  orig_pixels[0] = 0xff;
1076  orig_pixels[1] = 0xd8;  // SOI.
1077  for (int times = 0; times < benchmark_iterations_; ++times) {
1078    EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
1079  }
1080  // EOI but no SOI. Expect fail.
1081  orig_pixels[0] = 0;
1082  orig_pixels[1] = 0;
1083  orig_pixels[kSize - kOff + 0] = 0xff;
1084  orig_pixels[kSize - kOff + 1] = 0xd9;  // EOI.
1085  EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
1086
1087  free_aligned_buffer_page_end(orig_pixels);
1088}
1089
1090TEST_F(libyuvTest, MJPGToI420) {
1091  const int kOff = 10;
1092  const int kMinJpeg = 64;
1093  const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ?
1094    benchmark_width_ * benchmark_height_ : kMinJpeg;
1095  const int kSize = kImageSize + kOff;
1096  align_buffer_64(orig_pixels, kSize);
1097  align_buffer_64(dst_y_opt, benchmark_width_ * benchmark_height_);
1098  align_buffer_64(dst_u_opt,
1099                  SUBSAMPLE(benchmark_width_, 2) *
1100                  SUBSAMPLE(benchmark_height_, 2));
1101  align_buffer_64(dst_v_opt,
1102                  SUBSAMPLE(benchmark_width_, 2) *
1103                  SUBSAMPLE(benchmark_height_, 2));
1104
1105  // EOI, SOI to make MJPG appear valid.
1106  memset(orig_pixels, 0, kSize);
1107  orig_pixels[0] = 0xff;
1108  orig_pixels[1] = 0xd8;  // SOI.
1109  orig_pixels[kSize - kOff + 0] = 0xff;
1110  orig_pixels[kSize - kOff + 1] = 0xd9;  // EOI.
1111
1112  for (int times = 0; times < benchmark_iterations_; ++times) {
1113    int ret = MJPGToI420(orig_pixels, kSize,
1114                         dst_y_opt, benchmark_width_,
1115                         dst_u_opt, SUBSAMPLE(benchmark_width_, 2),
1116                         dst_v_opt, SUBSAMPLE(benchmark_width_, 2),
1117                         benchmark_width_, benchmark_height_,
1118                         benchmark_width_, benchmark_height_);
1119    // Expect failure because image is not really valid.
1120    EXPECT_EQ(1, ret);
1121  }
1122
1123  free_aligned_buffer_page_end(dst_y_opt);
1124  free_aligned_buffer_page_end(dst_u_opt);
1125  free_aligned_buffer_page_end(dst_v_opt);
1126  free_aligned_buffer_page_end(orig_pixels);
1127}
1128
1129TEST_F(libyuvTest, MJPGToARGB) {
1130  const int kOff = 10;
1131  const int kMinJpeg = 64;
1132  const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ?
1133    benchmark_width_ * benchmark_height_ : kMinJpeg;
1134  const int kSize = kImageSize + kOff;
1135  align_buffer_64(orig_pixels, kSize);
1136  align_buffer_64(dst_argb_opt, benchmark_width_ * benchmark_height_ * 4);
1137
1138  // EOI, SOI to make MJPG appear valid.
1139  memset(orig_pixels, 0, kSize);
1140  orig_pixels[0] = 0xff;
1141  orig_pixels[1] = 0xd8;  // SOI.
1142  orig_pixels[kSize - kOff + 0] = 0xff;
1143  orig_pixels[kSize - kOff + 1] = 0xd9;  // EOI.
1144
1145  for (int times = 0; times < benchmark_iterations_; ++times) {
1146    int ret = MJPGToARGB(orig_pixels, kSize,
1147                         dst_argb_opt, benchmark_width_ * 4,
1148                         benchmark_width_, benchmark_height_,
1149                         benchmark_width_, benchmark_height_);
1150    // Expect failure because image is not really valid.
1151    EXPECT_EQ(1, ret);
1152  }
1153
1154  free_aligned_buffer_page_end(dst_argb_opt);
1155  free_aligned_buffer_page_end(orig_pixels);
1156}
1157
1158#endif  // HAVE_JPEG
1159
1160TEST_F(libyuvTest, CropNV12) {
1161  const int SUBSAMP_X = 2;
1162  const int SUBSAMP_Y = 2;
1163  const int kWidth = benchmark_width_;
1164  const int kHeight = benchmark_height_;
1165  const int crop_y =
1166    (benchmark_height_ - (benchmark_height_ * 360 / 480)) / 2;
1167  const int kDestWidth = benchmark_width_;
1168  const int kDestHeight = benchmark_height_ - crop_y * 2;;
1169  const int sample_size = kWidth * kHeight +
1170    SUBSAMPLE(kWidth, SUBSAMP_X) *
1171    SUBSAMPLE(kHeight, SUBSAMP_Y) * 2;
1172  align_buffer_64(src_y, sample_size);
1173  uint8* src_uv = src_y + kWidth * kHeight;
1174
1175  align_buffer_64(dst_y, kDestWidth * kDestHeight);
1176  align_buffer_64(dst_u,
1177                  SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1178                  SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1179  align_buffer_64(dst_v,
1180                  SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1181                  SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1182
1183  align_buffer_64(dst_y_2, kDestWidth * kDestHeight);
1184  align_buffer_64(dst_u_2,
1185                  SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1186                  SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1187  align_buffer_64(dst_v_2,
1188                  SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1189                  SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1190
1191  srandom(time(NULL));
1192  for (int i = 0; i < kHeight; ++i)
1193    for (int j = 0; j < kWidth; ++j)
1194      src_y[(i * kWidth) + j] = (random() & 0xff);
1195  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {
1196    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {
1197      src_uv[(i * SUBSAMPLE(kWidth, SUBSAMP_X)) + j * 2 + 0] =
1198          (random() & 0xff);
1199      src_uv[(i * SUBSAMPLE(kWidth, SUBSAMP_X)) + j * 2 + 1] =
1200          (random() & 0xff);
1201    }
1202  }
1203  memset(dst_y, 1, kDestWidth * kDestHeight);
1204  memset(dst_u, 2, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1205                   SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1206  memset(dst_v, 3, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1207                   SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1208  memset(dst_y_2, 1, kDestWidth * kDestHeight);
1209  memset(dst_u_2, 2, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1210                     SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1211  memset(dst_v_2, 3, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
1212                     SUBSAMPLE(kDestHeight, SUBSAMP_Y));
1213
1214  NV12ToI420(src_y + crop_y * kWidth, kWidth,
1215             src_uv + (crop_y / 2) * kWidth, kWidth,
1216             dst_y, kDestWidth,
1217             dst_u, SUBSAMPLE(kDestWidth, SUBSAMP_X),
1218             dst_v, SUBSAMPLE(kDestWidth, SUBSAMP_X),
1219             kDestWidth, kDestHeight);
1220
1221  ConvertToI420(src_y, sample_size,
1222                dst_y_2, kDestWidth,
1223                dst_u_2, SUBSAMPLE(kDestWidth, SUBSAMP_X),
1224                dst_v_2, SUBSAMPLE(kDestWidth, SUBSAMP_X),
1225                0, crop_y,
1226                kWidth, kHeight,
1227                kDestWidth, kDestHeight,
1228                libyuv::kRotate0, libyuv::FOURCC_NV12);
1229
1230  for (int i = 0; i < kDestHeight; ++i) {
1231    for (int j = 0; j < kDestWidth; ++j) {
1232      EXPECT_EQ(dst_y[i * kWidth + j], dst_y_2[i * kWidth + j]);
1233    }
1234  }
1235  for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) {
1236    for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) {
1237      EXPECT_EQ(dst_u[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j],
1238                dst_u_2[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]);
1239    }
1240  }
1241  for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) {
1242    for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) {
1243      EXPECT_EQ(dst_v[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j],
1244                dst_v_2[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]);
1245    }
1246  }
1247  free_aligned_buffer_64(dst_y);
1248  free_aligned_buffer_64(dst_u);
1249  free_aligned_buffer_64(dst_v);
1250  free_aligned_buffer_64(dst_y_2);
1251  free_aligned_buffer_64(dst_u_2);
1252  free_aligned_buffer_64(dst_v_2);
1253  free_aligned_buffer_64(src_y);
1254}
1255
1256TEST_F(libyuvTest, HaveJPEG) {
1257#ifdef HAVE_JPEG
1258  printf("JPEG enabled\n.");
1259#else
1260  printf("JPEG disabled\n.");
1261#endif
1262}
1263
1264}  // namespace libyuv
1265