| Index: unit_test/convert_test.cc | 
| diff --git a/unit_test/convert_test.cc b/unit_test/convert_test.cc | 
| index 56a2bfd82d5752c6524a580b5d2104f069e14295..7227dcc353c81c37796f5e645a3cf40fcb3e1e84 100644 | 
| --- a/unit_test/convert_test.cc | 
| +++ b/unit_test/convert_test.cc | 
| @@ -174,6 +174,148 @@ TESTPLANARTOP(I420, 2, 2, I420Mirror, 2, 2) | 
| TESTPLANARTOP(I422, 2, 1, I422, 2, 1) | 
| TESTPLANARTOP(I444, 1, 1, I444, 1, 1) | 
|  | 
| + | 
| + | 
| +// Test Android 420 to I420 | 
| + | 
| +#define TESTAPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,          \ | 
| +                        FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF)  \ | 
| +TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) {                 \ | 
| +  const int kWidth = ((W1280) > 0) ? (W1280) : 1;                              \ | 
| +  const int kHeight = benchmark_height_;                                       \ | 
| +  align_buffer_page_end(src_y, kWidth * kHeight + OFF);                        \ | 
| +  align_buffer_page_end(src_u,                                                 \ | 
| +                        SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                     \ | 
| +                        SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);              \ | 
| +  align_buffer_page_end(src_v,                                                 \ | 
| +                        SUBSAMPLE(kWidth, SRC_SUBSAMP_X) *                     \ | 
| +                        SUBSAMPLE(kHeight, SRC_SUBSAMP_Y) + OFF);              \ | 
| +  align_buffer_page_end(dst_y_c, kWidth * kHeight);                            \ | 
| +  align_buffer_page_end(dst_u_c,                                               \ | 
| +                        SUBSAMPLE(kWidth, SUBSAMP_X) *                         \ | 
| +                        SUBSAMPLE(kHeight, SUBSAMP_Y));                        \ | 
| +  align_buffer_page_end(dst_v_c,                                               \ | 
| +                        SUBSAMPLE(kWidth, SUBSAMP_X) *                         \ | 
| +                        SUBSAMPLE(kHeight, SUBSAMP_Y));                        \ | 
| +  align_buffer_page_end(dst_y_opt, kWidth * kHeight);                          \ | 
| +  align_buffer_page_end(dst_u_opt,                                             \ | 
| +                        SUBSAMPLE(kWidth, SUBSAMP_X) *                         \ | 
| +                        SUBSAMPLE(kHeight, SUBSAMP_Y));                        \ | 
| +  align_buffer_page_end(dst_v_opt,                                             \ | 
| +                        SUBSAMPLE(kWidth, SUBSAMP_X) *                         \ | 
| +                        SUBSAMPLE(kHeight, SUBSAMP_Y));                        \ | 
| +  for (int i = 0; i < kHeight; ++i)                                            \ | 
| +    for (int j = 0; j < kWidth; ++j)                                           \ | 
| +      src_y[i * kWidth + j + OFF] = (fastrand() & 0xff);                       \ | 
| +  for (int i = 0; i < SUBSAMPLE(kHeight, SRC_SUBSAMP_Y); ++i) {                \ | 
| +    for (int j = 0; j < SUBSAMPLE(kWidth, SRC_SUBSAMP_X); ++j) {               \ | 
| +      src_u[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \ | 
| +          (fastrand() & 0xff);                                                 \ | 
| +      src_v[(i * SUBSAMPLE(kWidth, SRC_SUBSAMP_X)) + j + OFF] =                \ | 
| +          (fastrand() & 0xff);                                                 \ | 
| +    }                                                                          \ | 
| +  }                                                                            \ | 
| +  memset(dst_y_c, 1, kWidth * kHeight);                                        \ | 
| +  memset(dst_u_c, 2, SUBSAMPLE(kWidth, SUBSAMP_X) *                            \ | 
| +                     SUBSAMPLE(kHeight, SUBSAMP_Y));                           \ | 
| +  memset(dst_v_c, 3, SUBSAMPLE(kWidth, SUBSAMP_X) *                            \ | 
| +                     SUBSAMPLE(kHeight, SUBSAMP_Y));                           \ | 
| +  memset(dst_y_opt, 101, kWidth * kHeight);                                    \ | 
| +  memset(dst_u_opt, 102, SUBSAMPLE(kWidth, SUBSAMP_X) *                        \ | 
| +                         SUBSAMPLE(kHeight, SUBSAMP_Y));                       \ | 
| +  memset(dst_v_opt, 103, SUBSAMPLE(kWidth, SUBSAMP_X) *                        \ | 
| +                         SUBSAMPLE(kHeight, SUBSAMP_Y));                       \ | 
| +  MaskCpuFlags(disable_cpu_flags_);                                            \ | 
| +  SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                          \ | 
| +                                 src_u + OFF,                                  \ | 
| +                                 SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \ | 
| +                                 src_v + OFF,                                  \ | 
| +                                 SUBSAMPLE(kWidth, SRC_SUBSAMP_X),             \ | 
| +                                 1,                                            \ | 
| +                                 dst_y_c, kWidth,                              \ | 
| +                                 dst_u_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \ | 
| +                                 dst_v_c, SUBSAMPLE(kWidth, SUBSAMP_X),        \ | 
| +                                 kWidth, NEG kHeight);                         \ | 
| +  MaskCpuFlags(benchmark_cpu_info_);                                           \ | 
| +  for (int i = 0; i < benchmark_iterations_; ++i) {                            \ | 
| +    SRC_FMT_PLANAR##To##FMT_PLANAR(src_y + OFF, kWidth,                        \ | 
| +                                   src_u + OFF,                                \ | 
| +                                       SUBSAMPLE(kWidth, SRC_SUBSAMP_X),       \ | 
| +                                   src_v + OFF,                                \ | 
| +                                       SUBSAMPLE(kWidth, SRC_SUBSAMP_X),       \ | 
| +                                   1,                                          \ | 
| +                                   dst_y_opt, kWidth,                          \ | 
| +                                   dst_u_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \ | 
| +                                   dst_v_opt, SUBSAMPLE(kWidth, SUBSAMP_X),    \ | 
| +                                   kWidth, NEG kHeight);                       \ | 
| +  }                                                                            \ | 
| +  int max_diff = 0;                                                            \ | 
| +  for (int i = 0; i < kHeight; ++i) {                                          \ | 
| +    for (int j = 0; j < kWidth; ++j) {                                         \ | 
| +      int abs_diff =                                                           \ | 
| +          abs(static_cast<int>(dst_y_c[i * kWidth + j]) -                      \ | 
| +              static_cast<int>(dst_y_opt[i * kWidth + j]));                    \ | 
| +      if (abs_diff > max_diff) {                                               \ | 
| +        max_diff = abs_diff;                                                   \ | 
| +      }                                                                        \ | 
| +    }                                                                          \ | 
| +  }                                                                            \ | 
| +  EXPECT_EQ(0, max_diff);                                                      \ | 
| +  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \ | 
| +    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \ | 
| +      int abs_diff =                                                           \ | 
| +          abs(static_cast<int>(dst_u_c[i *                                     \ | 
| +                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \ | 
| +              static_cast<int>(dst_u_opt[i *                                   \ | 
| +                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \ | 
| +      if (abs_diff > max_diff) {                                               \ | 
| +        max_diff = abs_diff;                                                   \ | 
| +      }                                                                        \ | 
| +    }                                                                          \ | 
| +  }                                                                            \ | 
| +  EXPECT_LE(max_diff, 3);                                                      \ | 
| +  for (int i = 0; i < SUBSAMPLE(kHeight, SUBSAMP_Y); ++i) {                    \ | 
| +    for (int j = 0; j < SUBSAMPLE(kWidth, SUBSAMP_X); ++j) {                   \ | 
| +      int abs_diff =                                                           \ | 
| +          abs(static_cast<int>(dst_v_c[i *                                     \ | 
| +                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]) -            \ | 
| +              static_cast<int>(dst_v_opt[i *                                   \ | 
| +                               SUBSAMPLE(kWidth, SUBSAMP_X) + j]));            \ | 
| +      if (abs_diff > max_diff) {                                               \ | 
| +        max_diff = abs_diff;                                                   \ | 
| +      }                                                                        \ | 
| +    }                                                                          \ | 
| +  }                                                                            \ | 
| +  EXPECT_LE(max_diff, 3);                                                      \ | 
| +  free_aligned_buffer_page_end(dst_y_c);                                       \ | 
| +  free_aligned_buffer_page_end(dst_u_c);                                       \ | 
| +  free_aligned_buffer_page_end(dst_v_c);                                       \ | 
| +  free_aligned_buffer_page_end(dst_y_opt);                                     \ | 
| +  free_aligned_buffer_page_end(dst_u_opt);                                     \ | 
| +  free_aligned_buffer_page_end(dst_v_opt);                                     \ | 
| +  free_aligned_buffer_page_end(src_y);                                         \ | 
| +  free_aligned_buffer_page_end(src_u);                                         \ | 
| +  free_aligned_buffer_page_end(src_v);                                         \ | 
| +} | 
| + | 
| +#define TESTAPLANARTOP(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,           \ | 
| +                       FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y)                       \ | 
| +    TESTAPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \ | 
| +                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \ | 
| +                    benchmark_width_ - 4, _Any, +, 0)                          \ | 
| +    TESTAPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \ | 
| +                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \ | 
| +                    benchmark_width_, _Unaligned, +, 1)                        \ | 
| +    TESTAPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \ | 
| +                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \ | 
| +                    benchmark_width_, _Invert, -, 0)                           \ | 
| +    TESTAPLANARTOPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,              \ | 
| +                    FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y,                          \ | 
| +                    benchmark_width_, _Opt, +, 0) | 
| + | 
| +TESTAPLANARTOP(Android420, 2, 2, I420, 2, 2) | 
| + | 
| + | 
| #define TESTPLANARTOBPI(SRC_FMT_PLANAR, SRC_SUBSAMP_X, SRC_SUBSAMP_Y,          \ | 
| FMT_PLANAR, SUBSAMP_X, SUBSAMP_Y, W1280, N, NEG, OFF)   \ | 
| TEST_F(LibYUVConvertTest, SRC_FMT_PLANAR##To##FMT_PLANAR##N) {                 \ | 
|  |