Home | History | Annotate | Download | only in unit_test
      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/basic_types.h"
     15 #include "libyuv/compare.h"
     16 #include "libyuv/convert.h"
     17 #include "libyuv/convert_argb.h"
     18 #include "libyuv/convert_from.h"
     19 #include "libyuv/convert_from_argb.h"
     20 #include "libyuv/cpu_id.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/video_common.h"
     27 #include "../unit_test/unit_test.h"
     28 
     29 namespace libyuv {
     30 
     31 #define SUBSAMPLE(v, a) ((((v) + (a) - 1)) / (a))
     32 
     33 #define TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,           \
     34                        FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF)   \
     35 TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) {                 \
     36   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
     37   const int kHeight = benchmark_height_;                                       \
     38   align_buffer_page_end(src_y, kWidth * kHeight + OFF);                        \
     39   align_buffer_page_end(src_u,                                                 \
     40                         SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                     \
     41                         SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);              \
     42   align_buffer_page_end(src_v,                                                 \
     43                         SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                     \
     44                         SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);              \
     45   align_buffer_page_end(dst_y_c, kWidth * kHeight);                            \
     46   align_buffer_page_end(dst_u_c,                                               \
     47                         SUBSAMPLE(kWidth, SUBSAMP_X) *                         \
     48                         SUBSAMPLE(kHeight, SUBSAMP_Y));                        \
     49   align_buffer_page_end(dst_v_c,                                               \
     50                         SUBSAMPLE(kWidth, SUBSAMP_X) *                         \
     51                         SUBSAMPLE(kHeight, SUBSAMP_Y));                        \
     52   align_buffer_page_end(dst_y_opt, kWidth * kHeight);                          \
     53   align_buffer_page_end(dst_u_opt,                                             \
     54                         SUBSAMPLE(kWidth, SUBSAMP_X) *                         \
     55                         SUBSAMPLE(kHeight, SUBSAMP_Y));                        \
     56   align_buffer_page_end(dst_v_opt,                                             \
     57                         SUBSAMPLE(kWidth, SUBSAMP_X) *                         \
     58                         SUBSAMPLE(kHeight, SUBSAMP_Y));                        \
     59   for (int i = 0; i < kHeight; ++i)                                            \
     60     for (int j = 0; j < kWidth; ++j)                                           \
     61       src_y[i * kWidth + j + OFF] = (fastrand() & 0xff);                       \
     62   for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) {                \
     63     for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) {               \
     64       src_u[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \
     65           (fastrand() & 0xff);                                                 \
     66       src_v[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \
     67           (fastrand() & 0xff);                                                 \
     68     }                                                                          \
     69   }                                                                            \
     70   memset(dst_y_c, 1, kWidth * kHeight);                                        \
     71   memset(dst_u_c, 2, SUBSAMPLE(kWidth, SUBSAMP_X) *                            \
     72                      SUBSAMPLE(kHeight, SUBSAMP_Y));                           \
     73   memset(dst_v_c, 3, SUBSAMPLE(kWidth, SUBSAMP_X) *                            \
     74                      SUBSAMPLE(kHeight, SUBSAMP_Y));                           \
     75   memset(dst_y_opt, 101, kWidth * kHeight);                                    \
     76   memset(dst_u_opt, 102, SUBSAMPLE(kWidth, SUBSAMP_X) *                        \
     77                          SUBSAMPLE(kHeight, SUBSAMP_Y));                       \
     78   memset(dst_v_opt, 103, SUBSAMPLE(kWidth, SUBSAMP_X) *                        \
     79                          SUBSAMPLE(kHeight, SUBSAMP_Y));                       \
     80   MaskCpuFlags(disable_cpu_flags_);                                            \
     81   SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                          \
     82                                  src_u + OFF,                                  \
     83                                  SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \
     84                                  src_v + OFF,                                  \
     85                                  SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \
     86                                  dst_y_c, kWidth,                              \
     87                                  dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \
     88                                  dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \
     89                                  kWidth, NEG kHeight);                         \
     90   MaskCpuFlags(benchmark_cpu_info_);                                           \
     91   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
     92     SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                        \
     93                                    src_u + OFF,                                \
     94                                        SUBSAMPLE(kWidth, SRC_SUBSAMP_X),       \
     95                                    src_v + OFF,                                \
     96                                        SUBSAMPLE(kWidth, SRC_SUBSAMP_X),       \
     97                                    dst_y_opt, kWidth,                          \
     98                                    dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \
     99                                    dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \
    100                                    kWidth, NEG kHeight);                       \
    101   }                                                                            \
    102   int max_diff = 0;                                                            \
    103   for (int i = 0; i < kHeight; ++i) {                                          \
    104     for (int j = 0; j < kWidth; ++j) {                                         \
    105       int abs_diff =                                                           \
    106           abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
    107               static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
    108       if (abs_diff > max_diff) {                                               \
    109         max_diff = abs_diff;                                                   \
    110       }                                                                        \
    111     }                                                                          \
    112   }                                                                            \
    113   EXPECT_EQ(0, max_diff);                                                      \
    114   for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    115     for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
    116       int abs_diff =                                                           \
    117           abs(static_cast<int>(dst_u_c[i *                                     \
    118                                SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
    119               static_cast<int>(dst_u_opt[i *                                   \
    120                                SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
    121       if (abs_diff > max_diff) {                                               \
    122         max_diff = abs_diff;                                                   \
    123       }                                                                        \
    124     }                                                                          \
    125   }                                                                            \
    126   EXPECT_LE(max_diff, 3);                                                      \
    127   for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    128     for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
    129       int abs_diff =                                                           \
    130           abs(static_cast<int>(dst_v_c[i *                                     \
    131                                SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
    132               static_cast<int>(dst_v_opt[i *                                   \
    133                                SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
    134       if (abs_diff > max_diff) {                                               \
    135         max_diff = abs_diff;                                                   \
    136       }                                                                        \
    137     }                                                                          \
    138   }                                                                            \
    139   EXPECT_LE(max_diff, 3);                                                      \
    140   free_aligned_buffer_page_end(dst_y_c);                                       \
    141   free_aligned_buffer_page_end(dst_u_c);                                       \
    142   free_aligned_buffer_page_end(dst_v_c);                                       \
    143   free_aligned_buffer_page_end(dst_y_opt);                                     \
    144   free_aligned_buffer_page_end(dst_u_opt);                                     \
    145   free_aligned_buffer_page_end(dst_v_opt);                                     \
    146   free_aligned_buffer_page_end(src_y);                                         \
    147   free_aligned_buffer_page_end(src_u);                                         \
    148   free_aligned_buffer_page_end(src_v);                                         \
    149 }
    150 
    151 #define TESTPLANARTOP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,            \
    152                       FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y)                        \
    153     TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,               \
    154                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                           \
    155                    benchmark_width_ - 4, _Any, +, 0)                           \
    156     TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,               \
    157                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                           \
    158                    benchmark_width_, _Unaligned, +, 1)                         \
    159     TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,               \
    160                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                           \
    161                    benchmark_width_, _Invert, -, 0)                            \
    162     TESTPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,               \
    163                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                           \
    164                    benchmark_width_, _Opt, +, 0)
    165 
    166 TESTPLANARTOP(I420, 2, 2, I420, 2, 2)
    167 TESTPLANARTOP(I422, 2, 1, I420, 2, 2)
    168 TESTPLANARTOP(I444, 1, 1, I420, 2, 2)
    169 TESTPLANARTOP(I411, 4, 1, I420, 2, 2)
    170 TESTPLANARTOP(I420, 2, 2, I422, 2, 1)
    171 TESTPLANARTOP(I420, 2, 2, I444, 1, 1)
    172 TESTPLANARTOP(I420, 2, 2, I411, 4, 1)
    173 TESTPLANARTOP(I420, 2, 2, I420Mirror, 2, 2)
    174 TESTPLANARTOP(I422, 2, 1, I422, 2, 1)
    175 TESTPLANARTOP(I444, 1, 1, I444, 1, 1)
    176 
    177 #define TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,          \
    178                        FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF)   \
    179 TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) {                 \
    180   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
    181   const int kHeight = benchmark_height_;                                       \
    182   align_buffer_page_end(src_y, kWidth * kHeight + OFF);                        \
    183   align_buffer_page_end(src_u,                                                 \
    184                         SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                     \
    185                         SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);              \
    186   align_buffer_page_end(src_v,                                                 \
    187                         SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                     \
    188                         SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);              \
    189   align_buffer_page_end(dst_y_c, kWidth * kHeight);                            \
    190   align_buffer_page_end(dst_uv_c, SUBSAMPLE(kWidth * 2, SUBSAMP_X) *           \
    191                         SUBSAMPLE(kHeight, SUBSAMP_Y));                        \
    192   align_buffer_page_end(dst_y_opt, kWidth * kHeight);                          \
    193   align_buffer_page_end(dst_uv_opt, SUBSAMPLE(kWidth * 2, SUBSAMP_X) *         \
    194                         SUBSAMPLE(kHeight, SUBSAMP_Y));                        \
    195   for (int i = 0; i < kHeight; ++i)                                            \
    196     for (int j = 0; j < kWidth; ++j)                                           \
    197       src_y[i * kWidth + j + OFF] = (fastrand() & 0xff);                       \
    198   for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) {                \
    199     for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) {               \
    200       src_u[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \
    201           (fastrand() & 0xff);                                                 \
    202       src_v[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \
    203           (fastrand() & 0xff);                                                 \
    204     }                                                                          \
    205   }                                                                            \
    206   memset(dst_y_c, 1, kWidth * kHeight);                                        \
    207   memset(dst_uv_c, 2, SUBSAMPLE(kWidth * 2, SUBSAMP_X) *                       \
    208                       SUBSAMPLE(kHeight, SUBSAMP_Y));                          \
    209   memset(dst_y_opt, 101, kWidth * kHeight);                                    \
    210   memset(dst_uv_opt, 102, SUBSAMPLE(kWidth * 2, SUBSAMP_X) *                   \
    211                           SUBSAMPLE(kHeight, SUBSAMP_Y));                      \
    212   MaskCpuFlags(disable_cpu_flags_);                                            \
    213   SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                          \
    214                                  src_u + OFF,                                  \
    215                                  SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \
    216                                  src_v + OFF,                                  \
    217                                  SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \
    218                                  dst_y_c, kWidth,                              \
    219                                  dst_uv_c, SUBSAMPLE(kWidth * 2, SUBSAMP_X),   \
    220                                  kWidth, NEG kHeight);                         \
    221   MaskCpuFlags(benchmark_cpu_info_);                                           \
    222   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
    223     SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                        \
    224                                    src_u + OFF,                                \
    225                                    SUBSAMPLE(kWidth, SRC_SUBSAMP_X),           \
    226                                    src_v + OFF,                                \
    227                                    SUBSAMPLE(kWidth, SRC_SUBSAMP_X),           \
    228                                    dst_y_opt, kWidth,                          \
    229                                    dst_uv_opt,                                 \
    230                                    SUBSAMPLE(kWidth * 2, SUBSAMP_X),           \
    231                                    kWidth, NEG kHeight);                       \
    232   }                                                                            \
    233   int max_diff = 0;                                                            \
    234   for (int i = 0; i < kHeight; ++i) {                                          \
    235     for (int j = 0; j < kWidth; ++j) {                                         \
    236       int abs_diff =                                                           \
    237           abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
    238               static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
    239       if (abs_diff > max_diff) {                                               \
    240         max_diff = abs_diff;                                                   \
    241       }                                                                        \
    242     }                                                                          \
    243   }                                                                            \
    244   EXPECT_LE(max_diff, 1);                                                      \
    245   for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    246     for (int j = 0; j < SUBSAMPLE(kWidth * 2, SUBSAMP_X); ++j) {               \
    247       int abs_diff =                                                           \
    248           abs(static_cast<int>(dst_uv_c[i *                                    \
    249                                SUBSAMPLE(kWidth * 2, SUBSAMP_X) + j]) -        \
    250               static_cast<int>(dst_uv_opt[i *                                  \
    251                                SUBSAMPLE(kWidth * 2, SUBSAMP_X) + j]));        \
    252       if (abs_diff > max_diff) {                                               \
    253         max_diff = abs_diff;                                                   \
    254       }                                                                        \
    255     }                                                                          \
    256   }                                                                            \
    257   EXPECT_LE(max_diff, 1);                                                      \
    258   free_aligned_buffer_page_end(dst_y_c);                                       \
    259   free_aligned_buffer_page_end(dst_uv_c);                                      \
    260   free_aligned_buffer_page_end(dst_y_opt);                                     \
    261   free_aligned_buffer_page_end(dst_uv_opt);                                    \
    262   free_aligned_buffer_page_end(src_y);                                         \
    263   free_aligned_buffer_page_end(src_u);                                         \
    264   free_aligned_buffer_page_end(src_v);                                         \
    265 }
    266 
    267 #define TESTPLANARTOBP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,           \
    268                        FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y)                       \
    269     TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \
    270                     FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \
    271                     benchmark_width_ - 4, _Any, +, 0)                          \
    272     TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \
    273                     FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \
    274                     benchmark_width_, _Unaligned, +, 1)                        \
    275     TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \
    276                     FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \
    277                     benchmark_width_, _Invert, -, 0)                           \
    278     TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \
    279                     FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \
    280                     benchmark_width_, _Opt, +, 0)
    281 
    282 TESTPLANARTOBP(I420, 2, 2, NV12, 2, 2)
    283 TESTPLANARTOBP(I420, 2, 2, NV21, 2, 2)
    284 
    285 #define TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,         \
    286                          FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF) \
    287 TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) {                 \
    288   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
    289   const int kHeight = benchmark_height_;                                       \
    290   align_buffer_page_end(src_y, kWidth * kHeight + OFF);                        \
    291   align_buffer_page_end(src_uv, 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *         \
    292                         SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);              \
    293   align_buffer_page_end(dst_y_c, kWidth * kHeight);                            \
    294   align_buffer_page_end(dst_u_c,                                               \
    295                         SUBSAMPLE(kWidth, SUBSAMP_X) *                         \
    296                         SUBSAMPLE(kHeight, SUBSAMP_Y));                        \
    297   align_buffer_page_end(dst_v_c,                                               \
    298                         SUBSAMPLE(kWidth, SUBSAMP_X) *                         \
    299                         SUBSAMPLE(kHeight, SUBSAMP_Y));                        \
    300   align_buffer_page_end(dst_y_opt, kWidth * kHeight);                          \
    301   align_buffer_page_end(dst_u_opt,                                             \
    302                         SUBSAMPLE(kWidth, SUBSAMP_X) *                         \
    303                         SUBSAMPLE(kHeight, SUBSAMP_Y));                        \
    304   align_buffer_page_end(dst_v_opt,                                             \
    305                         SUBSAMPLE(kWidth, SUBSAMP_X) *                         \
    306                         SUBSAMPLE(kHeight, SUBSAMP_Y));                        \
    307   for (int i = 0; i < kHeight; ++i)                                            \
    308     for (int j = 0; j < kWidth; ++j)                                           \
    309       src_y[i * kWidth + j + OFF] = (fastrand() & 0xff);                       \
    310   for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) {                \
    311     for (int j = 0; j < 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) {           \
    312       src_uv[(i * 2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =           \
    313           (fastrand() & 0xff);                                                 \
    314     }                                                                          \
    315   }                                                                            \
    316   memset(dst_y_c, 1, kWidth * kHeight);                                        \
    317   memset(dst_u_c, 2, SUBSAMPLE(kWidth, SUBSAMP_X) *                            \
    318                      SUBSAMPLE(kHeight, SUBSAMP_Y));                           \
    319   memset(dst_v_c, 3, SUBSAMPLE(kWidth, SUBSAMP_X) *                            \
    320                      SUBSAMPLE(kHeight, SUBSAMP_Y));                           \
    321   memset(dst_y_opt, 101, kWidth * kHeight);                                    \
    322   memset(dst_u_opt, 102, SUBSAMPLE(kWidth, SUBSAMP_X) *                        \
    323                          SUBSAMPLE(kHeight, SUBSAMP_Y));                       \
    324   memset(dst_v_opt, 103, SUBSAMPLE(kWidth, SUBSAMP_X) *                        \
    325                          SUBSAMPLE(kHeight, SUBSAMP_Y));                       \
    326   MaskCpuFlags(disable_cpu_flags_);                                            \
    327   SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                          \
    328                                  src_uv + OFF,                                 \
    329                                  2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X),         \
    330                                  dst_y_c, kWidth,                              \
    331                                  dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \
    332                                  dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \
    333                                  kWidth, NEG kHeight);                         \
    334   MaskCpuFlags(benchmark_cpu_info_);                                           \
    335   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
    336     SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                        \
    337                                    src_uv + OFF,                               \
    338                                    2 * SUBSAMPLE(kWidth, SRC_SUBSAMP_X),       \
    339                                    dst_y_opt, kWidth,                          \
    340                                    dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \
    341                                    dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \
    342                                    kWidth, NEG kHeight);                       \
    343   }                                                                            \
    344   int max_diff = 0;                                                            \
    345   for (int i = 0; i < kHeight; ++i) {                                          \
    346     for (int j = 0; j < kWidth; ++j) {                                         \
    347       int abs_diff =                                                           \
    348           abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
    349               static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
    350       if (abs_diff > max_diff) {                                               \
    351         max_diff = abs_diff;                                                   \
    352       }                                                                        \
    353     }                                                                          \
    354   }                                                                            \
    355   EXPECT_LE(max_diff, 1);                                                      \
    356   for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    357     for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
    358       int abs_diff =                                                           \
    359           abs(static_cast<int>(dst_u_c[i *                                     \
    360                                SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
    361               static_cast<int>(dst_u_opt[i *                                   \
    362                                SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
    363       if (abs_diff > max_diff) {                                               \
    364         max_diff = abs_diff;                                                   \
    365       }                                                                        \
    366     }                                                                          \
    367   }                                                                            \
    368   EXPECT_LE(max_diff, 1);                                                      \
    369   for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    370     for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \
    371       int abs_diff =                                                           \
    372           abs(static_cast<int>(dst_v_c[i *                                     \
    373                                SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \
    374               static_cast<int>(dst_v_opt[i *                                   \
    375                                SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \
    376       if (abs_diff > max_diff) {                                               \
    377         max_diff = abs_diff;                                                   \
    378       }                                                                        \
    379     }                                                                          \
    380   }                                                                            \
    381   EXPECT_LE(max_diff, 1);                                                      \
    382   free_aligned_buffer_page_end(dst_y_c);                                       \
    383   free_aligned_buffer_page_end(dst_u_c);                                       \
    384   free_aligned_buffer_page_end(dst_v_c);                                       \
    385   free_aligned_buffer_page_end(dst_y_opt);                                     \
    386   free_aligned_buffer_page_end(dst_u_opt);                                     \
    387   free_aligned_buffer_page_end(dst_v_opt);                                     \
    388   free_aligned_buffer_page_end(src_y);                                         \
    389   free_aligned_buffer_page_end(src_uv);                                        \
    390 }
    391 
    392 #define TESTBIPLANARTOP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,          \
    393                         FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y)                      \
    394     TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,             \
    395                      FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                         \
    396                      benchmark_width_ - 4, _Any, +, 0)                         \
    397     TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,             \
    398                      FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                         \
    399                      benchmark_width_, _Unaligned, +, 1)                       \
    400     TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,             \
    401                      FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                         \
    402                      benchmark_width_, _Invert, -, 0)                          \
    403     TESTBIPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,             \
    404                      FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                         \
    405                      benchmark_width_, _Opt, +, 0)
    406 
    407 TESTBIPLANARTOP(NV12, 2, 2, I420, 2, 2)
    408 TESTBIPLANARTOP(NV21, 2, 2, I420, 2, 2)
    409 
    410 #define ALIGNINT(V, ALIGN) (((V) + (ALIGN) - 1) / (ALIGN) * (ALIGN))
    411 
    412 #define TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,  \
    413                        YALIGN, W1280, DIFF, N, NEG, OFF, FMT_C, BPP_C)         \
    414 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##N) {                          \
    415   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
    416   const int kHeight = ALIGNINT(benchmark_height_, YALIGN);                     \
    417   const int kStrideB = ALIGNINT(kWidth * BPP_B, ALIGN);                        \
    418   const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X);                          \
    419   const int kSizeUV = kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y);               \
    420   align_buffer_page_end(src_y, kWidth * kHeight + OFF);                        \
    421   align_buffer_page_end(src_u, kSizeUV + OFF);                                 \
    422   align_buffer_page_end(src_v, kSizeUV + OFF);                                 \
    423   align_buffer_page_end(dst_argb_c, kStrideB * kHeight + OFF);                 \
    424   align_buffer_page_end(dst_argb_opt, kStrideB * kHeight + OFF);               \
    425   for (int i = 0; i < kWidth * kHeight; ++i) {                                 \
    426     src_y[i + OFF] = (fastrand() & 0xff);                                      \
    427   }                                                                            \
    428   for (int i = 0; i < kSizeUV; ++i) {                                          \
    429     src_u[i + OFF] = (fastrand() & 0xff);                                      \
    430     src_v[i + OFF] = (fastrand() & 0xff);                                      \
    431   }                                                                            \
    432   memset(dst_argb_c + OFF, 1, kStrideB * kHeight);                             \
    433   memset(dst_argb_opt + OFF, 101, kStrideB * kHeight);                         \
    434   MaskCpuFlags(disable_cpu_flags_);                                            \
    435   FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                   \
    436                         src_u + OFF, kStrideUV,                                \
    437                         src_v + OFF, kStrideUV,                                \
    438                         dst_argb_c + OFF, kStrideB,                            \
    439                         kWidth, NEG kHeight);                                  \
    440   MaskCpuFlags(benchmark_cpu_info_);                                           \
    441   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
    442     FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                 \
    443                           src_u + OFF, kStrideUV,                              \
    444                           src_v + OFF, kStrideUV,                              \
    445                           dst_argb_opt + OFF, kStrideB,                        \
    446                           kWidth, NEG kHeight);                                \
    447   }                                                                            \
    448   int max_diff = 0;                                                            \
    449   /* Convert to ARGB so 565 is expanded to bytes that can be compared. */      \
    450   align_buffer_page_end(dst_argb32_c, kWidth * BPP_C  * kHeight);              \
    451   align_buffer_page_end(dst_argb32_opt, kWidth * BPP_C  * kHeight);            \
    452   memset(dst_argb32_c, 2, kWidth * BPP_C  * kHeight);                          \
    453   memset(dst_argb32_opt, 102, kWidth * BPP_C  * kHeight);                      \
    454   FMT_B##To##FMT_C(dst_argb_c + OFF, kStrideB,                                 \
    455                    dst_argb32_c, kWidth * BPP_C ,                              \
    456                    kWidth, kHeight);                                           \
    457   FMT_B##To##FMT_C(dst_argb_opt + OFF, kStrideB,                               \
    458                    dst_argb32_opt, kWidth * BPP_C ,                            \
    459                    kWidth, kHeight);                                           \
    460   for (int i = 0; i < kWidth * BPP_C * kHeight; ++i) {                         \
    461     int abs_diff =                                                             \
    462         abs(static_cast<int>(dst_argb32_c[i]) -                                \
    463             static_cast<int>(dst_argb32_opt[i]));                              \
    464     if (abs_diff > max_diff) {                                                 \
    465       max_diff = abs_diff;                                                     \
    466     }                                                                          \
    467   }                                                                            \
    468   EXPECT_LE(max_diff, DIFF);                                                   \
    469   free_aligned_buffer_page_end(src_y);                                         \
    470   free_aligned_buffer_page_end(src_u);                                         \
    471   free_aligned_buffer_page_end(src_v);                                         \
    472   free_aligned_buffer_page_end(dst_argb_c);                                    \
    473   free_aligned_buffer_page_end(dst_argb_opt);                                  \
    474   free_aligned_buffer_page_end(dst_argb32_c);                                  \
    475   free_aligned_buffer_page_end(dst_argb32_opt);                                \
    476 }
    477 
    478 #define TESTPLANARTOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,   \
    479                       YALIGN, DIFF, FMT_C, BPP_C)                              \
    480     TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,      \
    481         YALIGN, benchmark_width_ - 4, DIFF, _Any, +, 0, FMT_C, BPP_C)          \
    482     TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,      \
    483         YALIGN, benchmark_width_, DIFF, _Unaligned, +, 1, FMT_C, BPP_C)        \
    484     TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,      \
    485         YALIGN, benchmark_width_, DIFF, _Invert, -, 0, FMT_C, BPP_C)           \
    486     TESTPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,      \
    487         YALIGN, benchmark_width_, DIFF, _Opt, +, 0, FMT_C, BPP_C)
    488 
    489 TESTPLANARTOB(I420, 2, 2, ARGB, 4, 4, 1, 2, ARGB, 4)
    490 TESTPLANARTOB(J420, 2, 2, ARGB, 4, 4, 1, 2, ARGB, 4)
    491 TESTPLANARTOB(J420, 2, 2, ABGR, 4, 4, 1, 2, ARGB, 4)
    492 TESTPLANARTOB(H420, 2, 2, ARGB, 4, 4, 1, 2, ARGB, 4)
    493 TESTPLANARTOB(H420, 2, 2, ABGR, 4, 4, 1, 2, ARGB, 4)
    494 TESTPLANARTOB(I420, 2, 2, BGRA, 4, 4, 1, 2, ARGB, 4)
    495 TESTPLANARTOB(I420, 2, 2, ABGR, 4, 4, 1, 2, ARGB, 4)
    496 TESTPLANARTOB(I420, 2, 2, RGBA, 4, 4, 1, 2, ARGB, 4)
    497 TESTPLANARTOB(I420, 2, 2, RAW, 3, 3, 1, 2, ARGB, 4)
    498 TESTPLANARTOB(I420, 2, 2, RGB24, 3, 3, 1, 2, ARGB, 4)
    499 TESTPLANARTOB(I420, 2, 2, RGB565, 2, 2, 1, 9, ARGB, 4)
    500 TESTPLANARTOB(I420, 2, 2, ARGB1555, 2, 2, 1, 9, ARGB, 4)
    501 TESTPLANARTOB(I420, 2, 2, ARGB4444, 2, 2, 1, 17, ARGB, 4)
    502 TESTPLANARTOB(I422, 2, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
    503 TESTPLANARTOB(J422, 2, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
    504 TESTPLANARTOB(J422, 2, 1, ABGR, 4, 4, 1, 2, ARGB, 4)
    505 TESTPLANARTOB(H422, 2, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
    506 TESTPLANARTOB(H422, 2, 1, ABGR, 4, 4, 1, 2, ARGB, 4)
    507 TESTPLANARTOB(I422, 2, 1, BGRA, 4, 4, 1, 2, ARGB, 4)
    508 TESTPLANARTOB(I422, 2, 1, ABGR, 4, 4, 1, 2, ARGB, 4)
    509 TESTPLANARTOB(I422, 2, 1, RGBA, 4, 4, 1, 2, ARGB, 4)
    510 TESTPLANARTOB(I411, 4, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
    511 TESTPLANARTOB(I444, 1, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
    512 TESTPLANARTOB(J444, 1, 1, ARGB, 4, 4, 1, 2, ARGB, 4)
    513 TESTPLANARTOB(I444, 1, 1, ABGR, 4, 4, 1, 2, ARGB, 4)
    514 TESTPLANARTOB(I420, 2, 2, YUY2, 2, 4, 1, 1, ARGB, 4)
    515 TESTPLANARTOB(I420, 2, 2, UYVY, 2, 4, 1, 1, ARGB, 4)
    516 TESTPLANARTOB(I422, 2, 1, YUY2, 2, 4, 1, 0, ARGB, 4)
    517 TESTPLANARTOB(I422, 2, 1, UYVY, 2, 4, 1, 0, ARGB, 4)
    518 TESTPLANARTOB(I420, 2, 2, I400, 1, 1, 1, 0, ARGB, 4)
    519 TESTPLANARTOB(J420, 2, 2, J400, 1, 1, 1, 0, ARGB, 4)
    520 
    521 #define TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
    522                        YALIGN, W1280, DIFF, N, NEG, OFF, ATTEN)                \
    523 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##N) {                          \
    524   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
    525   const int kHeight = ALIGNINT(benchmark_height_, YALIGN);                     \
    526   const int kStrideB = ALIGNINT(kWidth * BPP_B, ALIGN);                        \
    527   const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X);                          \
    528   const int kSizeUV = kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y);               \
    529   align_buffer_page_end(src_y, kWidth * kHeight + OFF);                        \
    530   align_buffer_page_end(src_u, kSizeUV + OFF);                                 \
    531   align_buffer_page_end(src_v, kSizeUV + OFF);                                 \
    532   align_buffer_page_end(src_a, kWidth * kHeight + OFF);                        \
    533   align_buffer_page_end(dst_argb_c, kStrideB * kHeight + OFF);                 \
    534   align_buffer_page_end(dst_argb_opt, kStrideB * kHeight + OFF);               \
    535   for (int i = 0; i < kWidth * kHeight; ++i) {                                 \
    536     src_y[i + OFF] = (fastrand() & 0xff);                                      \
    537     src_a[i + OFF] = (fastrand() & 0xff);                                      \
    538   }                                                                            \
    539   for (int i = 0; i < kSizeUV; ++i) {                                          \
    540     src_u[i + OFF] = (fastrand() & 0xff);                                      \
    541     src_v[i + OFF] = (fastrand() & 0xff);                                      \
    542   }                                                                            \
    543   memset(dst_argb_c + OFF, 1, kStrideB * kHeight);                             \
    544   memset(dst_argb_opt + OFF, 101, kStrideB * kHeight);                         \
    545   MaskCpuFlags(disable_cpu_flags_);                                            \
    546   FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                   \
    547                         src_u + OFF, kStrideUV,                                \
    548                         src_v + OFF, kStrideUV,                                \
    549                         src_a + OFF, kWidth,                                   \
    550                         dst_argb_c + OFF, kStrideB,                            \
    551                         kWidth, NEG kHeight, ATTEN);                           \
    552   MaskCpuFlags(benchmark_cpu_info_);                                           \
    553   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
    554     FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                 \
    555                           src_u + OFF, kStrideUV,                              \
    556                           src_v + OFF, kStrideUV,                              \
    557                           src_a + OFF, kWidth,                                 \
    558                           dst_argb_opt + OFF, kStrideB,                        \
    559                           kWidth, NEG kHeight, ATTEN);                         \
    560   }                                                                            \
    561   int max_diff = 0;                                                            \
    562   for (int i = 0; i < kWidth * BPP_B * kHeight; ++i) {                         \
    563     int abs_diff =                                                             \
    564         abs(static_cast<int>(dst_argb_c[i + OFF]) -                            \
    565             static_cast<int>(dst_argb_opt[i + OFF]));                          \
    566     if (abs_diff > max_diff) {                                                 \
    567       max_diff = abs_diff;                                                     \
    568     }                                                                          \
    569   }                                                                            \
    570   EXPECT_LE(max_diff, DIFF);                                                   \
    571   free_aligned_buffer_page_end(src_y);                                         \
    572   free_aligned_buffer_page_end(src_u);                                         \
    573   free_aligned_buffer_page_end(src_v);                                         \
    574   free_aligned_buffer_page_end(src_a);                                         \
    575   free_aligned_buffer_page_end(dst_argb_c);                                    \
    576   free_aligned_buffer_page_end(dst_argb_opt);                                  \
    577 }
    578 
    579 #define TESTQPLANARTOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,  \
    580                        YALIGN, DIFF)                                           \
    581     TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,     \
    582         YALIGN, benchmark_width_ - 4, DIFF, _Any, +, 0, 0)                     \
    583     TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,     \
    584         YALIGN, benchmark_width_, DIFF, _Unaligned, +, 1, 0)                   \
    585     TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,     \
    586         YALIGN, benchmark_width_, DIFF, _Invert, -, 0, 0)                      \
    587     TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,     \
    588         YALIGN, benchmark_width_, DIFF, _Opt, +, 0, 0)                         \
    589     TESTQPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,     \
    590         YALIGN, benchmark_width_, DIFF, _Premult, +, 0, 1)
    591 
    592 TESTQPLANARTOB(I420Alpha, 2, 2, ARGB, 4, 4, 1, 2)
    593 TESTQPLANARTOB(I420Alpha, 2, 2, ABGR, 4, 4, 1, 2)
    594 
    595 #define TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,       \
    596                          W1280, DIFF, N, NEG, OFF)                             \
    597 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##N) {                          \
    598   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
    599   const int kHeight = benchmark_height_;                                       \
    600   const int kStrideB = kWidth * BPP_B;                                         \
    601   const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X);                          \
    602   align_buffer_page_end(src_y, kWidth * kHeight + OFF);                        \
    603   align_buffer_page_end(src_uv,                                                \
    604                         kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y) * 2 + OFF);  \
    605   align_buffer_page_end(dst_argb_c, kStrideB * kHeight);                       \
    606   align_buffer_page_end(dst_argb_opt, kStrideB * kHeight);                     \
    607   for (int i = 0; i < kHeight; ++i)                                            \
    608     for (int j = 0; j < kWidth; ++j)                                           \
    609       src_y[i * kWidth + j + OFF] = (fastrand() & 0xff);                       \
    610   for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    611     for (int j = 0; j < kStrideUV * 2; ++j) {                                  \
    612       src_uv[i * kStrideUV * 2 + j + OFF] = (fastrand() & 0xff);               \
    613     }                                                                          \
    614   }                                                                            \
    615   memset(dst_argb_c, 1, kStrideB * kHeight);                                   \
    616   memset(dst_argb_opt, 101, kStrideB * kHeight);                               \
    617   MaskCpuFlags(disable_cpu_flags_);                                            \
    618   FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                   \
    619                         src_uv + OFF, kStrideUV * 2,                           \
    620                         dst_argb_c, kWidth * BPP_B,                            \
    621                         kWidth, NEG kHeight);                                  \
    622   MaskCpuFlags(benchmark_cpu_info_);                                           \
    623   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
    624     FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                 \
    625                           src_uv + OFF, kStrideUV * 2,                         \
    626                           dst_argb_opt, kWidth * BPP_B,                        \
    627                           kWidth, NEG kHeight);                                \
    628   }                                                                            \
    629   /* Convert to ARGB so 565 is expanded to bytes that can be compared. */      \
    630   align_buffer_page_end(dst_argb32_c, kWidth * 4 * kHeight);                   \
    631   align_buffer_page_end(dst_argb32_opt, kWidth * 4 * kHeight);                 \
    632   memset(dst_argb32_c, 2, kWidth * 4 * kHeight);                               \
    633   memset(dst_argb32_opt, 102, kWidth * 4 * kHeight);                           \
    634   FMT_B##ToARGB(dst_argb_c, kStrideB,                                          \
    635                 dst_argb32_c, kWidth * 4,                                      \
    636                 kWidth, kHeight);                                              \
    637   FMT_B##ToARGB(dst_argb_opt, kStrideB,                                        \
    638                 dst_argb32_opt, kWidth * 4,                                    \
    639                 kWidth, kHeight);                                              \
    640   int max_diff = 0;                                                            \
    641   for (int i = 0; i < kHeight; ++i) {                                          \
    642     for (int j = 0; j < kWidth * 4; ++j) {                                     \
    643       int abs_diff =                                                           \
    644           abs(static_cast<int>(dst_argb32_c[i * kWidth * 4 + j]) -             \
    645               static_cast<int>(dst_argb32_opt[i * kWidth * 4 + j]));           \
    646       if (abs_diff > max_diff) {                                               \
    647         max_diff = abs_diff;                                                   \
    648       }                                                                        \
    649     }                                                                          \
    650   }                                                                            \
    651   EXPECT_LE(max_diff, DIFF);                                                   \
    652   free_aligned_buffer_page_end(src_y);                                         \
    653   free_aligned_buffer_page_end(src_uv);                                        \
    654   free_aligned_buffer_page_end(dst_argb_c);                                    \
    655   free_aligned_buffer_page_end(dst_argb_opt);                                  \
    656   free_aligned_buffer_page_end(dst_argb32_c);                                  \
    657   free_aligned_buffer_page_end(dst_argb32_opt);                                \
    658 }
    659 
    660 #define TESTBIPLANARTOB(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, DIFF)  \
    661     TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,           \
    662                      benchmark_width_ - 4, DIFF, _Any, +, 0)                   \
    663     TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,           \
    664                      benchmark_width_, DIFF, _Unaligned, +, 1)                 \
    665     TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,           \
    666                      benchmark_width_, DIFF, _Invert, -, 0)                    \
    667     TESTBIPLANARTOBI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B,           \
    668                      benchmark_width_, DIFF, _Opt, +, 0)
    669 
    670 TESTBIPLANARTOB(NV12, 2, 2, ARGB, 4, 2)
    671 TESTBIPLANARTOB(NV21, 2, 2, ARGB, 4, 2)
    672 TESTBIPLANARTOB(NV12, 2, 2, RGB565, 2, 9)
    673 
    674 #define TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, \
    675                        W1280, DIFF, N, NEG, OFF)                               \
    676 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_PLANAR##N) {                          \
    677   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
    678   const int kHeight = ALIGNINT(benchmark_height_, YALIGN);                     \
    679   const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X);                          \
    680   const int kStride =                                                          \
    681       (kStrideUV * SUBSAMP_X * 8 * BPP_A + 7) / 8;                             \
    682   align_buffer_page_end(src_argb, kStride * kHeight + OFF);                    \
    683   align_buffer_page_end(dst_y_c, kWidth * kHeight);                            \
    684   align_buffer_page_end(dst_u_c,                                               \
    685                         kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y));            \
    686   align_buffer_page_end(dst_v_c,                                               \
    687                         kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y));            \
    688   align_buffer_page_end(dst_y_opt, kWidth * kHeight);                          \
    689   align_buffer_page_end(dst_u_opt,                                             \
    690                         kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y));            \
    691   align_buffer_page_end(dst_v_opt,                                             \
    692                   kStrideUV *                                                  \
    693                   SUBSAMPLE(kHeight, SUBSAMP_Y));                              \
    694   memset(dst_y_c, 1, kWidth * kHeight);                                        \
    695   memset(dst_u_c, 2,                                                           \
    696          kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y));                           \
    697   memset(dst_v_c, 3,                                                           \
    698          kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y));                           \
    699   memset(dst_y_opt, 101, kWidth * kHeight);                                    \
    700   memset(dst_u_opt, 102,                                                       \
    701          kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y));                           \
    702   memset(dst_v_opt, 103,                                                       \
    703          kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y));                           \
    704   for (int i = 0; i < kHeight; ++i)                                            \
    705     for (int j = 0; j < kStride; ++j)                                          \
    706       src_argb[(i * kStride) + j + OFF] = (fastrand() & 0xff);                 \
    707   MaskCpuFlags(disable_cpu_flags_);                                            \
    708   FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride,                               \
    709                         dst_y_c, kWidth,                                       \
    710                         dst_u_c, kStrideUV,                                    \
    711                         dst_v_c, kStrideUV,                                    \
    712                         kWidth, NEG kHeight);                                  \
    713   MaskCpuFlags(benchmark_cpu_info_);                                           \
    714   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
    715     FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride,                             \
    716                           dst_y_opt, kWidth,                                   \
    717                           dst_u_opt, kStrideUV,                                \
    718                           dst_v_opt, kStrideUV,                                \
    719                           kWidth, NEG kHeight);                                \
    720   }                                                                            \
    721   for (int i = 0; i < kHeight; ++i) {                                          \
    722     for (int j = 0; j < kWidth; ++j) {                                         \
    723       EXPECT_NEAR(static_cast<int>(dst_y_c[i * kWidth + j]),                   \
    724                   static_cast<int>(dst_y_opt[i * kWidth + j]), DIFF);          \
    725     }                                                                          \
    726   }                                                                            \
    727   for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    728     for (int j = 0; j < kStrideUV; ++j) {                                      \
    729       EXPECT_NEAR(static_cast<int>(dst_u_c[i * kStrideUV + j]),                \
    730                   static_cast<int>(dst_u_opt[i * kStrideUV + j]), DIFF);       \
    731     }                                                                          \
    732   }                                                                            \
    733   for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    734     for (int j = 0; j < kStrideUV; ++j) {                                      \
    735       EXPECT_NEAR(static_cast<int>(dst_v_c[i *                                 \
    736                                    kStrideUV + j]),                            \
    737                   static_cast<int>(dst_v_opt[i *                               \
    738                                    kStrideUV + j]), DIFF);                     \
    739     }                                                                          \
    740   }                                                                            \
    741   free_aligned_buffer_page_end(dst_y_c);                                       \
    742   free_aligned_buffer_page_end(dst_u_c);                                       \
    743   free_aligned_buffer_page_end(dst_v_c);                                       \
    744   free_aligned_buffer_page_end(dst_y_opt);                                     \
    745   free_aligned_buffer_page_end(dst_u_opt);                                     \
    746   free_aligned_buffer_page_end(dst_v_opt);                                     \
    747   free_aligned_buffer_page_end(src_argb);                                      \
    748 }
    749 
    750 #define TESTATOPLANAR(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,  \
    751                       DIFF)                                                    \
    752     TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,     \
    753                    benchmark_width_ - 4, DIFF, _Any, +, 0)                     \
    754     TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,     \
    755                    benchmark_width_, DIFF, _Unaligned, +, 1)                   \
    756     TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,     \
    757                    benchmark_width_, DIFF, _Invert, -, 0)                      \
    758     TESTATOPLANARI(FMT_A, BPP_A, YALIGN, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,     \
    759                    benchmark_width_, DIFF, _Opt, +, 0)
    760 
    761 TESTATOPLANAR(ARGB, 4, 1, I420, 2, 2, 4)
    762 #if defined(__arm__) || defined (__aarch64__)
    763 // arm version subsamples by summing 4 pixels then multiplying by matrix with
    764 // 4x smaller coefficients which are rounded to nearest integer.
    765 TESTATOPLANAR(ARGB, 4, 1, J420, 2, 2, 4)
    766 TESTATOPLANAR(ARGB, 4, 1, J422, 2, 1, 4)
    767 #else
    768 TESTATOPLANAR(ARGB, 4, 1, J420, 2, 2, 0)
    769 TESTATOPLANAR(ARGB, 4, 1, J422, 2, 1, 0)
    770 #endif
    771 TESTATOPLANAR(BGRA, 4, 1, I420, 2, 2, 4)
    772 TESTATOPLANAR(ABGR, 4, 1, I420, 2, 2, 4)
    773 TESTATOPLANAR(RGBA, 4, 1, I420, 2, 2, 4)
    774 TESTATOPLANAR(RAW, 3, 1, I420, 2, 2, 4)
    775 TESTATOPLANAR(RGB24, 3, 1, I420, 2, 2, 4)
    776 TESTATOPLANAR(RGB565, 2, 1, I420, 2, 2, 5)
    777 // TODO(fbarchard): Make 1555 neon work same as C code, reduce to diff 9.
    778 TESTATOPLANAR(ARGB1555, 2, 1, I420, 2, 2, 15)
    779 TESTATOPLANAR(ARGB4444, 2, 1, I420, 2, 2, 17)
    780 TESTATOPLANAR(ARGB, 4, 1, I411, 4, 1, 4)
    781 TESTATOPLANAR(ARGB, 4, 1, I422, 2, 1, 2)
    782 TESTATOPLANAR(ARGB, 4, 1, I444, 1, 1, 2)
    783 TESTATOPLANAR(YUY2, 2, 1, I420, 2, 2, 2)
    784 TESTATOPLANAR(UYVY, 2, 1, I420, 2, 2, 2)
    785 TESTATOPLANAR(YUY2, 2, 1, I422, 2, 1, 2)
    786 TESTATOPLANAR(UYVY, 2, 1, I422, 2, 1, 2)
    787 TESTATOPLANAR(I400, 1, 1, I420, 2, 2, 2)
    788 TESTATOPLANAR(J400, 1, 1, J420, 2, 2, 2)
    789 
    790 #define TESTATOBIPLANARI(FMT_A, SUB_A, BPP_A, FMT_PLANAR,                      \
    791                          SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF)             \
    792 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_PLANAR##N) {                          \
    793   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
    794   const int kHeight = benchmark_height_;                                       \
    795   const int kStride = SUBSAMPLE(kWidth, SUB_A) * BPP_A;                        \
    796   const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X);                          \
    797   align_buffer_page_end(src_argb, kStride * kHeight + OFF);                    \
    798   align_buffer_page_end(dst_y_c, kWidth * kHeight);                            \
    799   align_buffer_page_end(dst_uv_c,                                              \
    800                         kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y));        \
    801   align_buffer_page_end(dst_y_opt, kWidth * kHeight);                          \
    802   align_buffer_page_end(dst_uv_opt,                                            \
    803                         kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y));        \
    804   for (int i = 0; i < kHeight; ++i)                                            \
    805     for (int j = 0; j < kStride; ++j)                                          \
    806       src_argb[(i * kStride) + j + OFF] = (fastrand() & 0xff);                 \
    807   memset(dst_y_c, 1, kWidth * kHeight);                                        \
    808   memset(dst_uv_c, 2, kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y));          \
    809   memset(dst_y_opt, 101, kWidth * kHeight);                                    \
    810   memset(dst_uv_opt, 102, kStrideUV * 2 * SUBSAMPLE(kHeight, SUBSAMP_Y));      \
    811   MaskCpuFlags(disable_cpu_flags_);                                            \
    812   FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride,                               \
    813                         dst_y_c, kWidth, dst_uv_c, kStrideUV * 2,              \
    814                         kWidth, NEG kHeight);                                  \
    815   MaskCpuFlags(benchmark_cpu_info_);                                           \
    816   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
    817     FMT_A##To##FMT_PLANAR(src_argb + OFF, kStride,                             \
    818                           dst_y_opt, kWidth,                                   \
    819                           dst_uv_opt, kStrideUV * 2, kWidth, NEG kHeight);     \
    820   }                                                                            \
    821   int max_diff = 0;                                                            \
    822   for (int i = 0; i < kHeight; ++i) {                                          \
    823     for (int j = 0; j < kWidth; ++j) {                                         \
    824       int abs_diff =                                                           \
    825           abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \
    826               static_cast<int>(dst_y_opt[i * kWidth + j]));                    \
    827       if (abs_diff > max_diff) {                                               \
    828         max_diff = abs_diff;                                                   \
    829       }                                                                        \
    830     }                                                                          \
    831   }                                                                            \
    832   EXPECT_LE(max_diff, 4);                                                      \
    833   for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \
    834     for (int j = 0; j < kStrideUV * 2; ++j) {                                  \
    835       int abs_diff =                                                           \
    836           abs(static_cast<int>(dst_uv_c[i * kStrideUV * 2 + j]) -              \
    837               static_cast<int>(dst_uv_opt[i * kStrideUV * 2 + j]));            \
    838       if (abs_diff > max_diff) {                                               \
    839         max_diff = abs_diff;                                                   \
    840       }                                                                        \
    841     }                                                                          \
    842   }                                                                            \
    843   EXPECT_LE(max_diff, 4);                                                      \
    844   free_aligned_buffer_page_end(dst_y_c);                                       \
    845   free_aligned_buffer_page_end(dst_uv_c);                                      \
    846   free_aligned_buffer_page_end(dst_y_opt);                                     \
    847   free_aligned_buffer_page_end(dst_uv_opt);                                    \
    848   free_aligned_buffer_page_end(src_argb);                                      \
    849 }
    850 
    851 #define TESTATOBIPLANAR(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y) \
    852     TESTATOBIPLANARI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,    \
    853                      benchmark_width_ - 4, _Any, +, 0)                         \
    854     TESTATOBIPLANARI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,    \
    855                      benchmark_width_, _Unaligned, +, 1)                       \
    856     TESTATOBIPLANARI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,    \
    857                      benchmark_width_, _Invert, -, 0)                          \
    858     TESTATOBIPLANARI(FMT_A, SUB_A, BPP_A, FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,    \
    859                      benchmark_width_, _Opt, +, 0)
    860 
    861 TESTATOBIPLANAR(ARGB, 1, 4, NV12, 2, 2)
    862 TESTATOBIPLANAR(ARGB, 1, 4, NV21, 2, 2)
    863 TESTATOBIPLANAR(YUY2, 2, 4, NV12, 2, 2)
    864 TESTATOBIPLANAR(UYVY, 2, 4, NV12, 2, 2)
    865 
    866 #define TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                            \
    867                   FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                            \
    868                   W1280, DIFF, N, NEG, OFF)                                    \
    869 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_B##N) {                               \
    870   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
    871   const int kHeight = benchmark_height_;                                       \
    872   const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A;         \
    873   const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B;         \
    874   const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;  \
    875   const int kStrideB = (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B;  \
    876   align_buffer_page_end(src_argb, kStrideA * kHeightA + OFF);                  \
    877   align_buffer_page_end(dst_argb_c, kStrideB * kHeightB);                      \
    878   align_buffer_page_end(dst_argb_opt, kStrideB * kHeightB);                    \
    879   for (int i = 0; i < kStrideA * kHeightA; ++i) {                              \
    880     src_argb[i + OFF] = (fastrand() & 0xff);                                   \
    881   }                                                                            \
    882   memset(dst_argb_c, 1, kStrideB * kHeightB);                                  \
    883   memset(dst_argb_opt, 101, kStrideB * kHeightB);                              \
    884   MaskCpuFlags(disable_cpu_flags_);                                            \
    885   FMT_A##To##FMT_B(src_argb + OFF, kStrideA,                                   \
    886                    dst_argb_c, kStrideB,                                       \
    887                    kWidth, NEG kHeight);                                       \
    888   MaskCpuFlags(benchmark_cpu_info_);                                           \
    889   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
    890     FMT_A##To##FMT_B(src_argb + OFF, kStrideA,                                 \
    891                      dst_argb_opt, kStrideB,                                   \
    892                      kWidth, NEG kHeight);                                     \
    893   }                                                                            \
    894   int max_diff = 0;                                                            \
    895   for (int i = 0; i < kStrideB * kHeightB; ++i) {                              \
    896     int abs_diff =                                                             \
    897         abs(static_cast<int>(dst_argb_c[i]) -                                  \
    898             static_cast<int>(dst_argb_opt[i]));                                \
    899     if (abs_diff > max_diff) {                                                 \
    900       max_diff = abs_diff;                                                     \
    901     }                                                                          \
    902   }                                                                            \
    903   EXPECT_LE(max_diff, DIFF);                                                   \
    904   free_aligned_buffer_page_end(src_argb);                                      \
    905   free_aligned_buffer_page_end(dst_argb_c);                                    \
    906   free_aligned_buffer_page_end(dst_argb_opt);                                  \
    907 }
    908 
    909 #define TESTATOBRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                       \
    910                        FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF)                 \
    911 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_B##_Random) {                         \
    912   for (int times = 0; times < benchmark_iterations_; ++times) {                \
    913     const int kWidth = (fastrand() & 63) + 1;                                  \
    914     const int kHeight = (fastrand() & 31) + 1;                                 \
    915     const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A;       \
    916     const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B;       \
    917     const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;\
    918     const int kStrideB = (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B;\
    919     align_buffer_page_end(src_argb, kStrideA * kHeightA);                      \
    920     align_buffer_page_end(dst_argb_c, kStrideB * kHeightB);                    \
    921     align_buffer_page_end(dst_argb_opt, kStrideB * kHeightB);                  \
    922     for (int i = 0; i < kStrideA * kHeightA; ++i) {                            \
    923       src_argb[i] = (fastrand() & 0xff);                                       \
    924     }                                                                          \
    925     memset(dst_argb_c, 123, kStrideB * kHeightB);                              \
    926     memset(dst_argb_opt, 123, kStrideB * kHeightB);                            \
    927     MaskCpuFlags(disable_cpu_flags_);                                          \
    928     FMT_A##To##FMT_B(src_argb, kStrideA,                                       \
    929                      dst_argb_c, kStrideB,                                     \
    930                      kWidth, kHeight);                                         \
    931     MaskCpuFlags(benchmark_cpu_info_);                                         \
    932     FMT_A##To##FMT_B(src_argb, kStrideA,                                       \
    933                      dst_argb_opt, kStrideB,                                   \
    934                      kWidth, kHeight);                                         \
    935     int max_diff = 0;                                                          \
    936     for (int i = 0; i < kStrideB * kHeightB; ++i) {                            \
    937       int abs_diff =                                                           \
    938           abs(static_cast<int>(dst_argb_c[i]) -                                \
    939               static_cast<int>(dst_argb_opt[i]));                              \
    940       if (abs_diff > max_diff) {                                               \
    941         max_diff = abs_diff;                                                   \
    942       }                                                                        \
    943     }                                                                          \
    944     EXPECT_LE(max_diff, DIFF);                                                 \
    945     free_aligned_buffer_page_end(src_argb);                                    \
    946     free_aligned_buffer_page_end(dst_argb_c);                                  \
    947     free_aligned_buffer_page_end(dst_argb_opt);                                \
    948   }                                                                            \
    949 }
    950 
    951 #define TESTATOB(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                             \
    952                  FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF)                       \
    953     TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                                \
    954               FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                                \
    955               benchmark_width_ - 4, DIFF, _Any, +, 0)                          \
    956     TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                                \
    957               FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                                \
    958               benchmark_width_, DIFF, _Unaligned, +, 1)                        \
    959     TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                                \
    960               FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                                \
    961               benchmark_width_, DIFF, _Invert, -, 0)                           \
    962     TESTATOBI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                                \
    963               FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                                \
    964               benchmark_width_, DIFF, _Opt, +, 0)                              \
    965     TESTATOBRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                           \
    966                    FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF)
    967 
    968 TESTATOB(ARGB, 4, 4, 1, ARGB, 4, 4, 1, 0)
    969 TESTATOB(ARGB, 4, 4, 1, BGRA, 4, 4, 1, 0)
    970 TESTATOB(ARGB, 4, 4, 1, ABGR, 4, 4, 1, 0)
    971 TESTATOB(ARGB, 4, 4, 1, RGBA, 4, 4, 1, 0)
    972 TESTATOB(ARGB, 4, 4, 1, RAW, 3, 3, 1, 0)
    973 TESTATOB(ARGB, 4, 4, 1, RGB24, 3, 3, 1, 0)
    974 TESTATOB(ARGB, 4, 4, 1, RGB565, 2, 2, 1, 0)
    975 TESTATOB(ARGB, 4, 4, 1, ARGB1555, 2, 2, 1, 0)
    976 TESTATOB(ARGB, 4, 4, 1, ARGB4444, 2, 2, 1, 0)
    977 TESTATOB(ARGB, 4, 4, 1, YUY2, 2, 4, 1, 4)
    978 TESTATOB(ARGB, 4, 4, 1, UYVY, 2, 4, 1, 4)
    979 TESTATOB(ARGB, 4, 4, 1, I400, 1, 1, 1, 2)
    980 TESTATOB(ARGB, 4, 4, 1, J400, 1, 1, 1, 2)
    981 TESTATOB(BGRA, 4, 4, 1, ARGB, 4, 4, 1, 0)
    982 TESTATOB(ABGR, 4, 4, 1, ARGB, 4, 4, 1, 0)
    983 TESTATOB(RGBA, 4, 4, 1, ARGB, 4, 4, 1, 0)
    984 TESTATOB(RAW, 3, 3, 1, ARGB, 4, 4, 1, 0)
    985 TESTATOB(RAW, 3, 3, 1, RGB24, 3, 3, 1, 0)
    986 TESTATOB(RGB24, 3, 3, 1, ARGB, 4, 4, 1, 0)
    987 TESTATOB(RGB565, 2, 2, 1, ARGB, 4, 4, 1, 0)
    988 TESTATOB(ARGB1555, 2, 2, 1, ARGB, 4, 4, 1, 0)
    989 TESTATOB(ARGB4444, 2, 2, 1, ARGB, 4, 4, 1, 0)
    990 TESTATOB(YUY2, 2, 4, 1, ARGB, 4, 4, 1, 4)
    991 TESTATOB(UYVY, 2, 4, 1, ARGB, 4, 4, 1, 4)
    992 TESTATOB(I400, 1, 1, 1, ARGB, 4, 4, 1, 0)
    993 TESTATOB(J400, 1, 1, 1, ARGB, 4, 4, 1, 0)
    994 TESTATOB(I400, 1, 1, 1, I400, 1, 1, 1, 0)
    995 TESTATOB(J400, 1, 1, 1, J400, 1, 1, 1, 0)
    996 TESTATOB(I400, 1, 1, 1, I400Mirror, 1, 1, 1, 0)
    997 TESTATOB(ARGB, 4, 4, 1, ARGBMirror, 4, 4, 1, 0)
    998 
    999 #define TESTATOBDI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                           \
   1000                    FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                           \
   1001                    W1280, DIFF, N, NEG, OFF)                                   \
   1002 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_B##Dither##N) {                       \
   1003   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
   1004   const int kHeight = benchmark_height_;                                       \
   1005   const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A;         \
   1006   const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B;         \
   1007   const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;  \
   1008   const int kStrideB = (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B;  \
   1009   align_buffer_page_end(src_argb, kStrideA * kHeightA + OFF);                  \
   1010   align_buffer_page_end(dst_argb_c, kStrideB * kHeightB);                      \
   1011   align_buffer_page_end(dst_argb_opt, kStrideB * kHeightB);                    \
   1012   for (int i = 0; i < kStrideA * kHeightA; ++i) {                              \
   1013     src_argb[i + OFF] = (fastrand() & 0xff);                                   \
   1014   }                                                                            \
   1015   memset(dst_argb_c, 1, kStrideB * kHeightB);                                  \
   1016   memset(dst_argb_opt, 101, kStrideB * kHeightB);                              \
   1017   MaskCpuFlags(disable_cpu_flags_);                                            \
   1018   FMT_A##To##FMT_B##Dither(src_argb + OFF, kStrideA,                           \
   1019                            dst_argb_c, kStrideB,                               \
   1020                            NULL, kWidth, NEG kHeight);                         \
   1021   MaskCpuFlags(benchmark_cpu_info_);                                           \
   1022   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
   1023     FMT_A##To##FMT_B##Dither(src_argb + OFF, kStrideA,                         \
   1024                              dst_argb_opt, kStrideB,                           \
   1025                              NULL, kWidth, NEG kHeight);                       \
   1026   }                                                                            \
   1027   int max_diff = 0;                                                            \
   1028   for (int i = 0; i < kStrideB * kHeightB; ++i) {                              \
   1029     int abs_diff =                                                             \
   1030         abs(static_cast<int>(dst_argb_c[i]) -                                  \
   1031             static_cast<int>(dst_argb_opt[i]));                                \
   1032     if (abs_diff > max_diff) {                                                 \
   1033       max_diff = abs_diff;                                                     \
   1034     }                                                                          \
   1035   }                                                                            \
   1036   EXPECT_LE(max_diff, DIFF);                                                   \
   1037   free_aligned_buffer_page_end(src_argb);                                      \
   1038   free_aligned_buffer_page_end(dst_argb_c);                                    \
   1039   free_aligned_buffer_page_end(dst_argb_opt);                                  \
   1040 }
   1041 
   1042 #define TESTATOBDRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                      \
   1043                        FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF)                 \
   1044 TEST_F(LibYUVConvertTest, FMT_A##To##FMT_B##Dither_Random) {                   \
   1045   for (int times = 0; times < benchmark_iterations_; ++times) {                \
   1046     const int kWidth = (fastrand() & 63) + 1;                                  \
   1047     const int kHeight = (fastrand() & 31) + 1;                                 \
   1048     const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A;       \
   1049     const int kHeightB = (kHeight + HEIGHT_B - 1) / HEIGHT_B * HEIGHT_B;       \
   1050     const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;\
   1051     const int kStrideB = (kWidth * BPP_B + STRIDE_B - 1) / STRIDE_B * STRIDE_B;\
   1052     align_buffer_page_end(src_argb, kStrideA * kHeightA);                      \
   1053     align_buffer_page_end(dst_argb_c, kStrideB * kHeightB);                    \
   1054     align_buffer_page_end(dst_argb_opt, kStrideB * kHeightB);                  \
   1055     for (int i = 0; i < kStrideA * kHeightA; ++i) {                            \
   1056       src_argb[i] = (fastrand() & 0xff);                                       \
   1057     }                                                                          \
   1058     memset(dst_argb_c, 123, kStrideB * kHeightB);                              \
   1059     memset(dst_argb_opt, 123, kStrideB * kHeightB);                            \
   1060     MaskCpuFlags(disable_cpu_flags_);                                          \
   1061     FMT_A##To##FMT_B##Dither(src_argb, kStrideA,                               \
   1062                              dst_argb_c, kStrideB,                             \
   1063                              NULL, kWidth, kHeight);                           \
   1064     MaskCpuFlags(benchmark_cpu_info_);                                         \
   1065     FMT_A##To##FMT_B##Dither(src_argb, kStrideA,                               \
   1066                              dst_argb_opt, kStrideB,                           \
   1067                              NULL, kWidth, kHeight);                           \
   1068     int max_diff = 0;                                                          \
   1069     for (int i = 0; i < kStrideB * kHeightB; ++i) {                            \
   1070       int abs_diff =                                                           \
   1071           abs(static_cast<int>(dst_argb_c[i]) -                                \
   1072               static_cast<int>(dst_argb_opt[i]));                              \
   1073       if (abs_diff > max_diff) {                                               \
   1074         max_diff = abs_diff;                                                   \
   1075       }                                                                        \
   1076     }                                                                          \
   1077     EXPECT_LE(max_diff, DIFF);                                                 \
   1078     free_aligned_buffer_page_end(src_argb);                                    \
   1079     free_aligned_buffer_page_end(dst_argb_c);                                  \
   1080     free_aligned_buffer_page_end(dst_argb_opt);                                \
   1081   }                                                                            \
   1082 }
   1083 
   1084 #define TESTATOBD(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                            \
   1085                   FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF)                      \
   1086     TESTATOBDI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                               \
   1087                FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                               \
   1088                benchmark_width_ - 4, DIFF, _Any, +, 0)                         \
   1089     TESTATOBDI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                               \
   1090                FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                               \
   1091                benchmark_width_, DIFF, _Unaligned, +, 1)                       \
   1092     TESTATOBDI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                               \
   1093                FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                               \
   1094                benchmark_width_, DIFF, _Invert, -, 0)                          \
   1095     TESTATOBDI(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                               \
   1096                FMT_B, BPP_B, STRIDE_B, HEIGHT_B,                               \
   1097                benchmark_width_, DIFF, _Opt, +, 0)                             \
   1098     TESTATOBDRANDOM(FMT_A, BPP_A, STRIDE_A, HEIGHT_A,                          \
   1099                     FMT_B, BPP_B, STRIDE_B, HEIGHT_B, DIFF)
   1100 
   1101 TESTATOBD(ARGB, 4, 4, 1, RGB565, 2, 2, 1, 0)
   1102 
   1103 #define TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A,                          \
   1104                  W1280, N, NEG, OFF)                                           \
   1105 TEST_F(LibYUVConvertTest, FMT_ATOB##_Symetric##N) {                            \
   1106   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
   1107   const int kHeight = benchmark_height_;                                       \
   1108   const int kHeightA = (kHeight + HEIGHT_A - 1) / HEIGHT_A * HEIGHT_A;         \
   1109   const int kStrideA = (kWidth * BPP_A + STRIDE_A - 1) / STRIDE_A * STRIDE_A;  \
   1110   align_buffer_page_end(src_argb, kStrideA * kHeightA + OFF);                  \
   1111   align_buffer_page_end(dst_argb_c, kStrideA * kHeightA);                      \
   1112   align_buffer_page_end(dst_argb_opt, kStrideA * kHeightA);                    \
   1113   for (int i = 0; i < kStrideA * kHeightA; ++i) {                              \
   1114     src_argb[i + OFF] = (fastrand() & 0xff);                                   \
   1115   }                                                                            \
   1116   memset(dst_argb_c, 1, kStrideA * kHeightA);                                  \
   1117   memset(dst_argb_opt, 101, kStrideA * kHeightA);                              \
   1118   MaskCpuFlags(disable_cpu_flags_);                                            \
   1119   FMT_ATOB(src_argb + OFF, kStrideA,                                           \
   1120            dst_argb_c, kStrideA,                                               \
   1121            kWidth, NEG kHeight);                                               \
   1122   MaskCpuFlags(benchmark_cpu_info_);                                           \
   1123   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
   1124     FMT_ATOB(src_argb + OFF, kStrideA,                                         \
   1125              dst_argb_opt, kStrideA,                                           \
   1126              kWidth, NEG kHeight);                                             \
   1127   }                                                                            \
   1128   MaskCpuFlags(disable_cpu_flags_);                                            \
   1129   FMT_ATOB(dst_argb_c, kStrideA,                                               \
   1130            dst_argb_c, kStrideA,                                               \
   1131            kWidth, NEG kHeight);                                               \
   1132   MaskCpuFlags(benchmark_cpu_info_);                                           \
   1133   FMT_ATOB(dst_argb_opt, kStrideA,                                             \
   1134            dst_argb_opt, kStrideA,                                             \
   1135            kWidth, NEG kHeight);                                               \
   1136   for (int i = 0; i < kStrideA * kHeightA; ++i) {                              \
   1137     EXPECT_EQ(src_argb[i + OFF], dst_argb_opt[i]);                             \
   1138     EXPECT_EQ(dst_argb_c[i], dst_argb_opt[i]);                                 \
   1139   }                                                                            \
   1140   free_aligned_buffer_page_end(src_argb);                                      \
   1141   free_aligned_buffer_page_end(dst_argb_c);                                    \
   1142   free_aligned_buffer_page_end(dst_argb_opt);                                  \
   1143 }
   1144 
   1145 #define TESTSYM(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A)                           \
   1146     TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A,                              \
   1147              benchmark_width_ - 4, _Any, +, 0)                                 \
   1148     TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A,                              \
   1149              benchmark_width_, _Unaligned, +, 1)                               \
   1150     TESTSYMI(FMT_ATOB, BPP_A, STRIDE_A, HEIGHT_A,                              \
   1151              benchmark_width_, _Opt, +, 0)
   1152 
   1153 TESTSYM(ARGBToARGB, 4, 4, 1)
   1154 TESTSYM(ARGBToBGRA, 4, 4, 1)
   1155 TESTSYM(ARGBToABGR, 4, 4, 1)
   1156 TESTSYM(BGRAToARGB, 4, 4, 1)
   1157 TESTSYM(ABGRToARGB, 4, 4, 1)
   1158 
   1159 TEST_F(LibYUVConvertTest, Test565) {
   1160   SIMD_ALIGNED(uint8 orig_pixels[256][4]);
   1161   SIMD_ALIGNED(uint8 pixels565[256][2]);
   1162 
   1163   for (int i = 0; i < 256; ++i) {
   1164     for (int j = 0; j < 4; ++j) {
   1165       orig_pixels[i][j] = i;
   1166     }
   1167   }
   1168   ARGBToRGB565(&orig_pixels[0][0], 0, &pixels565[0][0], 0, 256, 1);
   1169   uint32 checksum = HashDjb2(&pixels565[0][0], sizeof(pixels565), 5381);
   1170   EXPECT_EQ(610919429u, checksum);
   1171 }
   1172 
   1173 #ifdef HAVE_JPEG
   1174 TEST_F(LibYUVConvertTest, ValidateJpeg) {
   1175   const int kOff = 10;
   1176   const int kMinJpeg = 64;
   1177   const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ?
   1178     benchmark_width_ * benchmark_height_ : kMinJpeg;
   1179   const int kSize = kImageSize + kOff;
   1180   align_buffer_page_end(orig_pixels, kSize);
   1181 
   1182   // No SOI or EOI. Expect fail.
   1183   memset(orig_pixels, 0, kSize);
   1184   EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
   1185 
   1186   // Test special value that matches marker start.
   1187   memset(orig_pixels, 0xff, kSize);
   1188   EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
   1189 
   1190   // EOI, SOI. Expect pass.
   1191   orig_pixels[0] = 0xff;
   1192   orig_pixels[1] = 0xd8;  // SOI.
   1193   orig_pixels[kSize - kOff + 0] = 0xff;
   1194   orig_pixels[kSize - kOff + 1] = 0xd9;  // EOI.
   1195   for (int times = 0; times < benchmark_iterations_; ++times) {
   1196     EXPECT_TRUE(ValidateJpeg(orig_pixels, kSize));
   1197   }
   1198   free_aligned_buffer_page_end(orig_pixels);
   1199 }
   1200 
   1201 TEST_F(LibYUVConvertTest, ValidateJpegLarge) {
   1202   const int kOff = 10;
   1203   const int kMinJpeg = 64;
   1204   const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ?
   1205     benchmark_width_ * benchmark_height_ : kMinJpeg;
   1206   const int kSize = kImageSize + kOff;
   1207   const int kMultiple = 10;
   1208   const int kBufSize = kImageSize * kMultiple + kOff;
   1209   align_buffer_page_end(orig_pixels, kBufSize);
   1210 
   1211   // No SOI or EOI. Expect fail.
   1212   memset(orig_pixels, 0, kBufSize);
   1213   EXPECT_FALSE(ValidateJpeg(orig_pixels, kBufSize));
   1214 
   1215   // EOI, SOI. Expect pass.
   1216   orig_pixels[0] = 0xff;
   1217   orig_pixels[1] = 0xd8;  // SOI.
   1218   orig_pixels[kSize - kOff + 0] = 0xff;
   1219   orig_pixels[kSize - kOff + 1] = 0xd9;  // EOI.
   1220   for (int times = 0; times < benchmark_iterations_; ++times) {
   1221     EXPECT_TRUE(ValidateJpeg(orig_pixels, kBufSize));
   1222   }
   1223   free_aligned_buffer_page_end(orig_pixels);
   1224 }
   1225 
   1226 TEST_F(LibYUVConvertTest, InvalidateJpeg) {
   1227   const int kOff = 10;
   1228   const int kMinJpeg = 64;
   1229   const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ?
   1230     benchmark_width_ * benchmark_height_ : kMinJpeg;
   1231   const int kSize = kImageSize + kOff;
   1232   align_buffer_page_end(orig_pixels, kSize);
   1233 
   1234   // NULL pointer. Expect fail.
   1235   EXPECT_FALSE(ValidateJpeg(NULL, kSize));
   1236 
   1237   // Negative size. Expect fail.
   1238   EXPECT_FALSE(ValidateJpeg(orig_pixels, -1));
   1239 
   1240   // Too large size. Expect fail.
   1241   EXPECT_FALSE(ValidateJpeg(orig_pixels, 0xfb000000ull));
   1242 
   1243   // No SOI or EOI. Expect fail.
   1244   memset(orig_pixels, 0, kSize);
   1245   EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
   1246 
   1247   // SOI but no EOI. Expect fail.
   1248   orig_pixels[0] = 0xff;
   1249   orig_pixels[1] = 0xd8;  // SOI.
   1250   for (int times = 0; times < benchmark_iterations_; ++times) {
   1251     EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
   1252   }
   1253 
   1254   // EOI but no SOI. Expect fail.
   1255   orig_pixels[0] = 0;
   1256   orig_pixels[1] = 0;
   1257   orig_pixels[kSize - kOff + 0] = 0xff;
   1258   orig_pixels[kSize - kOff + 1] = 0xd9;  // EOI.
   1259   EXPECT_FALSE(ValidateJpeg(orig_pixels, kSize));
   1260 
   1261   free_aligned_buffer_page_end(orig_pixels);
   1262 }
   1263 
   1264 TEST_F(LibYUVConvertTest, FuzzJpeg) {
   1265   // SOI but no EOI. Expect fail.
   1266   for (int times = 0; times < benchmark_iterations_; ++times) {
   1267     const int kSize = fastrand() % 5000 + 2;
   1268     align_buffer_page_end(orig_pixels, kSize);
   1269     MemRandomize(orig_pixels, kSize);
   1270 
   1271     // Add SOI so frame will be scanned.
   1272     orig_pixels[0] = 0xff;
   1273     orig_pixels[1] = 0xd8;  // SOI.
   1274     orig_pixels[kSize - 1] = 0xff;
   1275     ValidateJpeg(orig_pixels, kSize);  // Failure normally expected.
   1276     free_aligned_buffer_page_end(orig_pixels);
   1277   }
   1278 }
   1279 
   1280 TEST_F(LibYUVConvertTest, MJPGToI420) {
   1281   const int kOff = 10;
   1282   const int kMinJpeg = 64;
   1283   const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ?
   1284     benchmark_width_ * benchmark_height_ : kMinJpeg;
   1285   const int kSize = kImageSize + kOff;
   1286   align_buffer_page_end(orig_pixels, kSize);
   1287   align_buffer_page_end(dst_y_opt, benchmark_width_ * benchmark_height_);
   1288   align_buffer_page_end(dst_u_opt,
   1289                         SUBSAMPLE(benchmark_width_, 2) *
   1290                         SUBSAMPLE(benchmark_height_, 2));
   1291   align_buffer_page_end(dst_v_opt,
   1292                         SUBSAMPLE(benchmark_width_, 2) *
   1293                         SUBSAMPLE(benchmark_height_, 2));
   1294 
   1295   // EOI, SOI to make MJPG appear valid.
   1296   memset(orig_pixels, 0, kSize);
   1297   orig_pixels[0] = 0xff;
   1298   orig_pixels[1] = 0xd8;  // SOI.
   1299   orig_pixels[kSize - kOff + 0] = 0xff;
   1300   orig_pixels[kSize - kOff + 1] = 0xd9;  // EOI.
   1301 
   1302   for (int times = 0; times < benchmark_iterations_; ++times) {
   1303     int ret = MJPGToI420(orig_pixels, kSize,
   1304                          dst_y_opt, benchmark_width_,
   1305                          dst_u_opt, SUBSAMPLE(benchmark_width_, 2),
   1306                          dst_v_opt, SUBSAMPLE(benchmark_width_, 2),
   1307                          benchmark_width_, benchmark_height_,
   1308                          benchmark_width_, benchmark_height_);
   1309     // Expect failure because image is not really valid.
   1310     EXPECT_EQ(1, ret);
   1311   }
   1312 
   1313   free_aligned_buffer_page_end(dst_y_opt);
   1314   free_aligned_buffer_page_end(dst_u_opt);
   1315   free_aligned_buffer_page_end(dst_v_opt);
   1316   free_aligned_buffer_page_end(orig_pixels);
   1317 }
   1318 
   1319 TEST_F(LibYUVConvertTest, MJPGToARGB) {
   1320   const int kOff = 10;
   1321   const int kMinJpeg = 64;
   1322   const int kImageSize = benchmark_width_ * benchmark_height_ >= kMinJpeg ?
   1323     benchmark_width_ * benchmark_height_ : kMinJpeg;
   1324   const int kSize = kImageSize + kOff;
   1325   align_buffer_page_end(orig_pixels, kSize);
   1326   align_buffer_page_end(dst_argb_opt, benchmark_width_ * benchmark_height_ * 4);
   1327 
   1328   // EOI, SOI to make MJPG appear valid.
   1329   memset(orig_pixels, 0, kSize);
   1330   orig_pixels[0] = 0xff;
   1331   orig_pixels[1] = 0xd8;  // SOI.
   1332   orig_pixels[kSize - kOff + 0] = 0xff;
   1333   orig_pixels[kSize - kOff + 1] = 0xd9;  // EOI.
   1334 
   1335   for (int times = 0; times < benchmark_iterations_; ++times) {
   1336     int ret = MJPGToARGB(orig_pixels, kSize,
   1337                          dst_argb_opt, benchmark_width_ * 4,
   1338                          benchmark_width_, benchmark_height_,
   1339                          benchmark_width_, benchmark_height_);
   1340     // Expect failure because image is not really valid.
   1341     EXPECT_EQ(1, ret);
   1342   }
   1343 
   1344   free_aligned_buffer_page_end(dst_argb_opt);
   1345   free_aligned_buffer_page_end(orig_pixels);
   1346 }
   1347 
   1348 #endif  // HAVE_JPEG
   1349 
   1350 TEST_F(LibYUVConvertTest, NV12Crop) {
   1351   const int SUBSAMP_X = 2;
   1352   const int SUBSAMP_Y = 2;
   1353   const int kWidth = benchmark_width_;
   1354   const int kHeight = benchmark_height_;
   1355   const int crop_y =
   1356     ((benchmark_height_ - (benchmark_height_ * 360 / 480)) / 2 + 1) & ~1;
   1357   const int kDestWidth = benchmark_width_;
   1358   const int kDestHeight = benchmark_height_ - crop_y * 2;
   1359   const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X);
   1360   const int sample_size = kWidth * kHeight +
   1361     kStrideUV *
   1362     SUBSAMPLE(kHeight, SUBSAMP_Y) * 2;
   1363   align_buffer_page_end(src_y, sample_size);
   1364   uint8* src_uv = src_y + kWidth * kHeight;
   1365 
   1366   align_buffer_page_end(dst_y, kDestWidth * kDestHeight);
   1367   align_buffer_page_end(dst_u,
   1368                   SUBSAMPLE(kDestWidth, SUBSAMP_X) *
   1369                   SUBSAMPLE(kDestHeight, SUBSAMP_Y));
   1370   align_buffer_page_end(dst_v,
   1371                   SUBSAMPLE(kDestWidth, SUBSAMP_X) *
   1372                   SUBSAMPLE(kDestHeight, SUBSAMP_Y));
   1373 
   1374   align_buffer_page_end(dst_y_2, kDestWidth * kDestHeight);
   1375   align_buffer_page_end(dst_u_2,
   1376                   SUBSAMPLE(kDestWidth, SUBSAMP_X) *
   1377                   SUBSAMPLE(kDestHeight, SUBSAMP_Y));
   1378   align_buffer_page_end(dst_v_2,
   1379                   SUBSAMPLE(kDestWidth, SUBSAMP_X) *
   1380                   SUBSAMPLE(kDestHeight, SUBSAMP_Y));
   1381 
   1382   for (int i = 0; i < kHeight * kWidth; ++i) {
   1383     src_y[i] = (fastrand() & 0xff);
   1384   }
   1385   for (int i = 0; i < (SUBSAMPLE(kHeight, SUBSAMP_Y) *
   1386        kStrideUV) * 2; ++i) {
   1387     src_uv[i] = (fastrand() & 0xff);
   1388   }
   1389   memset(dst_y, 1, kDestWidth * kDestHeight);
   1390   memset(dst_u, 2, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
   1391                    SUBSAMPLE(kDestHeight, SUBSAMP_Y));
   1392   memset(dst_v, 3, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
   1393                    SUBSAMPLE(kDestHeight, SUBSAMP_Y));
   1394   memset(dst_y_2, 1, kDestWidth * kDestHeight);
   1395   memset(dst_u_2, 2, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
   1396                      SUBSAMPLE(kDestHeight, SUBSAMP_Y));
   1397   memset(dst_v_2, 3, SUBSAMPLE(kDestWidth, SUBSAMP_X) *
   1398                      SUBSAMPLE(kDestHeight, SUBSAMP_Y));
   1399 
   1400   ConvertToI420(src_y, sample_size,
   1401                 dst_y_2, kDestWidth,
   1402                 dst_u_2, SUBSAMPLE(kDestWidth, SUBSAMP_X),
   1403                 dst_v_2, SUBSAMPLE(kDestWidth, SUBSAMP_X),
   1404                 0, crop_y,
   1405                 kWidth, kHeight,
   1406                 kDestWidth, kDestHeight,
   1407                 libyuv::kRotate0, libyuv::FOURCC_NV12);
   1408 
   1409   NV12ToI420(src_y + crop_y * kWidth, kWidth,
   1410              src_uv + (crop_y / 2) * kStrideUV * 2,
   1411                kStrideUV * 2,
   1412              dst_y, kDestWidth,
   1413              dst_u, SUBSAMPLE(kDestWidth, SUBSAMP_X),
   1414              dst_v, SUBSAMPLE(kDestWidth, SUBSAMP_X),
   1415              kDestWidth, kDestHeight);
   1416 
   1417   for (int i = 0; i < kDestHeight; ++i) {
   1418     for (int j = 0; j < kDestWidth; ++j) {
   1419       EXPECT_EQ(dst_y[i * kWidth + j], dst_y_2[i * kWidth + j]);
   1420     }
   1421   }
   1422   for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) {
   1423     for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) {
   1424       EXPECT_EQ(dst_u[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j],
   1425                 dst_u_2[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]);
   1426     }
   1427   }
   1428   for (int i = 0; i < SUBSAMPLE(kDestHeight, SUBSAMP_Y); ++i) {
   1429     for (int j = 0; j < SUBSAMPLE(kDestWidth, SUBSAMP_X); ++j) {
   1430       EXPECT_EQ(dst_v[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j],
   1431                 dst_v_2[i * SUBSAMPLE(kDestWidth, SUBSAMP_X) + j]);
   1432     }
   1433   }
   1434   free_aligned_buffer_page_end(dst_y);
   1435   free_aligned_buffer_page_end(dst_u);
   1436   free_aligned_buffer_page_end(dst_v);
   1437   free_aligned_buffer_page_end(dst_y_2);
   1438   free_aligned_buffer_page_end(dst_u_2);
   1439   free_aligned_buffer_page_end(dst_v_2);
   1440   free_aligned_buffer_page_end(src_y);
   1441 }
   1442 
   1443 TEST_F(LibYUVConvertTest, TestYToARGB) {
   1444   uint8 y[32];
   1445   uint8 expectedg[32];
   1446   for (int i = 0; i < 32; ++i) {
   1447     y[i] = i * 5 + 17;
   1448     expectedg[i] = static_cast<int>((y[i] - 16) * 1.164f + 0.5f);
   1449   }
   1450   uint8 argb[32 * 4];
   1451   YToARGB(y, 0, argb, 0, 32, 1);
   1452 
   1453   for (int i = 0; i < 32; ++i) {
   1454     printf("%2d %d: %d <-> %d,%d,%d,%d\n", i, y[i], expectedg[i],
   1455            argb[i * 4 + 0],
   1456            argb[i * 4 + 1],
   1457            argb[i * 4 + 2],
   1458            argb[i * 4 + 3]);
   1459   }
   1460   for (int i = 0; i < 32; ++i) {
   1461     EXPECT_EQ(expectedg[i], argb[i * 4 + 0]);
   1462   }
   1463 }
   1464 
   1465 static const uint8 kNoDither4x4[16] = {
   1466   0, 0, 0, 0,
   1467   0, 0, 0, 0,
   1468   0, 0, 0, 0,
   1469   0, 0, 0, 0,
   1470 };
   1471 
   1472 TEST_F(LibYUVConvertTest, TestNoDither) {
   1473   align_buffer_page_end(src_argb, benchmark_width_ * benchmark_height_ * 4);
   1474   align_buffer_page_end(dst_rgb565, benchmark_width_ * benchmark_height_ * 2);
   1475   align_buffer_page_end(dst_rgb565dither,
   1476                         benchmark_width_ * benchmark_height_ * 2);
   1477   MemRandomize(src_argb, benchmark_width_ * benchmark_height_ * 4);
   1478   MemRandomize(dst_rgb565, benchmark_width_ * benchmark_height_ * 2);
   1479   MemRandomize(dst_rgb565dither, benchmark_width_ * benchmark_height_ * 2);
   1480   ARGBToRGB565(src_argb, benchmark_width_ * 4,
   1481                dst_rgb565, benchmark_width_ * 2,
   1482                benchmark_width_, benchmark_height_);
   1483   ARGBToRGB565Dither(src_argb, benchmark_width_ * 4,
   1484                      dst_rgb565dither, benchmark_width_ * 2,
   1485                      kNoDither4x4, benchmark_width_, benchmark_height_);
   1486   for (int i = 0; i < benchmark_width_ * benchmark_height_ * 2; ++i) {
   1487     EXPECT_EQ(dst_rgb565[i], dst_rgb565dither[i]);
   1488   }
   1489 
   1490   free_aligned_buffer_page_end(src_argb);
   1491   free_aligned_buffer_page_end(dst_rgb565);
   1492   free_aligned_buffer_page_end(dst_rgb565dither);
   1493 }
   1494 
   1495 // Ordered 4x4 dither for 888 to 565.  Values from 0 to 7.
   1496 static const uint8 kDither565_4x4[16] = {
   1497   0, 4, 1, 5,
   1498   6, 2, 7, 3,
   1499   1, 5, 0, 4,
   1500   7, 3, 6, 2,
   1501 };
   1502 
   1503 TEST_F(LibYUVConvertTest, TestDither) {
   1504   align_buffer_page_end(src_argb, benchmark_width_ * benchmark_height_ * 4);
   1505   align_buffer_page_end(dst_rgb565, benchmark_width_ * benchmark_height_ * 2);
   1506   align_buffer_page_end(dst_rgb565dither,
   1507                         benchmark_width_ * benchmark_height_ * 2);
   1508   align_buffer_page_end(dst_argb, benchmark_width_ * benchmark_height_ * 4);
   1509   align_buffer_page_end(dst_argbdither,
   1510                         benchmark_width_ * benchmark_height_ * 4);
   1511   MemRandomize(src_argb, benchmark_width_ * benchmark_height_ * 4);
   1512   MemRandomize(dst_rgb565, benchmark_width_ * benchmark_height_ * 2);
   1513   MemRandomize(dst_rgb565dither, benchmark_width_ * benchmark_height_ * 2);
   1514   MemRandomize(dst_argb, benchmark_width_ * benchmark_height_ * 4);
   1515   MemRandomize(dst_argbdither, benchmark_width_ * benchmark_height_ * 4);
   1516   ARGBToRGB565(src_argb, benchmark_width_ * 4,
   1517                dst_rgb565, benchmark_width_ * 2,
   1518                benchmark_width_, benchmark_height_);
   1519   ARGBToRGB565Dither(src_argb, benchmark_width_ * 4,
   1520                      dst_rgb565dither, benchmark_width_ * 2,
   1521                      kDither565_4x4, benchmark_width_, benchmark_height_);
   1522   RGB565ToARGB(dst_rgb565, benchmark_width_ * 2,
   1523                dst_argb, benchmark_width_ * 4,
   1524                benchmark_width_, benchmark_height_);
   1525   RGB565ToARGB(dst_rgb565dither, benchmark_width_ * 2,
   1526                dst_argbdither, benchmark_width_ * 4,
   1527                benchmark_width_, benchmark_height_);
   1528 
   1529   for (int i = 0; i < benchmark_width_ * benchmark_height_ * 4; ++i) {
   1530     EXPECT_NEAR(dst_argb[i], dst_argbdither[i], 9);
   1531   }
   1532   free_aligned_buffer_page_end(src_argb);
   1533   free_aligned_buffer_page_end(dst_rgb565);
   1534   free_aligned_buffer_page_end(dst_rgb565dither);
   1535   free_aligned_buffer_page_end(dst_argb);
   1536   free_aligned_buffer_page_end(dst_argbdither);
   1537 }
   1538 
   1539 #define TESTPLANARTOBID(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN, \
   1540                        YALIGN, W1280, DIFF, N, NEG, OFF, FMT_C, BPP_C)         \
   1541 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##Dither##N) {                  \
   1542   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
   1543   const int kHeight = ALIGNINT(benchmark_height_, YALIGN);                     \
   1544   const int kStrideB = ALIGNINT(kWidth * BPP_B, ALIGN);                        \
   1545   const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X);                          \
   1546   const int kSizeUV = kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y);               \
   1547   align_buffer_page_end(src_y, kWidth * kHeight + OFF);                        \
   1548   align_buffer_page_end(src_u, kSizeUV + OFF);                                 \
   1549   align_buffer_page_end(src_v, kSizeUV + OFF);                                 \
   1550   align_buffer_page_end(dst_argb_c, kStrideB * kHeight + OFF);                 \
   1551   align_buffer_page_end(dst_argb_opt, kStrideB * kHeight + OFF);               \
   1552   for (int i = 0; i < kWidth * kHeight; ++i) {                                 \
   1553     src_y[i + OFF] = (fastrand() & 0xff);                                      \
   1554   }                                                                            \
   1555   for (int i = 0; i < kSizeUV; ++i) {                                          \
   1556     src_u[i + OFF] = (fastrand() & 0xff);                                      \
   1557     src_v[i + OFF] = (fastrand() & 0xff);                                      \
   1558   }                                                                            \
   1559   memset(dst_argb_c + OFF, 1, kStrideB * kHeight);                             \
   1560   memset(dst_argb_opt + OFF, 101, kStrideB * kHeight);                         \
   1561   MaskCpuFlags(disable_cpu_flags_);                                            \
   1562   FMT_PLANAR##To##FMT_B##Dither(src_y + OFF, kWidth,                           \
   1563                         src_u + OFF, kStrideUV,                                \
   1564                         src_v + OFF, kStrideUV,                                \
   1565                         dst_argb_c + OFF, kStrideB,                            \
   1566                         NULL, kWidth, NEG kHeight);                            \
   1567   MaskCpuFlags(benchmark_cpu_info_);                                           \
   1568   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
   1569     FMT_PLANAR##To##FMT_B##Dither(src_y + OFF, kWidth,                         \
   1570                           src_u + OFF, kStrideUV,                              \
   1571                           src_v + OFF, kStrideUV,                              \
   1572                           dst_argb_opt + OFF, kStrideB,                        \
   1573                           NULL, kWidth, NEG kHeight);                          \
   1574   }                                                                            \
   1575   int max_diff = 0;                                                            \
   1576   /* Convert to ARGB so 565 is expanded to bytes that can be compared. */      \
   1577   align_buffer_page_end(dst_argb32_c, kWidth * BPP_C  * kHeight);              \
   1578   align_buffer_page_end(dst_argb32_opt, kWidth * BPP_C  * kHeight);            \
   1579   memset(dst_argb32_c, 2, kWidth * BPP_C  * kHeight);                          \
   1580   memset(dst_argb32_opt, 102, kWidth * BPP_C  * kHeight);                      \
   1581   FMT_B##To##FMT_C(dst_argb_c + OFF, kStrideB,                                 \
   1582                    dst_argb32_c, kWidth * BPP_C ,                              \
   1583                    kWidth, kHeight);                                           \
   1584   FMT_B##To##FMT_C(dst_argb_opt + OFF, kStrideB,                               \
   1585                    dst_argb32_opt, kWidth * BPP_C ,                            \
   1586                    kWidth, kHeight);                                           \
   1587   for (int i = 0; i < kWidth * BPP_C * kHeight; ++i) {                         \
   1588     int abs_diff =                                                             \
   1589         abs(static_cast<int>(dst_argb32_c[i]) -                                \
   1590             static_cast<int>(dst_argb32_opt[i]));                              \
   1591     if (abs_diff > max_diff) {                                                 \
   1592       max_diff = abs_diff;                                                     \
   1593     }                                                                          \
   1594   }                                                                            \
   1595   EXPECT_LE(max_diff, DIFF);                                                   \
   1596   free_aligned_buffer_page_end(src_y);                                         \
   1597   free_aligned_buffer_page_end(src_u);                                         \
   1598   free_aligned_buffer_page_end(src_v);                                         \
   1599   free_aligned_buffer_page_end(dst_argb_c);                                    \
   1600   free_aligned_buffer_page_end(dst_argb_opt);                                  \
   1601   free_aligned_buffer_page_end(dst_argb32_c);                                  \
   1602   free_aligned_buffer_page_end(dst_argb32_opt);                                \
   1603 }
   1604 
   1605 #define TESTPLANARTOBD(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,  \
   1606                       YALIGN, DIFF, FMT_C, BPP_C)                              \
   1607     TESTPLANARTOBID(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,     \
   1608         YALIGN, benchmark_width_ - 4, DIFF, _Any, +, 0, FMT_C, BPP_C)          \
   1609     TESTPLANARTOBID(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,     \
   1610         YALIGN, benchmark_width_, DIFF, _Unaligned, +, 1, FMT_C, BPP_C)        \
   1611     TESTPLANARTOBID(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,     \
   1612         YALIGN, benchmark_width_, DIFF, _Invert, -, 0, FMT_C, BPP_C)           \
   1613     TESTPLANARTOBID(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, BPP_B, ALIGN,     \
   1614         YALIGN, benchmark_width_, DIFF, _Opt, +, 0, FMT_C, BPP_C)
   1615 
   1616 TESTPLANARTOBD(I420, 2, 2, RGB565, 2, 2, 1, 9, ARGB, 4)
   1617 
   1618 #define TESTPTOB(NAME, UYVYTOI420, UYVYTONV12)                                 \
   1619 TEST_F(LibYUVConvertTest, NAME) {                                              \
   1620   const int kWidth = benchmark_width_;                                         \
   1621   const int kHeight = benchmark_height_;                                       \
   1622                                                                                \
   1623   align_buffer_page_end(orig_uyvy,                                             \
   1624                   4 * SUBSAMPLE(kWidth, 2) * kHeight);                         \
   1625   align_buffer_page_end(orig_y, kWidth * kHeight);                             \
   1626   align_buffer_page_end(orig_u,                                                \
   1627                   SUBSAMPLE(kWidth, 2) *                                       \
   1628                   SUBSAMPLE(kHeight, 2));                                      \
   1629   align_buffer_page_end(orig_v,                                                \
   1630                   SUBSAMPLE(kWidth, 2) *                                       \
   1631                   SUBSAMPLE(kHeight, 2));                                      \
   1632                                                                                \
   1633   align_buffer_page_end(dst_y_orig, kWidth * kHeight);                         \
   1634   align_buffer_page_end(dst_uv_orig, 2 *                                       \
   1635                   SUBSAMPLE(kWidth, 2) *                                       \
   1636                   SUBSAMPLE(kHeight, 2));                                      \
   1637                                                                                \
   1638   align_buffer_page_end(dst_y, kWidth * kHeight);                              \
   1639   align_buffer_page_end(dst_uv, 2 *                                            \
   1640                   SUBSAMPLE(kWidth, 2) *                                       \
   1641                   SUBSAMPLE(kHeight, 2));                                      \
   1642                                                                                \
   1643   MemRandomize(orig_uyvy, 4 * SUBSAMPLE(kWidth, 2) * kHeight);                 \
   1644                                                                                \
   1645   /* Convert UYVY to NV12 in 2 steps for reference */                          \
   1646   libyuv::UYVYTOI420(orig_uyvy, 4 * SUBSAMPLE(kWidth, 2),                      \
   1647                      orig_y, kWidth,                                           \
   1648                      orig_u, SUBSAMPLE(kWidth, 2),                             \
   1649                      orig_v, SUBSAMPLE(kWidth, 2),                             \
   1650                      kWidth, kHeight);                                         \
   1651   libyuv::I420ToNV12(orig_y, kWidth,                                           \
   1652                      orig_u, SUBSAMPLE(kWidth, 2),                             \
   1653                      orig_v, SUBSAMPLE(kWidth, 2),                             \
   1654                      dst_y_orig, kWidth,                                       \
   1655                      dst_uv_orig, 2 * SUBSAMPLE(kWidth, 2),                    \
   1656                      kWidth, kHeight);                                         \
   1657                                                                                \
   1658   /* Convert to NV12 */                                                        \
   1659   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
   1660     libyuv::UYVYTONV12(orig_uyvy, 4 * SUBSAMPLE(kWidth, 2),                    \
   1661                        dst_y, kWidth,                                          \
   1662                        dst_uv, 2 * SUBSAMPLE(kWidth, 2),                       \
   1663                        kWidth, kHeight);                                       \
   1664   }                                                                            \
   1665                                                                                \
   1666   for (int i = 0; i < kWidth * kHeight; ++i) {                                 \
   1667     EXPECT_EQ(orig_y[i], dst_y[i]);                                            \
   1668   }                                                                            \
   1669   for (int i = 0; i < kWidth * kHeight; ++i) {                                 \
   1670     EXPECT_EQ(dst_y_orig[i], dst_y[i]);                                        \
   1671   }                                                                            \
   1672   for (int i = 0; i < 2 * SUBSAMPLE(kWidth, 2) * SUBSAMPLE(kHeight, 2); ++i) { \
   1673     EXPECT_EQ(dst_uv_orig[i], dst_uv[i]);                                      \
   1674   }                                                                            \
   1675                                                                                \
   1676   free_aligned_buffer_page_end(orig_uyvy);                                     \
   1677   free_aligned_buffer_page_end(orig_y);                                        \
   1678   free_aligned_buffer_page_end(orig_u);                                        \
   1679   free_aligned_buffer_page_end(orig_v);                                        \
   1680   free_aligned_buffer_page_end(dst_y_orig);                                    \
   1681   free_aligned_buffer_page_end(dst_uv_orig);                                   \
   1682   free_aligned_buffer_page_end(dst_y);                                         \
   1683   free_aligned_buffer_page_end(dst_uv);                                        \
   1684 }
   1685 
   1686 TESTPTOB(TestYUY2ToNV12, YUY2ToI420, YUY2ToNV12)
   1687 TESTPTOB(TestUYVYToNV12, UYVYToI420, UYVYToNV12)
   1688 
   1689 #define TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B,  \
   1690                        W1280, N, NEG, OFF, FMT_C, BPP_C)                       \
   1691 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##_##FMT_C##N) {                \
   1692   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
   1693   const int kHeight = benchmark_height_;                                       \
   1694   const int kStrideB = SUBSAMPLE(kWidth, SUB_B) * BPP_B;                       \
   1695   const int kStrideUV = SUBSAMPLE(kWidth, SUBSAMP_X);                          \
   1696   const int kSizeUV = kStrideUV * SUBSAMPLE(kHeight, SUBSAMP_Y);               \
   1697   align_buffer_page_end(src_y, kWidth * kHeight + OFF);                        \
   1698   align_buffer_page_end(src_u, kSizeUV + OFF);                                 \
   1699   align_buffer_page_end(src_v, kSizeUV + OFF);                                 \
   1700   align_buffer_page_end(dst_argb_b, kStrideB * kHeight + OFF);                 \
   1701   for (int i = 0; i < kWidth * kHeight; ++i) {                                 \
   1702     src_y[i + OFF] = (fastrand() & 0xff);                                      \
   1703   }                                                                            \
   1704   for (int i = 0; i < kSizeUV; ++i) {                                          \
   1705     src_u[i + OFF] = (fastrand() & 0xff);                                      \
   1706     src_v[i + OFF] = (fastrand() & 0xff);                                      \
   1707   }                                                                            \
   1708   memset(dst_argb_b + OFF, 1, kStrideB * kHeight);                             \
   1709   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
   1710     FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                 \
   1711                           src_u + OFF, kStrideUV,                              \
   1712                           src_v + OFF, kStrideUV,                              \
   1713                           dst_argb_b + OFF, kStrideB,                          \
   1714                           kWidth, NEG kHeight);                                \
   1715   }                                                                            \
   1716   /* Convert to a 3rd format in 1 step and 2 steps and compare  */             \
   1717   const int kStrideC = kWidth * BPP_C;                                         \
   1718   align_buffer_page_end(dst_argb_c, kStrideC * kHeight + OFF);                 \
   1719   align_buffer_page_end(dst_argb_bc, kStrideC * kHeight + OFF);                \
   1720   memset(dst_argb_c + OFF, 2, kStrideC * kHeight);                             \
   1721   memset(dst_argb_bc + OFF, 3, kStrideC * kHeight);                            \
   1722   FMT_PLANAR##To##FMT_C(src_y + OFF, kWidth,                                   \
   1723                         src_u + OFF, kStrideUV,                                \
   1724                         src_v + OFF, kStrideUV,                                \
   1725                         dst_argb_c + OFF, kStrideC,                            \
   1726                         kWidth, NEG kHeight);                                  \
   1727   /* Convert B to C */                                                         \
   1728   FMT_B##To##FMT_C(dst_argb_b + OFF, kStrideB,                                 \
   1729                    dst_argb_bc + OFF, kStrideC,                                \
   1730                    kWidth, kHeight);                                           \
   1731   for (int i = 0; i < kStrideC * kHeight; ++i) {                               \
   1732     EXPECT_EQ(dst_argb_c[i + OFF], dst_argb_bc[i + OFF]);                      \
   1733   }                                                                            \
   1734   free_aligned_buffer_page_end(src_y);                                         \
   1735   free_aligned_buffer_page_end(src_u);                                         \
   1736   free_aligned_buffer_page_end(src_v);                                         \
   1737   free_aligned_buffer_page_end(dst_argb_b);                                    \
   1738   free_aligned_buffer_page_end(dst_argb_c);                                    \
   1739   free_aligned_buffer_page_end(dst_argb_bc);                                   \
   1740 }
   1741 
   1742 #define TESTPLANARTOE(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B,   \
   1743                       FMT_C, BPP_C)                                            \
   1744     TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B,      \
   1745         benchmark_width_ - 4, _Any, +, 0, FMT_C, BPP_C)                        \
   1746     TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B,      \
   1747         benchmark_width_, _Unaligned, +, 1, FMT_C, BPP_C)                      \
   1748     TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B,      \
   1749         benchmark_width_, _Invert, -, 0, FMT_C, BPP_C)                         \
   1750     TESTPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B,      \
   1751         benchmark_width_, _Opt, +, 0, FMT_C, BPP_C)
   1752 
   1753 TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, ABGR, 4)
   1754 TESTPLANARTOE(J420, 2, 2, ARGB, 1, 4, ARGB, 4)
   1755 TESTPLANARTOE(J420, 2, 2, ABGR, 1, 4, ARGB, 4)
   1756 TESTPLANARTOE(H420, 2, 2, ARGB, 1, 4, ARGB, 4)
   1757 TESTPLANARTOE(H420, 2, 2, ABGR, 1, 4, ARGB, 4)
   1758 TESTPLANARTOE(I420, 2, 2, BGRA, 1, 4, ARGB, 4)
   1759 TESTPLANARTOE(I420, 2, 2, ABGR, 1, 4, ARGB, 4)
   1760 TESTPLANARTOE(I420, 2, 2, RGBA, 1, 4, ARGB, 4)
   1761 TESTPLANARTOE(I420, 2, 2, RGB24, 1, 3, ARGB, 4)
   1762 TESTPLANARTOE(I420, 2, 2, RAW, 1, 3, RGB24, 3)
   1763 TESTPLANARTOE(I420, 2, 2, RGB24, 1, 3, RAW, 3)
   1764 TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, RAW, 3)
   1765 TESTPLANARTOE(I420, 2, 2, RAW, 1, 3, ARGB, 4)
   1766 TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, RGB565, 2)
   1767 TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, ARGB1555, 2)
   1768 TESTPLANARTOE(I420, 2, 2, ARGB, 1, 4, ARGB4444, 2)
   1769 TESTPLANARTOE(I422, 2, 1, ARGB, 1, 4, ARGB, 4)
   1770 TESTPLANARTOE(J422, 2, 1, ARGB, 1, 4, ARGB, 4)
   1771 TESTPLANARTOE(J422, 2, 1, ABGR, 1, 4, ARGB, 4)
   1772 TESTPLANARTOE(H422, 2, 1, ARGB, 1, 4, ARGB, 4)
   1773 TESTPLANARTOE(H422, 2, 1, ABGR, 1, 4, ARGB, 4)
   1774 TESTPLANARTOE(I422, 2, 1, BGRA, 1, 4, ARGB, 4)
   1775 TESTPLANARTOE(I422, 2, 1, ABGR, 1, 4, ARGB, 4)
   1776 TESTPLANARTOE(I422, 2, 1, RGBA, 1, 4, ARGB, 4)
   1777 TESTPLANARTOE(I411, 4, 1, ARGB, 1, 4, ARGB, 4)
   1778 TESTPLANARTOE(I444, 1, 1, ARGB, 1, 4, ARGB, 4)
   1779 TESTPLANARTOE(J444, 1, 1, ARGB, 1, 4, ARGB, 4)
   1780 TESTPLANARTOE(I444, 1, 1, ABGR, 1, 4, ARGB, 4)
   1781 TESTPLANARTOE(I420, 2, 2, YUY2, 2, 4, ARGB, 4)
   1782 TESTPLANARTOE(I420, 2, 2, UYVY, 2, 4, ARGB, 4)
   1783 TESTPLANARTOE(I422, 2, 1, YUY2, 2, 4, ARGB, 4)
   1784 TESTPLANARTOE(I422, 2, 1, UYVY, 2, 4, ARGB, 4)
   1785 
   1786 #define TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B, \
   1787                        W1280, N, NEG, OFF, FMT_C, BPP_C, ATTEN)                \
   1788 TEST_F(LibYUVConvertTest, FMT_PLANAR##To##FMT_B##_##FMT_C##N) {                \
   1789   const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \
   1790   const int kHeight = benchmark_height_;                                       \
   1791   const int kStrideB = SUBSAMPLE(kWidth, SUB_B) * BPP_B;                       \
   1792   const int kSizeUV =                                                          \
   1793     SUBSAMPLE(kWidth, SUBSAMP_X) * SUBSAMPLE(kHeight, SUBSAMP_Y);              \
   1794   align_buffer_page_end(src_y, kWidth * kHeight + OFF);                        \
   1795   align_buffer_page_end(src_u, kSizeUV + OFF);                                 \
   1796   align_buffer_page_end(src_v, kSizeUV + OFF);                                 \
   1797   align_buffer_page_end(src_a, kWidth * kHeight + OFF);                        \
   1798   align_buffer_page_end(dst_argb_b, kStrideB * kHeight + OFF);                 \
   1799   for (int i = 0; i < kWidth * kHeight; ++i) {                                 \
   1800     src_y[i + OFF] = (fastrand() & 0xff);                                      \
   1801     src_a[i + OFF] = (fastrand() & 0xff);                                      \
   1802   }                                                                            \
   1803   for (int i = 0; i < kSizeUV; ++i) {                                          \
   1804     src_u[i + OFF] = (fastrand() & 0xff);                                      \
   1805     src_v[i + OFF] = (fastrand() & 0xff);                                      \
   1806   }                                                                            \
   1807   memset(dst_argb_b + OFF, 1, kStrideB * kHeight);                             \
   1808   for (int i = 0; i < benchmark_iterations_; ++i) {                            \
   1809     FMT_PLANAR##To##FMT_B(src_y + OFF, kWidth,                                 \
   1810                           src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X),           \
   1811                           src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X),           \
   1812                           src_a + OFF, kWidth,                                 \
   1813                           dst_argb_b + OFF, kStrideB,                          \
   1814                           kWidth, NEG kHeight, ATTEN);                         \
   1815   }                                                                            \
   1816   int max_diff = 0;                                                            \
   1817   /* Convert to a 3rd format in 1 step and 2 steps and compare  */             \
   1818   const int kStrideC = kWidth * BPP_C;                                         \
   1819   align_buffer_page_end(dst_argb_c, kStrideC * kHeight + OFF);                 \
   1820   align_buffer_page_end(dst_argb_bc, kStrideC * kHeight + OFF);                \
   1821   memset(dst_argb_c + OFF, 2, kStrideC * kHeight);                             \
   1822   memset(dst_argb_bc + OFF, 3, kStrideC * kHeight);                            \
   1823   FMT_PLANAR##To##FMT_C(src_y + OFF, kWidth,                                   \
   1824                         src_u + OFF, SUBSAMPLE(kWidth, SUBSAMP_X),             \
   1825                         src_v + OFF, SUBSAMPLE(kWidth, SUBSAMP_X),             \
   1826                         src_a + OFF, kWidth,                                   \
   1827                         dst_argb_c + OFF, kStrideC,                            \
   1828                         kWidth, NEG kHeight, ATTEN);                           \
   1829   /* Convert B to C */                                                         \
   1830   FMT_B##To##FMT_C(dst_argb_b + OFF, kStrideB,                                 \
   1831                    dst_argb_bc + OFF, kStrideC,                                \
   1832                    kWidth, kHeight);                                           \
   1833   for (int i = 0; i < kStrideC * kHeight; ++i) {                               \
   1834     EXPECT_EQ(dst_argb_c[i + OFF], dst_argb_bc[i + OFF]);                      \
   1835   }                                                                            \
   1836   free_aligned_buffer_page_end(src_y);                                         \
   1837   free_aligned_buffer_page_end(src_u);                                         \
   1838   free_aligned_buffer_page_end(src_v);                                         \
   1839   free_aligned_buffer_page_end(src_a);                                         \
   1840   free_aligned_buffer_page_end(dst_argb_b);                                    \
   1841   free_aligned_buffer_page_end(dst_argb_c);                                    \
   1842   free_aligned_buffer_page_end(dst_argb_bc);                                   \
   1843 }
   1844 
   1845 #define TESTQPLANARTOE(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B,  \
   1846                       FMT_C, BPP_C)                                            \
   1847     TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B,     \
   1848         benchmark_width_ - 4, _Any, +, 0, FMT_C, BPP_C, 0)                     \
   1849     TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B,     \
   1850         benchmark_width_, _Unaligned, +, 1, FMT_C, BPP_C, 0)                   \
   1851     TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B,     \
   1852         benchmark_width_, _Invert, -, 0, FMT_C, BPP_C, 0)                      \
   1853     TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B,     \
   1854         benchmark_width_, _Opt, +, 0, FMT_C, BPP_C, 0)                         \
   1855       TESTQPLANARTOEI(FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, FMT_B, SUB_B, BPP_B,   \
   1856           benchmark_width_, _Premult, +, 0, FMT_C, BPP_C, 1)
   1857 
   1858 TESTQPLANARTOE(I420Alpha, 2, 2, ARGB, 1, 4, ABGR, 4)
   1859 TESTQPLANARTOE(I420Alpha, 2, 2, ABGR, 1, 4, ARGB, 4)
   1860 
   1861 }  // namespace libyuv
   1862