Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 1 | /* |
Yaowu Xu | bde4ac8 | 2016-11-28 15:26:06 -0800 | [diff] [blame] | 2 | * Copyright (c) 2016, Alliance for Open Media. All rights reserved |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 3 | * |
Yaowu Xu | bde4ac8 | 2016-11-28 15:26:06 -0800 | [diff] [blame] | 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. |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 10 | */ |
Yaowu Xu | bde4ac8 | 2016-11-28 15:26:06 -0800 | [diff] [blame] | 11 | |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 12 | #ifndef TEST_TRANSFORM_TEST_BASE_H_ |
| 13 | #define TEST_TRANSFORM_TEST_BASE_H_ |
| 14 | |
Tom Finegan | 60e653d | 2018-05-22 11:34:58 -0700 | [diff] [blame] | 15 | #include "config/aom_config.h" |
| 16 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 17 | #include "aom_mem/aom_mem.h" |
| 18 | #include "aom/aom_codec.h" |
Lester Lu | 27319b6 | 2017-07-10 16:57:15 -0700 | [diff] [blame] | 19 | #include "aom_dsp/txfm_common.h" |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 20 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 21 | namespace libaom_test { |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 22 | |
| 23 | // Note: |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 24 | // Same constant are defined in av1/common/av1_entropy.h and |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 25 | // av1/common/entropy.h. Goal is to make this base class |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 26 | // to use for future codec transform testing. But including |
| 27 | // either of them would lead to compiling error when we do |
| 28 | // unit test for another codec. Suggest to move the definition |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 29 | // to a aom header file. |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 30 | const int kDctMaxValue = 16384; |
| 31 | |
| 32 | typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride, |
Lester Lu | 27319b6 | 2017-07-10 16:57:15 -0700 | [diff] [blame] | 33 | TxfmParam *txfm_param); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 34 | |
Peter de Rivaz | 1baecfe | 2016-09-29 09:14:54 +0100 | [diff] [blame] | 35 | typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride, |
Lester Lu | 27319b6 | 2017-07-10 16:57:15 -0700 | [diff] [blame] | 36 | const TxfmParam *txfm_param); |
Peter de Rivaz | 1baecfe | 2016-09-29 09:14:54 +0100 | [diff] [blame] | 37 | |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 38 | class TransformTestBase { |
| 39 | public: |
| 40 | virtual ~TransformTestBase() {} |
| 41 | |
| 42 | protected: |
| 43 | virtual void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) = 0; |
| 44 | |
| 45 | virtual void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) = 0; |
| 46 | |
Angie Chiang | e6aece8 | 2017-01-09 17:27:56 -0800 | [diff] [blame] | 47 | void RunAccuracyCheck(uint32_t ref_max_error, double ref_avg_error) { |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 48 | ACMRandom rnd(ACMRandom::DeterministicSeed()); |
| 49 | uint32_t max_error = 0; |
| 50 | int64_t total_error = 0; |
| 51 | const int count_test_block = 10000; |
| 52 | |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 53 | int16_t *test_input_block = reinterpret_cast<int16_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 54 | aom_memalign(16, sizeof(int16_t) * num_coeffs_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 55 | tran_low_t *test_temp_block = reinterpret_cast<tran_low_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 56 | aom_memalign(16, sizeof(tran_low_t) * num_coeffs_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 57 | uint8_t *dst = reinterpret_cast<uint8_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 58 | aom_memalign(16, sizeof(uint8_t) * num_coeffs_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 59 | uint8_t *src = reinterpret_cast<uint8_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 60 | aom_memalign(16, sizeof(uint8_t) * num_coeffs_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 61 | uint16_t *dst16 = reinterpret_cast<uint16_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 62 | aom_memalign(16, sizeof(uint16_t) * num_coeffs_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 63 | uint16_t *src16 = reinterpret_cast<uint16_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 64 | aom_memalign(16, sizeof(uint16_t) * num_coeffs_)); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 65 | |
| 66 | for (int i = 0; i < count_test_block; ++i) { |
| 67 | // Initialize a test block with input range [-255, 255]. |
| 68 | for (int j = 0; j < num_coeffs_; ++j) { |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 69 | if (bit_depth_ == AOM_BITS_8) { |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 70 | src[j] = rnd.Rand8(); |
| 71 | dst[j] = rnd.Rand8(); |
| 72 | test_input_block[j] = src[j] - dst[j]; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 73 | } else { |
| 74 | src16[j] = rnd.Rand16() & mask_; |
| 75 | dst16[j] = rnd.Rand16() & mask_; |
| 76 | test_input_block[j] = src16[j] - dst16[j]; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 77 | } |
| 78 | } |
| 79 | |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 80 | ASM_REGISTER_STATE_CHECK( |
| 81 | RunFwdTxfm(test_input_block, test_temp_block, pitch_)); |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 82 | if (bit_depth_ == AOM_BITS_8) { |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 83 | ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_)); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 84 | } else { |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 85 | ASM_REGISTER_STATE_CHECK( |
| 86 | RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_)); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 87 | } |
| 88 | |
| 89 | for (int j = 0; j < num_coeffs_; ++j) { |
Yaowu Xu | 59b969d | 2016-10-24 09:21:09 -0700 | [diff] [blame] | 90 | const int diff = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 91 | bit_depth_ == AOM_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 92 | const uint32_t error = diff * diff; |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 93 | if (max_error < error) max_error = error; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 94 | total_error += error; |
| 95 | } |
| 96 | } |
| 97 | |
Angie Chiang | e6aece8 | 2017-01-09 17:27:56 -0800 | [diff] [blame] | 98 | double avg_error = total_error * 1. / count_test_block / num_coeffs_; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 99 | |
Angie Chiang | e6aece8 | 2017-01-09 17:27:56 -0800 | [diff] [blame] | 100 | EXPECT_GE(ref_max_error, max_error) |
| 101 | << "Error: FHT/IHT has an individual round trip error > " |
| 102 | << ref_max_error; |
| 103 | |
| 104 | EXPECT_GE(ref_avg_error, avg_error) |
| 105 | << "Error: FHT/IHT has average round trip error > " << ref_avg_error |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 106 | << " per block"; |
| 107 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 108 | aom_free(test_input_block); |
| 109 | aom_free(test_temp_block); |
| 110 | aom_free(dst); |
| 111 | aom_free(src); |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 112 | aom_free(dst16); |
| 113 | aom_free(src16); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 114 | } |
| 115 | |
| 116 | void RunCoeffCheck() { |
| 117 | ACMRandom rnd(ACMRandom::DeterministicSeed()); |
| 118 | const int count_test_block = 5000; |
| 119 | |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 120 | // Use a stride value which is not the width of any transform, to catch |
| 121 | // cases where the transforms use the stride incorrectly. |
| 122 | int stride = 96; |
| 123 | |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 124 | int16_t *input_block = reinterpret_cast<int16_t *>( |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 125 | aom_memalign(16, sizeof(int16_t) * stride * height_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 126 | tran_low_t *output_ref_block = reinterpret_cast<tran_low_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 127 | aom_memalign(16, sizeof(tran_low_t) * num_coeffs_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 128 | tran_low_t *output_block = reinterpret_cast<tran_low_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 129 | aom_memalign(16, sizeof(tran_low_t) * num_coeffs_)); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 130 | |
| 131 | for (int i = 0; i < count_test_block; ++i) { |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 132 | int j, k; |
| 133 | for (j = 0; j < height_; ++j) { |
| 134 | for (k = 0; k < pitch_; ++k) { |
| 135 | int in_idx = j * stride + k; |
| 136 | int out_idx = j * pitch_ + k; |
| 137 | input_block[in_idx] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); |
| 138 | if (bit_depth_ == AOM_BITS_8) { |
| 139 | output_block[out_idx] = output_ref_block[out_idx] = rnd.Rand8(); |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 140 | } else { |
| 141 | output_block[out_idx] = output_ref_block[out_idx] = |
| 142 | rnd.Rand16() & mask_; |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 143 | } |
Peter de Rivaz | 1baecfe | 2016-09-29 09:14:54 +0100 | [diff] [blame] | 144 | } |
| 145 | } |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 146 | |
Lester Lu | 27319b6 | 2017-07-10 16:57:15 -0700 | [diff] [blame] | 147 | fwd_txfm_ref(input_block, output_ref_block, stride, &txfm_param_); |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 148 | ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, stride)); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 149 | |
| 150 | // The minimum quant value is 4. |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 151 | for (j = 0; j < height_; ++j) { |
| 152 | for (k = 0; k < pitch_; ++k) { |
| 153 | int out_idx = j * pitch_ + k; |
| 154 | ASSERT_EQ(output_block[out_idx], output_ref_block[out_idx]) |
| 155 | << "Error: not bit-exact result at index: " << out_idx |
| 156 | << " at test block: " << i; |
| 157 | } |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 158 | } |
| 159 | } |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 160 | aom_free(input_block); |
| 161 | aom_free(output_ref_block); |
| 162 | aom_free(output_block); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 163 | } |
| 164 | |
Peter de Rivaz | 1baecfe | 2016-09-29 09:14:54 +0100 | [diff] [blame] | 165 | void RunInvCoeffCheck() { |
| 166 | ACMRandom rnd(ACMRandom::DeterministicSeed()); |
| 167 | const int count_test_block = 5000; |
| 168 | |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 169 | // Use a stride value which is not the width of any transform, to catch |
| 170 | // cases where the transforms use the stride incorrectly. |
| 171 | int stride = 96; |
| 172 | |
Peter de Rivaz | 1baecfe | 2016-09-29 09:14:54 +0100 | [diff] [blame] | 173 | int16_t *input_block = reinterpret_cast<int16_t *>( |
| 174 | aom_memalign(16, sizeof(int16_t) * num_coeffs_)); |
| 175 | tran_low_t *trans_block = reinterpret_cast<tran_low_t *>( |
| 176 | aom_memalign(16, sizeof(tran_low_t) * num_coeffs_)); |
| 177 | uint8_t *output_block = reinterpret_cast<uint8_t *>( |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 178 | aom_memalign(16, sizeof(uint8_t) * stride * height_)); |
Peter de Rivaz | 1baecfe | 2016-09-29 09:14:54 +0100 | [diff] [blame] | 179 | uint8_t *output_ref_block = reinterpret_cast<uint8_t *>( |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 180 | aom_memalign(16, sizeof(uint8_t) * stride * height_)); |
Peter de Rivaz | 1baecfe | 2016-09-29 09:14:54 +0100 | [diff] [blame] | 181 | |
| 182 | for (int i = 0; i < count_test_block; ++i) { |
| 183 | // Initialize a test block with input range [-mask_, mask_]. |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 184 | int j, k; |
| 185 | for (j = 0; j < height_; ++j) { |
| 186 | for (k = 0; k < pitch_; ++k) { |
| 187 | int in_idx = j * pitch_ + k; |
| 188 | int out_idx = j * stride + k; |
| 189 | input_block[in_idx] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_); |
| 190 | output_ref_block[out_idx] = rnd.Rand16() & mask_; |
| 191 | output_block[out_idx] = output_ref_block[out_idx]; |
| 192 | } |
Peter de Rivaz | 1baecfe | 2016-09-29 09:14:54 +0100 | [diff] [blame] | 193 | } |
| 194 | |
Lester Lu | 27319b6 | 2017-07-10 16:57:15 -0700 | [diff] [blame] | 195 | fwd_txfm_ref(input_block, trans_block, pitch_, &txfm_param_); |
Peter de Rivaz | 1baecfe | 2016-09-29 09:14:54 +0100 | [diff] [blame] | 196 | |
Lester Lu | 27319b6 | 2017-07-10 16:57:15 -0700 | [diff] [blame] | 197 | inv_txfm_ref(trans_block, output_ref_block, stride, &txfm_param_); |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 198 | ASM_REGISTER_STATE_CHECK(RunInvTxfm(trans_block, output_block, stride)); |
Peter de Rivaz | 1baecfe | 2016-09-29 09:14:54 +0100 | [diff] [blame] | 199 | |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 200 | for (j = 0; j < height_; ++j) { |
| 201 | for (k = 0; k < pitch_; ++k) { |
| 202 | int out_idx = j * stride + k; |
| 203 | ASSERT_EQ(output_block[out_idx], output_ref_block[out_idx]) |
| 204 | << "Error: not bit-exact result at index: " << out_idx |
Yi Luo | 7317200 | 2016-10-28 10:52:04 -0700 | [diff] [blame] | 205 | << " j = " << j << " k = " << k << " at test block: " << i; |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 206 | } |
Peter de Rivaz | 1baecfe | 2016-09-29 09:14:54 +0100 | [diff] [blame] | 207 | } |
| 208 | } |
| 209 | aom_free(input_block); |
| 210 | aom_free(trans_block); |
| 211 | aom_free(output_ref_block); |
| 212 | aom_free(output_block); |
| 213 | } |
| 214 | |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 215 | void RunMemCheck() { |
| 216 | ACMRandom rnd(ACMRandom::DeterministicSeed()); |
| 217 | const int count_test_block = 5000; |
| 218 | |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 219 | int16_t *input_extreme_block = reinterpret_cast<int16_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 220 | aom_memalign(16, sizeof(int16_t) * num_coeffs_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 221 | tran_low_t *output_ref_block = reinterpret_cast<tran_low_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 222 | aom_memalign(16, sizeof(tran_low_t) * num_coeffs_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 223 | tran_low_t *output_block = reinterpret_cast<tran_low_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 224 | aom_memalign(16, sizeof(tran_low_t) * num_coeffs_)); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 225 | |
| 226 | for (int i = 0; i < count_test_block; ++i) { |
| 227 | // Initialize a test block with input range [-mask_, mask_]. |
| 228 | for (int j = 0; j < num_coeffs_; ++j) { |
| 229 | input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_; |
| 230 | } |
| 231 | if (i == 0) { |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 232 | for (int j = 0; j < num_coeffs_; ++j) input_extreme_block[j] = mask_; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 233 | } else if (i == 1) { |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 234 | for (int j = 0; j < num_coeffs_; ++j) input_extreme_block[j] = -mask_; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 235 | } |
| 236 | |
Lester Lu | 27319b6 | 2017-07-10 16:57:15 -0700 | [diff] [blame] | 237 | fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, &txfm_param_); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 238 | ASM_REGISTER_STATE_CHECK( |
| 239 | RunFwdTxfm(input_extreme_block, output_block, pitch_)); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 240 | |
| 241 | int row_length = FindRowLength(); |
| 242 | // The minimum quant value is 4. |
| 243 | for (int j = 0; j < num_coeffs_; ++j) { |
Urvang Joshi | 4d5cf53 | 2017-12-20 16:54:10 -0800 | [diff] [blame] | 244 | ASSERT_EQ(output_block[j], output_ref_block[j]) |
Yi Luo | 63bd6dc | 2016-11-17 09:13:39 -0800 | [diff] [blame] | 245 | << "Not bit-exact at test index: " << i << ", " |
| 246 | << "j = " << j << std::endl; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 247 | EXPECT_GE(row_length * kDctMaxValue << (bit_depth_ - 8), |
| 248 | abs(output_block[j])) |
| 249 | << "Error: NxN FDCT has coefficient larger than N*DCT_MAX_VALUE"; |
| 250 | } |
| 251 | } |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 252 | aom_free(input_extreme_block); |
| 253 | aom_free(output_ref_block); |
| 254 | aom_free(output_block); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 255 | } |
| 256 | |
| 257 | void RunInvAccuracyCheck(int limit) { |
| 258 | ACMRandom rnd(ACMRandom::DeterministicSeed()); |
| 259 | const int count_test_block = 1000; |
| 260 | |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 261 | int16_t *in = reinterpret_cast<int16_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 262 | aom_memalign(16, sizeof(int16_t) * num_coeffs_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 263 | tran_low_t *coeff = reinterpret_cast<tran_low_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 264 | aom_memalign(16, sizeof(tran_low_t) * num_coeffs_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 265 | uint8_t *dst = reinterpret_cast<uint8_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 266 | aom_memalign(16, sizeof(uint8_t) * num_coeffs_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 267 | uint8_t *src = reinterpret_cast<uint8_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 268 | aom_memalign(16, sizeof(uint8_t) * num_coeffs_)); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 269 | |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 270 | uint16_t *dst16 = reinterpret_cast<uint16_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 271 | aom_memalign(16, sizeof(uint16_t) * num_coeffs_)); |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 272 | uint16_t *src16 = reinterpret_cast<uint16_t *>( |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 273 | aom_memalign(16, sizeof(uint16_t) * num_coeffs_)); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 274 | |
| 275 | for (int i = 0; i < count_test_block; ++i) { |
| 276 | // Initialize a test block with input range [-mask_, mask_]. |
| 277 | for (int j = 0; j < num_coeffs_; ++j) { |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 278 | if (bit_depth_ == AOM_BITS_8) { |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 279 | src[j] = rnd.Rand8(); |
| 280 | dst[j] = rnd.Rand8(); |
| 281 | in[j] = src[j] - dst[j]; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 282 | } else { |
| 283 | src16[j] = rnd.Rand16() & mask_; |
| 284 | dst16[j] = rnd.Rand16() & mask_; |
| 285 | in[j] = src16[j] - dst16[j]; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 286 | } |
| 287 | } |
| 288 | |
Lester Lu | 27319b6 | 2017-07-10 16:57:15 -0700 | [diff] [blame] | 289 | fwd_txfm_ref(in, coeff, pitch_, &txfm_param_); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 290 | |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 291 | if (bit_depth_ == AOM_BITS_8) { |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 292 | ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_)); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 293 | } else { |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 294 | ASM_REGISTER_STATE_CHECK( |
| 295 | RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16), pitch_)); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 296 | } |
| 297 | |
| 298 | for (int j = 0; j < num_coeffs_; ++j) { |
Yaowu Xu | 59b969d | 2016-10-24 09:21:09 -0700 | [diff] [blame] | 299 | const int diff = |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 300 | bit_depth_ == AOM_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j]; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 301 | const uint32_t error = diff * diff; |
Urvang Joshi | 4d5cf53 | 2017-12-20 16:54:10 -0800 | [diff] [blame] | 302 | ASSERT_GE(static_cast<uint32_t>(limit), error) |
clang-format | 3a826f1 | 2016-08-11 17:46:05 -0700 | [diff] [blame] | 303 | << "Error: 4x4 IDCT has error " << error << " at index " << j; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 304 | } |
| 305 | } |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 306 | aom_free(in); |
| 307 | aom_free(coeff); |
| 308 | aom_free(dst); |
| 309 | aom_free(src); |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 310 | aom_free(src16); |
| 311 | aom_free(dst16); |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 312 | } |
| 313 | |
| 314 | int pitch_; |
David Barker | 7825022 | 2016-10-13 15:10:14 +0100 | [diff] [blame] | 315 | int height_; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 316 | FhtFunc fwd_txfm_ref; |
Peter de Rivaz | 1baecfe | 2016-09-29 09:14:54 +0100 | [diff] [blame] | 317 | IhtFunc inv_txfm_ref; |
Yaowu Xu | f883b42 | 2016-08-30 14:01:10 -0700 | [diff] [blame] | 318 | aom_bit_depth_t bit_depth_; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 319 | int mask_; |
| 320 | int num_coeffs_; |
Lester Lu | 27319b6 | 2017-07-10 16:57:15 -0700 | [diff] [blame] | 321 | TxfmParam txfm_param_; |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 322 | |
| 323 | private: |
| 324 | // Assume transform size is 4x4, 8x8, 16x16,... |
| 325 | int FindRowLength() const { |
| 326 | int row = 4; |
| 327 | if (16 == num_coeffs_) { |
| 328 | row = 4; |
| 329 | } else if (64 == num_coeffs_) { |
| 330 | row = 8; |
| 331 | } else if (256 == num_coeffs_) { |
| 332 | row = 16; |
| 333 | } else if (1024 == num_coeffs_) { |
| 334 | row = 32; |
| 335 | } |
| 336 | return row; |
| 337 | } |
| 338 | }; |
| 339 | |
Yaowu Xu | c27fc14 | 2016-08-22 16:08:15 -0700 | [diff] [blame] | 340 | } // namespace libaom_test |
Yi Luo | 267f73a | 2016-02-29 09:53:42 -0800 | [diff] [blame] | 341 | |
| 342 | #endif // TEST_TRANSFORM_TEST_BASE_H_ |