tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

error_block_test.cc (10923B)


      1 /*
      2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
      3 *
      4 * This source code is subject to the terms of the BSD 2 Clause License and
      5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
      6 * was not distributed with this source code in the LICENSE file, you can
      7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
      8 * Media Patent License 1.0 was not distributed with this source code in the
      9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
     10 */
     11 
     12 #include <cmath>
     13 #include <cstdlib>
     14 #include <string>
     15 #include <tuple>
     16 
     17 #include "gtest/gtest.h"
     18 
     19 #include "config/aom_config.h"
     20 #include "config/av1_rtcd.h"
     21 
     22 #include "test/acm_random.h"
     23 #include "test/register_state_check.h"
     24 #include "test/util.h"
     25 #include "av1/common/entropy.h"
     26 #include "aom/aom_codec.h"
     27 #include "aom/aom_integer.h"
     28 
     29 using libaom_test::ACMRandom;
     30 
     31 namespace {
     32 const int kNumIterations = 1000;
     33 
     34 using ErrorBlockFunc = int64_t (*)(const tran_low_t *coeff,
     35                                   const tran_low_t *dqcoeff,
     36                                   intptr_t block_size, int64_t *ssz, int bps);
     37 
     38 using ErrorBlockFunc8Bits = int64_t (*)(const tran_low_t *coeff,
     39                                        const tran_low_t *dqcoeff,
     40                                        intptr_t block_size, int64_t *ssz);
     41 
     42 using ErrorBlockLpFunc = int64_t (*)(const int16_t *coeff,
     43                                     const int16_t *dqcoeff,
     44                                     intptr_t block_size);
     45 
     46 using ErrorBlockParam =
     47    std::tuple<ErrorBlockFunc, ErrorBlockFunc, aom_bit_depth_t>;
     48 
     49 template <ErrorBlockFunc8Bits fn>
     50 int64_t BlockError8BitWrapper(const tran_low_t *coeff,
     51                              const tran_low_t *dqcoeff, intptr_t block_size,
     52                              int64_t *ssz, int bps) {
     53  EXPECT_EQ(bps, 8);
     54  return fn(coeff, dqcoeff, block_size, ssz);
     55 }
     56 
     57 template <ErrorBlockLpFunc fn>
     58 int64_t BlockErrorLpWrapper(const tran_low_t *coeff, const tran_low_t *dqcoeff,
     59                            intptr_t block_size, int64_t *ssz, int bps) {
     60  EXPECT_EQ(bps, 8);
     61  *ssz = -1;
     62  return fn(reinterpret_cast<const int16_t *>(coeff),
     63            reinterpret_cast<const int16_t *>(dqcoeff), block_size);
     64 }
     65 
     66 class ErrorBlockTest : public ::testing::TestWithParam<ErrorBlockParam> {
     67 public:
     68  ~ErrorBlockTest() override = default;
     69  void SetUp() override {
     70    error_block_op_ = GET_PARAM(0);
     71    ref_error_block_op_ = GET_PARAM(1);
     72    bit_depth_ = GET_PARAM(2);
     73  }
     74 
     75 protected:
     76  aom_bit_depth_t bit_depth_;
     77  ErrorBlockFunc error_block_op_;
     78  ErrorBlockFunc ref_error_block_op_;
     79 };
     80 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ErrorBlockTest);
     81 
     82 TEST_P(ErrorBlockTest, OperationCheck) {
     83  ACMRandom rnd(ACMRandom::DeterministicSeed());
     84  DECLARE_ALIGNED(16, tran_low_t, coeff[4096]);
     85  DECLARE_ALIGNED(16, tran_low_t, dqcoeff[4096]);
     86  int err_count_total = 0;
     87  int first_failure = -1;
     88  intptr_t block_size;
     89  int64_t ssz;
     90  int64_t ret;
     91  int64_t ref_ssz;
     92  int64_t ref_ret;
     93  const int msb = bit_depth_ + 8 - 1;
     94  for (int i = 0; i < kNumIterations; ++i) {
     95    int err_count = 0;
     96    block_size = 16 << (i % 9);  // All block sizes from 4x4, 8x4 ..64x64
     97    for (int j = 0; j < block_size; j++) {
     98      // coeff and dqcoeff will always have at least the same sign, and this
     99      // can be used for optimization, so generate test input precisely.
    100      if (rnd(2)) {
    101        // Positive number
    102        coeff[j] = rnd(1 << msb);
    103        dqcoeff[j] = rnd(1 << msb);
    104      } else {
    105        // Negative number
    106        coeff[j] = -rnd(1 << msb);
    107        dqcoeff[j] = -rnd(1 << msb);
    108      }
    109    }
    110    ref_ret =
    111        ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz, bit_depth_);
    112    API_REGISTER_STATE_CHECK(
    113        ret = error_block_op_(coeff, dqcoeff, block_size, &ssz, bit_depth_));
    114    err_count += (ref_ret != ret) | (ref_ssz != ssz);
    115    if (err_count && !err_count_total) {
    116      first_failure = i;
    117    }
    118    err_count_total += err_count;
    119  }
    120  EXPECT_EQ(0, err_count_total)
    121      << "Error: Error Block Test, C output doesn't match optimized output. "
    122      << "First failed at test case " << first_failure;
    123 }
    124 
    125 TEST_P(ErrorBlockTest, ExtremeValues) {
    126  ACMRandom rnd(ACMRandom::DeterministicSeed());
    127  DECLARE_ALIGNED(16, tran_low_t, coeff[4096]);
    128  DECLARE_ALIGNED(16, tran_low_t, dqcoeff[4096]);
    129  int err_count_total = 0;
    130  int first_failure = -1;
    131  intptr_t block_size;
    132  int64_t ssz;
    133  int64_t ret;
    134  int64_t ref_ssz;
    135  int64_t ref_ret;
    136  const int msb = bit_depth_ + 8 - 1;
    137  int max_val = ((1 << msb) - 1);
    138  for (int i = 0; i < kNumIterations; ++i) {
    139    int err_count = 0;
    140    int k = (i / 9) % 9;
    141 
    142    // Change the maximum coeff value, to test different bit boundaries
    143    if (k == 8 && (i % 9) == 0) {
    144      max_val >>= 1;
    145    }
    146    block_size = 16 << (i % 9);  // All block sizes from 4x4, 8x4 ..64x64
    147    for (int j = 0; j < block_size; j++) {
    148      if (k < 4) {
    149        // Test at positive maximum values
    150        coeff[j] = k % 2 ? max_val : 0;
    151        dqcoeff[j] = (k >> 1) % 2 ? max_val : 0;
    152      } else if (k < 8) {
    153        // Test at negative maximum values
    154        coeff[j] = k % 2 ? -max_val : 0;
    155        dqcoeff[j] = (k >> 1) % 2 ? -max_val : 0;
    156      } else {
    157        if (rnd(2)) {
    158          // Positive number
    159          coeff[j] = rnd(1 << 14);
    160          dqcoeff[j] = rnd(1 << 14);
    161        } else {
    162          // Negative number
    163          coeff[j] = -rnd(1 << 14);
    164          dqcoeff[j] = -rnd(1 << 14);
    165        }
    166      }
    167    }
    168    ref_ret =
    169        ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz, bit_depth_);
    170    API_REGISTER_STATE_CHECK(
    171        ret = error_block_op_(coeff, dqcoeff, block_size, &ssz, bit_depth_));
    172    err_count += (ref_ret != ret) | (ref_ssz != ssz);
    173    if (err_count && !err_count_total) {
    174      first_failure = i;
    175    }
    176    err_count_total += err_count;
    177  }
    178  EXPECT_EQ(0, err_count_total)
    179      << "Error: Error Block Test, C output doesn't match optimized output. "
    180      << "First failed at test case " << first_failure;
    181 }
    182 
    183 TEST_P(ErrorBlockTest, DISABLED_Speed) {
    184  ACMRandom rnd(ACMRandom::DeterministicSeed());
    185  DECLARE_ALIGNED(16, tran_low_t, coeff[4096]);
    186  DECLARE_ALIGNED(16, tran_low_t, dqcoeff[4096]);
    187  intptr_t block_size;
    188  int64_t ssz;
    189  int num_iters = 100000;
    190  int64_t ref_ssz;
    191  const int msb = bit_depth_ + 8 - 1;
    192  for (int i = 0; i < 9; ++i) {
    193    block_size = 16 << (i % 9);  // All block sizes from 4x4, 8x4 ..64x64
    194    for (int k = 0; k < 9; k++) {
    195      for (int j = 0; j < block_size; j++) {
    196        if (k < 5) {
    197          if (rnd(2)) {
    198            // Positive number
    199            coeff[j] = rnd(1 << msb);
    200            dqcoeff[j] = rnd(1 << msb);
    201          } else {
    202            // Negative number
    203            coeff[j] = -rnd(1 << msb);
    204            dqcoeff[j] = -rnd(1 << msb);
    205          }
    206        } else {
    207          if (rnd(2)) {
    208            // Positive number
    209            coeff[j] = rnd(1 << 14);
    210            dqcoeff[j] = rnd(1 << 14);
    211          } else {
    212            // Negative number
    213            coeff[j] = -rnd(1 << 14);
    214            dqcoeff[j] = -rnd(1 << 14);
    215          }
    216        }
    217      }
    218      aom_usec_timer ref_timer, test_timer;
    219 
    220      aom_usec_timer_start(&ref_timer);
    221      for (int iter = 0; iter < num_iters; ++iter) {
    222        ref_error_block_op_(coeff, dqcoeff, block_size, &ref_ssz, bit_depth_);
    223      }
    224      aom_usec_timer_mark(&ref_timer);
    225      const int elapsed_time_c =
    226          static_cast<int>(aom_usec_timer_elapsed(&ref_timer));
    227 
    228      aom_usec_timer_start(&test_timer);
    229      for (int iter = 0; iter < num_iters; ++iter) {
    230        error_block_op_(coeff, dqcoeff, block_size, &ssz, bit_depth_);
    231      }
    232      aom_usec_timer_mark(&test_timer);
    233 
    234      const int elapsed_time_simd =
    235          static_cast<int>(aom_usec_timer_elapsed(&test_timer));
    236 
    237      printf(
    238          " c_time=%d \t simd_time=%d \t "
    239          "gain=%d \n",
    240          elapsed_time_c, elapsed_time_simd,
    241          (elapsed_time_c / elapsed_time_simd));
    242    }
    243  }
    244 }
    245 
    246 using std::make_tuple;
    247 
    248 #if HAVE_SSE2
    249 const ErrorBlockParam kErrorBlockTestParamsSse2[] = {
    250 #if CONFIG_AV1_HIGHBITDEPTH
    251  make_tuple(&av1_highbd_block_error_sse2, &av1_highbd_block_error_c,
    252             AOM_BITS_10),
    253  make_tuple(&av1_highbd_block_error_sse2, &av1_highbd_block_error_c,
    254             AOM_BITS_12),
    255  make_tuple(&av1_highbd_block_error_sse2, &av1_highbd_block_error_c,
    256             AOM_BITS_8),
    257 #endif
    258  make_tuple(&BlockError8BitWrapper<av1_block_error_sse2>,
    259             &BlockError8BitWrapper<av1_block_error_c>, AOM_BITS_8),
    260  make_tuple(&BlockErrorLpWrapper<av1_block_error_lp_sse2>,
    261             &BlockErrorLpWrapper<av1_block_error_lp_c>, AOM_BITS_8)
    262 };
    263 
    264 INSTANTIATE_TEST_SUITE_P(SSE2, ErrorBlockTest,
    265                         ::testing::ValuesIn(kErrorBlockTestParamsSse2));
    266 #endif  // HAVE_SSE2
    267 
    268 #if HAVE_AVX2
    269 const ErrorBlockParam kErrorBlockTestParamsAvx2[] = {
    270 #if CONFIG_AV1_HIGHBITDEPTH
    271  make_tuple(&av1_highbd_block_error_avx2, &av1_highbd_block_error_c,
    272             AOM_BITS_10),
    273  make_tuple(&av1_highbd_block_error_avx2, &av1_highbd_block_error_c,
    274             AOM_BITS_12),
    275  make_tuple(&av1_highbd_block_error_avx2, &av1_highbd_block_error_c,
    276             AOM_BITS_8),
    277 #endif
    278  make_tuple(&BlockError8BitWrapper<av1_block_error_avx2>,
    279             &BlockError8BitWrapper<av1_block_error_c>, AOM_BITS_8),
    280  make_tuple(&BlockErrorLpWrapper<av1_block_error_lp_avx2>,
    281             &BlockErrorLpWrapper<av1_block_error_lp_c>, AOM_BITS_8)
    282 };
    283 
    284 INSTANTIATE_TEST_SUITE_P(AVX2, ErrorBlockTest,
    285                         ::testing::ValuesIn(kErrorBlockTestParamsAvx2));
    286 #endif  // HAVE_AVX2
    287 
    288 #if HAVE_NEON
    289 const ErrorBlockParam kErrorBlockTestParamsNeon[] = {
    290 #if CONFIG_AV1_HIGHBITDEPTH
    291  make_tuple(&av1_highbd_block_error_neon, &av1_highbd_block_error_c,
    292             AOM_BITS_10),
    293  make_tuple(&av1_highbd_block_error_neon, &av1_highbd_block_error_c,
    294             AOM_BITS_12),
    295  make_tuple(&av1_highbd_block_error_neon, &av1_highbd_block_error_c,
    296             AOM_BITS_8),
    297 #endif
    298  make_tuple(&BlockError8BitWrapper<av1_block_error_neon>,
    299             &BlockError8BitWrapper<av1_block_error_c>, AOM_BITS_8),
    300  make_tuple(&BlockErrorLpWrapper<av1_block_error_lp_neon>,
    301             &BlockErrorLpWrapper<av1_block_error_lp_c>, AOM_BITS_8)
    302 };
    303 
    304 INSTANTIATE_TEST_SUITE_P(NEON, ErrorBlockTest,
    305                         ::testing::ValuesIn(kErrorBlockTestParamsNeon));
    306 #endif  // HAVE_NEON
    307 
    308 #if HAVE_SVE
    309 const ErrorBlockParam kErrorBlockTestParamsSVE[] = {
    310  make_tuple(&BlockError8BitWrapper<av1_block_error_sve>,
    311             &BlockError8BitWrapper<av1_block_error_c>, AOM_BITS_8),
    312  make_tuple(&BlockErrorLpWrapper<av1_block_error_lp_sve>,
    313             &BlockErrorLpWrapper<av1_block_error_lp_c>, AOM_BITS_8)
    314 };
    315 
    316 INSTANTIATE_TEST_SUITE_P(SVE, ErrorBlockTest,
    317                         ::testing::ValuesIn(kErrorBlockTestParamsSVE));
    318 #endif  // HAVE_SVE
    319 }  // namespace