Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: source/libvpx/test/fdct4x4_test.cc

Issue 111463005: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « source/libvpx/test/external_frame_buffer_test.cc ('k') | source/libvpx/test/fdct8x8_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include <math.h> 11 #include <math.h>
12 #include <stdlib.h> 12 #include <stdlib.h>
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
17 extern "C" { 21 extern "C" {
22 #include "vp9/common/vp9_entropy.h"
18 #include "./vp9_rtcd.h" 23 #include "./vp9_rtcd.h"
19 } 24 void vp9_idct4x4_16_add_c(const int16_t *input, uint8_t *output, int pitch);
20 25 }
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
25 using libvpx_test::ACMRandom; 28 using libvpx_test::ACMRandom;
26 29
27 namespace { 30 namespace {
28 void fdct4x4(int16_t *in, int16_t *out, uint8_t* /*dst*/, 31 const int kNumCoeffs = 16;
29 int stride, int /*tx_type*/) { 32 typedef void (*fdct_t)(const int16_t *in, int16_t *out, int stride);
33 typedef void (*idct_t)(const int16_t *in, uint8_t *out, int stride);
34 typedef void (*fht_t) (const int16_t *in, int16_t *out, int stride,
35 int tx_type);
36 typedef void (*iht_t) (const int16_t *in, uint8_t *out, int stride,
37 int tx_type);
38
39 typedef std::tr1::tuple<fdct_t, idct_t, int> dct_4x4_param_t;
40 typedef std::tr1::tuple<fht_t, iht_t, int> ht_4x4_param_t;
41
42 void fdct4x4_ref(const int16_t *in, int16_t *out, int stride, int tx_type) {
30 vp9_fdct4x4_c(in, out, stride); 43 vp9_fdct4x4_c(in, out, stride);
31 } 44 }
32 void idct4x4_add(int16_t* /*in*/, int16_t *out, uint8_t *dst, 45
33 int stride, int /*tx_type*/) { 46 void fht4x4_ref(const int16_t *in, int16_t *out, int stride, int tx_type) {
34 vp9_idct4x4_16_add_c(out, dst, stride);
35 }
36 void 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); 47 vp9_short_fht4x4_c(in, out, stride, tx_type);
39 } 48 }
40 void iht4x4_add(int16_t* /*in*/, int16_t *out, uint8_t *dst, 49
41 int stride, int tx_type) { 50 class Trans4x4TestBase {
42 vp9_iht4x4_16_add_c(out, dst, stride, tx_type);
43 }
44
45 class FwdTrans4x4Test : public ::testing::TestWithParam<int> {
46 public: 51 public:
47 virtual ~FwdTrans4x4Test() {} 52 virtual ~Trans4x4TestBase() {}
53
54 protected:
55 virtual void RunFwdTxfm(const int16_t *in, int16_t *out, int stride) = 0;
56
57 virtual void RunInvTxfm(const int16_t *out, uint8_t *dst, int stride) = 0;
58
59 void RunAccuracyCheck() {
60 ACMRandom rnd(ACMRandom::DeterministicSeed());
61 uint32_t max_error = 0;
62 int64_t total_error = 0;
63 const int count_test_block = 10000;
64 for (int i = 0; i < count_test_block; ++i) {
65 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, kNumCoeffs);
66 DECLARE_ALIGNED_ARRAY(16, int16_t, test_temp_block, kNumCoeffs);
67 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs);
68 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs);
69
70 // Initialize a test block with input range [-255, 255].
71 for (int j = 0; j < kNumCoeffs; ++j) {
72 src[j] = rnd.Rand8();
73 dst[j] = rnd.Rand8();
74 test_input_block[j] = src[j] - dst[j];
75 }
76
77 REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block,
78 test_temp_block, pitch_));
79 REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
80
81 for (int j = 0; j < kNumCoeffs; ++j) {
82 const uint32_t diff = dst[j] - src[j];
83 const uint32_t error = diff * diff;
84 if (max_error < error)
85 max_error = error;
86 total_error += error;
87 }
88 }
89
90 EXPECT_GE(1u, max_error)
91 << "Error: 4x4 FHT/IHT has an individual round trip error > 1";
92
93 EXPECT_GE(count_test_block , total_error)
94 << "Error: 4x4 FHT/IHT has average round trip error > 1 per block";
95 }
96
97 void RunCoeffCheck() {
98 ACMRandom rnd(ACMRandom::DeterministicSeed());
99 const int count_test_block = 5000;
100 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs);
101 DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs);
102 DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, kNumCoeffs);
103
104 for (int i = 0; i < count_test_block; ++i) {
105 // Initialize a test block with input range [-255, 255].
106 for (int j = 0; j < kNumCoeffs; ++j)
107 input_block[j] = rnd.Rand8() - rnd.Rand8();
108
109 fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_);
110 REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_));
111
112 // The minimum quant value is 4.
113 for (int j = 0; j < kNumCoeffs; ++j)
114 EXPECT_EQ(output_block[j], output_ref_block[j]);
115 }
116 }
117
118 void RunMemCheck() {
119 ACMRandom rnd(ACMRandom::DeterministicSeed());
120 const int count_test_block = 5000;
121 DECLARE_ALIGNED_ARRAY(16, int16_t, input_block, kNumCoeffs);
122 DECLARE_ALIGNED_ARRAY(16, int16_t, input_extreme_block, kNumCoeffs);
123 DECLARE_ALIGNED_ARRAY(16, int16_t, output_ref_block, kNumCoeffs);
124 DECLARE_ALIGNED_ARRAY(16, int16_t, output_block, kNumCoeffs);
125
126 for (int i = 0; i < count_test_block; ++i) {
127 // Initialize a test block with input range [-255, 255].
128 for (int j = 0; j < kNumCoeffs; ++j) {
129 input_block[j] = rnd.Rand8() - rnd.Rand8();
130 input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255;
131 }
132 if (i == 0)
133 for (int j = 0; j < kNumCoeffs; ++j)
134 input_extreme_block[j] = 255;
135 if (i == 1)
136 for (int j = 0; j < kNumCoeffs; ++j)
137 input_extreme_block[j] = -255;
138
139 fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);
140 REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block,
141 output_block, pitch_));
142
143 // The minimum quant value is 4.
144 for (int j = 0; j < kNumCoeffs; ++j) {
145 EXPECT_EQ(output_block[j], output_ref_block[j]);
146 EXPECT_GE(4 * DCT_MAX_VALUE, abs(output_block[j]))
147 << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE";
148 }
149 }
150 }
151
152 void RunInvAccuracyCheck() {
153 ACMRandom rnd(ACMRandom::DeterministicSeed());
154 const int count_test_block = 1000;
155 DECLARE_ALIGNED_ARRAY(16, int16_t, in, kNumCoeffs);
156 DECLARE_ALIGNED_ARRAY(16, int16_t, coeff, kNumCoeffs);
157 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs);
158 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs);
159
160 for (int i = 0; i < count_test_block; ++i) {
161 // Initialize a test block with input range [-255, 255].
162 for (int j = 0; j < kNumCoeffs; ++j) {
163 src[j] = rnd.Rand8();
164 dst[j] = rnd.Rand8();
165 in[j] = src[j] - dst[j];
166 }
167
168 fwd_txfm_ref(in, coeff, pitch_, tx_type_);
169
170 REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
171
172 for (int j = 0; j < kNumCoeffs; ++j) {
173 const uint32_t diff = dst[j] - src[j];
174 const uint32_t error = diff * diff;
175 EXPECT_GE(1u, error)
176 << "Error: 16x16 IDCT has error " << error
177 << " at index " << j;
178 }
179 }
180 }
181
182 int pitch_;
183 int tx_type_;
184 fht_t fwd_txfm_ref;
185 };
186
187 class Trans4x4DCT
188 : public Trans4x4TestBase,
189 public ::testing::TestWithParam<dct_4x4_param_t> {
190 public:
191 virtual ~Trans4x4DCT() {}
192
48 virtual void SetUp() { 193 virtual void SetUp() {
49 tx_type_ = GetParam(); 194 fwd_txfm_ = GET_PARAM(0);
50 if (tx_type_ == 0) { 195 inv_txfm_ = GET_PARAM(1);
51 fwd_txfm_ = fdct4x4; 196 tx_type_ = GET_PARAM(2);
52 inv_txfm_ = idct4x4_add; 197 pitch_ = 4;
53 } else { 198 fwd_txfm_ref = fdct4x4_ref;
54 fwd_txfm_ = fht4x4; 199 }
55 inv_txfm_ = iht4x4_add; 200 virtual void TearDown() { libvpx_test::ClearSystemState(); }
56 }
57 }
58 201
59 protected: 202 protected:
60 void RunFwdTxfm(int16_t *in, int16_t *out, uint8_t *dst, 203 void RunFwdTxfm(const int16_t *in, int16_t *out, int stride) {
61 int stride, int tx_type) { 204 fwd_txfm_(in, out, stride);
62 (*fwd_txfm_)(in, out, dst, stride, tx_type); 205 }
63 } 206 void RunInvTxfm(const int16_t *out, uint8_t *dst, int stride) {
64 207 inv_txfm_(out, dst, stride);
65 void RunInvTxfm(int16_t *in, int16_t *out, uint8_t *dst, 208 }
66 int stride, int tx_type) { 209
67 (*inv_txfm_)(in, out, dst, stride, tx_type); 210 fdct_t fwd_txfm_;
68 } 211 idct_t inv_txfm_;
69
70 int tx_type_;
71 void (*fwd_txfm_)(int16_t *in, int16_t *out, uint8_t *dst,
72 int stride, int tx_type);
73 void (*inv_txfm_)(int16_t *in, int16_t *out, uint8_t *dst,
74 int stride, int tx_type);
75 }; 212 };
76 213
77 TEST_P(FwdTrans4x4Test, SignBiasCheck) { 214 TEST_P(Trans4x4DCT, AccuracyCheck) {
78 ACMRandom rnd(ACMRandom::DeterministicSeed()); 215 RunAccuracyCheck();
79 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 16); 216 }
80 DECLARE_ALIGNED_ARRAY(16, int16_t, test_output_block, 16); 217
81 const int pitch = 4; 218 TEST_P(Trans4x4DCT, CoeffCheck) {
82 int count_sign_block[16][2]; 219 RunCoeffCheck();
83 const int count_test_block = 1000000; 220 }
84 221
85 memset(count_sign_block, 0, sizeof(count_sign_block)); 222 TEST_P(Trans4x4DCT, MemCheck) {
86 for (int i = 0; i < count_test_block; ++i) { 223 RunMemCheck();
87 // Initialize a test block with input range [-255, 255]. 224 }
88 for (int j = 0; j < 16; ++j) 225
89 test_input_block[j] = rnd.Rand8() - rnd.Rand8(); 226 TEST_P(Trans4x4DCT, InvAccuracyCheck) {
90 227 RunInvAccuracyCheck();
91 RunFwdTxfm(test_input_block, test_output_block, NULL, pitch, tx_type_); 228 }
92 229
93 for (int j = 0; j < 16; ++j) { 230 class Trans4x4HT
94 if (test_output_block[j] < 0) 231 : public Trans4x4TestBase,
95 ++count_sign_block[j][0]; 232 public ::testing::TestWithParam<ht_4x4_param_t> {
96 else if (test_output_block[j] > 0) 233 public:
97 ++count_sign_block[j][1]; 234 virtual ~Trans4x4HT() {}
98 } 235
99 } 236 virtual void SetUp() {
100 237 fwd_txfm_ = GET_PARAM(0);
101 for (int j = 0; j < 16; ++j) { 238 inv_txfm_ = GET_PARAM(1);
102 const bool bias_acceptable = (abs(count_sign_block[j][0] - 239 tx_type_ = GET_PARAM(2);
103 count_sign_block[j][1]) < 10000); 240 pitch_ = 4;
104 EXPECT_TRUE(bias_acceptable) 241 fwd_txfm_ref = fht4x4_ref;
105 << "Error: 4x4 FDCT/FHT has a sign bias > 1%" 242 }
106 << " for input range [-255, 255] at index " << j 243 virtual void TearDown() { libvpx_test::ClearSystemState(); }
107 << " tx_type " << tx_type_; 244
108 } 245 protected:
109 246 void RunFwdTxfm(const int16_t *in, int16_t *out, int stride) {
110 memset(count_sign_block, 0, sizeof(count_sign_block)); 247 fwd_txfm_(in, out, stride, tx_type_);
111 for (int i = 0; i < count_test_block; ++i) { 248 }
112 // Initialize a test block with input range [-15, 15]. 249
113 for (int j = 0; j < 16; ++j) 250 void RunInvTxfm(const int16_t *out, uint8_t *dst, int stride) {
114 test_input_block[j] = (rnd.Rand8() >> 4) - (rnd.Rand8() >> 4); 251 inv_txfm_(out, dst, stride, tx_type_);
115 252 }
116 RunFwdTxfm(test_input_block, test_output_block, NULL, pitch, tx_type_); 253
117 254 fht_t fwd_txfm_;
118 for (int j = 0; j < 16; ++j) { 255 iht_t inv_txfm_;
119 if (test_output_block[j] < 0) 256 };
120 ++count_sign_block[j][0]; 257
121 else if (test_output_block[j] > 0) 258 TEST_P(Trans4x4HT, AccuracyCheck) {
122 ++count_sign_block[j][1]; 259 RunAccuracyCheck();
123 } 260 }
124 } 261
125 262 TEST_P(Trans4x4HT, CoeffCheck) {
126 for (int j = 0; j < 16; ++j) { 263 RunCoeffCheck();
127 const bool bias_acceptable = (abs(count_sign_block[j][0] - 264 }
128 count_sign_block[j][1]) < 100000); 265
129 EXPECT_TRUE(bias_acceptable) 266 TEST_P(Trans4x4HT, MemCheck) {
130 << "Error: 4x4 FDCT/FHT has a sign bias > 10%" 267 RunMemCheck();
131 << " for input range [-15, 15] at index " << j; 268 }
132 } 269
133 } 270 TEST_P(Trans4x4HT, InvAccuracyCheck) {
134 271 RunInvAccuracyCheck();
135 TEST_P(FwdTrans4x4Test, RoundTripErrorCheck) { 272 }
136 ACMRandom rnd(ACMRandom::DeterministicSeed()); 273
137 274 using std::tr1::make_tuple;
138 int max_error = 0; 275
139 int total_error = 0; 276 INSTANTIATE_TEST_CASE_P(
140 const int count_test_block = 1000000; 277 C, Trans4x4DCT,
141 for (int i = 0; i < count_test_block; ++i) { 278 ::testing::Values(
142 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 16); 279 make_tuple(&vp9_fdct4x4_c, &vp9_idct4x4_16_add_c, 0)));
143 DECLARE_ALIGNED_ARRAY(16, int16_t, test_temp_block, 16); 280 INSTANTIATE_TEST_CASE_P(
144 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, 16); 281 C, Trans4x4HT,
145 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, 16); 282 ::testing::Values(
146 283 make_tuple(&vp9_short_fht4x4_c, &vp9_iht4x4_16_add_c, 0),
147 for (int j = 0; j < 16; ++j) { 284 make_tuple(&vp9_short_fht4x4_c, &vp9_iht4x4_16_add_c, 1),
148 src[j] = rnd.Rand8(); 285 make_tuple(&vp9_short_fht4x4_c, &vp9_iht4x4_16_add_c, 2),
149 dst[j] = rnd.Rand8(); 286 make_tuple(&vp9_short_fht4x4_c, &vp9_iht4x4_16_add_c, 3)));
150 } 287
151 // Initialize a test block with input range [-255, 255]. 288 #if HAVE_SSE2
152 for (int j = 0; j < 16; ++j) 289 INSTANTIATE_TEST_CASE_P(
153 test_input_block[j] = src[j] - dst[j]; 290 SSE2, Trans4x4DCT,
154 291 ::testing::Values(
155 const int pitch = 4; 292 make_tuple(&vp9_fdct4x4_sse2,
156 RunFwdTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_); 293 &vp9_idct4x4_16_add_sse2, 0)));
157 294 INSTANTIATE_TEST_CASE_P(
158 for (int j = 0; j < 16; ++j) { 295 SSE2, Trans4x4HT,
159 if (test_temp_block[j] > 0) { 296 ::testing::Values(
160 test_temp_block[j] += 2; 297 make_tuple(&vp9_short_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 0),
161 test_temp_block[j] /= 4; 298 make_tuple(&vp9_short_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 1),
162 test_temp_block[j] *= 4; 299 make_tuple(&vp9_short_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 2),
163 } else { 300 make_tuple(&vp9_short_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 3)));
164 test_temp_block[j] -= 2; 301 #endif
165 test_temp_block[j] /= 4; 302
166 test_temp_block[j] *= 4;
167 }
168 }
169
170 // inverse transform and reconstruct the pixel block
171 RunInvTxfm(test_input_block, test_temp_block, dst, pitch, tx_type_);
172
173 for (int j = 0; j < 16; ++j) {
174 const int diff = dst[j] - src[j];
175 const int error = diff * diff;
176 if (max_error < error)
177 max_error = error;
178 total_error += error;
179 }
180 }
181 EXPECT_GE(1, max_error)
182 << "Error: FDCT/IDCT or FHT/IHT has an individual roundtrip error > 1";
183
184 EXPECT_GE(count_test_block, total_error)
185 << "Error: FDCT/IDCT or FHT/IHT has average "
186 << "roundtrip error > 1 per block";
187 }
188
189 INSTANTIATE_TEST_CASE_P(VP9, FwdTrans4x4Test, ::testing::Range(0, 4));
190 } // namespace 303 } // namespace
OLDNEW
« no previous file with comments | « source/libvpx/test/external_frame_buffer_test.cc ('k') | source/libvpx/test/fdct8x8_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698