av1_fwd_txfm2d_test.cc 7.77 KB
Newer Older
Angie Chiang's avatar
Angie Chiang committed
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Angie Chiang's avatar
Angie Chiang committed
3
 *
4 5 6 7 8 9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
Angie Chiang's avatar
Angie Chiang committed
10 11
 */

Angie Chiang's avatar
Angie Chiang committed
12
#include <math.h>
Angie Chiang's avatar
Angie Chiang committed
13 14
#include <stdio.h>
#include <stdlib.h>
15
#include <vector>
Angie Chiang's avatar
Angie Chiang committed
16 17

#include "test/acm_random.h"
18
#include "test/util.h"
Yaowu Xu's avatar
Yaowu Xu committed
19 20 21
#include "test/av1_txfm_test.h"
#include "av1/common/av1_txfm.h"
#include "./av1_rtcd.h"
Angie Chiang's avatar
Angie Chiang committed
22

23 24 25 26 27 28
using libaom_test::ACMRandom;
using libaom_test::input_base;
using libaom_test::bd;
using libaom_test::compute_avg_abs_error;
using libaom_test::Fwd_Txfm2d_Func;
using libaom_test::TYPE_TXFM;
Angie Chiang's avatar
Angie Chiang committed
29

30 31
using std::vector;

Angie Chiang's avatar
Angie Chiang committed
32
namespace {
33
// tx_type_, tx_size_, max_error_, max_avg_error_
Yaowu Xu's avatar
Yaowu Xu committed
34
typedef std::tr1::tuple<TX_TYPE, TX_SIZE, double, double> AV1FwdTxfm2dParam;
35

Yaowu Xu's avatar
Yaowu Xu committed
36
class AV1FwdTxfm2d : public ::testing::TestWithParam<AV1FwdTxfm2dParam> {
37 38 39 40 41 42 43
 public:
  virtual void SetUp() {
    tx_type_ = GET_PARAM(0);
    tx_size_ = GET_PARAM(1);
    max_error_ = GET_PARAM(2);
    max_avg_error_ = GET_PARAM(3);
    count_ = 500;
44 45
    TXFM_2D_FLIP_CFG fwd_txfm_flip_cfg;
    av1_get_fwd_txfm_cfg(tx_type_, tx_size_, &fwd_txfm_flip_cfg);
46
    amplify_factor_ = libaom_test::get_amplification_factor(tx_type_, tx_size_);
47 48
    tx_width_ = fwd_txfm_flip_cfg.row_cfg->txfm_size;
    tx_height_ = fwd_txfm_flip_cfg.col_cfg->txfm_size;
49 50
    ud_flip_ = fwd_txfm_flip_cfg.ud_flip;
    lr_flip_ = fwd_txfm_flip_cfg.lr_flip;
51

52
    fwd_txfm_ = libaom_test::fwd_txfm_func_ls[tx_size_];
53
    txfm2d_size_ = tx_width_ * tx_height_;
clang-format's avatar
clang-format committed
54
    input_ = reinterpret_cast<int16_t *>(
Yaowu Xu's avatar
Yaowu Xu committed
55
        aom_memalign(16, sizeof(input_[0]) * txfm2d_size_));
clang-format's avatar
clang-format committed
56
    output_ = reinterpret_cast<int32_t *>(
Yaowu Xu's avatar
Yaowu Xu committed
57
        aom_memalign(16, sizeof(output_[0]) * txfm2d_size_));
clang-format's avatar
clang-format committed
58
    ref_input_ = reinterpret_cast<double *>(
Yaowu Xu's avatar
Yaowu Xu committed
59
        aom_memalign(16, sizeof(ref_input_[0]) * txfm2d_size_));
clang-format's avatar
clang-format committed
60
    ref_output_ = reinterpret_cast<double *>(
Yaowu Xu's avatar
Yaowu Xu committed
61
        aom_memalign(16, sizeof(ref_output_[0]) * txfm2d_size_));
62 63 64 65 66 67 68 69 70 71 72
  }

  void RunFwdAccuracyCheck() {
    ACMRandom rnd(ACMRandom::DeterministicSeed());
    double avg_abs_error = 0;
    for (int ci = 0; ci < count_; ci++) {
      for (int ni = 0; ni < txfm2d_size_; ++ni) {
        input_[ni] = rnd.Rand16() % input_base;
        ref_input_[ni] = static_cast<double>(input_[ni]);
        output_[ni] = 0;
        ref_output_[ni] = 0;
Angie Chiang's avatar
Angie Chiang committed
73
      }
74

75
      fwd_txfm_(input_, output_, tx_width_, tx_type_, bd);
76

77 78 79 80 81 82 83
      if (lr_flip_ && ud_flip_) {
        libaom_test::fliplrud(ref_input_, tx_width_, tx_height_, tx_width_);
      } else if (lr_flip_) {
        libaom_test::fliplr(ref_input_, tx_width_, tx_height_, tx_width_);
      } else if (ud_flip_) {
        libaom_test::flipud(ref_input_, tx_width_, tx_height_, tx_width_);
      }
84

85 86
      libaom_test::reference_hybrid_2d(ref_input_, ref_output_, tx_type_,
                                       tx_size_);
87

88
      double actual_max_error = 0;
89
      for (int ni = 0; ni < txfm2d_size_; ++ni) {
90
        ref_output_[ni] = round(ref_output_[ni]);
91 92 93
        const double this_error =
            fabs(output_[ni] - ref_output_[ni]) / amplify_factor_;
        actual_max_error = AOMMAX(actual_max_error, this_error);
94
      }
95 96 97 98 99 100
      EXPECT_GE(max_error_, actual_max_error)
          << "tx_size = " << tx_size_ << ", tx_type = " << tx_type_;
      if (actual_max_error > max_error_) {  // exit early.
        break;
      }

101 102
      avg_abs_error += compute_avg_abs_error<int32_t, double>(
          output_, ref_output_, txfm2d_size_);
Angie Chiang's avatar
Angie Chiang committed
103 104
    }

105 106
    avg_abs_error /= amplify_factor_;
    avg_abs_error /= count_;
107 108
    EXPECT_GE(max_avg_error_, avg_abs_error)
        << "tx_size = " << tx_size_ << ", tx_type = " << tx_type_;
109 110 111
  }

  virtual void TearDown() {
Yaowu Xu's avatar
Yaowu Xu committed
112 113 114 115
    aom_free(input_);
    aom_free(output_);
    aom_free(ref_input_);
    aom_free(ref_output_);
Angie Chiang's avatar
Angie Chiang committed
116
  }
117 118 119 120 121 122 123 124

 private:
  double max_error_;
  double max_avg_error_;
  int count_;
  double amplify_factor_;
  TX_TYPE tx_type_;
  TX_SIZE tx_size_;
125 126
  int tx_width_;
  int tx_height_;
127 128
  int txfm2d_size_;
  Fwd_Txfm2d_Func fwd_txfm_;
clang-format's avatar
clang-format committed
129 130 131 132
  int16_t *input_;
  int32_t *output_;
  double *ref_input_;
  double *ref_output_;
133 134
  int ud_flip_;  // flip upside down
  int lr_flip_;  // flip left to right
135 136
};

137 138
vector<AV1FwdTxfm2dParam> GetTxfm2dParamList() {
  vector<AV1FwdTxfm2dParam> param_list;
139
  for (int t = 0; t < TX_TYPES; ++t) {
140
    const TX_TYPE tx_type = static_cast<TX_TYPE>(t);
141
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_4X4, 2, 0.5));
142 143 144
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_8X8, 5, 0.6));
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_16X16, 11, 1.5));
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_32X32, 70, 7));
145 146 147 148 149
#if CONFIG_TX64X64
    if (tx_type == DCT_DCT) {  // Other types not supported by these tx sizes.
      param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_64X64, 70, 7));
    }
#endif  // CONFIG_TX64X64
150

151 152
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_4X8, 3.2, 0.58));
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_8X4, 3.2, 0.58));
153 154 155
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_8X16, 15, 1.5));
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_16X8, 15, 1.5));
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_16X32, 55, 7));
156 157
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_32X16, 30, 7));

158 159
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_4X16, 5, 0.7));
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_16X4, 5.5, 0.9));
160 161
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_8X32, 20, 2.2));
    param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_32X8, 15, 1.8));
162

163
#if CONFIG_TX64X64
164 165 166
    if (tx_type == DCT_DCT) {  // Other types not supported by these tx sizes.
      param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_32X64, 136, 7));
      param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_64X32, 136, 7));
167 168
      param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_16X64, 30, 3.6));
      param_list.push_back(AV1FwdTxfm2dParam(tx_type, TX_64X16, 50, 6.0));
169
    }
170
#endif  // CONFIG_TX64X64
171 172 173
  }
  return param_list;
}
174

Yaowu Xu's avatar
Yaowu Xu committed
175
INSTANTIATE_TEST_CASE_P(C, AV1FwdTxfm2d,
176 177 178
                        ::testing::ValuesIn(GetTxfm2dParamList()));

TEST_P(AV1FwdTxfm2d, RunFwdAccuracyCheck) { RunFwdAccuracyCheck(); }
Angie Chiang's avatar
Angie Chiang committed
179

Angie Chiang's avatar
Angie Chiang committed
180 181 182 183 184
TEST(AV1FwdTxfm2d, CfgTest) {
  for (int bd_idx = 0; bd_idx < BD_NUM; ++bd_idx) {
    int bd = libaom_test::bd_arr[bd_idx];
    int8_t low_range = libaom_test::low_range_arr[bd_idx];
    int8_t high_range = libaom_test::high_range_arr[bd_idx];
185
    for (int tx_size = 0; tx_size < TX_SIZES_ALL; ++tx_size) {
Angie Chiang's avatar
Angie Chiang committed
186
      for (int tx_type = 0; tx_type < TX_TYPES; ++tx_type) {
Urvang Joshi's avatar
Urvang Joshi committed
187
#if CONFIG_TX64X64
188 189 190 191
        if ((tx_size_wide[tx_size] == 64 || tx_size_high[tx_size] == 64) &&
            tx_type != DCT_DCT) {
          continue;
        }
Urvang Joshi's avatar
Urvang Joshi committed
192
#endif  // CONFIG_TX64X64
193 194 195
        TXFM_2D_FLIP_CFG cfg;
        av1_get_fwd_txfm_cfg(static_cast<TX_TYPE>(tx_type),
                             static_cast<TX_SIZE>(tx_size), &cfg);
Angie Chiang's avatar
Angie Chiang committed
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
        int8_t stage_range_col[MAX_TXFM_STAGE_NUM];
        int8_t stage_range_row[MAX_TXFM_STAGE_NUM];
        av1_gen_fwd_stage_range(stage_range_col, stage_range_row, &cfg, bd);
        const TXFM_1D_CFG *col_cfg = cfg.col_cfg;
        const TXFM_1D_CFG *row_cfg = cfg.row_cfg;
        libaom_test::txfm_stage_range_check(stage_range_col, col_cfg->stage_num,
                                            col_cfg->cos_bit, low_range,
                                            high_range);
        libaom_test::txfm_stage_range_check(stage_range_row, row_cfg->stage_num,
                                            row_cfg->cos_bit, low_range,
                                            high_range);
      }
    }
  }
}

212
}  // namespace