tor-browser

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

av1_quantize_test.cc (10030B)


      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 #include <stdlib.h>
     12 
     13 #include "gtest/gtest.h"
     14 
     15 #include "config/aom_config.h"
     16 #include "config/av1_rtcd.h"
     17 
     18 #include "test/acm_random.h"
     19 #include "test/register_state_check.h"
     20 #include "av1/common/scan.h"
     21 #include "av1/encoder/av1_quantize.h"
     22 
     23 namespace {
     24 
     25 using QuantizeFpFunc = void (*)(
     26    const tran_low_t *coeff_ptr, intptr_t count, const int16_t *zbin_ptr,
     27    const int16_t *round_ptr, const int16_t *quant_ptr,
     28    const int16_t *quant_shift_ptr, tran_low_t *qcoeff_ptr,
     29    tran_low_t *dqcoeff_ptr, const int16_t *dequant_ptr, uint16_t *eob_ptr,
     30    const int16_t *scan, const int16_t *iscan, int log_scale);
     31 
     32 struct QuantizeFuncParams {
     33  QuantizeFuncParams(QuantizeFpFunc qF = nullptr,
     34                     QuantizeFpFunc qRefF = nullptr, int count = 16)
     35      : qFunc(qF), qFuncRef(qRefF), coeffCount(count) {}
     36  QuantizeFpFunc qFunc;
     37  QuantizeFpFunc qFuncRef;
     38  int coeffCount;
     39 };
     40 
     41 using libaom_test::ACMRandom;
     42 
     43 const int numTests = 1000;
     44 const int maxSize = 1024;
     45 const int roundFactorRange = 127;
     46 const int dequantRange = 32768;
     47 const int coeffRange = (1 << 20) - 1;
     48 
     49 class AV1QuantizeTest : public ::testing::TestWithParam<QuantizeFuncParams> {
     50 public:
     51  void RunQuantizeTest() {
     52    ACMRandom rnd(ACMRandom::DeterministicSeed());
     53    DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[maxSize]);
     54    DECLARE_ALIGNED(16, int16_t, zbin_ptr[8]);
     55    DECLARE_ALIGNED(16, int16_t, round_ptr[8]);
     56    DECLARE_ALIGNED(16, int16_t, quant_ptr[8]);
     57    DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[8]);
     58    DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[maxSize]);
     59    DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[maxSize]);
     60    DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[maxSize]);
     61    DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[maxSize]);
     62    DECLARE_ALIGNED(16, int16_t, dequant_ptr[8]);
     63    uint16_t eob;
     64    uint16_t ref_eob;
     65    int err_count_total = 0;
     66    int first_failure = -1;
     67    int count = params_.coeffCount;
     68    const TX_SIZE txSize = getTxSize(count);
     69    int log_scale = (txSize == TX_32X32);
     70    QuantizeFpFunc quanFunc = params_.qFunc;
     71    QuantizeFpFunc quanFuncRef = params_.qFuncRef;
     72 
     73    const SCAN_ORDER scanOrder = av1_scan_orders[txSize][DCT_DCT];
     74    for (int i = 0; i < numTests; i++) {
     75      int err_count = 0;
     76      ref_eob = eob = UINT16_MAX;
     77      for (int j = 0; j < count; j++) {
     78        coeff_ptr[j] = rnd(coeffRange);
     79      }
     80 
     81      for (int j = 0; j < 2; j++) {
     82        zbin_ptr[j] = rnd.Rand16Signed();
     83        quant_shift_ptr[j] = rnd.Rand16Signed();
     84        // int16_t positive
     85        dequant_ptr[j] = abs(rnd(dequantRange));
     86        quant_ptr[j] = static_cast<int16_t>((1 << 16) / dequant_ptr[j]);
     87        round_ptr[j] = (abs(rnd(roundFactorRange)) * dequant_ptr[j]) >> 7;
     88      }
     89      for (int j = 2; j < 8; ++j) {
     90        zbin_ptr[j] = zbin_ptr[1];
     91        quant_shift_ptr[j] = quant_shift_ptr[1];
     92        dequant_ptr[j] = dequant_ptr[1];
     93        quant_ptr[j] = quant_ptr[1];
     94        round_ptr[j] = round_ptr[1];
     95      }
     96      quanFuncRef(coeff_ptr, count, zbin_ptr, round_ptr, quant_ptr,
     97                  quant_shift_ptr, ref_qcoeff_ptr, ref_dqcoeff_ptr, dequant_ptr,
     98                  &ref_eob, scanOrder.scan, scanOrder.iscan, log_scale);
     99 
    100      API_REGISTER_STATE_CHECK(
    101          quanFunc(coeff_ptr, count, zbin_ptr, round_ptr, quant_ptr,
    102                   quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr, &eob,
    103                   scanOrder.scan, scanOrder.iscan, log_scale));
    104 
    105      for (int j = 0; j < count; ++j) {
    106        err_count += (ref_qcoeff_ptr[j] != qcoeff_ptr[j]) |
    107                     (ref_dqcoeff_ptr[j] != dqcoeff_ptr[j]);
    108        ASSERT_EQ(ref_qcoeff_ptr[j], qcoeff_ptr[j])
    109            << "qcoeff error: i = " << i << " j = " << j << "\n";
    110        EXPECT_EQ(ref_dqcoeff_ptr[j], dqcoeff_ptr[j])
    111            << "dqcoeff error: i = " << i << " j = " << j << "\n";
    112      }
    113      EXPECT_EQ(ref_eob, eob) << "eob error: "
    114                              << "i = " << i << "\n";
    115      err_count += (ref_eob != eob);
    116      if (err_count && !err_count_total) {
    117        first_failure = i;
    118      }
    119      err_count_total += err_count;
    120    }
    121    EXPECT_EQ(0, err_count_total)
    122        << "Error: Quantization Test, C output doesn't match SSE2 output. "
    123        << "First failed at test case " << first_failure;
    124  }
    125 
    126  void RunEobTest() {
    127    ACMRandom rnd(ACMRandom::DeterministicSeed());
    128    DECLARE_ALIGNED(16, tran_low_t, coeff_ptr[maxSize]);
    129    DECLARE_ALIGNED(16, int16_t, zbin_ptr[8]);
    130    DECLARE_ALIGNED(16, int16_t, round_ptr[8]);
    131    DECLARE_ALIGNED(16, int16_t, quant_ptr[8]);
    132    DECLARE_ALIGNED(16, int16_t, quant_shift_ptr[8]);
    133    DECLARE_ALIGNED(16, tran_low_t, qcoeff_ptr[maxSize]);
    134    DECLARE_ALIGNED(16, tran_low_t, dqcoeff_ptr[maxSize]);
    135    DECLARE_ALIGNED(16, tran_low_t, ref_qcoeff_ptr[maxSize]);
    136    DECLARE_ALIGNED(16, tran_low_t, ref_dqcoeff_ptr[maxSize]);
    137    DECLARE_ALIGNED(16, int16_t, dequant_ptr[8]);
    138    uint16_t eob;
    139    uint16_t ref_eob;
    140    int count = params_.coeffCount;
    141    const TX_SIZE txSize = getTxSize(count);
    142    int log_scale = (txSize == TX_32X32);
    143    QuantizeFpFunc quanFunc = params_.qFunc;
    144    QuantizeFpFunc quanFuncRef = params_.qFuncRef;
    145    const SCAN_ORDER scanOrder = av1_scan_orders[txSize][DCT_DCT];
    146 
    147    for (int i = 0; i < numTests; i++) {
    148      ref_eob = eob = UINT16_MAX;
    149      for (int j = 0; j < count; j++) {
    150        coeff_ptr[j] = 0;
    151      }
    152 
    153      coeff_ptr[rnd(count)] = rnd(coeffRange);
    154      coeff_ptr[rnd(count)] = rnd(coeffRange);
    155      coeff_ptr[rnd(count)] = rnd(coeffRange);
    156 
    157      for (int j = 0; j < 2; j++) {
    158        zbin_ptr[j] = rnd.Rand16Signed();
    159        quant_shift_ptr[j] = rnd.Rand16Signed();
    160        // int16_t positive
    161        dequant_ptr[j] = abs(rnd(dequantRange));
    162        quant_ptr[j] = (1 << 16) / dequant_ptr[j];
    163        round_ptr[j] = (abs(rnd(roundFactorRange)) * dequant_ptr[j]) >> 7;
    164      }
    165      for (int j = 2; j < 8; ++j) {
    166        zbin_ptr[j] = zbin_ptr[1];
    167        quant_shift_ptr[j] = quant_shift_ptr[1];
    168        dequant_ptr[j] = dequant_ptr[1];
    169        quant_ptr[j] = quant_ptr[1];
    170        round_ptr[j] = round_ptr[1];
    171      }
    172 
    173      quanFuncRef(coeff_ptr, count, zbin_ptr, round_ptr, quant_ptr,
    174                  quant_shift_ptr, ref_qcoeff_ptr, ref_dqcoeff_ptr, dequant_ptr,
    175                  &ref_eob, scanOrder.scan, scanOrder.iscan, log_scale);
    176 
    177      API_REGISTER_STATE_CHECK(
    178          quanFunc(coeff_ptr, count, zbin_ptr, round_ptr, quant_ptr,
    179                   quant_shift_ptr, qcoeff_ptr, dqcoeff_ptr, dequant_ptr, &eob,
    180                   scanOrder.scan, scanOrder.iscan, log_scale));
    181      EXPECT_EQ(ref_eob, eob) << "eob error: "
    182                              << "i = " << i << "\n";
    183    }
    184  }
    185 
    186  void SetUp() override { params_ = GetParam(); }
    187 
    188  ~AV1QuantizeTest() override = default;
    189 
    190 private:
    191  TX_SIZE getTxSize(int count) {
    192    switch (count) {
    193      case 16: return TX_4X4;
    194      case 64: return TX_8X8;
    195      case 256: return TX_16X16;
    196      case 1024: return TX_32X32;
    197      default: return TX_4X4;
    198    }
    199  }
    200 
    201  QuantizeFuncParams params_;
    202 };
    203 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AV1QuantizeTest);
    204 
    205 TEST_P(AV1QuantizeTest, BitExactCheck) { RunQuantizeTest(); }
    206 TEST_P(AV1QuantizeTest, EobVerify) { RunEobTest(); }
    207 
    208 TEST(AV1QuantizeTest, QuantizeFpNoQmatrix) {
    209  // Here we use a uniform quantizer as an example
    210  const int16_t dequant_ptr[2] = { 78, 93 };  // quantize step
    211  const int16_t round_ptr[2] = { 39, 46 };    // round ~= dequant / 2
    212 
    213  // quant ~= 2^16 / dequant. This is a 16-bit fixed point representation of the
    214  // inverse of quantize step.
    215  const int16_t quant_ptr[2] = { 840, 704 };
    216  int log_scale = 0;
    217  int coeff_count = 4;
    218  const tran_low_t coeff_ptr[4] = { -449, 624, -14, 24 };
    219  const tran_low_t ref_qcoeff_ptr[4] = { -6, 7, 0, 0 };
    220  const tran_low_t ref_dqcoeff_ptr[4] = { -468, 651, 0, 0 };
    221  const int16_t scan[4] = { 0, 1, 2, 3 };
    222  tran_low_t qcoeff_ptr[4];
    223  tran_low_t dqcoeff_ptr[4];
    224  int eob = av1_quantize_fp_no_qmatrix(quant_ptr, dequant_ptr, round_ptr,
    225                                       log_scale, scan, coeff_count, coeff_ptr,
    226                                       qcoeff_ptr, dqcoeff_ptr);
    227  EXPECT_EQ(eob, 2);
    228  for (int i = 0; i < coeff_count; ++i) {
    229    EXPECT_EQ(qcoeff_ptr[i], ref_qcoeff_ptr[i]);
    230    EXPECT_EQ(dqcoeff_ptr[i], ref_dqcoeff_ptr[i]);
    231  }
    232 }
    233 
    234 #if HAVE_SSE4_1
    235 const QuantizeFuncParams qfps[4] = {
    236  QuantizeFuncParams(&av1_highbd_quantize_fp_sse4_1, &av1_highbd_quantize_fp_c,
    237                     16),
    238  QuantizeFuncParams(&av1_highbd_quantize_fp_sse4_1, &av1_highbd_quantize_fp_c,
    239                     64),
    240  QuantizeFuncParams(&av1_highbd_quantize_fp_sse4_1, &av1_highbd_quantize_fp_c,
    241                     256),
    242  QuantizeFuncParams(&av1_highbd_quantize_fp_sse4_1, &av1_highbd_quantize_fp_c,
    243                     1024),
    244 };
    245 
    246 INSTANTIATE_TEST_SUITE_P(SSE4_1, AV1QuantizeTest, ::testing::ValuesIn(qfps));
    247 #endif  // HAVE_SSE4_1
    248 
    249 #if HAVE_AVX2
    250 const QuantizeFuncParams qfps_avx2[4] = {
    251  QuantizeFuncParams(&av1_highbd_quantize_fp_avx2, &av1_highbd_quantize_fp_c,
    252                     16),
    253  QuantizeFuncParams(&av1_highbd_quantize_fp_avx2, &av1_highbd_quantize_fp_c,
    254                     64),
    255  QuantizeFuncParams(&av1_highbd_quantize_fp_avx2, &av1_highbd_quantize_fp_c,
    256                     256),
    257  QuantizeFuncParams(&av1_highbd_quantize_fp_avx2, &av1_highbd_quantize_fp_c,
    258                     1024),
    259 };
    260 
    261 INSTANTIATE_TEST_SUITE_P(AVX2, AV1QuantizeTest, ::testing::ValuesIn(qfps_avx2));
    262 #endif  // HAVE_AVX2
    263 
    264 }  // namespace