Home | History | Annotate | Download | only in test
      1 /*
      2  *  Copyright (c) 2013 The WebM 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 <string.h>
     13 
     14 #include "third_party/googletest/src/include/gtest/gtest.h"
     15 
     16 #include "./vp8_rtcd.h"
     17 #include "./vpx_config.h"
     18 #include "test/acm_random.h"
     19 #include "test/clear_system_state.h"
     20 #include "test/register_state_check.h"
     21 #include "test/util.h"
     22 #include "vpx/vpx_integer.h"
     23 #include "vpx_mem/vpx_mem.h"
     24 
     25 namespace {
     26 
     27 using libvpx_test::ACMRandom;
     28 using std::tr1::make_tuple;
     29 
     30 typedef void (*PredictFunc)(uint8_t *src_ptr, int src_pixels_per_line,
     31                             int xoffset, int yoffset, uint8_t *dst_ptr,
     32                             int dst_pitch);
     33 
     34 typedef std::tr1::tuple<int, int, PredictFunc> PredictParam;
     35 
     36 class PredictTestBase : public ::testing::TestWithParam<PredictParam> {
     37  public:
     38   PredictTestBase()
     39       : width_(GET_PARAM(0)), height_(GET_PARAM(1)), predict_(GET_PARAM(2)),
     40         src_(NULL), padded_dst_(NULL), dst_(NULL), dst_c_(NULL) {}
     41 
     42   virtual void SetUp() {
     43     src_ = new uint8_t[kSrcSize];
     44     ASSERT_TRUE(src_ != NULL);
     45 
     46     // padded_dst_ provides a buffer of kBorderSize around the destination
     47     // memory to facilitate detecting out of bounds writes.
     48     dst_stride_ = kBorderSize + width_ + kBorderSize;
     49     padded_dst_size_ = dst_stride_ * (kBorderSize + height_ + kBorderSize);
     50     padded_dst_ =
     51         reinterpret_cast<uint8_t *>(vpx_memalign(16, padded_dst_size_));
     52     ASSERT_TRUE(padded_dst_ != NULL);
     53     dst_ = padded_dst_ + (kBorderSize * dst_stride_) + kBorderSize;
     54 
     55     dst_c_ = new uint8_t[16 * 16];
     56     ASSERT_TRUE(dst_c_ != NULL);
     57 
     58     memset(src_, 0, kSrcSize);
     59     memset(padded_dst_, 128, padded_dst_size_);
     60     memset(dst_c_, 0, 16 * 16);
     61   }
     62 
     63   virtual void TearDown() {
     64     delete[] src_;
     65     src_ = NULL;
     66     vpx_free(padded_dst_);
     67     padded_dst_ = NULL;
     68     dst_ = NULL;
     69     delete[] dst_c_;
     70     dst_c_ = NULL;
     71     libvpx_test::ClearSystemState();
     72   }
     73 
     74  protected:
     75   // Make reference arrays big enough for 16x16 functions. Six-tap filters need
     76   // 5 extra pixels outside of the macroblock.
     77   static const int kSrcStride = 21;
     78   static const int kSrcSize = kSrcStride * kSrcStride;
     79   static const int kBorderSize = 16;
     80 
     81   int width_;
     82   int height_;
     83   PredictFunc predict_;
     84   uint8_t *src_;
     85   uint8_t *padded_dst_;
     86   uint8_t *dst_;
     87   int padded_dst_size_;
     88   uint8_t *dst_c_;
     89   int dst_stride_;
     90 
     91   bool CompareBuffers(const uint8_t *a, int a_stride, const uint8_t *b,
     92                       int b_stride) const {
     93     for (int height = 0; height < height_; ++height) {
     94       EXPECT_EQ(0, memcmp(a + height * a_stride, b + height * b_stride,
     95                           sizeof(*a) * width_))
     96           << "Row " << height << " does not match.";
     97     }
     98 
     99     return !HasFailure();
    100   }
    101 
    102   // Given a block of memory 'a' with size 'a_size', determine if all regions
    103   // excepting block 'b' described by 'b_stride', 'b_height', and 'b_width'
    104   // match pixel value 'c'.
    105   bool CheckBorder(const uint8_t *a, int a_size, const uint8_t *b, int b_width,
    106                    int b_height, int b_stride, uint8_t c) const {
    107     const uint8_t *a_end = a + a_size;
    108     const int b_size = (b_stride * b_height) + b_width;
    109     const uint8_t *b_end = b + b_size;
    110     const int left_border = (b_stride - b_width) / 2;
    111     const int right_border = left_border + ((b_stride - b_width) % 2);
    112 
    113     EXPECT_GE(b - left_border, a) << "'b' does not start within 'a'";
    114     EXPECT_LE(b_end + right_border, a_end) << "'b' does not end within 'a'";
    115 
    116     // Top border.
    117     for (int pixel = 0; pixel < b - a - left_border; ++pixel) {
    118       EXPECT_EQ(c, a[pixel]) << "Mismatch at " << pixel << " in top border.";
    119     }
    120 
    121     // Left border.
    122     for (int height = 0; height < b_height; ++height) {
    123       for (int width = left_border; width > 0; --width) {
    124         EXPECT_EQ(c, b[height * b_stride - width])
    125             << "Mismatch at row " << height << " column " << left_border - width
    126             << " in left border.";
    127       }
    128     }
    129 
    130     // Right border.
    131     for (int height = 0; height < b_height; ++height) {
    132       for (int width = b_width; width < b_width + right_border; ++width) {
    133         EXPECT_EQ(c, b[height * b_stride + width])
    134             << "Mismatch at row " << height << " column " << width - b_width
    135             << " in right border.";
    136       }
    137     }
    138 
    139     // Bottom border.
    140     for (int pixel = static_cast<int>(b - a + b_size); pixel < a_size;
    141          ++pixel) {
    142       EXPECT_EQ(c, a[pixel]) << "Mismatch at " << pixel << " in bottom border.";
    143     }
    144 
    145     return !HasFailure();
    146   }
    147 
    148   void TestWithRandomData(PredictFunc reference) {
    149     ACMRandom rnd(ACMRandom::DeterministicSeed());
    150 
    151     // Run tests for almost all possible offsets.
    152     for (int xoffset = 0; xoffset < 8; ++xoffset) {
    153       for (int yoffset = 0; yoffset < 8; ++yoffset) {
    154         if (xoffset == 0 && yoffset == 0) {
    155           // This represents a copy which is not required to be handled by this
    156           // module.
    157           continue;
    158         }
    159 
    160         for (int i = 0; i < kSrcSize; ++i) {
    161           src_[i] = rnd.Rand8();
    162         }
    163         reference(&src_[kSrcStride * 2 + 2], kSrcStride, xoffset, yoffset,
    164                   dst_c_, 16);
    165 
    166         ASM_REGISTER_STATE_CHECK(predict_(&src_[kSrcStride * 2 + 2], kSrcStride,
    167                                           xoffset, yoffset, dst_, dst_stride_));
    168 
    169         ASSERT_TRUE(CompareBuffers(dst_c_, 16, dst_, dst_stride_));
    170         ASSERT_TRUE(CheckBorder(padded_dst_, padded_dst_size_, dst_, width_,
    171                                 height_, dst_stride_, 128));
    172       }
    173     }
    174   }
    175 
    176   void TestWithUnalignedDst(PredictFunc reference) {
    177     ACMRandom rnd(ACMRandom::DeterministicSeed());
    178 
    179     // Only the 4x4 need to be able to handle unaligned writes.
    180     if (width_ == 4 && height_ == 4) {
    181       for (int xoffset = 0; xoffset < 8; ++xoffset) {
    182         for (int yoffset = 0; yoffset < 8; ++yoffset) {
    183           if (xoffset == 0 && yoffset == 0) {
    184             continue;
    185           }
    186           for (int i = 0; i < kSrcSize; ++i) {
    187             src_[i] = rnd.Rand8();
    188           }
    189           reference(&src_[kSrcStride * 2 + 2], kSrcStride, xoffset, yoffset,
    190                     dst_c_, 16);
    191 
    192           for (int i = 1; i < 4; ++i) {
    193             memset(padded_dst_, 128, padded_dst_size_);
    194 
    195             ASM_REGISTER_STATE_CHECK(predict_(&src_[kSrcStride * 2 + 2],
    196                                               kSrcStride, xoffset, yoffset,
    197                                               dst_ + i, dst_stride_ + i));
    198 
    199             ASSERT_TRUE(CompareBuffers(dst_c_, 16, dst_ + i, dst_stride_ + i));
    200             ASSERT_TRUE(CheckBorder(padded_dst_, padded_dst_size_, dst_ + i,
    201                                     width_, height_, dst_stride_ + i, 128));
    202           }
    203         }
    204       }
    205     }
    206   }
    207 };
    208 
    209 class SixtapPredictTest : public PredictTestBase {};
    210 
    211 TEST_P(SixtapPredictTest, TestWithRandomData) {
    212   TestWithRandomData(vp8_sixtap_predict16x16_c);
    213 }
    214 TEST_P(SixtapPredictTest, TestWithUnalignedDst) {
    215   TestWithUnalignedDst(vp8_sixtap_predict16x16_c);
    216 }
    217 
    218 TEST_P(SixtapPredictTest, TestWithPresetData) {
    219   // Test input
    220   static const uint8_t kTestData[kSrcSize] = {
    221     184, 4,   191, 82,  92,  41,  0,   1,   226, 236, 172, 20,  182, 42,  226,
    222     177, 79,  94,  77,  179, 203, 206, 198, 22,  192, 19,  75,  17,  192, 44,
    223     233, 120, 48,  168, 203, 141, 210, 203, 143, 180, 184, 59,  201, 110, 102,
    224     171, 32,  182, 10,  109, 105, 213, 60,  47,  236, 253, 67,  55,  14,  3,
    225     99,  247, 124, 148, 159, 71,  34,  114, 19,  177, 38,  203, 237, 239, 58,
    226     83,  155, 91,  10,  166, 201, 115, 124, 5,   163, 104, 2,   231, 160, 16,
    227     234, 4,   8,   103, 153, 167, 174, 187, 26,  193, 109, 64,  141, 90,  48,
    228     200, 174, 204, 36,  184, 114, 237, 43,  238, 242, 207, 86,  245, 182, 247,
    229     6,   161, 251, 14,  8,   148, 182, 182, 79,  208, 120, 188, 17,  6,   23,
    230     65,  206, 197, 13,  242, 126, 128, 224, 170, 110, 211, 121, 197, 200, 47,
    231     188, 207, 208, 184, 221, 216, 76,  148, 143, 156, 100, 8,   89,  117, 14,
    232     112, 183, 221, 54,  197, 208, 180, 69,  176, 94,  180, 131, 215, 121, 76,
    233     7,   54,  28,  216, 238, 249, 176, 58,  142, 64,  215, 242, 72,  49,  104,
    234     87,  161, 32,  52,  216, 230, 4,   141, 44,  181, 235, 224, 57,  195, 89,
    235     134, 203, 144, 162, 163, 126, 156, 84,  185, 42,  148, 145, 29,  221, 194,
    236     134, 52,  100, 166, 105, 60,  140, 110, 201, 184, 35,  181, 153, 93,  121,
    237     243, 227, 68,  131, 134, 232, 2,   35,  60,  187, 77,  209, 76,  106, 174,
    238     15,  241, 227, 115, 151, 77,  175, 36,  187, 121, 221, 223, 47,  118, 61,
    239     168, 105, 32,  237, 236, 167, 213, 238, 202, 17,  170, 24,  226, 247, 131,
    240     145, 6,   116, 117, 121, 11,  194, 41,  48,  126, 162, 13,  93,  209, 131,
    241     154, 122, 237, 187, 103, 217, 99,  60,  200, 45,  78,  115, 69,  49,  106,
    242     200, 194, 112, 60,  56,  234, 72,  251, 19,  120, 121, 182, 134, 215, 135,
    243     10,  114, 2,   247, 46,  105, 209, 145, 165, 153, 191, 243, 12,  5,   36,
    244     119, 206, 231, 231, 11,  32,  209, 83,  27,  229, 204, 149, 155, 83,  109,
    245     35,  93,  223, 37,  84,  14,  142, 37,  160, 52,  191, 96,  40,  204, 101,
    246     77,  67,  52,  53,  43,  63,  85,  253, 147, 113, 226, 96,  6,   125, 179,
    247     115, 161, 17,  83,  198, 101, 98,  85,  139, 3,   137, 75,  99,  178, 23,
    248     201, 255, 91,  253, 52,  134, 60,  138, 131, 208, 251, 101, 48,  2,   227,
    249     228, 118, 132, 245, 202, 75,  91,  44,  160, 231, 47,  41,  50,  147, 220,
    250     74,  92,  219, 165, 89,  16
    251   };
    252 
    253   // Expected results for xoffset = 2 and yoffset = 2.
    254   static const int kExpectedDstStride = 16;
    255   static const uint8_t kExpectedDst[256] = {
    256     117, 102, 74,  135, 42,  98,  175, 206, 70,  73,  222, 197, 50,  24,  39,
    257     49,  38,  105, 90,  47,  169, 40,  171, 215, 200, 73,  109, 141, 53,  85,
    258     177, 164, 79,  208, 124, 89,  212, 18,  81,  145, 151, 164, 217, 153, 91,
    259     154, 102, 102, 159, 75,  164, 152, 136, 51,  213, 219, 186, 116, 193, 224,
    260     186, 36,  231, 208, 84,  211, 155, 167, 35,  59,  42,  76,  216, 149, 73,
    261     201, 78,  149, 184, 100, 96,  196, 189, 198, 188, 235, 195, 117, 129, 120,
    262     129, 49,  25,  133, 113, 69,  221, 114, 70,  143, 99,  157, 108, 189, 140,
    263     78,  6,   55,  65,  240, 255, 245, 184, 72,  90,  100, 116, 131, 39,  60,
    264     234, 167, 33,  160, 88,  185, 200, 157, 159, 176, 127, 151, 138, 102, 168,
    265     106, 170, 86,  82,  219, 189, 76,  33,  115, 197, 106, 96,  198, 136, 97,
    266     141, 237, 151, 98,  137, 191, 185, 2,   57,  95,  142, 91,  255, 185, 97,
    267     137, 76,  162, 94,  173, 131, 193, 161, 81,  106, 72,  135, 222, 234, 137,
    268     66,  137, 106, 243, 210, 147, 95,  15,  137, 110, 85,  66,  16,  96,  167,
    269     147, 150, 173, 203, 140, 118, 196, 84,  147, 160, 19,  95,  101, 123, 74,
    270     132, 202, 82,  166, 12,  131, 166, 189, 170, 159, 85,  79,  66,  57,  152,
    271     132, 203, 194, 0,   1,   56,  146, 180, 224, 156, 28,  83,  181, 79,  76,
    272     80,  46,  160, 175, 59,  106, 43,  87,  75,  136, 85,  189, 46,  71,  200,
    273     90
    274   };
    275 
    276   ASM_REGISTER_STATE_CHECK(
    277       predict_(const_cast<uint8_t *>(kTestData) + kSrcStride * 2 + 2,
    278                kSrcStride, 2, 2, dst_, dst_stride_));
    279 
    280   ASSERT_TRUE(
    281       CompareBuffers(kExpectedDst, kExpectedDstStride, dst_, dst_stride_));
    282 }
    283 
    284 INSTANTIATE_TEST_CASE_P(
    285     C, SixtapPredictTest,
    286     ::testing::Values(make_tuple(16, 16, &vp8_sixtap_predict16x16_c),
    287                       make_tuple(8, 8, &vp8_sixtap_predict8x8_c),
    288                       make_tuple(8, 4, &vp8_sixtap_predict8x4_c),
    289                       make_tuple(4, 4, &vp8_sixtap_predict4x4_c)));
    290 #if HAVE_NEON
    291 INSTANTIATE_TEST_CASE_P(
    292     NEON, SixtapPredictTest,
    293     ::testing::Values(make_tuple(16, 16, &vp8_sixtap_predict16x16_neon),
    294                       make_tuple(8, 8, &vp8_sixtap_predict8x8_neon),
    295                       make_tuple(8, 4, &vp8_sixtap_predict8x4_neon),
    296                       make_tuple(4, 4, &vp8_sixtap_predict4x4_neon)));
    297 #endif
    298 #if HAVE_MMX
    299 INSTANTIATE_TEST_CASE_P(
    300     MMX, SixtapPredictTest,
    301     ::testing::Values(make_tuple(4, 4, &vp8_sixtap_predict4x4_mmx)));
    302 #endif
    303 #if HAVE_SSE2
    304 INSTANTIATE_TEST_CASE_P(
    305     SSE2, SixtapPredictTest,
    306     ::testing::Values(make_tuple(16, 16, &vp8_sixtap_predict16x16_sse2),
    307                       make_tuple(8, 8, &vp8_sixtap_predict8x8_sse2),
    308                       make_tuple(8, 4, &vp8_sixtap_predict8x4_sse2)));
    309 #endif
    310 #if HAVE_SSSE3
    311 INSTANTIATE_TEST_CASE_P(
    312     SSSE3, SixtapPredictTest,
    313     ::testing::Values(make_tuple(16, 16, &vp8_sixtap_predict16x16_ssse3),
    314                       make_tuple(8, 8, &vp8_sixtap_predict8x8_ssse3),
    315                       make_tuple(8, 4, &vp8_sixtap_predict8x4_ssse3),
    316                       make_tuple(4, 4, &vp8_sixtap_predict4x4_ssse3)));
    317 #endif
    318 #if HAVE_MSA
    319 INSTANTIATE_TEST_CASE_P(
    320     MSA, SixtapPredictTest,
    321     ::testing::Values(make_tuple(16, 16, &vp8_sixtap_predict16x16_msa),
    322                       make_tuple(8, 8, &vp8_sixtap_predict8x8_msa),
    323                       make_tuple(8, 4, &vp8_sixtap_predict8x4_msa),
    324                       make_tuple(4, 4, &vp8_sixtap_predict4x4_msa)));
    325 #endif
    326 
    327 #if HAVE_MMI
    328 INSTANTIATE_TEST_CASE_P(
    329     MMI, SixtapPredictTest,
    330     ::testing::Values(make_tuple(16, 16, &vp8_sixtap_predict16x16_mmi),
    331                       make_tuple(8, 8, &vp8_sixtap_predict8x8_mmi),
    332                       make_tuple(8, 4, &vp8_sixtap_predict8x4_mmi),
    333                       make_tuple(4, 4, &vp8_sixtap_predict4x4_mmi)));
    334 #endif
    335 
    336 class BilinearPredictTest : public PredictTestBase {};
    337 
    338 TEST_P(BilinearPredictTest, TestWithRandomData) {
    339   TestWithRandomData(vp8_bilinear_predict16x16_c);
    340 }
    341 TEST_P(BilinearPredictTest, TestWithUnalignedDst) {
    342   TestWithUnalignedDst(vp8_bilinear_predict16x16_c);
    343 }
    344 
    345 INSTANTIATE_TEST_CASE_P(
    346     C, BilinearPredictTest,
    347     ::testing::Values(make_tuple(16, 16, &vp8_bilinear_predict16x16_c),
    348                       make_tuple(8, 8, &vp8_bilinear_predict8x8_c),
    349                       make_tuple(8, 4, &vp8_bilinear_predict8x4_c),
    350                       make_tuple(4, 4, &vp8_bilinear_predict4x4_c)));
    351 #if HAVE_NEON
    352 INSTANTIATE_TEST_CASE_P(
    353     NEON, BilinearPredictTest,
    354     ::testing::Values(make_tuple(16, 16, &vp8_bilinear_predict16x16_neon),
    355                       make_tuple(8, 8, &vp8_bilinear_predict8x8_neon),
    356                       make_tuple(8, 4, &vp8_bilinear_predict8x4_neon),
    357                       make_tuple(4, 4, &vp8_bilinear_predict4x4_neon)));
    358 #endif
    359 #if HAVE_MMX
    360 INSTANTIATE_TEST_CASE_P(
    361     MMX, BilinearPredictTest,
    362     ::testing::Values(make_tuple(8, 4, &vp8_bilinear_predict8x4_mmx),
    363                       make_tuple(4, 4, &vp8_bilinear_predict4x4_mmx)));
    364 #endif
    365 #if HAVE_SSE2
    366 INSTANTIATE_TEST_CASE_P(
    367     SSE2, BilinearPredictTest,
    368     ::testing::Values(make_tuple(16, 16, &vp8_bilinear_predict16x16_sse2),
    369                       make_tuple(8, 8, &vp8_bilinear_predict8x8_sse2)));
    370 #endif
    371 #if HAVE_SSSE3
    372 INSTANTIATE_TEST_CASE_P(
    373     SSSE3, BilinearPredictTest,
    374     ::testing::Values(make_tuple(16, 16, &vp8_bilinear_predict16x16_ssse3),
    375                       make_tuple(8, 8, &vp8_bilinear_predict8x8_ssse3)));
    376 #endif
    377 #if HAVE_MSA
    378 INSTANTIATE_TEST_CASE_P(
    379     MSA, BilinearPredictTest,
    380     ::testing::Values(make_tuple(16, 16, &vp8_bilinear_predict16x16_msa),
    381                       make_tuple(8, 8, &vp8_bilinear_predict8x8_msa),
    382                       make_tuple(8, 4, &vp8_bilinear_predict8x4_msa),
    383                       make_tuple(4, 4, &vp8_bilinear_predict4x4_msa)));
    384 #endif
    385 }  // namespace
    386