Home | History | Annotate | Download | only in test
      1 /*
      2  *  Copyright (c) 2017 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 "third_party/googletest/src/include/gtest/gtest.h"
     12 
     13 #include "./vpx_dsp_rtcd.h"
     14 
     15 #include "test/acm_random.h"
     16 #include "test/buffer.h"
     17 #include "test/register_state_check.h"
     18 #include "vpx_ports/vpx_timer.h"
     19 
     20 namespace {
     21 
     22 using ::libvpx_test::ACMRandom;
     23 using ::libvpx_test::Buffer;
     24 
     25 typedef void (*AvgPredFunc)(uint8_t *a, const uint8_t *b, int w, int h,
     26                             const uint8_t *c, int c_stride);
     27 
     28 uint8_t avg_with_rounding(uint8_t a, uint8_t b) { return (a + b + 1) >> 1; }
     29 
     30 void reference_pred(const Buffer<uint8_t> &pred, const Buffer<uint8_t> &ref,
     31                     int width, int height, Buffer<uint8_t> *avg) {
     32   for (int y = 0; y < height; ++y) {
     33     for (int x = 0; x < width; ++x) {
     34       avg->TopLeftPixel()[y * avg->stride() + x] =
     35           avg_with_rounding(pred.TopLeftPixel()[y * pred.stride() + x],
     36                             ref.TopLeftPixel()[y * ref.stride() + x]);
     37     }
     38   }
     39 }
     40 
     41 class AvgPredTest : public ::testing::TestWithParam<AvgPredFunc> {
     42  public:
     43   virtual void SetUp() {
     44     avg_pred_func_ = GetParam();
     45     rnd_.Reset(ACMRandom::DeterministicSeed());
     46   }
     47 
     48  protected:
     49   AvgPredFunc avg_pred_func_;
     50   ACMRandom rnd_;
     51 };
     52 
     53 TEST_P(AvgPredTest, SizeCombinations) {
     54   // This is called as part of the sub pixel variance. As such it must be one of
     55   // the variance block sizes.
     56 
     57   for (int width_pow = 2; width_pow <= 6; ++width_pow) {
     58     for (int height_pow = width_pow - 1; height_pow <= width_pow + 1;
     59          ++height_pow) {
     60       // Don't test 4x2 or 64x128
     61       if (height_pow == 1 || height_pow == 7) continue;
     62 
     63       // The sse2 special-cases when ref width == stride, so make sure to test
     64       // it.
     65       for (int ref_padding = 0; ref_padding < 2; ref_padding++) {
     66         const int width = 1 << width_pow;
     67         const int height = 1 << height_pow;
     68         // Only the reference buffer may have a stride not equal to width.
     69         Buffer<uint8_t> ref =
     70             Buffer<uint8_t>(width, height, ref_padding ? 8 : 0);
     71         ASSERT_TRUE(ref.Init());
     72         Buffer<uint8_t> pred = Buffer<uint8_t>(width, height, 0, 16);
     73         ASSERT_TRUE(pred.Init());
     74         Buffer<uint8_t> avg_ref = Buffer<uint8_t>(width, height, 0, 16);
     75         ASSERT_TRUE(avg_ref.Init());
     76         Buffer<uint8_t> avg_chk = Buffer<uint8_t>(width, height, 0, 16);
     77         ASSERT_TRUE(avg_chk.Init());
     78 
     79         ref.Set(&rnd_, &ACMRandom::Rand8);
     80         pred.Set(&rnd_, &ACMRandom::Rand8);
     81 
     82         reference_pred(pred, ref, width, height, &avg_ref);
     83         ASM_REGISTER_STATE_CHECK(
     84             avg_pred_func_(avg_chk.TopLeftPixel(), pred.TopLeftPixel(), width,
     85                            height, ref.TopLeftPixel(), ref.stride()));
     86 
     87         EXPECT_TRUE(avg_chk.CheckValues(avg_ref));
     88         if (HasFailure()) {
     89           printf("Width: %d Height: %d\n", width, height);
     90           avg_chk.PrintDifference(avg_ref);
     91           return;
     92         }
     93       }
     94     }
     95   }
     96 }
     97 
     98 TEST_P(AvgPredTest, CompareReferenceRandom) {
     99   const int width = 64;
    100   const int height = 32;
    101   Buffer<uint8_t> ref = Buffer<uint8_t>(width, height, 8);
    102   ASSERT_TRUE(ref.Init());
    103   Buffer<uint8_t> pred = Buffer<uint8_t>(width, height, 0, 16);
    104   ASSERT_TRUE(pred.Init());
    105   Buffer<uint8_t> avg_ref = Buffer<uint8_t>(width, height, 0, 16);
    106   ASSERT_TRUE(avg_ref.Init());
    107   Buffer<uint8_t> avg_chk = Buffer<uint8_t>(width, height, 0, 16);
    108   ASSERT_TRUE(avg_chk.Init());
    109 
    110   for (int i = 0; i < 500; ++i) {
    111     ref.Set(&rnd_, &ACMRandom::Rand8);
    112     pred.Set(&rnd_, &ACMRandom::Rand8);
    113 
    114     reference_pred(pred, ref, width, height, &avg_ref);
    115     ASM_REGISTER_STATE_CHECK(avg_pred_func_(avg_chk.TopLeftPixel(),
    116                                             pred.TopLeftPixel(), width, height,
    117                                             ref.TopLeftPixel(), ref.stride()));
    118     EXPECT_TRUE(avg_chk.CheckValues(avg_ref));
    119     if (HasFailure()) {
    120       printf("Width: %d Height: %d\n", width, height);
    121       avg_chk.PrintDifference(avg_ref);
    122       return;
    123     }
    124   }
    125 }
    126 
    127 TEST_P(AvgPredTest, DISABLED_Speed) {
    128   for (int width_pow = 2; width_pow <= 6; ++width_pow) {
    129     for (int height_pow = width_pow - 1; height_pow <= width_pow + 1;
    130          ++height_pow) {
    131       // Don't test 4x2 or 64x128
    132       if (height_pow == 1 || height_pow == 7) continue;
    133 
    134       for (int ref_padding = 0; ref_padding < 2; ref_padding++) {
    135         const int width = 1 << width_pow;
    136         const int height = 1 << height_pow;
    137         Buffer<uint8_t> ref =
    138             Buffer<uint8_t>(width, height, ref_padding ? 8 : 0);
    139         ASSERT_TRUE(ref.Init());
    140         Buffer<uint8_t> pred = Buffer<uint8_t>(width, height, 0, 16);
    141         ASSERT_TRUE(pred.Init());
    142         Buffer<uint8_t> avg = Buffer<uint8_t>(width, height, 0, 16);
    143         ASSERT_TRUE(avg.Init());
    144 
    145         ref.Set(&rnd_, &ACMRandom::Rand8);
    146         pred.Set(&rnd_, &ACMRandom::Rand8);
    147 
    148         vpx_usec_timer timer;
    149         vpx_usec_timer_start(&timer);
    150         for (int i = 0; i < 10000000 / (width * height); ++i) {
    151           avg_pred_func_(avg.TopLeftPixel(), pred.TopLeftPixel(), width, height,
    152                          ref.TopLeftPixel(), ref.stride());
    153         }
    154         vpx_usec_timer_mark(&timer);
    155 
    156         const int elapsed_time =
    157             static_cast<int>(vpx_usec_timer_elapsed(&timer));
    158         printf("Average Test (ref_padding: %d) %dx%d time: %5d us\n",
    159                ref_padding, width, height, elapsed_time);
    160       }
    161     }
    162   }
    163 }
    164 
    165 INSTANTIATE_TEST_CASE_P(C, AvgPredTest,
    166                         ::testing::Values(&vpx_comp_avg_pred_c));
    167 
    168 #if HAVE_SSE2
    169 INSTANTIATE_TEST_CASE_P(SSE2, AvgPredTest,
    170                         ::testing::Values(&vpx_comp_avg_pred_sse2));
    171 #endif  // HAVE_SSE2
    172 
    173 #if HAVE_NEON
    174 INSTANTIATE_TEST_CASE_P(NEON, AvgPredTest,
    175                         ::testing::Values(&vpx_comp_avg_pred_neon));
    176 #endif  // HAVE_NEON
    177 
    178 #if HAVE_VSX
    179 INSTANTIATE_TEST_CASE_P(VSX, AvgPredTest,
    180                         ::testing::Values(&vpx_comp_avg_pred_vsx));
    181 #endif  // HAVE_VSX
    182 }  // namespace
    183