convert_test.cc 67.5 KB
Newer Older
1 2 3 4 5 6
/*
 *  Copyright 2011 The LibYuv Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
7
 *  in the file PATENTS. All contributing project authors may
8 9 10 11 12 13 14 15 16 17 18 19 20
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <stdlib.h>
#include <time.h>

#include "libyuv/compare.h"
#include "libyuv/convert.h"
#include "libyuv/convert_argb.h"
#include "libyuv/convert_from.h"
#include "libyuv/convert_from_argb.h"
#include "libyuv/cpu_id.h"
#include "libyuv/format_conversion.h"
21 22 23
#ifdef HAVE_JPEG
#include "libyuv/mjpeg_decoder.h"
#endif
24 25 26 27 28 29 30 31 32 33 34 35
#include "libyuv/planar_functions.h"
#include "libyuv/rotate.h"
#include "../unit_test/unit_test.h"

#if defined(_MSC_VER)
#define SIMD_ALIGNED(var) __declspec(align(16)) var
#else  // __GNUC__
#define SIMD_ALIGNED(var) var __attribute__((aligned(16)))
#endif

namespace libyuv {

36 37
#define SUBSAMPLE(v, a) ((((v) + (a) - 1)) / (a))

38
#define TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,           \
39
                       FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF)   \
40
TEST_F(libyuvTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) {                        \
41
  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
42
  const int kHeight = benchmark_height_;                                       \
43 44
  align_buffer_64(src_y, kWidth * kHeight + OFF);                              \
  align_buffer_64(src_u,                                                       \
45 46
                  SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                           \
                  SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);                    \
47
  align_buffer_64(src_v,                                                       \
48 49
                  SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                           \
                  SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);                    \
50
  align_buffer_64(dst_y_c, kWidth * kHeight);                                  \
51 52 53 54 55 56
  align_buffer_64(dst_u_c,                                                     \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
  align_buffer_64(dst_v_c,                                                     \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
57
  align_buffer_64(dst_y_opt, kWidth * kHeight);                                \
58 59 60 61 62 63
  align_buffer_64(dst_u_opt,                                                   \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
  align_buffer_64(dst_v_opt,                                                   \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
64 65 66
  srandom(time(NULL));                                                         \
  for (int i = 0; i < kHeight; ++i)                                            \
    for (int j = 0; j < kWidth; ++j)                                           \
67
      src_y[(i * kWidth) + j + OFF] = (random() & 0xff);                       \
68 69 70 71 72 73
  for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) {                \
    for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) {               \
      src_u[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \
          (random() & 0xff);                                                   \
      src_v[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \
          (random() & 0xff);                                                   \
74
    }                                                                          \
75
  }                                                                            \
76
  MaskCpuFlags(0);                                                             \
77
  SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                          \
78 79 80 81
                                 src_u + OFF,                                  \
                                 SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \
                                 src_v + OFF,                                  \
                                 SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \
82
                                 dst_y_c, kWidth,                              \
83 84
                                 dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \
                                 dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \
85 86 87
                                 kWidth, NEG kHeight);                         \
  MaskCpuFlags(-1);                                                            \
  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
88
    SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                        \
89 90 91 92
                                   src_u + OFF,                                \
                                       SUBSAMPLE(kWidth, SRC_SUBSAMP_X),       \
                                   src_v + OFF,                                \
                                       SUBSAMPLE(kWidth, SRC_SUBSAMP_X),       \
93
                                   dst_y_opt, kWidth,                          \
94 95
                                   dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \
                                   dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \
96 97 98 99 100 101 102 103 104 105 106 107 108
                                   kWidth, NEG kHeight);                       \
  }                                                                            \
  int max_diff = 0;                                                            \
  for (int i = 0; i < kHeight; ++i) {                                          \
    for (int j = 0; j < kWidth; ++j) {                                         \
      int abs_diff =                                                           \
          abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
              static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
109
  EXPECT_LE(max_diff, 1);                                                      \
110 111
  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
112
      int abs_diff =                                                           \
113 114 115 116
          abs(static_cast<int>(dst_u_c[i *                                     \
                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
              static_cast<int>(dst_u_opt[i *                                   \
                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
117 118 119 120 121
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
122
  EXPECT_LE(max_diff, 1);                                                      \
123 124
  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
125
      int abs_diff =                                                           \
126 127 128 129
          abs(static_cast<int>(dst_v_c[i *                                     \
                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
              static_cast<int>(dst_v_opt[i *                                   \
                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
130 131 132 133 134
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
135
  EXPECT_LE(max_diff, 1);                                                      \
136 137 138 139 140 141 142 143 144
  free_aligned_buffer_64(dst_y_c)                                              \
  free_aligned_buffer_64(dst_u_c)                                              \
  free_aligned_buffer_64(dst_v_c)                                              \
  free_aligned_buffer_64(dst_y_opt)                                            \
  free_aligned_buffer_64(dst_u_opt)                                            \
  free_aligned_buffer_64(dst_v_opt)                                            \
  free_aligned_buffer_64(src_y)                                                \
  free_aligned_buffer_64(src_u)                                                \
  free_aligned_buffer_64(src_v)                                                \
145 146 147 148 149
}

#define TESTPLANARTOP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,            \
                      FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y)                        \
    TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,               \
150
                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                           \
fbarchard@google.com's avatar
fbarchard@google.com committed
151
                   benchmark_width_ - 4, _Any, +, 0)                           \
152
    TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,               \
153 154
                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                           \
                   benchmark_width_, _Unaligned, +, 1)                         \
155
    TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,               \
156 157
                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                           \
                   benchmark_width_, _Invert, -, 0)                            \
158
    TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,               \
159
                   FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                           \
160
                   benchmark_width_, _Opt, +, 0)
161 162 163 164 165 166 167 168

TESTPLANARTOP(I420, 2, 2, I420, 2, 2)
TESTPLANARTOP(I422, 2, 1, I420, 2, 2)
TESTPLANARTOP(I444, 1, 1, I420, 2, 2)
TESTPLANARTOP(I411, 4, 1, I420, 2, 2)
TESTPLANARTOP(I420, 2, 2, I422, 2, 1)
TESTPLANARTOP(I420, 2, 2, I444, 1, 1)
TESTPLANARTOP(I420, 2, 2, I411, 4, 1)
169
TESTPLANARTOP(I420, 2, 2, I420Mirror, 2, 2)
170 171
TESTPLANARTOP(I422, 2, 1, I422, 2, 1)
TESTPLANARTOP(I444, 1, 1, I444, 1, 1)
172

173 174 175
#define TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,          \
                       FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF)   \
TEST_F(libyuvTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) {                        \
176
  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
177
  const int kHeight = benchmark_height_;                                       \
178 179
  align_buffer_64(src_y, kWidth * kHeight + OFF);                              \
  align_buffer_64(src_u,                                                       \
180 181
                  SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                           \
                  SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);                    \
182
  align_buffer_64(src_v,                                                       \
183 184
                  SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                           \
                  SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);                    \
185
  align_buffer_64(dst_y_c, kWidth * kHeight);                                  \
186 187
  align_buffer_64(dst_uv_c, SUBSAMPLE(kWidth * 2, SUBSAMP_X) *                 \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
188
  align_buffer_64(dst_y_opt, kWidth * kHeight);                                \
189 190
  align_buffer_64(dst_uv_opt, SUBSAMPLE(kWidth * 2, SUBSAMP_X) *               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
191 192 193 194
  srandom(time(NULL));                                                         \
  for (int i = 0; i < kHeight; ++i)                                            \
    for (int j = 0; j < kWidth; ++j)                                           \
      src_y[(i * kWidth) + j + OFF] = (random() & 0xff);                       \
195 196 197 198 199 200
  for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) {                \
    for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) {               \
      src_u[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \
          (random() & 0xff);                                                   \
      src_v[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \
          (random() & 0xff);                                                   \
201 202 203 204
    }                                                                          \
  }                                                                            \
  MaskCpuFlags(0);                                                             \
  SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                          \
205 206 207 208
                                 src_u + OFF,                                  \
                                 SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \
                                 src_v + OFF,                                  \
                                 SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \
209
                                 dst_y_c, kWidth,                              \
210
                                 dst_uv_c, SUBSAMPLE(kWidth * 2, SUBSAMP_X),   \
211 212 213 214
                                 kWidth, NEG kHeight);                         \
  MaskCpuFlags(-1);                                                            \
  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
    SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                        \
215 216 217 218
                                   src_u + OFF,                                \
                                   SUBSAMPLE(kWidth, SRC_SUBSAMP_X),           \
                                   src_v + OFF,                                \
                                   SUBSAMPLE(kWidth, SRC_SUBSAMP_X),           \
219
                                   dst_y_opt, kWidth,                          \
220 221
                                   dst_uv_opt,                                 \
                                   SUBSAMPLE(kWidth * 2, SUBSAMP_X),           \
222 223 224 225 226 227 228 229 230 231 232 233 234 235
                                   kWidth, NEG kHeight);                       \
  }                                                                            \
  int max_diff = 0;                                                            \
  for (int i = 0; i < kHeight; ++i) {                                          \
    for (int j = 0; j < kWidth; ++j) {                                         \
      int abs_diff =                                                           \
          abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
              static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
  EXPECT_LE(max_diff, 1);                                                      \
236 237
  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    for (int j = 0; j < SUBSAMPLE(kWidth * 2, SUBSAMP_X); ++j) {               \
238
      int abs_diff =                                                           \
239 240 241 242
          abs(static_cast<int>(dst_uv_c[i *                                    \
                               SUBSAMPLE(kWidth * 2, SUBSAMP_X) + j]) -        \
              static_cast<int>(dst_uv_opt[i *                                  \
                               SUBSAMPLE(kWidth * 2, SUBSAMP_X) + j]));        \
243 244 245 246 247 248
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
  EXPECT_LE(max_diff, 1);                                                      \
249 250 251 252 253 254 255
  free_aligned_buffer_64(dst_y_c)                                              \
  free_aligned_buffer_64(dst_uv_c)                                             \
  free_aligned_buffer_64(dst_y_opt)                                            \
  free_aligned_buffer_64(dst_uv_opt)                                           \
  free_aligned_buffer_64(src_y)                                                \
  free_aligned_buffer_64(src_u)                                                \
  free_aligned_buffer_64(src_v)                                                \
256 257 258
}

#define TESTPLANARTOBP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,           \
259
                       FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y)                       \
260
    TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \
261
                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \
262
                    benchmark_width_ - 4, _Any, +, 0)                          \
263
    TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \
264 265
                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \
                    benchmark_width_, _Unaligned, +, 1)                        \
266
    TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \
267 268
                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \
                    benchmark_width_, _Invert, -, 0)                           \
269
    TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \
270
                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \
271
                    benchmark_width_, _Opt, +, 0)
272 273 274 275

TESTPLANARTOBP(I420, 2, 2, NV12, 2, 2)
TESTPLANARTOBP(I420, 2, 2, NV21, 2, 2)

276
#define TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,         \
277
                         FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF) \
278
TEST_F(libyuvTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) {                        \
279
  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
280
  const int kHeight = benchmark_height_;                                       \
281
  align_buffer_64(src_y, kWidth * kHeight + OFF);                              \
282 283
  align_buffer_64(src_uv, 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *               \
                  SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);                    \
284
  align_buffer_64(dst_y_c, kWidth * kHeight);                                  \
285 286 287 288 289 290
  align_buffer_64(dst_u_c,                                                     \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
  align_buffer_64(dst_v_c,                                                     \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
291
  align_buffer_64(dst_y_opt, kWidth * kHeight);                                \
292 293 294 295 296 297
  align_buffer_64(dst_u_opt,                                                   \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
  align_buffer_64(dst_v_opt,                                                   \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
298 299 300
  srandom(time(NULL));                                                         \
  for (int i = 0; i < kHeight; ++i)                                            \
    for (int j = 0; j < kWidth; ++j)                                           \
301
      src_y[(i * kWidth) + j + OFF] = (random() & 0xff);                       \
302 303 304 305
  for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) {                \
    for (int j = 0; j < 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) {           \
      src_uv[(i * 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =           \
          (random() & 0xff);                                                   \
306 307 308
    }                                                                          \
  }                                                                            \
  MaskCpuFlags(0);                                                             \
309
  SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                          \
310 311
                                 src_uv + OFF,                                 \
                                 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X),         \
312
                                 dst_y_c, kWidth,                              \
313 314
                                 dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \
                                 dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \
315 316 317
                                 kWidth, NEG kHeight);                         \
  MaskCpuFlags(-1);                                                            \
  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
318
    SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                        \
319 320
                                   src_uv + OFF,                               \
                                   2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X),       \
321
                                   dst_y_opt, kWidth,                          \
322 323
                                   dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \
                                   dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \
324 325 326 327 328 329 330 331 332 333 334 335 336
                                   kWidth, NEG kHeight);                       \
  }                                                                            \
  int max_diff = 0;                                                            \
  for (int i = 0; i < kHeight; ++i) {                                          \
    for (int j = 0; j < kWidth; ++j) {                                         \
      int abs_diff =                                                           \
          abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
              static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
337
  EXPECT_LE(max_diff, 1);                                                      \
338 339
  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
340
      int abs_diff =                                                           \
341 342 343 344
          abs(static_cast<int>(dst_u_c[i *                                     \
                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
              static_cast<int>(dst_u_opt[i *                                   \
                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
345 346 347 348 349
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
350
  EXPECT_LE(max_diff, 1);                                                      \
351 352
  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
353
      int abs_diff =                                                           \
354 355 356 357
          abs(static_cast<int>(dst_v_c[i *                                     \
                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
              static_cast<int>(dst_v_opt[i *                                   \
                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
358 359 360 361 362
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
363
  EXPECT_LE(max_diff, 1);                                                      \
364 365 366 367 368 369 370 371
  free_aligned_buffer_64(dst_y_c)                                              \
  free_aligned_buffer_64(dst_u_c)                                              \
  free_aligned_buffer_64(dst_v_c)                                              \
  free_aligned_buffer_64(dst_y_opt)                                            \
  free_aligned_buffer_64(dst_u_opt)                                            \
  free_aligned_buffer_64(dst_v_opt)                                            \
  free_aligned_buffer_64(src_y)                                                \
  free_aligned_buffer_64(src_uv)                                               \
372 373 374 375 376
}

#define TESTBIPLANARTOP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,          \
                        FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y)                      \
    TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,             \
377
                     FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                         \
fbarchard@google.com's avatar
fbarchard@google.com committed
378
                     benchmark_width_ - 4, _Any, +, 0)                         \
379
    TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,             \
380 381
                     FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                         \
                     benchmark_width_, _Unaligned, +, 1)                       \
382
    TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,             \
383 384
                     FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                         \
                     benchmark_width_, _Invert, -, 0)                          \
385
    TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,             \
386
                     FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                         \
387
                     benchmark_width_, _Opt, +, 0)
388 389

TESTBIPLANARTOP(NV12, 2, 2, I420, 2, 2)
390
TESTBIPLANARTOP(NV21, 2, 2, I420, 2, 2)
391

392 393
#define ALIGNINT(V, ALIGN) (((V) + (ALIGN) - 1) / (ALIGN) * (ALIGN))

394
#define TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,  \
395
                       YALIGN, W1280, DIFF, N, NEG, OFF, FMT_C, BPP_C)         \
396
TEST_F(libyuvTest, FMT_PLANAR##To##FMT_B##N) {                                 \
397
  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
398 399
  const int kHeight = ALIGNINT(benchmark_height_, YALIGN);                     \
  const int kStrideB = ALIGNINT(kWidth * BPP_B, ALIGN);                        \
400 401
  const int kSizeUV =                                                          \
    SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y);              \
402
  align_buffer_64(src_y, kWidth * kHeight + OFF);                              \
403 404
  align_buffer_64(src_u, kSizeUV + OFF);                                       \
  align_buffer_64(src_v, kSizeUV + OFF);                                       \
405 406
  align_buffer_64(dst_argb_c, kStrideB * kHeight);                             \
  align_buffer_64(dst_argb_opt, kStrideB * kHeight);                           \
407 408 409
  memset(dst_argb_c, 0, kStrideB * kHeight);                                   \
  memset(dst_argb_opt, 0, kStrideB * kHeight);                                 \
  srandom(time(NULL));                                                         \
410 411
  for (int i = 0; i < kWidth * kHeight; ++i) {                                 \
    src_y[i + OFF] = (random() & 0xff);                                        \
412
  }                                                                            \
413 414 415
  for (int i = 0; i < kSizeUV; ++i) {                                          \
    src_u[i + OFF] = (random() & 0xff);                                        \
    src_v[i + OFF] = (random() & 0xff);                                        \
416
  }                                                                            \
417
  MaskCpuFlags(0);                                                             \
418
  FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                   \
419 420
                        src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X),             \
                        src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X),             \
421 422
                        dst_argb_c, kStrideB,                                  \
                        kWidth, NEG kHeight);                                  \
423
  MaskCpuFlags(-1);                                                            \
424
  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
425
    FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                 \
426 427
                          src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X),           \
                          src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X),           \
428 429 430 431
                          dst_argb_opt, kStrideB,                              \
                          kWidth, NEG kHeight);                                \
  }                                                                            \
  int max_diff = 0;                                                            \
432
  /* Convert to ARGB so 565 is expanded to bytes that can be compared. */      \
433 434 435 436 437 438 439 440 441 442
  align_buffer_64(dst_argb32_c, kWidth * BPP_C  * kHeight);                    \
  align_buffer_64(dst_argb32_opt, kWidth * BPP_C  * kHeight);                  \
  memset(dst_argb32_c, 0, kWidth * BPP_C  * kHeight);                          \
  memset(dst_argb32_opt, 0, kWidth * BPP_C  * kHeight);                        \
  FMT_B##To##FMT_C(dst_argb_c, kStrideB,                                       \
                   dst_argb32_c, kWidth * BPP_C ,                              \
                   kWidth, kHeight);                                           \
  FMT_B##To##FMT_C(dst_argb_opt, kStrideB,                                     \
                   dst_argb32_opt, kWidth * BPP_C ,                            \
                   kWidth, kHeight);                                           \
443 444 445 446 447 448
  for (int i = 0; i < kWidth * BPP_C * kHeight; ++i) {                         \
    int abs_diff =                                                             \
        abs(static_cast<int>(dst_argb32_c[i]) -                                \
            static_cast<int>(dst_argb32_opt[i]));                              \
    if (abs_diff > max_diff) {                                                 \
      max_diff = abs_diff;                                                     \
449 450
    }                                                                          \
  }                                                                            \
451
  EXPECT_LE(max_diff, DIFF);                                                   \
452 453 454 455 456 457 458
  free_aligned_buffer_64(src_y)                                                \
  free_aligned_buffer_64(src_u)                                                \
  free_aligned_buffer_64(src_v)                                                \
  free_aligned_buffer_64(dst_argb_c)                                           \
  free_aligned_buffer_64(dst_argb_opt)                                         \
  free_aligned_buffer_64(dst_argb32_c)                                         \
  free_aligned_buffer_64(dst_argb32_opt)                                       \
459 460
}

461
#define TESTPLANARTOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,   \
462
                      YALIGN, DIFF, FMT_C, BPP_C)                              \
fbarchard@google.com's avatar
fbarchard@google.com committed
463
    TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,      \
464
        YALIGN, benchmark_width_ - 4, DIFF, _Any, +, 0, FMT_C, BPP_C)          \
fbarchard@google.com's avatar
fbarchard@google.com committed
465
    TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,      \
466
        YALIGN, benchmark_width_, DIFF, _Unaligned, +, 1, FMT_C, BPP_C)        \
fbarchard@google.com's avatar
fbarchard@google.com committed
467
    TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,      \
468
        YALIGN, benchmark_width_, DIFF, _Invert, -, 0, FMT_C, BPP_C)           \
469
    TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,      \
470
        YALIGN, benchmark_width_, DIFF, _Opt, +, 0, FMT_C, BPP_C)
471

472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
// TODO(fbarchard): Make vertical alignment unnecessary on bayer.
TESTPLANARTOB(I420, 2, 2, ARGB, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, BGRA, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, ABGR, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, RGBA, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, RAW, 3, 3, 1, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, RGB24, 3, 3, 1, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, RGB565, 2, 2, 1, 9, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, ARGB1555, 2, 2, 1, 9, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, ARGB4444, 2, 2, 1, 17, ARGB, 4)
TESTPLANARTOB(I422, 2, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I422, 2, 1, BGRA, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I422, 2, 1, ABGR, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I422, 2, 1, RGBA, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I411, 4, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I444, 1, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, YUY2, 2, 4, 1, 1, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, UYVY, 2, 4, 1, 1, ARGB, 4)
TESTPLANARTOB(I422, 2, 1, YUY2, 2, 4, 1, 0, ARGB, 4)
TESTPLANARTOB(I422, 2, 1, UYVY, 2, 4, 1, 0, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, I400, 1, 1, 1, 0, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, BayerBGGR, 1, 2, 2, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, BayerRGGB, 1, 2, 2, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, BayerGBRG, 1, 2, 2, 2, ARGB, 4)
TESTPLANARTOB(I420, 2, 2, BayerGRBG, 1, 2, 2, 2, ARGB, 4)
497 498

#define TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,       \
499
                         W1280, DIFF, N, NEG, OFF)                             \
500
TEST_F(libyuvTest, FMT_PLANAR##To##FMT_B##N) {                                 \
501
  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
502
  const int kHeight = benchmark_height_;                                       \
503
  const int kStrideB = kWidth * BPP_B;                                         \
504
  align_buffer_64(src_y, kWidth * kHeight + OFF);                              \
505 506 507
  align_buffer_64(src_uv,                                                      \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y) * 2 + OFF);                    \
508 509
  align_buffer_64(dst_argb_c, kStrideB * kHeight);                             \
  align_buffer_64(dst_argb_opt, kStrideB * kHeight);                           \
510 511 512
  srandom(time(NULL));                                                         \
  for (int i = 0; i < kHeight; ++i)                                            \
    for (int j = 0; j < kWidth; ++j)                                           \
513
      src_y[(i * kWidth) + j + OFF] = (random() & 0xff);                       \
514 515 516 517
  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i)                      \
    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X) * 2; ++j) {               \
      src_uv[(i * SUBSAMPLE(kWidth, SUBSAMP_X)) * 2 + j + OFF] =               \
          (random() & 0xff);                                                   \
518 519
    }                                                                          \
  MaskCpuFlags(0);                                                             \
520
  FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                   \
521
                        src_uv + OFF, SUBSAMPLE(kWidth, SUBSAMP_X) * 2,        \
522 523 524 525
                        dst_argb_c, kWidth * BPP_B,                            \
                        kWidth, NEG kHeight);                                  \
  MaskCpuFlags(-1);                                                            \
  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
526
    FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                 \
527
                          src_uv + OFF, SUBSAMPLE(kWidth, SUBSAMP_X) * 2,      \
528 529 530
                          dst_argb_opt, kWidth * BPP_B,                        \
                          kWidth, NEG kHeight);                                \
  }                                                                            \
531
  /* Convert to ARGB so 565 is expanded to bytes that can be compared. */      \
532 533
  align_buffer_64(dst_argb32_c, kWidth * 4 * kHeight);                         \
  align_buffer_64(dst_argb32_opt, kWidth * 4 * kHeight);                       \
534 535
  memset(dst_argb32_c, 1, kWidth * 4 * kHeight);                               \
  memset(dst_argb32_opt, 2, kWidth * 4 * kHeight);                             \
536 537 538 539 540 541
  FMT_B##ToARGB(dst_argb_c, kStrideB,                                          \
                dst_argb32_c, kWidth * 4,                                      \
                kWidth, kHeight);                                              \
  FMT_B##ToARGB(dst_argb_opt, kStrideB,                                        \
                dst_argb32_opt, kWidth * 4,                                    \
                kWidth, kHeight);                                              \
542 543
  int max_diff = 0;                                                            \
  for (int i = 0; i < kHeight; ++i) {                                          \
544
    for (int j = 0; j < kWidth * 4; ++j) {                                     \
545
      int abs_diff =                                                           \
546 547
          abs(static_cast<int>(dst_argb32_c[i * kWidth * 4 + j]) -             \
              static_cast<int>(dst_argb32_opt[i * kWidth * 4 + j]));           \
548 549 550 551 552
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
553
  EXPECT_LE(max_diff, DIFF);                                                   \
554 555 556 557 558 559
  free_aligned_buffer_64(src_y)                                                \
  free_aligned_buffer_64(src_uv)                                               \
  free_aligned_buffer_64(dst_argb_c)                                           \
  free_aligned_buffer_64(dst_argb_opt)                                         \
  free_aligned_buffer_64(dst_argb32_c)                                         \
  free_aligned_buffer_64(dst_argb32_opt)                                       \
560 561
}

562
#define TESTBIPLANARTOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, DIFF)  \
563
    TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,           \
fbarchard@google.com's avatar
fbarchard@google.com committed
564
                     benchmark_width_ - 4, DIFF, _Any, +, 0)                   \
565
    TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,           \
566
                     benchmark_width_, DIFF, _Unaligned, +, 1)                 \
567
    TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,           \
568
                     benchmark_width_, DIFF, _Invert, -, 0)                    \
569
    TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,           \
570
                     benchmark_width_, DIFF, _Opt, +, 0)
571

572 573
TESTBIPLANARTOB(NV12, 2, 2, ARGB, 4, 2)
TESTBIPLANARTOB(NV21, 2, 2, ARGB, 4, 2)
574 575
TESTBIPLANARTOB(NV12, 2, 2, RGB565, 2, 9)
TESTBIPLANARTOB(NV21, 2, 2, RGB565, 2, 9)
576

577
#define TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
fbarchard@google.com's avatar
fbarchard@google.com committed
578
                       W1280, DIFF, N, NEG, OFF)                               \
579
TEST_F(libyuvTest, FMT_A##To##FMT_PLANAR##N) {                                 \
580
  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
581
  const int kHeight = ALIGNINT(benchmark_height_, YALIGN);                     \
582
  const int kStride = (kWidth * 8 * BPP_A + 7) / 8;                            \
583 584
  align_buffer_64(src_argb, kStride * kHeight + OFF);                          \
  align_buffer_64(dst_y_c, kWidth * kHeight);                                  \
585 586 587 588 589 590
  align_buffer_64(dst_u_c,                                                     \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
  align_buffer_64(dst_v_c,                                                     \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
591
  align_buffer_64(dst_y_opt, kWidth * kHeight);                                \
592 593 594 595 596 597
  align_buffer_64(dst_u_opt,                                                   \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
  align_buffer_64(dst_v_opt,                                                   \
                  SUBSAMPLE(kWidth, SUBSAMP_X) *                               \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
598
  memset(dst_y_c, 1, kWidth * kHeight);                                        \
599 600 601 602
  memset(dst_u_c, 0,                                                           \
         SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y));        \
  memset(dst_v_c, 0,                                                           \
         SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y));        \
603
  memset(dst_y_opt, 2, kWidth * kHeight);                                      \
604 605 606 607
  memset(dst_u_opt, 0,                                                         \
         SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y));        \
  memset(dst_v_opt, 0,                                                         \
         SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y));        \
608 609 610
  srandom(time(NULL));                                                         \
  for (int i = 0; i < kHeight; ++i)                                            \
    for (int j = 0; j < kStride; ++j)                                          \
611
      src_argb[(i * kStride) + j + OFF] = (random() & 0xff);                   \
612
  MaskCpuFlags(0);                                                             \
613
  FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride,                               \
614
                        dst_y_c, kWidth,                                       \
615 616
                        dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X),                 \
                        dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X),                 \
617 618 619
                        kWidth, NEG kHeight);                                  \
  MaskCpuFlags(-1);                                                            \
  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
620
    FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride,                             \
621
                          dst_y_opt, kWidth,                                   \
622 623
                          dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X),             \
                          dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X),             \
624 625 626 627 628 629 630 631 632 633 634 635 636
                          kWidth, NEG kHeight);                                \
  }                                                                            \
  int max_diff = 0;                                                            \
  for (int i = 0; i < kHeight; ++i) {                                          \
    for (int j = 0; j < kWidth; ++j) {                                         \
      int abs_diff =                                                           \
          abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
              static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
fbarchard@google.com's avatar
fbarchard@google.com committed
637
  EXPECT_LE(max_diff, DIFF);                                                   \
638 639
  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
640
      int abs_diff =                                                           \
641 642 643 644
          abs(static_cast<int>(dst_u_c[i *                                     \
                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
              static_cast<int>(dst_u_opt[i *                                   \
                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
645 646 647 648 649
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
fbarchard@google.com's avatar
fbarchard@google.com committed
650
  EXPECT_LE(max_diff, DIFF);                                                   \
651 652
  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
653
      int abs_diff =                                                           \
654 655 656 657
          abs(static_cast<int>(dst_v_c[i *                                     \
                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
              static_cast<int>(dst_v_opt[i *                                   \
                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
658 659 660 661 662
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
fbarchard@google.com's avatar
fbarchard@google.com committed
663
  EXPECT_LE(max_diff, DIFF);                                                   \
664 665 666 667 668 669 670
  free_aligned_buffer_64(dst_y_c)                                              \
  free_aligned_buffer_64(dst_u_c)                                              \
  free_aligned_buffer_64(dst_v_c)                                              \
  free_aligned_buffer_64(dst_y_opt)                                            \
  free_aligned_buffer_64(dst_u_opt)                                            \
  free_aligned_buffer_64(dst_v_opt)                                            \
  free_aligned_buffer_64(src_argb)                                             \
671 672
}

673 674 675
#define TESTATOPLANAR(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,  \
                      DIFF)                                                    \
    TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,     \
fbarchard@google.com's avatar
fbarchard@google.com committed
676
                   benchmark_width_ - 4, DIFF, _Any, +, 0)                     \
677
    TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,     \
fbarchard@google.com's avatar
fbarchard@google.com committed
678
                   benchmark_width_, DIFF, _Unaligned, +, 1)                   \
679
    TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,     \
fbarchard@google.com's avatar
fbarchard@google.com committed
680
                   benchmark_width_, DIFF, _Invert, -, 0)                      \
681
    TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,     \
fbarchard@google.com's avatar
fbarchard@google.com committed
682
                   benchmark_width_, DIFF, _Opt, +, 0)
683

684
TESTATOPLANAR(ARGB, 4, 1, I420, 2, 2, 4)
685
#ifdef __arm__
686
TESTATOPLANAR(ARGB, 4, 1, J420, 2, 2, 4)
687
#else
688
TESTATOPLANAR(ARGB, 4, 1, J420, 2, 2, 0)
689
#endif
690 691 692 693 694 695
TESTATOPLANAR(BGRA, 4, 1, I420, 2, 2, 4)
TESTATOPLANAR(ABGR, 4, 1, I420, 2, 2, 4)
TESTATOPLANAR(RGBA, 4, 1, I420, 2, 2, 4)
TESTATOPLANAR(RAW, 3, 1, I420, 2, 2, 4)
TESTATOPLANAR(RGB24, 3, 1, I420, 2, 2, 4)
TESTATOPLANAR(RGB565, 2, 1, I420, 2, 2, 5)
696
// TODO(fbarchard): Make 1555 neon work same as C code, reduce to diff 9.
697 698 699 700 701 702 703 704 705 706 707 708 709 710
TESTATOPLANAR(ARGB1555, 2, 1, I420, 2, 2, 15)
TESTATOPLANAR(ARGB4444, 2, 1, I420, 2, 2, 17)
TESTATOPLANAR(ARGB, 4, 1, I411, 4, 1, 4)
TESTATOPLANAR(ARGB, 4, 1, I422, 2, 1, 2)
TESTATOPLANAR(ARGB, 4, 1, I444, 1, 1, 2)
TESTATOPLANAR(YUY2, 2, 1, I420, 2, 2, 2)
TESTATOPLANAR(UYVY, 2, 1, I420, 2, 2, 2)
TESTATOPLANAR(YUY2, 2, 1, I422, 2, 1, 2)
TESTATOPLANAR(UYVY, 2, 1, I422, 2, 1, 2)
TESTATOPLANAR(I400, 1, 1, I420, 2, 2, 2)
TESTATOPLANAR(BayerBGGR, 1, 2, I420, 2, 2, 4)
TESTATOPLANAR(BayerRGGB, 1, 2, I420, 2, 2, 4)
TESTATOPLANAR(BayerGBRG, 1, 2, I420, 2, 2, 4)
TESTATOPLANAR(BayerGRBG, 1, 2, I420, 2, 2, 4)
711

712 713 714
#define TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,       \
                       W1280, N, NEG, OFF)                                     \
TEST_F(libyuvTest, FMT_A##To##FMT_PLANAR##N) {                                 \
715
  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
716 717
  const int kHeight = benchmark_height_;                                       \
  const int kStride = (kWidth * 8 * BPP_A + 7) / 8;                            \
718 719
  align_buffer_64(src_argb, kStride * kHeight + OFF);                          \
  align_buffer_64(dst_y_c, kWidth * kHeight);                                  \
720 721 722
  align_buffer_64(dst_uv_c,                                                    \
                  SUBSAMPLE(kWidth, SUBSAMP_X) * 2 *                           \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
723
  align_buffer_64(dst_y_opt, kWidth * kHeight);                                \
724 725 726
  align_buffer_64(dst_uv_opt,                                                  \
                  SUBSAMPLE(kWidth, SUBSAMP_X) * 2 *                           \
                  SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
727 728 729 730 731 732 733
  srandom(time(NULL));                                                         \
  for (int i = 0; i < kHeight; ++i)                                            \
    for (int j = 0; j < kStride; ++j)                                          \
      src_argb[(i * kStride) + j + OFF] = (random() & 0xff);                   \
  MaskCpuFlags(0);                                                             \
  FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride,                               \
                        dst_y_c, kWidth,                                       \
734
                        dst_uv_c, SUBSAMPLE(kWidth, SUBSAMP_X) * 2,            \
735 736 737 738 739
                        kWidth, NEG kHeight);                                  \
  MaskCpuFlags(-1);                                                            \
  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
    FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride,                             \
                          dst_y_opt, kWidth,                                   \
740
                          dst_uv_opt, SUBSAMPLE(kWidth, SUBSAMP_X) * 2,        \
741 742 743 744 745 746 747 748 749 750 751 752 753
                          kWidth, NEG kHeight);                                \
  }                                                                            \
  int max_diff = 0;                                                            \
  for (int i = 0; i < kHeight; ++i) {                                          \
    for (int j = 0; j < kWidth; ++j) {                                         \
      int abs_diff =                                                           \
          abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
              static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
fbarchard@google.com's avatar
fbarchard@google.com committed
754
  EXPECT_LE(max_diff, 4);                                                      \
755 756
  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X) * 2; ++j) {               \
757
      int abs_diff =                                                           \
758 759 760 761
          abs(static_cast<int>(dst_uv_c[i *                                    \
                               SUBSAMPLE(kWidth, SUBSAMP_X) * 2 + j]) -        \
              static_cast<int>(dst_uv_opt[i *                                  \
                               SUBSAMPLE(kWidth, SUBSAMP_X) * 2 + j]));        \
762 763 764 765 766
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
  }                                                                            \
fbarchard@google.com's avatar
fbarchard@google.com committed
767
  EXPECT_LE(max_diff, 4);                                                      \
768 769 770 771 772
  free_aligned_buffer_64(dst_y_c)                                              \
  free_aligned_buffer_64(dst_uv_c)                                             \
  free_aligned_buffer_64(dst_y_opt)                                            \
  free_aligned_buffer_64(dst_uv_opt)                                           \
  free_aligned_buffer_64(src_argb)                                             \
773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
}

#define TESTATOBIPLANAR(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y)        \
    TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,           \
                   benchmark_width_ - 4, _Any, +, 0)                           \
    TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,           \
                   benchmark_width_, _Unaligned, +, 1)                         \
    TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,           \
                   benchmark_width_, _Invert, -, 0)                            \
    TESTATOBIPLANARI(FMT_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,           \
                   benchmark_width_, _Opt, +, 0)

TESTATOBIPLANAR(ARGB, 4, NV12, 2, 2)
TESTATOBIPLANAR(ARGB, 4, NV21, 2, 2)

#define TESTATOBI(FMT_A, BPP_A, STRIDE_A,                                      \
                  FMT_B, BPP_B, STRIDE_B,                                      \
                  W1280, DIFF, N, NEG, OFF)                                    \
791
TEST_F(libyuvTest, FMT_A##To##FMT_B##N) {                                      \
792
  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
793
  const int kHeight = benchmark_height_;                                       \
794 795
  const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;  \
  const int kStrideB = (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B;  \
796 797 798
  align_buffer_64(src_argb, kStrideA * kHeight + OFF);                         \
  align_buffer_64(dst_argb_c, kStrideB * kHeight);                             \
  align_buffer_64(dst_argb_opt, kStrideB * kHeight);                           \
799 800
  memset(dst_argb_c, 0, kStrideB * kHeight);                                   \
  memset(dst_argb_opt, 0, kStrideB * kHeight);                                 \
801
  srandom(time(NULL));                                                         \
802
  for (int i = 0; i < kStrideA * kHeight; ++i) {                               \
803
    src_argb[i + OFF] = (random() & 0xff);                                     \
804 805
  }                                                                            \
  MaskCpuFlags(0);                                                             \
806 807
  FMT_A##To##FMT_B(src_argb + OFF, kStrideA,                                   \
                   dst_argb_c, kStrideB,                                       \
808 809 810
                   kWidth, NEG kHeight);                                       \
  MaskCpuFlags(-1);                                                            \
  for (int i = 0; i < benchmark_iterations_; ++i) {                            \
811 812
    FMT_A##To##FMT_B(src_argb + OFF, kStrideA,                                 \
                     dst_argb_opt, kStrideB,                                   \
813 814 815
                     kWidth, NEG kHeight);                                     \
  }                                                                            \
  int max_diff = 0;                                                            \
816
  for (int i = 0; i < kStrideB * kHeight; ++i) {                               \
817 818 819 820 821 822 823
    int abs_diff =                                                             \
        abs(static_cast<int>(dst_argb_c[i]) -                                  \
            static_cast<int>(dst_argb_opt[i]));                                \
    if (abs_diff > max_diff) {                                                 \
      max_diff = abs_diff;                                                     \
    }                                                                          \
  }                                                                            \
824
  EXPECT_LE(max_diff, DIFF);                                                   \
825 826 827
  free_aligned_buffer_64(src_argb)                                             \
  free_aligned_buffer_64(dst_argb_c)                                           \
  free_aligned_buffer_64(dst_argb_opt)                                         \
828
}
829 830 831

#define TESTATOBRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                       \
                       FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF)                 \
832 833 834 835 836
TEST_F(libyuvTest, FMT_A##To##FMT_B##_Random) {                                \
  srandom(time(NULL));                                                         \
  for (int times = 0; times < benchmark_iterations_; ++times) {                \
    const int kWidth = (random() & 63) + 1;                                    \
    const int kHeight = (random() & 31) + 1;                                   \
837 838
    const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A;       \
    const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B;       \
839 840
    const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;\
    const int kStrideB = (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B;\
841 842 843
    align_buffer_page_end(src_argb, kStrideA * kHeightA);                      \
    align_buffer_page_end(dst_argb_c, kStrideB * kHeightB);                    \
    align_buffer_page_end(dst_argb_opt, kStrideB * kHeightB);                  \
844 845
    memset(dst_argb_c, 0, kStrideB * kHeightB);                                \
    memset(dst_argb_opt, 0, kStrideB * kHeightB);                              \
846
    for (int i = 0; i < kStrideA * kHeightA; ++i) {                            \
847 848 849 850 851 852 853 854 855 856 857
      src_argb[i] = (random() & 0xff);                                         \
    }                                                                          \
    MaskCpuFlags(0);                                                           \
    FMT_A##To##FMT_B(src_argb, kStrideA,                                       \
                     dst_argb_c, kStrideB,                                     \
                     kWidth, kHeight);                                         \
    MaskCpuFlags(-1);                                                          \
    FMT_A##To##FMT_B(src_argb, kStrideA,                                       \
                     dst_argb_opt, kStrideB,                                   \
                     kWidth, kHeight);                                         \
    int max_diff = 0;                                                          \
858
    for (int i = 0; i < kStrideB * kHeightB; ++i) {                            \
859 860 861 862 863 864 865
      int abs_diff =                                                           \
          abs(static_cast<int>(dst_argb_c[i]) -                                \
              static_cast<int>(dst_argb_opt[i]));                              \
      if (abs_diff > max_diff) {                                               \
        max_diff = abs_diff;                                                   \
      }                                                                        \
    }                                                                          \
866
    EXPECT_LE(max_diff, DIFF);                                                 \
867 868 869 870 871 872
    free_aligned_buffer_page_end(src_argb)                                     \
    free_aligned_buffer_page_end(dst_argb_c)                                   \
    free_aligned_buffer_page_end(dst_argb_opt)                                 \
  }                                                                            \
}

873 874 875 876
#define TESTATOB(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                             \
                 FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF)                       \
    TESTATOBI(FMT_A, BPP_A, STRIDE_A,                                          \
              FMT_B, BPP_B, STRIDE_B,                                          \
877
              benchmark_width_ - 4, DIFF, _Any, +, 0)                          \
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902
    TESTATOBI(FMT_A, BPP_A, STRIDE_A,                                          \
              FMT_B, BPP_B, STRIDE_B,                                          \
              benchmark_width_, DIFF, _Unaligned, +, 1)                        \
    TESTATOBI(FMT_A, BPP_A, STRIDE_A,                                          \
              FMT_B, BPP_B, STRIDE_B,                                          \
              benchmark_width_, DIFF, _Invert, -, 0)                           \
    TESTATOBI(FMT_A, BPP_A, STRIDE_A,                                          \
              FMT_B, BPP_B, STRIDE_B,                                          \
              benchmark_width_, DIFF, _Opt, +, 0)                              \
    TESTATOBRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                           \
                   FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF)

TESTATOB(ARGB, 4, 4, 1, ARGB, 4, 4, 1, 0)
TESTATOB(ARGB, 4, 4, 1, BGRA, 4, 4, 1, 0)
TESTATOB(ARGB, 4, 4, 1, ABGR, 4, 4, 1, 0)
TESTATOB(ARGB, 4, 4, 1, RGBA, 4, 4, 1, 0)
TESTATOB(ARGB, 4, 4, 1, RAW, 3, 3, 1, 0)
TESTATOB(ARGB, 4, 4, 1, RGB24, 3, 3, 1, 0)
TESTATOB(ARGB, 4, 4, 1, RGB565, 2, 2, 1, 0)
TESTATOB(ARGB, 4, 4, 1, ARGB1555, 2, 2, 1, 0)
TESTATOB(ARGB, 4, 4, 1, ARGB4444, 2, 2, 1, 0)
TESTATOB(ARGB, 4, 4, 1, BayerBGGR, 1, 2, 2, 0)
TESTATOB(ARGB, 4, 4, 1, BayerRGGB, 1, 2, 2, 0)
TESTATOB(ARGB, 4, 4, 1, BayerGBRG, 1, 2, 2, 0)
TESTATOB(ARGB, 4, 4, 1, BayerGRBG, 1, 2, 2, 0)
fbarchard@google.com's avatar
fbarchard@google.com committed
903 904
TESTATOB(ARGB, 4, 4, 1, YUY2, 2, 4, 1, 4)
TESTATOB(ARGB, 4, 4, 1, UYVY, 2, 4, 1, 4)
905
TESTATOB(ARGB, 4, 4, 1, I400, 1, 1, 1, 2)
906
TESTATOB(ARGB, 4, 4, 1, J400, 1, 1, 1, 2)
907 908 909 910 911 912 913 914
TESTATOB(BGRA, 4, 4, 1, ARGB, 4, 4, 1, 0)
TESTATOB(ABGR, 4, 4, 1, ARGB, 4, 4, 1, 0)
TESTATOB(RGBA, 4, 4, 1, ARGB, 4, 4, 1, 0)
TESTATOB(RAW, 3, 3, 1, ARGB, 4, 4, 1, 0)
TESTATOB(RGB24, 3, 3, 1, ARGB, 4, 4, 1, 0)
TESTATOB(RGB565, 2, 2, 1, ARGB, 4, 4, 1, 0)
TESTATOB(ARGB1555, 2, 2, 1, ARGB, 4, 4, 1, 0)
TESTATOB(ARGB4444, 2, 2, 1, ARGB, 4, 4, 1, 0)
915 916
TESTATOB(YUY2, 2, 4, 1, ARGB, 4, 4, 1, 4)
TESTATOB(UYVY, 2, 4, 1, ARGB, 4, 4, 1, 4)
917 918 919 920 921 922 923 924 925
TESTATOB(BayerBGGR, 1, 2, 2, ARGB, 4, 4, 1, 0)
TESTATOB(BayerRGGB, 1, 2, 2, ARGB, 4, 4, 1, 0)
TESTATOB(BayerGBRG, 1, 2, 2, ARGB, 4, 4, 1, 0)
TESTATOB(BayerGRBG, 1, 2, 2, ARGB, 4, 4, 1, 0)
TESTATOB(I400, 1, 1, 1, ARGB, 4, 4, 1, 0)
TESTATOB(I400, 1, 1, 1, I400, 1, 1, 1, 0)
TESTATOB(I400, 1, 1, 1, I400Mirror, 1, 1, 1, 0)
TESTATOB(Y, 1, 1, 1, ARGB, 4, 4, 1, 0)
TESTATOB(ARGB, 4, 4, 1, ARGBMirror, 4, 4, 1, 0)
926 927 928 929 930 931 932 933 934 935 936 937 938 939 940

TEST_F(libyuvTest, Test565) {
  SIMD_ALIGNED(uint8 orig_pixels[256][4]);
  SIMD_ALIGNED(uint8 pixels565[256][2]);

  for (int i = 0; i < 256; ++i) {
    for (int j = 0; j < 4; ++j) {
      orig_pixels[i][j] = i;
    }
  }
  ARGBToRGB565(&orig_pixels[0][0], 0, &pixels565[0][0], 0, 256, 1);
  uint32 checksum = HashDjb2(&pixels565[0][0], sizeof(pixels565), 5381);
  EXPECT_EQ(610919429u, checksum);
}

941 942 943
#ifdef HAVE_JPEG
TEST_F(libyuvTest, ValidateJpeg) {
  const int kOff = 10;
944 945 946 947 948
  const int kMinJpeg = 64;
  const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ?
    benchmark_width_ * benchmark_height_ : kMinJpeg;
  const int kSize = kImageSize + kOff;
  align_buffer_64(orig_pixels, kSize);
949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965

  // No SOI or EOI. Expect fail.
  memset(orig_pixels, 0, kSize);

  // EOI, SOI. Expect pass.
  orig_pixels[0] = 0xff;
  orig_pixels[1] = 0xd8;  // SOI.
  orig_pixels[kSize - kOff + 0] = 0xff;
  orig_pixels[kSize - kOff + 1] = 0xd9;  // EOI.
  for (int times = 0; times < benchmark_iterations_; ++times) {
    EXPECT_TRUE(ValidateJpeg(orig_pixels, kSize));
  }
  free_aligned_buffer_page_end(orig_pixels);
}

TEST_F(libyuvTest, InvalidateJpeg) {
  const int kOff = 10;
966 967 968 969
  const int kMinJpeg = 64;
  const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ?
    benchmark_width_ * benchmark_height_ : kMinJpeg;
  const int kSize = kImageSize + kOff;
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993
  align_buffer_64(orig_pixels, kSize);

  // No SOI or EOI. Expect fail.
  memset(orig_pixels, 0, kSize);
  EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));

  // SOI but no EOI. Expect fail.
  orig_pixels[0] = 0xff;
  orig_pixels[1] = 0xd8;  // SOI.
  for (int times = 0; times < benchmark_iterations_; ++times) {
    EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
  }
  // EOI but no SOI. Expect fail.
  orig_pixels[0] = 0;
  orig_pixels[1] = 0;
  orig_pixels[kSize - kOff + 0] = 0xff;
  orig_pixels[kSize - kOff + 1] = 0xd9;  // EOI.
  EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));

  free_aligned_buffer_page_end(orig_pixels);
}

#endif

994
}  // namespace libyuv