History

Merge "Enable 4x4 DCT/ADST transform unit test"

Jingning Han committed 13 years ago

Commit 4995dbc2 parents b6ca9d9 30d4c5e1 file · +244 −134Browse files

Unified · Split

test/fdct4x4_test.cc+244−134
@@ -13,178 +13,288 @@ · 12 unmodified lines
13#include <string.h>13#include <string.h>
14 14
15#include "third_party/googletest/src/include/gtest/gtest.h"15#include "third_party/googletest/src/include/gtest/gtest.h"
16#include "test/acm_random.h"
17#include "test/clear_system_state.h"
18#include "test/register_state_check.h"
19#include "test/util.h"
16 20
17extern "C" {21extern "C" {
22#include "vp9/common/vp9_entropy.h"
18#include "./vp9_rtcd.h"23#include "./vp9_rtcd.h"
24void vp9_idct4x4_16_add_c(const int16_t *input, uint8_t *output, int pitch);
19}25}
20
21#include "test/acm_random.h"
22#include "vpx/vpx_integer.h"26#include "vpx/vpx_integer.h"
23#include "vpx_ports/mem.h"
24 27
25using libvpx_test::ACMRandom;28using libvpx_test::ACMRandom;
26 29
27namespace {30namespace {
28void fdct4x4(int16_t *in, int16_t *out, uint8_t* /*dst*/,31const int kNumCoeffs = 16;
29 int stride, int /*tx_type*/) {32typedef void (*fdct_t)(const int16_t *in, int16_t *out, int stride);
33typedef void (*idct_t)(const int16_t *in, uint8_t *out, int stride);
34typedef void (*fht_t) (const int16_t *in, int16_t *out, int stride,
35 int tx_type);
36typedef void (*iht_t) (const int16_t *in, uint8_t *out, int stride,
37 int tx_type);
38
39void fdct4x4_ref(const int16_t *in, int16_t *out, int stride, int tx_type) {
30 vp9_fdct4x4_c(in, out, stride);40 vp9_fdct4x4_c(in, out, stride);
31}41}
32void idct4x4_add(int16_t* /*in*/, int16_t *out, uint8_t *dst,42
33 int stride, int /*tx_type*/) {43void fht4x4_ref(const int16_t *in, int16_t *out, int stride, int tx_type) {
34 vp9_idct4x4_16_add_c(out, dst, stride);
35}
36void fht4x4(int16_t *in, int16_t *out, uint8_t* /*dst*/,
37 int stride, int tx_type) {
38 vp9_short_fht4x4_c(in, out, stride, tx_type);44 vp9_short_fht4x4_c(in, out, stride, tx_type);
39}45}
40void iht4x4_add(int16_t* /*in*/, int16_t *out, uint8_t *dst,
41 int stride, int tx_type) {
42 vp9_iht4x4_16_add_c(out, dst, stride, tx_type);
43}
44 46
45class FwdTrans4x4Test : public ::testing::TestWithParam<int> {47class Trans4x4TestBase {
46 public:48 public:
47 virtual ~FwdTrans4x4Test() {}49 virtual ~Trans4x4TestBase() {}
48 virtual void SetUp() {
49 tx_type_ = GetParam();
50 if (tx_type_ == 0) {
51 fwd_txfm_ = fdct4x4;
52 inv_txfm_ = idct4x4_add;
53 } else {
54 fwd_txfm_ = fht4x4;
55 inv_txfm_ = iht4x4_add;
56 }
57 }
58 50
59 protected:51 protected:
60 void RunFwdTxfm(int16_t *in, int16_t *out, uint8_t *dst,52 virtual void RunFwdTxfm(const int16_t *in, int16_t *out, int stride) = 0;
61 int stride, int tx_type) {53
62 (*fwd_txfm_)(in, out, dst, stride, tx_type);54 virtual void RunInvTxfm(const int16_t *out, uint8_t *dst, int stride) = 0;
63 }55
56 void RunAccuracyCheck() {
57 ACMRandom rnd(ACMRandom::DeterministicSeed());
58 uint32_t max_error = 0;
59 int64_t total_error = 0;
60 const int count_test_block = 10000;
61 for (int i = 0; i < count_test_block; ++i) {
62 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, kNumCoeffs);
63 DECLARE_ALIGNED_ARRAY(16, int16_t, test_temp_block, kNumCoeffs);
64 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs);
65 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs);
66
67 // Initialize a test block with input range [-255, 255].
68 for (int j = 0; j < kNumCoeffs; ++j) {
69 src[j] = rnd.Rand8();
70 dst[j] = rnd.Rand8();
71 test_input_block[j] = src[j] - dst[j];
72 }
73
74 REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block,
75 test_temp_block, pitch_));
76 REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
77
78 for (int j = 0; j < kNumCoeffs; ++j) {
79 const uint32_t diff = dst[j] - src[j];
80 const uint32_t error = diff * diff;
81 if (max_error < error)
82 max_error = error;
83 total_error += error;
84 }
85 }
64 86
65 void RunInvTxfm(int16_t *in, int16_t *out, uint8_t *dst,87 EXPECT_GE(1u, max_error)
66 int stride, int tx_type) {88 << "Error: 4x4 FHT/IHT has an individual round trip error > 1";
67 (*inv_txfm_)(in, out, dst, stride, tx_type);89
90 EXPECT_GE(count_test_block , total_error)
91 << "Error: 4x4 FHT/IHT has average round trip error > 1 per block";
68 }92 }
69 93
70 int tx_type_;94 void RunCoeffCheck() {
71 void (*fwd_txfm_)(int16_t *in, int16_t *out, uint8_t *dst,95 ACMRandom rnd(ACMRandom::DeterministicSeed());
72 int stride, int tx_type);96 const int count_test_block = 5000;
73 void (*inv_txfm_)(int16_t *in, int16_t *out, uint8_t *dst,97 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs);
74 int stride, int tx_type);98 DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs);
75};99 DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, kNumCoeffs);
100
101 for (int i = 0; i < count_test_block; ++i) {
102 // Initialize a test block with input range [-255, 255].
103 for (int j = 0; j < kNumCoeffs; ++j)
104 input_block[j] = rnd.Rand8() - rnd.Rand8();
105
106 fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_);
107 REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_));
76 108
77TEST_P(FwdTrans4x4Test, SignBiasCheck) {109 // The minimum quant value is 4.
78 ACMRandom rnd(ACMRandom::DeterministicSeed());110 for (int j = 0; j < kNumCoeffs; ++j)
79 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 16);111 EXPECT_EQ(output_block[j], output_ref_block[j]);
80 DECLARE_ALIGNED_ARRAY(16, int16_t, test_output_block, 16);
81 const int pitch = 4;
82 int count_sign_block[16][2];
83 const int count_test_block = 1000000;
84
85 memset(count_sign_block, 0, sizeof(count_sign_block));
86 for (int i = 0; i < count_test_block; ++i) {
87 // Initialize a test block with input range [-255, 255].
88 for (int j = 0; j < 16; ++j)
89 test_input_block[j] = rnd.Rand8() - rnd.Rand8();
90
91 RunFwdTxfm(test_input_block, test_output_block, NULL, pitch, tx_type_);
92
93 for (int j = 0; j < 16; ++j) {
94 if (test_output_block[j] < 0)
95 ++count_sign_block[j][0];
96 else if (test_output_block[j] > 0)
97 ++count_sign_block[j][1];
98 }112 }
99 }113 }
100 114
101 for (int j = 0; j < 16; ++j) {115 void RunMemCheck() {
102 const bool bias_acceptable = (abs(count_sign_block[j][0] -116 ACMRandom rnd(ACMRandom::DeterministicSeed());
103 count_sign_block[j][1]) < 10000);117 const int count_test_block = 5000;
104 EXPECT_TRUE(bias_acceptable)118 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs);
105 << "Error: 4x4 FDCT/FHT has a sign bias > 1%"119 DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs);
106 << " for input range [-255, 255] at index " << j120 DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs);
107 << " tx_type " << tx_type_;121 DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, kNumCoeffs);
122
123 for (int i = 0; i < count_test_block; ++i) {
124 // Initialize a test block with input range [-255, 255].
125 for (int j = 0; j < kNumCoeffs; ++j) {
126 input_block[j] = rnd.Rand8() - rnd.Rand8();
127 input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255;
128 }
129 if (i == 0)
130 for (int j = 0; j < kNumCoeffs; ++j)
131 input_extreme_block[j] = 255;
132 if (i == 1)
133 for (int j = 0; j < kNumCoeffs; ++j)
134 input_extreme_block[j] = -255;
135
136 fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);
137 REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block,
138 output_block, pitch_));
139
140 // The minimum quant value is 4.
141 for (int j = 0; j < kNumCoeffs; ++j) {
142 EXPECT_EQ(output_block[j], output_ref_block[j]);
143 EXPECT_GE(4 * DCT_MAX_VALUE, abs(output_block[j]))
144 << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE";
145 }
146 }
108 }147 }
109 148
110 memset(count_sign_block, 0, sizeof(count_sign_block));149 void RunInvAccuracyCheck() {
111 for (int i = 0; i < count_test_block; ++i) {150 ACMRandom rnd(ACMRandom::DeterministicSeed());
112 // Initialize a test block with input range [-15, 15].151 const int count_test_block = 1000;
113 for (int j = 0; j < 16; ++j)152 DECLARE_ALIGNED_ARRAY(16, int16_t, in, kNumCoeffs);
114 test_input_block[j] = (rnd.Rand8() >> 4) - (rnd.Rand8() >> 4);153 DECLARE_ALIGNED_ARRAY(16, int16_t, coeff, kNumCoeffs);
154 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs);
155 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs);
115 156
116 RunFwdTxfm(test_input_block, test_output_block, NULL, pitch, tx_type_);157 for (int i = 0; i < count_test_block; ++i) {
158 // Initialize a test block with input range [-255, 255].
159 for (int j = 0; j < kNumCoeffs; ++j) {
160 src[j] = rnd.Rand8();
161 dst[j] = rnd.Rand8();
162 in[j] = src[j] - dst[j];
163 }
117 164
118 for (int j = 0; j < 16; ++j) {165 fwd_txfm_ref(in, coeff, pitch_, tx_type_);
119 if (test_output_block[j] < 0)166
120 ++count_sign_block[j][0];167 REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
121 else if (test_output_block[j] > 0)168
122 ++count_sign_block[j][1];169 for (int j = 0; j < kNumCoeffs; ++j) {
170 const uint32_t diff = dst[j] - src[j];
171 const uint32_t error = diff * diff;
172 EXPECT_GE(1u, error)
173 << "Error: 16x16 IDCT has error " << error
174 << " at index " << j;
175 }
123 }176 }
124 }177 }
125 178
126 for (int j = 0; j < 16; ++j) {179 int pitch_;
127 const bool bias_acceptable = (abs(count_sign_block[j][0] -180 int tx_type_;
128 count_sign_block[j][1]) < 100000);181 fht_t fwd_txfm_ref;
129 EXPECT_TRUE(bias_acceptable)182};
130 << "Error: 4x4 FDCT/FHT has a sign bias > 10%"183
131 << " for input range [-15, 15] at index " << j;184class Trans4x4DCT
185 : public Trans4x4TestBase,
186 public PARAMS(fdct_t, idct_t, int) {
187 public:
188 virtual ~Trans4x4DCT() {}
189
190 virtual void SetUp() {
191 fwd_txfm_ = GET_PARAM(0);
192 inv_txfm_ = GET_PARAM(1);
193 tx_type_ = GET_PARAM(2);
194 pitch_ = 4;
195 fwd_txfm_ref = fdct4x4_ref;
132 }196 }
197 virtual void TearDown() { libvpx_test::ClearSystemState(); }
198
199 protected:
200 void RunFwdTxfm(const int16_t *in, int16_t *out, int stride) {
201 fwd_txfm_(in, out, stride);
202 }
203 void RunInvTxfm(const int16_t *out, uint8_t *dst, int stride) {
204 inv_txfm_(out, dst, stride);
205 }
206
207 fdct_t fwd_txfm_;
208 idct_t inv_txfm_;
209};
210
211TEST_P(Trans4x4DCT, AccuracyCheck) {
212 RunAccuracyCheck();
133}213}
134 214
135TEST_P(FwdTrans4x4Test, RoundTripErrorCheck) {215TEST_P(Trans4x4DCT, CoeffCheck) {
136 ACMRandom rnd(ACMRandom::DeterministicSeed());216 RunCoeffCheck();
137 217}
138 int max_error = 0;
139 int total_error = 0;
140 const int count_test_block = 1000000;
141 for (int i = 0; i < count_test_block; ++i) {
142 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 16);
143 DECLARE_ALIGNED_ARRAY(16, int16_t, test_temp_block, 16);
144 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, 16);
145 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, 16);
146
147 for (int j = 0; j < 16; ++j) {
148 src[j] = rnd.Rand8();
149 dst[j] = rnd.Rand8();
150 }
151 // Initialize a test block with input range [-255, 255].
152 for (int j = 0; j < 16; ++j)
153 test_input_block[j] = src[j] - dst[j];
154
155 const int pitch = 4;
156 RunFwdTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_);
157
158 for (int j = 0; j < 16; ++j) {
159 if (test_temp_block[j] > 0) {
160 test_temp_block[j] += 2;
161 test_temp_block[j] /= 4;
162 test_temp_block[j] *= 4;
163 } else {
164 test_temp_block[j] -= 2;
165 test_temp_block[j] /= 4;
166 test_temp_block[j] *= 4;
167 }
168 }
169 218
170 // inverse transform and reconstruct the pixel block219TEST_P(Trans4x4DCT, MemCheck) {
171 RunInvTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_);220 RunMemCheck();
221}
172 222
173 for (int j = 0; j < 16; ++j) {223TEST_P(Trans4x4DCT, InvAccuracyCheck) {
174 const int diff = dst[j] - src[j];224 RunInvAccuracyCheck();
175 const int error = diff * diff;225}
176 if (max_error < error)226
177 max_error = error;227class Trans4x4HT
178 total_error += error;228 : public Trans4x4TestBase,
179 }229 public PARAMS(fht_t, iht_t, int) {
230 public:
231 virtual ~Trans4x4HT() {}
232
233 virtual void SetUp() {
234 fwd_txfm_ = GET_PARAM(0);
235 inv_txfm_ = GET_PARAM(1);
236 tx_type_ = GET_PARAM(2);
237 pitch_ = 4;
238 fwd_txfm_ref = fht4x4_ref;
180 }239 }
181 EXPECT_GE(1, max_error)240 virtual void TearDown() { libvpx_test::ClearSystemState(); }
182 << "Error: FDCT/IDCT or FHT/IHT has an individual roundtrip error > 1";
183 241
184 EXPECT_GE(count_test_block, total_error)242 protected:
185 << "Error: FDCT/IDCT or FHT/IHT has average "243 void RunFwdTxfm(const int16_t *in, int16_t *out, int stride) {
186 << "roundtrip error > 1 per block";244 fwd_txfm_(in, out, stride, tx_type_);
245 }
246
247 void RunInvTxfm(const int16_t *out, uint8_t *dst, int stride) {
248 inv_txfm_(out, dst, stride, tx_type_);
249 }
250
251 fht_t fwd_txfm_;
252 iht_t inv_txfm_;
253};
254
255TEST_P(Trans4x4HT, AccuracyCheck) {
256 RunAccuracyCheck();
257}
258
259TEST_P(Trans4x4HT, CoeffCheck) {
260 RunCoeffCheck();
261}
262
263TEST_P(Trans4x4HT, MemCheck) {
264 RunMemCheck();
265}
266
267TEST_P(Trans4x4HT, InvAccuracyCheck) {
268 RunInvAccuracyCheck();
187}269}
188 270
189INSTANTIATE_TEST_CASE_P(VP9, FwdTrans4x4Test, ::testing::Range(0, 4));271using std::tr1::make_tuple;
272
273INSTANTIATE_TEST_CASE_P(
274 C, Trans4x4DCT,
275 ::testing::Values(
276 make_tuple(&vp9_fdct4x4_c, &vp9_idct4x4_16_add_c, 0)));
277INSTANTIATE_TEST_CASE_P(
278 C, Trans4x4HT,
279 ::testing::Values(
280 make_tuple(&vp9_short_fht4x4_c, &vp9_iht4x4_16_add_c, 0),
281 make_tuple(&vp9_short_fht4x4_c, &vp9_iht4x4_16_add_c, 1),
282 make_tuple(&vp9_short_fht4x4_c, &vp9_iht4x4_16_add_c, 2),
283 make_tuple(&vp9_short_fht4x4_c, &vp9_iht4x4_16_add_c, 3)));
284
285#if HAVE_SSE2
286INSTANTIATE_TEST_CASE_P(
287 SSE2, Trans4x4DCT,
288 ::testing::Values(
289 make_tuple(&vp9_fdct4x4_sse2,
290 &vp9_idct4x4_16_add_sse2, 0)));
291INSTANTIATE_TEST_CASE_P(
292 SSE2, Trans4x4HT,
293 ::testing::Values(
294 make_tuple(&vp9_short_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 0),
295 make_tuple(&vp9_short_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 1),
296 make_tuple(&vp9_short_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 2),
297 make_tuple(&vp9_short_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 3)));
298#endif
299
190} // namespace300} // namespace

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t