blob: f46c85631a7f31164b8962a3405f0a18b09182fa [file] [log] [blame]
Yaowu Xuf883b422016-08-30 14:01:10 -07001/*
Yaowu Xubde4ac82016-11-28 15:26:06 -08002 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Yaowu Xuf883b422016-08-30 14:01:10 -07003 *
Yaowu Xubde4ac82016-11-28 15:26:06 -08004 * 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.
Yaowu Xuf883b422016-08-30 14:01:10 -070010 */
11
12#include <math.h>
13#include <stdio.h>
14#include <stdlib.h>
Urvang Joshie035b5d2017-12-13 10:01:59 -080015#include <vector>
Yaowu Xuf883b422016-08-30 14:01:10 -070016
17#include "./av1_rtcd.h"
18#include "test/acm_random.h"
19#include "test/util.h"
20#include "test/av1_txfm_test.h"
Sarah Parkereec47e62017-05-15 20:49:22 -070021#include "av1/common/av1_inv_txfm1d_cfg.h"
Yaowu Xuf883b422016-08-30 14:01:10 -070022
23using libaom_test::ACMRandom;
24using libaom_test::input_base;
25using libaom_test::bd;
26using libaom_test::compute_avg_abs_error;
27using libaom_test::Fwd_Txfm2d_Func;
28using libaom_test::Inv_Txfm2d_Func;
29
Urvang Joshie035b5d2017-12-13 10:01:59 -080030using std::vector;
31
Yaowu Xuf883b422016-08-30 14:01:10 -070032namespace {
33
Yaowu Xuf883b422016-08-30 14:01:10 -070034// AV1InvTxfm2dParam argument list:
35// tx_type_, tx_size_, max_error_, max_avg_error_
36typedef std::tr1::tuple<TX_TYPE, TX_SIZE, int, double> AV1InvTxfm2dParam;
37
38class AV1InvTxfm2d : public ::testing::TestWithParam<AV1InvTxfm2dParam> {
39 public:
40 virtual void SetUp() {
41 tx_type_ = GET_PARAM(0);
42 tx_size_ = GET_PARAM(1);
43 max_error_ = GET_PARAM(2);
44 max_avg_error_ = GET_PARAM(3);
Yaowu Xuf883b422016-08-30 14:01:10 -070045 }
46
47 void RunRoundtripCheck() {
Angie Chiangd2db6582017-08-06 20:46:48 -070048 int tx_w = tx_size_wide[tx_size_];
49 int tx_h = tx_size_high[tx_size_];
50 int txfm2d_size = tx_w * tx_h;
Yaowu Xuf883b422016-08-30 14:01:10 -070051 const Fwd_Txfm2d_Func fwd_txfm_func =
52 libaom_test::fwd_txfm_func_ls[tx_size_];
53 const Inv_Txfm2d_Func inv_txfm_func =
54 libaom_test::inv_txfm_func_ls[tx_size_];
55 double avg_abs_error = 0;
56 ACMRandom rnd(ACMRandom::DeterministicSeed());
Sebastien Alaiwanf7829f42017-07-04 11:54:33 +020057
Sebastien Alaiwan6c933e12017-07-07 14:54:29 +020058 const int count = 500;
Sebastien Alaiwanf7829f42017-07-04 11:54:33 +020059
Sebastien Alaiwan6c933e12017-07-07 14:54:29 +020060 for (int ci = 0; ci < count; ci++) {
Yaowu Xub971c862017-12-14 17:58:50 -080061 DECLARE_ALIGNED(16, int16_t, input[64 * 64]) = { 0 };
Urvang Joshi5dbb9b42017-12-13 18:32:58 -080062 ASSERT_LE(txfm2d_size, NELEMENTS(input));
Sebastien Alaiwan7a6e87b2017-07-04 12:32:46 +020063
Angie Chiangd2db6582017-08-06 20:46:48 -070064 for (int ni = 0; ni < txfm2d_size; ++ni) {
Yaowu Xuf883b422016-08-30 14:01:10 -070065 if (ci == 0) {
66 int extreme_input = input_base - 1;
Urvang Joshi5dbb9b42017-12-13 18:32:58 -080067 input[ni] = extreme_input; // extreme case
Yaowu Xuf883b422016-08-30 14:01:10 -070068 } else {
Urvang Joshi5dbb9b42017-12-13 18:32:58 -080069 input[ni] = rnd.Rand16() % input_base;
70 }
71 }
72
Yaowu Xub971c862017-12-14 17:58:50 -080073 DECLARE_ALIGNED(16, uint16_t, expected[64 * 64]) = { 0 };
Urvang Joshi5dbb9b42017-12-13 18:32:58 -080074 ASSERT_LE(txfm2d_size, NELEMENTS(expected));
75 if (TxfmUsesApproximation()) {
76 // Compare reference forward HT + inverse HT vs forward HT + inverse HT.
77 double ref_input[64 * 64];
78 ASSERT_LE(txfm2d_size, NELEMENTS(ref_input));
79 for (int ni = 0; ni < txfm2d_size; ++ni) {
80 ref_input[ni] = input[ni];
81 }
82 double ref_coeffs[64 * 64] = { 0 };
83 ASSERT_LE(txfm2d_size, NELEMENTS(ref_coeffs));
84 ASSERT_EQ(tx_type_, DCT_DCT);
85 libaom_test::reference_hybrid_2d(ref_input, ref_coeffs, tx_type_,
86 tx_size_);
Yaowu Xue3fb5682017-12-15 07:51:50 -080087 DECLARE_ALIGNED(16, int32_t, ref_coeffs_int[64 * 64]) = { 0 };
Urvang Joshi5dbb9b42017-12-13 18:32:58 -080088 ASSERT_LE(txfm2d_size, NELEMENTS(ref_coeffs_int));
89 for (int ni = 0; ni < txfm2d_size; ++ni) {
90 ref_coeffs_int[ni] = (int32_t)round(ref_coeffs[ni]);
91 }
92 inv_txfm_func(ref_coeffs_int, expected, tx_w, tx_type_, bd);
93 } else {
94 // Compare original input vs forward HT + inverse HT.
95 for (int ni = 0; ni < txfm2d_size; ++ni) {
96 expected[ni] = input[ni];
Yaowu Xuf883b422016-08-30 14:01:10 -070097 }
98 }
99
Yaowu Xub971c862017-12-14 17:58:50 -0800100 DECLARE_ALIGNED(16, int32_t, coeffs[64 * 64]) = { 0 };
Urvang Joshi0e301ba2017-12-11 17:49:13 -0800101 ASSERT_LE(txfm2d_size, NELEMENTS(coeffs));
Urvang Joshi5dbb9b42017-12-13 18:32:58 -0800102 fwd_txfm_func(input, coeffs, tx_w, tx_type_, bd);
Sebastien Alaiwan7a6e87b2017-07-04 12:32:46 +0200103
Yaowu Xub971c862017-12-14 17:58:50 -0800104 DECLARE_ALIGNED(16, uint16_t, actual[64 * 64]) = { 0 };
Urvang Joshi0e301ba2017-12-11 17:49:13 -0800105 ASSERT_LE(txfm2d_size, NELEMENTS(actual));
Angie Chiangd2db6582017-08-06 20:46:48 -0700106 inv_txfm_func(coeffs, actual, tx_w, tx_type_, bd);
Yaowu Xuf883b422016-08-30 14:01:10 -0700107
Urvang Joshie035b5d2017-12-13 10:01:59 -0800108 double actual_max_error = 0;
Angie Chiangd2db6582017-08-06 20:46:48 -0700109 for (int ni = 0; ni < txfm2d_size; ++ni) {
Urvang Joshie035b5d2017-12-13 10:01:59 -0800110 const double this_error = abs(expected[ni] - actual[ni]);
111 actual_max_error = AOMMAX(actual_max_error, this_error);
112 }
113 EXPECT_GE(max_error_, actual_max_error)
114 << " tx_w: " << tx_w << " tx_h " << tx_h << " tx_type: " << tx_type_;
115 if (actual_max_error > max_error_) { // exit early.
116 break;
Yaowu Xuf883b422016-08-30 14:01:10 -0700117 }
Urvang Joshi5dbb9b42017-12-13 18:32:58 -0800118 avg_abs_error += compute_avg_abs_error<uint16_t, uint16_t>(
Angie Chiangd2db6582017-08-06 20:46:48 -0700119 expected, actual, txfm2d_size);
Yaowu Xuf883b422016-08-30 14:01:10 -0700120 }
121
Sebastien Alaiwan6c933e12017-07-07 14:54:29 +0200122 avg_abs_error /= count;
Angie Chiangd2db6582017-08-06 20:46:48 -0700123 EXPECT_GE(max_avg_error_, avg_abs_error)
124 << " tx_w: " << tx_w << " tx_h " << tx_h << " tx_type: " << tx_type_;
Yaowu Xuf883b422016-08-30 14:01:10 -0700125 }
126
Yaowu Xuf883b422016-08-30 14:01:10 -0700127 private:
Urvang Joshi5dbb9b42017-12-13 18:32:58 -0800128 bool TxfmUsesApproximation() {
129#if CONFIG_TX64X64
130 if (tx_size_wide[tx_size_] == 64 || tx_size_high[tx_size_] == 64) {
131 return true;
132 }
133#endif // CONFIG_TX64X64
134 return false;
135 }
136
Yaowu Xuf883b422016-08-30 14:01:10 -0700137 int max_error_;
138 double max_avg_error_;
139 TX_TYPE tx_type_;
140 TX_SIZE tx_size_;
Yaowu Xuf883b422016-08-30 14:01:10 -0700141};
142
Urvang Joshie035b5d2017-12-13 10:01:59 -0800143vector<AV1InvTxfm2dParam> GetInvTxfm2dParamList() {
144 vector<AV1InvTxfm2dParam> param_list;
Debargha Mukherjeeaa84f3e2018-01-04 12:45:10 -0800145 for (int t = 0; t < TX_TYPES; ++t) {
Urvang Joshie035b5d2017-12-13 10:01:59 -0800146 const TX_TYPE tx_type = static_cast<TX_TYPE>(t);
147 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_4X4, 2, 0.002));
Urvang Joshi4d5cf532017-12-20 16:54:10 -0800148 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_8X8, 2, 0.025));
Urvang Joshie035b5d2017-12-13 10:01:59 -0800149 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_16X16, 2, 0.04));
150 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_32X32, 4, 0.4));
Yue Chenc1d9aef2017-12-28 16:13:13 -0800151#if CONFIG_TX64X64
152 if (tx_type == DCT_DCT) { // Other types not supported by these tx sizes.
153 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_64X64, 3, 0.2));
154 }
155#endif // CONFIG_TX64X64
Yaowu Xuf883b422016-08-30 14:01:10 -0700156
Urvang Joshi4d5cf532017-12-20 16:54:10 -0800157 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_4X8, 2, 0.016));
158 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_8X4, 2, 0.016));
Yue Chen7580f252018-01-03 11:25:59 -0800159 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_8X16, 2, 0.2));
160 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_16X8, 2, 0.2));
Debargha Mukherjee1158bff2018-01-01 18:23:59 -0800161 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_16X32, 3, 0.4));
162 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_32X16, 3, 0.4));
Angie Chiangd2db6582017-08-06 20:46:48 -0700163
Debargha Mukherjee1158bff2018-01-01 18:23:59 -0800164 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_4X16, 2, 0.2));
165 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_16X4, 2, 0.2));
Urvang Joshi46e8fda2017-12-14 14:53:36 -0800166 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_8X32, 2, 0.2));
Debargha Mukherjee1158bff2018-01-01 18:23:59 -0800167 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_32X8, 2, 0.2));
Angie Chiangd2db6582017-08-06 20:46:48 -0700168
Urvang Joshi0e301ba2017-12-11 17:49:13 -0800169#if CONFIG_TX64X64
Urvang Joshie035b5d2017-12-13 10:01:59 -0800170 if (tx_type == DCT_DCT) { // Other types not supported by these tx sizes.
Yue Chen7580f252018-01-03 11:25:59 -0800171 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_32X64, 5, 0.38));
172 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_64X32, 5, 0.38));
Debargha Mukherjee1158bff2018-01-01 18:23:59 -0800173 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_16X64, 3, 0.38));
174 param_list.push_back(AV1InvTxfm2dParam(tx_type, TX_64X16, 3, 0.38));
Urvang Joshie035b5d2017-12-13 10:01:59 -0800175 }
Urvang Joshi0e301ba2017-12-11 17:49:13 -0800176#endif // CONFIG_TX64X64
Urvang Joshie035b5d2017-12-13 10:01:59 -0800177 }
178 return param_list;
179}
Yaowu Xuf883b422016-08-30 14:01:10 -0700180
181INSTANTIATE_TEST_CASE_P(C, AV1InvTxfm2d,
Urvang Joshie035b5d2017-12-13 10:01:59 -0800182 ::testing::ValuesIn(GetInvTxfm2dParamList()));
183
184TEST_P(AV1InvTxfm2d, RunRoundtripCheck) { RunRoundtripCheck(); }
Yaowu Xuf883b422016-08-30 14:01:10 -0700185
Angie Chiang9c7089a2017-08-08 16:21:11 -0700186TEST(AV1InvTxfm2d, CfgTest) {
187 for (int bd_idx = 0; bd_idx < BD_NUM; ++bd_idx) {
188 int bd = libaom_test::bd_arr[bd_idx];
189 int8_t low_range = libaom_test::low_range_arr[bd_idx];
190 int8_t high_range = libaom_test::high_range_arr[bd_idx];
Urvang Joshia989d832017-12-11 16:41:26 -0800191 for (int tx_size = 0; tx_size < TX_SIZES_ALL; ++tx_size) {
Angie Chiang9c7089a2017-08-08 16:21:11 -0700192 for (int tx_type = 0; tx_type < TX_TYPES; ++tx_type) {
Urvang Joshiab2b36e2017-10-03 11:01:06 -0700193#if CONFIG_TX64X64
Urvang Joshia989d832017-12-11 16:41:26 -0800194 if ((tx_size_wide[tx_size] == 64 || tx_size_high[tx_size] == 64) &&
195 tx_type != DCT_DCT) {
196 continue;
197 }
Urvang Joshiab2b36e2017-10-03 11:01:06 -0700198#endif // CONFIG_TX64X64
Urvang Joshic5022162017-11-21 15:57:42 -0800199 TXFM_2D_FLIP_CFG cfg;
200 av1_get_inv_txfm_cfg(static_cast<TX_TYPE>(tx_type),
201 static_cast<TX_SIZE>(tx_size), &cfg);
Angie Chiang9c7089a2017-08-08 16:21:11 -0700202 int8_t stage_range_col[MAX_TXFM_STAGE_NUM];
203 int8_t stage_range_row[MAX_TXFM_STAGE_NUM];
204 av1_gen_inv_stage_range(stage_range_col, stage_range_row, &cfg,
Debargha Mukherjee1158bff2018-01-01 18:23:59 -0800205 (TX_SIZE)tx_size, bd);
Angie Chiang9c7089a2017-08-08 16:21:11 -0700206 const TXFM_1D_CFG *col_cfg = cfg.col_cfg;
207 const TXFM_1D_CFG *row_cfg = cfg.row_cfg;
208 libaom_test::txfm_stage_range_check(stage_range_col, col_cfg->stage_num,
209 col_cfg->cos_bit, low_range,
210 high_range);
211 libaom_test::txfm_stage_range_check(stage_range_row, row_cfg->stage_num,
212 row_cfg->cos_bit, low_range,
213 high_range);
214 }
215 }
216 }
217}
Yaowu Xuf883b422016-08-30 14:01:10 -0700218} // namespace