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

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

Issue 592203002: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 6 years, 2 months 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/fdct4x4_test.cc ('k') | source/libvpx/test/idct8x8_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" 16 #include "test/acm_random.h"
17 #include "test/clear_system_state.h" 17 #include "test/clear_system_state.h"
18 #include "test/register_state_check.h" 18 #include "test/register_state_check.h"
19 #include "test/util.h" 19 #include "test/util.h"
20 20
21 #include "./vp9_rtcd.h" 21 #include "./vp9_rtcd.h"
22 #include "vp9/common/vp9_entropy.h" 22 #include "vp9/common/vp9_entropy.h"
23 #include "vpx/vpx_codec.h"
23 #include "vpx/vpx_integer.h" 24 #include "vpx/vpx_integer.h"
24 25
25 extern "C" { 26 const int kNumCoeffs = 64;
26 void vp9_idct8x8_64_add_c(const int16_t *input, uint8_t *output, int pitch); 27 const double kPi = 3.141592653589793238462643383279502884;
28 void reference_8x8_dct_1d(const double in[8], double out[8], int stride) {
29 const double kInvSqrt2 = 0.707106781186547524400844362104;
30 for (int k = 0; k < 8; k++) {
31 out[k] = 0.0;
32 for (int n = 0; n < 8; n++)
33 out[k] += in[n] * cos(kPi * (2 * n + 1) * k / 16.0);
34 if (k == 0)
35 out[k] = out[k] * kInvSqrt2;
36 }
37 }
38
39 void reference_8x8_dct_2d(const int16_t input[kNumCoeffs],
40 double output[kNumCoeffs]) {
41 // First transform columns
42 for (int i = 0; i < 8; ++i) {
43 double temp_in[8], temp_out[8];
44 for (int j = 0; j < 8; ++j)
45 temp_in[j] = input[j*8 + i];
46 reference_8x8_dct_1d(temp_in, temp_out, 1);
47 for (int j = 0; j < 8; ++j)
48 output[j * 8 + i] = temp_out[j];
49 }
50 // Then transform rows
51 for (int i = 0; i < 8; ++i) {
52 double temp_in[8], temp_out[8];
53 for (int j = 0; j < 8; ++j)
54 temp_in[j] = output[j + i*8];
55 reference_8x8_dct_1d(temp_in, temp_out, 1);
56 // Scale by some magic number
57 for (int j = 0; j < 8; ++j)
58 output[j + i * 8] = temp_out[j] * 2;
59 }
27 } 60 }
28 61
29 using libvpx_test::ACMRandom; 62 using libvpx_test::ACMRandom;
30 63
31 namespace { 64 namespace {
32 typedef void (*FdctFunc)(const int16_t *in, int16_t *out, int stride); 65 typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride);
33 typedef void (*IdctFunc)(const int16_t *in, uint8_t *out, int stride); 66 typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride);
34 typedef void (*FhtFunc)(const int16_t *in, int16_t *out, int stride, 67 typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
35 int tx_type); 68 int tx_type);
36 typedef void (*IhtFunc)(const int16_t *in, uint8_t *out, int stride, 69 typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
37 int tx_type); 70 int tx_type);
38 71
39 typedef std::tr1::tuple<FdctFunc, IdctFunc, int> Dct8x8Param; 72 typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct8x8Param;
40 typedef std::tr1::tuple<FhtFunc, IhtFunc, int> Ht8x8Param; 73 typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht8x8Param;
41 74
42 void fdct8x8_ref(const int16_t *in, int16_t *out, int stride, int /*tx_type*/) { 75 void fdct8x8_ref(const int16_t *in, tran_low_t *out, int stride, int tx_type) {
43 vp9_fdct8x8_c(in, out, stride); 76 vp9_fdct8x8_c(in, out, stride);
44 } 77 }
45 78
46 void fht8x8_ref(const int16_t *in, int16_t *out, int stride, int tx_type) { 79 void fht8x8_ref(const int16_t *in, tran_low_t *out, int stride, int tx_type) {
47 vp9_fht8x8_c(in, out, stride, tx_type); 80 vp9_fht8x8_c(in, out, stride, tx_type);
48 } 81 }
49 82
83 #if CONFIG_VP9_HIGHBITDEPTH
84 void idct8x8_10(const tran_low_t *in, uint8_t *out, int stride) {
85 vp9_high_idct8x8_64_add_c(in, out, stride, 10);
86 }
87
88 void idct8x8_12(const tran_low_t *in, uint8_t *out, int stride) {
89 vp9_high_idct8x8_64_add_c(in, out, stride, 12);
90 }
91
92 void iht8x8_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
93 vp9_high_iht8x8_64_add_c(in, out, stride, tx_type, 10);
94 }
95
96 void iht8x8_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
97 vp9_high_iht8x8_64_add_c(in, out, stride, tx_type, 12);
98 }
99 #endif
100
50 class FwdTrans8x8TestBase { 101 class FwdTrans8x8TestBase {
51 public: 102 public:
52 virtual ~FwdTrans8x8TestBase() {} 103 virtual ~FwdTrans8x8TestBase() {}
53 104
54 protected: 105 protected:
55 virtual void RunFwdTxfm(int16_t *in, int16_t *out, int stride) = 0; 106 virtual void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) = 0;
56 virtual void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) = 0; 107 virtual void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) = 0;
57 108
58 void RunSignBiasCheck() { 109 void RunSignBiasCheck() {
59 ACMRandom rnd(ACMRandom::DeterministicSeed()); 110 ACMRandom rnd(ACMRandom::DeterministicSeed());
60 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 64); 111 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 64);
61 DECLARE_ALIGNED_ARRAY(16, int16_t, test_output_block, 64); 112 DECLARE_ALIGNED_ARRAY(16, tran_low_t, test_output_block, 64);
62 int count_sign_block[64][2]; 113 int count_sign_block[64][2];
63 const int count_test_block = 100000; 114 const int count_test_block = 100000;
64 115
65 memset(count_sign_block, 0, sizeof(count_sign_block)); 116 memset(count_sign_block, 0, sizeof(count_sign_block));
66 117
67 for (int i = 0; i < count_test_block; ++i) { 118 for (int i = 0; i < count_test_block; ++i) {
68 // Initialize a test block with input range [-255, 255]. 119 // Initialize a test block with input range [-255, 255].
69 for (int j = 0; j < 64; ++j) 120 for (int j = 0; j < 64; ++j)
70 test_input_block[j] = rnd.Rand8() - rnd.Rand8(); 121 test_input_block[j] = ((rnd.Rand16() >> (16 - bit_depth_)) & mask_) -
122 ((rnd.Rand16() >> (16 - bit_depth_)) & mask_);
71 ASM_REGISTER_STATE_CHECK( 123 ASM_REGISTER_STATE_CHECK(
72 RunFwdTxfm(test_input_block, test_output_block, pitch_)); 124 RunFwdTxfm(test_input_block, test_output_block, pitch_));
73 125
74 for (int j = 0; j < 64; ++j) { 126 for (int j = 0; j < 64; ++j) {
75 if (test_output_block[j] < 0) 127 if (test_output_block[j] < 0)
76 ++count_sign_block[j][0]; 128 ++count_sign_block[j][0];
77 else if (test_output_block[j] > 0) 129 else if (test_output_block[j] > 0)
78 ++count_sign_block[j][1]; 130 ++count_sign_block[j][1];
79 } 131 }
80 } 132 }
81 133
82 for (int j = 0; j < 64; ++j) { 134 for (int j = 0; j < 64; ++j) {
83 const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]); 135 const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
84 const int max_diff = 1125; 136 const int max_diff = 1125;
85 EXPECT_LT(diff, max_diff) 137 EXPECT_LT(diff, max_diff << (bit_depth_ - 8))
86 << "Error: 8x8 FDCT/FHT has a sign bias > " 138 << "Error: 8x8 FDCT/FHT has a sign bias > "
87 << 1. * max_diff / count_test_block * 100 << "%" 139 << 1. * max_diff / count_test_block * 100 << "%"
88 << " for input range [-255, 255] at index " << j 140 << " for input range [-255, 255] at index " << j
89 << " count0: " << count_sign_block[j][0] 141 << " count0: " << count_sign_block[j][0]
90 << " count1: " << count_sign_block[j][1] 142 << " count1: " << count_sign_block[j][1]
91 << " diff: " << diff; 143 << " diff: " << diff;
92 } 144 }
93 145
94 memset(count_sign_block, 0, sizeof(count_sign_block)); 146 memset(count_sign_block, 0, sizeof(count_sign_block));
95 147
96 for (int i = 0; i < count_test_block; ++i) { 148 for (int i = 0; i < count_test_block; ++i) {
97 // Initialize a test block with input range [-15, 15]. 149 // Initialize a test block with input range [-15, 15].
98 for (int j = 0; j < 64; ++j) 150 for (int j = 0; j < 64; ++j)
99 test_input_block[j] = (rnd.Rand8() >> 4) - (rnd.Rand8() >> 4); 151 test_input_block[j] = (rnd.Rand8() >> 4) - (rnd.Rand8() >> 4);
100 ASM_REGISTER_STATE_CHECK( 152 ASM_REGISTER_STATE_CHECK(
101 RunFwdTxfm(test_input_block, test_output_block, pitch_)); 153 RunFwdTxfm(test_input_block, test_output_block, pitch_));
102 154
103 for (int j = 0; j < 64; ++j) { 155 for (int j = 0; j < 64; ++j) {
104 if (test_output_block[j] < 0) 156 if (test_output_block[j] < 0)
105 ++count_sign_block[j][0]; 157 ++count_sign_block[j][0];
106 else if (test_output_block[j] > 0) 158 else if (test_output_block[j] > 0)
107 ++count_sign_block[j][1]; 159 ++count_sign_block[j][1];
108 } 160 }
109 } 161 }
110 162
111 for (int j = 0; j < 64; ++j) { 163 for (int j = 0; j < 64; ++j) {
112 const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]); 164 const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
113 const int max_diff = 10000; 165 const int max_diff = 10000;
114 EXPECT_LT(diff, max_diff) 166 EXPECT_LT(diff, max_diff << (bit_depth_ - 8))
115 << "Error: 4x4 FDCT/FHT has a sign bias > " 167 << "Error: 4x4 FDCT/FHT has a sign bias > "
116 << 1. * max_diff / count_test_block * 100 << "%" 168 << 1. * max_diff / count_test_block * 100 << "%"
117 << " for input range [-15, 15] at index " << j 169 << " for input range [-15, 15] at index " << j
118 << " count0: " << count_sign_block[j][0] 170 << " count0: " << count_sign_block[j][0]
119 << " count1: " << count_sign_block[j][1] 171 << " count1: " << count_sign_block[j][1]
120 << " diff: " << diff; 172 << " diff: " << diff;
121 } 173 }
122 } 174 }
123 175
124 void RunRoundTripErrorCheck() { 176 void RunRoundTripErrorCheck() {
125 ACMRandom rnd(ACMRandom::DeterministicSeed()); 177 ACMRandom rnd(ACMRandom::DeterministicSeed());
126 int max_error = 0; 178 int max_error = 0;
127 int total_error = 0; 179 int total_error = 0;
128 const int count_test_block = 100000; 180 const int count_test_block = 100000;
129 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 64); 181 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 64);
130 DECLARE_ALIGNED_ARRAY(16, int16_t, test_temp_block, 64); 182 DECLARE_ALIGNED_ARRAY(16, tran_low_t, test_temp_block, 64);
131 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, 64); 183 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, 64);
132 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, 64); 184 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, 64);
185 #if CONFIG_VP9_HIGHBITDEPTH
186 DECLARE_ALIGNED_ARRAY(16, uint16_t, dst16, 64);
187 DECLARE_ALIGNED_ARRAY(16, uint16_t, src16, 64);
188 #endif
133 189
134 for (int i = 0; i < count_test_block; ++i) { 190 for (int i = 0; i < count_test_block; ++i) {
135 // Initialize a test block with input range [-255, 255]. 191 // Initialize a test block with input range [-255, 255].
136 for (int j = 0; j < 64; ++j) { 192 for (int j = 0; j < 64; ++j) {
137 src[j] = rnd.Rand8(); 193 if (bit_depth_ == VPX_BITS_8) {
138 dst[j] = rnd.Rand8(); 194 src[j] = rnd.Rand8();
139 test_input_block[j] = src[j] - dst[j]; 195 dst[j] = rnd.Rand8();
196 test_input_block[j] = src[j] - dst[j];
197 #if CONFIG_VP9_HIGHBITDEPTH
198 } else {
199 src16[j] = rnd.Rand16() & mask_;
200 dst16[j] = rnd.Rand16() & mask_;
201 test_input_block[j] = src16[j] - dst16[j];
202 #endif
203 }
140 } 204 }
141 205
142 ASM_REGISTER_STATE_CHECK( 206 ASM_REGISTER_STATE_CHECK(
143 RunFwdTxfm(test_input_block, test_temp_block, pitch_)); 207 RunFwdTxfm(test_input_block, test_temp_block, pitch_));
144 for (int j = 0; j < 64; ++j) { 208 for (int j = 0; j < 64; ++j) {
145 if (test_temp_block[j] > 0) { 209 if (test_temp_block[j] > 0) {
146 test_temp_block[j] += 2; 210 test_temp_block[j] += 2;
147 test_temp_block[j] /= 4; 211 test_temp_block[j] /= 4;
148 test_temp_block[j] *= 4; 212 test_temp_block[j] *= 4;
149 } else { 213 } else {
150 test_temp_block[j] -= 2; 214 test_temp_block[j] -= 2;
151 test_temp_block[j] /= 4; 215 test_temp_block[j] /= 4;
152 test_temp_block[j] *= 4; 216 test_temp_block[j] *= 4;
153 } 217 }
154 } 218 }
155 ASM_REGISTER_STATE_CHECK( 219 if (bit_depth_ == VPX_BITS_8) {
156 RunInvTxfm(test_temp_block, dst, pitch_)); 220 ASM_REGISTER_STATE_CHECK(
221 RunInvTxfm(test_temp_block, dst, pitch_));
222 #if CONFIG_VP9_HIGHBITDEPTH
223 } else {
224 ASM_REGISTER_STATE_CHECK(
225 RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
226 #endif
227 }
157 228
158 for (int j = 0; j < 64; ++j) { 229 for (int j = 0; j < 64; ++j) {
230 #if CONFIG_VP9_HIGHBITDEPTH
231 const int diff =
232 bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
233 #else
159 const int diff = dst[j] - src[j]; 234 const int diff = dst[j] - src[j];
235 #endif
160 const int error = diff * diff; 236 const int error = diff * diff;
161 if (max_error < error) 237 if (max_error < error)
162 max_error = error; 238 max_error = error;
163 total_error += error; 239 total_error += error;
164 } 240 }
165 } 241 }
166 242
167 EXPECT_GE(1, max_error) 243 EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error)
168 << "Error: 8x8 FDCT/IDCT or FHT/IHT has an individual" 244 << "Error: 8x8 FDCT/IDCT or FHT/IHT has an individual"
169 << " roundtrip error > 1"; 245 << " roundtrip error > 1";
170 246
171 EXPECT_GE(count_test_block/5, total_error) 247 EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8))/5, total_error)
172 << "Error: 8x8 FDCT/IDCT or FHT/IHT has average roundtrip " 248 << "Error: 8x8 FDCT/IDCT or FHT/IHT has average roundtrip "
173 << "error > 1/5 per block"; 249 << "error > 1/5 per block";
174 } 250 }
175 251
176 void RunExtremalCheck() { 252 void RunExtremalCheck() {
177 ACMRandom rnd(ACMRandom::DeterministicSeed()); 253 ACMRandom rnd(ACMRandom::DeterministicSeed());
178 int max_error = 0; 254 int max_error = 0;
179 int total_error = 0; 255 int total_error = 0;
180 int total_coeff_error = 0; 256 int total_coeff_error = 0;
181 const int count_test_block = 100000; 257 const int count_test_block = 100000;
182 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 64); 258 DECLARE_ALIGNED_ARRAY(16, int16_t, test_input_block, 64);
183 DECLARE_ALIGNED_ARRAY(16, int16_t, test_temp_block, 64); 259 DECLARE_ALIGNED_ARRAY(16, tran_low_t, test_temp_block, 64);
184 DECLARE_ALIGNED_ARRAY(16, int16_t, ref_temp_block, 64); 260 DECLARE_ALIGNED_ARRAY(16, tran_low_t, ref_temp_block, 64);
185 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, 64); 261 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, 64);
186 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, 64); 262 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, 64);
263 #if CONFIG_VP9_HIGHBITDEPTH
264 DECLARE_ALIGNED_ARRAY(16, uint16_t, dst16, 64);
265 DECLARE_ALIGNED_ARRAY(16, uint16_t, src16, 64);
266 #endif
187 267
188 for (int i = 0; i < count_test_block; ++i) { 268 for (int i = 0; i < count_test_block; ++i) {
189 // Initialize a test block with input range [-255, 255]. 269 // Initialize a test block with input range [-mask_, mask_].
190 for (int j = 0; j < 64; ++j) { 270 for (int j = 0; j < 64; ++j) {
191 if (i == 0) { 271 if (bit_depth_ == VPX_BITS_8) {
192 src[j] = 255; 272 if (i == 0) {
193 dst[j] = 0; 273 src[j] = 255;
194 } else if (i == 1) { 274 dst[j] = 0;
195 src[j] = 0; 275 } else if (i == 1) {
196 dst[j] = 255; 276 src[j] = 0;
277 dst[j] = 255;
278 } else {
279 src[j] = rnd.Rand8() % 2 ? 255 : 0;
280 dst[j] = rnd.Rand8() % 2 ? 255 : 0;
281 }
282 test_input_block[j] = src[j] - dst[j];
283 #if CONFIG_VP9_HIGHBITDEPTH
197 } else { 284 } else {
198 src[j] = rnd.Rand8() % 2 ? 255 : 0; 285 if (i == 0) {
199 dst[j] = rnd.Rand8() % 2 ? 255 : 0; 286 src16[j] = mask_;
287 dst16[j] = 0;
288 } else if (i == 1) {
289 src16[j] = 0;
290 dst16[j] = mask_;
291 } else {
292 src16[j] = rnd.Rand8() % 2 ? mask_ : 0;
293 dst16[j] = rnd.Rand8() % 2 ? mask_ : 0;
294 }
295 test_input_block[j] = src16[j] - dst16[j];
296 #endif
200 } 297 }
201
202 test_input_block[j] = src[j] - dst[j];
203 } 298 }
204 299
205 ASM_REGISTER_STATE_CHECK( 300 ASM_REGISTER_STATE_CHECK(
206 RunFwdTxfm(test_input_block, test_temp_block, pitch_)); 301 RunFwdTxfm(test_input_block, test_temp_block, pitch_));
207 ASM_REGISTER_STATE_CHECK( 302 ASM_REGISTER_STATE_CHECK(
208 fwd_txfm_ref(test_input_block, ref_temp_block, pitch_, tx_type_)); 303 fwd_txfm_ref(test_input_block, ref_temp_block, pitch_, tx_type_));
209 ASM_REGISTER_STATE_CHECK( 304 if (bit_depth_ == VPX_BITS_8) {
210 RunInvTxfm(test_temp_block, dst, pitch_)); 305 ASM_REGISTER_STATE_CHECK(
306 RunInvTxfm(test_temp_block, dst, pitch_));
307 #if CONFIG_VP9_HIGHBITDEPTH
308 } else {
309 ASM_REGISTER_STATE_CHECK(
310 RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
311 #endif
312 }
211 313
212 for (int j = 0; j < 64; ++j) { 314 for (int j = 0; j < 64; ++j) {
315 #if CONFIG_VP9_HIGHBITDEPTH
316 const int diff =
317 bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
318 #else
213 const int diff = dst[j] - src[j]; 319 const int diff = dst[j] - src[j];
320 #endif
214 const int error = diff * diff; 321 const int error = diff * diff;
215 if (max_error < error) 322 if (max_error < error)
216 max_error = error; 323 max_error = error;
217 total_error += error; 324 total_error += error;
218 325
219 const int coeff_diff = test_temp_block[j] - ref_temp_block[j]; 326 const int coeff_diff = test_temp_block[j] - ref_temp_block[j];
220 total_coeff_error += abs(coeff_diff); 327 total_coeff_error += abs(coeff_diff);
221 } 328 }
222 329
223 EXPECT_GE(1, max_error) 330 EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error)
224 << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has" 331 << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has"
225 << "an individual roundtrip error > 1"; 332 << "an individual roundtrip error > 1";
226 333
227 EXPECT_GE(count_test_block/5, total_error) 334 EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8))/5, total_error)
228 << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has average" 335 << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has average"
229 << " roundtrip error > 1/5 per block"; 336 << " roundtrip error > 1/5 per block";
230 337
231 EXPECT_EQ(0, total_coeff_error) 338 EXPECT_EQ(0, total_coeff_error)
232 << "Error: Extremal 8x8 FDCT/FHT has" 339 << "Error: Extremal 8x8 FDCT/FHT has"
233 << "overflow issues in the intermediate steps > 1"; 340 << "overflow issues in the intermediate steps > 1";
234 } 341 }
235 } 342 }
236 343
344 void RunInvAccuracyCheck() {
345 ACMRandom rnd(ACMRandom::DeterministicSeed());
346 const int count_test_block = 1000;
347 DECLARE_ALIGNED_ARRAY(16, int16_t, in, kNumCoeffs);
348 DECLARE_ALIGNED_ARRAY(16, tran_low_t, coeff, kNumCoeffs);
349 DECLARE_ALIGNED_ARRAY(16, uint8_t, dst, kNumCoeffs);
350 DECLARE_ALIGNED_ARRAY(16, uint8_t, src, kNumCoeffs);
351 #if CONFIG_VP9_HIGHBITDEPTH
352 DECLARE_ALIGNED_ARRAY(16, uint16_t, src16, kNumCoeffs);
353 DECLARE_ALIGNED_ARRAY(16, uint16_t, dst16, kNumCoeffs);
354 #endif
355
356 for (int i = 0; i < count_test_block; ++i) {
357 double out_r[kNumCoeffs];
358
359 // Initialize a test block with input range [-255, 255].
360 for (int j = 0; j < kNumCoeffs; ++j) {
361 if (bit_depth_ == VPX_BITS_8) {
362 src[j] = rnd.Rand8() % 2 ? 255 : 0;
363 dst[j] = src[j] > 0 ? 0 : 255;
364 in[j] = src[j] - dst[j];
365 #if CONFIG_VP9_HIGHBITDEPTH
366 } else {
367 src16[j] = rnd.Rand8() % 2 ? mask_ : 0;
368 dst16[j] = src16[j] > 0 ? 0 : mask_;
369 in[j] = src16[j] - dst16[j];
370 #endif
371 }
372 }
373
374 reference_8x8_dct_2d(in, out_r);
375 for (int j = 0; j < kNumCoeffs; ++j)
376 coeff[j] = static_cast<tran_low_t>(round(out_r[j]));
377
378 if (bit_depth_ == VPX_BITS_8) {
379 ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
380 #if CONFIG_VP9_HIGHBITDEPTH
381 } else {
382 ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16),
383 pitch_));
384 #endif
385 }
386
387 for (int j = 0; j < kNumCoeffs; ++j) {
388 #if CONFIG_VP9_HIGHBITDEPTH
389 const uint32_t diff =
390 bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
391 #else
392 const uint32_t diff = dst[j] - src[j];
393 #endif
394 const uint32_t error = diff * diff;
395 EXPECT_GE(1u << 2 * (bit_depth_ - 8), error)
396 << "Error: 8x8 IDCT has error " << error
397 << " at index " << j;
398 }
399 }
400 }
401
402 void RunFwdAccuracyCheck() {
403 ACMRandom rnd(ACMRandom::DeterministicSeed());
404 const int count_test_block = 1000;
405 DECLARE_ALIGNED_ARRAY(16, int16_t, in, kNumCoeffs);
406 DECLARE_ALIGNED_ARRAY(16, tran_low_t, coeff_r, kNumCoeffs);
407 DECLARE_ALIGNED_ARRAY(16, tran_low_t, coeff, kNumCoeffs);
408
409 for (int i = 0; i < count_test_block; ++i) {
410 double out_r[kNumCoeffs];
411
412 // Initialize a test block with input range [-mask_, mask_].
413 for (int j = 0; j < kNumCoeffs; ++j)
414 in[j] = rnd.Rand8() % 2 == 0 ? mask_ : -mask_;
415
416 RunFwdTxfm(in, coeff, pitch_);
417 reference_8x8_dct_2d(in, out_r);
418 for (int j = 0; j < kNumCoeffs; ++j)
419 coeff_r[j] = static_cast<tran_low_t>(round(out_r[j]));
420
421 for (int j = 0; j < kNumCoeffs; ++j) {
422 const uint32_t diff = coeff[j] - coeff_r[j];
423 const uint32_t error = diff * diff;
424 EXPECT_GE(9u << 2 * (bit_depth_ - 8), error)
425 << "Error: 8x8 DCT has error " << error
426 << " at index " << j;
427 }
428 }
429 }
237 int pitch_; 430 int pitch_;
238 int tx_type_; 431 int tx_type_;
239 FhtFunc fwd_txfm_ref; 432 FhtFunc fwd_txfm_ref;
433 vpx_bit_depth_t bit_depth_;
434 int mask_;
240 }; 435 };
241 436
242 class FwdTrans8x8DCT 437 class FwdTrans8x8DCT
243 : public FwdTrans8x8TestBase, 438 : public FwdTrans8x8TestBase,
244 public ::testing::TestWithParam<Dct8x8Param> { 439 public ::testing::TestWithParam<Dct8x8Param> {
245 public: 440 public:
246 virtual ~FwdTrans8x8DCT() {} 441 virtual ~FwdTrans8x8DCT() {}
247 442
248 virtual void SetUp() { 443 virtual void SetUp() {
249 fwd_txfm_ = GET_PARAM(0); 444 fwd_txfm_ = GET_PARAM(0);
250 inv_txfm_ = GET_PARAM(1); 445 inv_txfm_ = GET_PARAM(1);
251 tx_type_ = GET_PARAM(2); 446 tx_type_ = GET_PARAM(2);
252 pitch_ = 8; 447 pitch_ = 8;
253 fwd_txfm_ref = fdct8x8_ref; 448 fwd_txfm_ref = fdct8x8_ref;
449 bit_depth_ = GET_PARAM(3);
450 mask_ = (1 << bit_depth_) - 1;
254 } 451 }
255 452
256 virtual void TearDown() { libvpx_test::ClearSystemState(); } 453 virtual void TearDown() { libvpx_test::ClearSystemState(); }
257 454
258 protected: 455 protected:
259 void RunFwdTxfm(int16_t *in, int16_t *out, int stride) { 456 void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
260 fwd_txfm_(in, out, stride); 457 fwd_txfm_(in, out, stride);
261 } 458 }
262 void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) { 459 void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
263 inv_txfm_(out, dst, stride); 460 inv_txfm_(out, dst, stride);
264 } 461 }
265 462
266 FdctFunc fwd_txfm_; 463 FdctFunc fwd_txfm_;
267 IdctFunc inv_txfm_; 464 IdctFunc inv_txfm_;
268 }; 465 };
269 466
270 TEST_P(FwdTrans8x8DCT, SignBiasCheck) { 467 TEST_P(FwdTrans8x8DCT, SignBiasCheck) {
271 RunSignBiasCheck(); 468 RunSignBiasCheck();
272 } 469 }
273 470
274 TEST_P(FwdTrans8x8DCT, RoundTripErrorCheck) { 471 TEST_P(FwdTrans8x8DCT, RoundTripErrorCheck) {
275 RunRoundTripErrorCheck(); 472 RunRoundTripErrorCheck();
276 } 473 }
277 474
278 TEST_P(FwdTrans8x8DCT, ExtremalCheck) { 475 TEST_P(FwdTrans8x8DCT, ExtremalCheck) {
279 RunExtremalCheck(); 476 RunExtremalCheck();
280 } 477 }
281 478
479 TEST_P(FwdTrans8x8DCT, FwdAccuracyCheck) {
480 RunFwdAccuracyCheck();
481 }
482
483 TEST_P(FwdTrans8x8DCT, InvAccuracyCheck) {
484 RunInvAccuracyCheck();
485 }
486
282 class FwdTrans8x8HT 487 class FwdTrans8x8HT
283 : public FwdTrans8x8TestBase, 488 : public FwdTrans8x8TestBase,
284 public ::testing::TestWithParam<Ht8x8Param> { 489 public ::testing::TestWithParam<Ht8x8Param> {
285 public: 490 public:
286 virtual ~FwdTrans8x8HT() {} 491 virtual ~FwdTrans8x8HT() {}
287 492
288 virtual void SetUp() { 493 virtual void SetUp() {
289 fwd_txfm_ = GET_PARAM(0); 494 fwd_txfm_ = GET_PARAM(0);
290 inv_txfm_ = GET_PARAM(1); 495 inv_txfm_ = GET_PARAM(1);
291 tx_type_ = GET_PARAM(2); 496 tx_type_ = GET_PARAM(2);
292 pitch_ = 8; 497 pitch_ = 8;
293 fwd_txfm_ref = fht8x8_ref; 498 fwd_txfm_ref = fht8x8_ref;
499 bit_depth_ = GET_PARAM(3);
500 mask_ = (1 << bit_depth_) - 1;
294 } 501 }
295 502
296 virtual void TearDown() { libvpx_test::ClearSystemState(); } 503 virtual void TearDown() { libvpx_test::ClearSystemState(); }
297 504
298 protected: 505 protected:
299 void RunFwdTxfm(int16_t *in, int16_t *out, int stride) { 506 void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
300 fwd_txfm_(in, out, stride, tx_type_); 507 fwd_txfm_(in, out, stride, tx_type_);
301 } 508 }
302 void RunInvTxfm(int16_t *out, uint8_t *dst, int stride) { 509 void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
303 inv_txfm_(out, dst, stride, tx_type_); 510 inv_txfm_(out, dst, stride, tx_type_);
304 } 511 }
305 512
306 FhtFunc fwd_txfm_; 513 FhtFunc fwd_txfm_;
307 IhtFunc inv_txfm_; 514 IhtFunc inv_txfm_;
308 }; 515 };
309 516
310 TEST_P(FwdTrans8x8HT, SignBiasCheck) { 517 TEST_P(FwdTrans8x8HT, SignBiasCheck) {
311 RunSignBiasCheck(); 518 RunSignBiasCheck();
312 } 519 }
313 520
314 TEST_P(FwdTrans8x8HT, RoundTripErrorCheck) { 521 TEST_P(FwdTrans8x8HT, RoundTripErrorCheck) {
315 RunRoundTripErrorCheck(); 522 RunRoundTripErrorCheck();
316 } 523 }
317 524
318 TEST_P(FwdTrans8x8HT, ExtremalCheck) { 525 TEST_P(FwdTrans8x8HT, ExtremalCheck) {
319 RunExtremalCheck(); 526 RunExtremalCheck();
320 } 527 }
321 528
322 using std::tr1::make_tuple; 529 using std::tr1::make_tuple;
323 530
531 #if CONFIG_VP9_HIGHBITDEPTH
324 INSTANTIATE_TEST_CASE_P( 532 INSTANTIATE_TEST_CASE_P(
325 C, FwdTrans8x8DCT, 533 C, FwdTrans8x8DCT,
326 ::testing::Values( 534 ::testing::Values(
327 make_tuple(&vp9_fdct8x8_c, &vp9_idct8x8_64_add_c, 0))); 535 make_tuple(&vp9_high_fdct8x8_c, &idct8x8_10, 0, VPX_BITS_10),
536 make_tuple(&vp9_high_fdct8x8_c, &idct8x8_12, 0, VPX_BITS_12),
537 make_tuple(&vp9_fdct8x8_c, &vp9_idct8x8_64_add_c, 0, VPX_BITS_8)));
538 #else
539 INSTANTIATE_TEST_CASE_P(
540 C, FwdTrans8x8DCT,
541 ::testing::Values(
542 make_tuple(&vp9_fdct8x8_c, &vp9_idct8x8_64_add_c, 0, VPX_BITS_8)));
543 #endif
544
545 #if CONFIG_VP9_HIGHBITDEPTH
328 INSTANTIATE_TEST_CASE_P( 546 INSTANTIATE_TEST_CASE_P(
329 C, FwdTrans8x8HT, 547 C, FwdTrans8x8HT,
330 ::testing::Values( 548 ::testing::Values(
331 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 0), 549 make_tuple(&vp9_high_fht8x8_c, &iht8x8_10, 0, VPX_BITS_10),
332 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 1), 550 make_tuple(&vp9_high_fht8x8_c, &iht8x8_10, 1, VPX_BITS_10),
333 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 2), 551 make_tuple(&vp9_high_fht8x8_c, &iht8x8_10, 2, VPX_BITS_10),
334 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 3))); 552 make_tuple(&vp9_high_fht8x8_c, &iht8x8_10, 3, VPX_BITS_10),
553 make_tuple(&vp9_high_fht8x8_c, &iht8x8_12, 0, VPX_BITS_12),
554 make_tuple(&vp9_high_fht8x8_c, &iht8x8_12, 1, VPX_BITS_12),
555 make_tuple(&vp9_high_fht8x8_c, &iht8x8_12, 2, VPX_BITS_12),
556 make_tuple(&vp9_high_fht8x8_c, &iht8x8_12, 3, VPX_BITS_12),
557 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 0, VPX_BITS_8),
558 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 1, VPX_BITS_8),
559 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 2, VPX_BITS_8),
560 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 3, VPX_BITS_8)));
561 #else
562 INSTANTIATE_TEST_CASE_P(
563 C, FwdTrans8x8HT,
564 ::testing::Values(
565 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 0, VPX_BITS_8),
566 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 1, VPX_BITS_8),
567 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 2, VPX_BITS_8),
568 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 3, VPX_BITS_8)));
569 #endif
335 570
336 #if HAVE_NEON_ASM 571 #if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH
337 INSTANTIATE_TEST_CASE_P( 572 INSTANTIATE_TEST_CASE_P(
338 NEON, FwdTrans8x8DCT, 573 NEON, FwdTrans8x8DCT,
339 ::testing::Values( 574 ::testing::Values(
340 make_tuple(&vp9_fdct8x8_neon, &vp9_idct8x8_64_add_neon, 0))); 575 make_tuple(&vp9_fdct8x8_neon, &vp9_idct8x8_64_add_neon, 0,
576 VPX_BITS_8)));
341 INSTANTIATE_TEST_CASE_P( 577 INSTANTIATE_TEST_CASE_P(
342 DISABLED_NEON, FwdTrans8x8HT, 578 DISABLED_NEON, FwdTrans8x8HT,
343 ::testing::Values( 579 ::testing::Values(
344 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 0), 580 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 0, VPX_BITS_8),
345 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 1), 581 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 1, VPX_BITS_8),
346 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 2), 582 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 2, VPX_BITS_8),
347 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 3))); 583 make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 3, VPX_BITS_8)));
348 #endif 584 #endif
349 585
350 #if HAVE_SSE2 586 #if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH
351 INSTANTIATE_TEST_CASE_P( 587 INSTANTIATE_TEST_CASE_P(
352 SSE2, FwdTrans8x8DCT, 588 SSE2, FwdTrans8x8DCT,
353 ::testing::Values( 589 ::testing::Values(
354 make_tuple(&vp9_fdct8x8_sse2, &vp9_idct8x8_64_add_sse2, 0))); 590 make_tuple(&vp9_fdct8x8_sse2, &vp9_idct8x8_64_add_sse2, 0,
591 VPX_BITS_8)));
355 INSTANTIATE_TEST_CASE_P( 592 INSTANTIATE_TEST_CASE_P(
356 SSE2, FwdTrans8x8HT, 593 SSE2, FwdTrans8x8HT,
357 ::testing::Values( 594 ::testing::Values(
358 make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 0), 595 make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 0, VPX_BITS_8),
359 make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 1), 596 make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 1, VPX_BITS_8),
360 make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 2), 597 make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 2, VPX_BITS_8),
361 make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 3))); 598 make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 3, VPX_BITS_8)));
362 #endif 599 #endif
363 600
364 #if HAVE_SSSE3 && ARCH_X86_64 601 #if HAVE_SSSE3 && ARCH_X86_64 && !CONFIG_VP9_HIGHBITDEPTH
365 INSTANTIATE_TEST_CASE_P( 602 INSTANTIATE_TEST_CASE_P(
366 SSSE3, FwdTrans8x8DCT, 603 SSSE3, FwdTrans8x8DCT,
367 ::testing::Values( 604 ::testing::Values(
368 make_tuple(&vp9_fdct8x8_ssse3, &vp9_idct8x8_64_add_ssse3, 0))); 605 make_tuple(&vp9_fdct8x8_ssse3, &vp9_idct8x8_64_add_ssse3, 0,
606 VPX_BITS_8)));
369 #endif 607 #endif
370 } // namespace 608 } // namespace
OLDNEW
« no previous file with comments | « source/libvpx/test/fdct4x4_test.cc ('k') | source/libvpx/test/idct8x8_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698