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

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

Issue 11555023: libvpx: Add VP9 decoder. (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 8 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3 *
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
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <math.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "third_party/googletest/src/include/gtest/gtest.h"
16
17 extern "C" {
18 #include "vp9/common/entropy.h"
19 #include "vp9_rtcd.h"
20 }
21
22 #include "acm_random.h"
23 #include "vpx/vpx_integer.h"
24
25 using libvpx_test::ACMRandom;
26
27 namespace {
28
29 const double PI = 3.1415926535898;
30 void reference2_16x16_idct_2d(double *input, double *output) {
31 double x;
32 for (int l = 0; l < 16; ++l) {
33 for (int k = 0; k < 16; ++k) {
34 double s = 0;
35 for (int i = 0; i < 16; ++i) {
36 for (int j = 0; j < 16; ++j) {
37 x=cos(PI*j*(l+0.5)/16.0)*cos(PI*i*(k+0.5)/16.0)*input[i*16+j]/256;
38 if (i != 0)
39 x *= sqrt(2.0);
40 if (j != 0)
41 x *= sqrt(2.0);
42 s += x;
43 }
44 }
45 output[k*16+l] = s;
46 }
47 }
48 }
49
50
51 static const double C1 = 0.995184726672197;
52 static const double C2 = 0.98078528040323;
53 static const double C3 = 0.956940335732209;
54 static const double C4 = 0.923879532511287;
55 static const double C5 = 0.881921264348355;
56 static const double C6 = 0.831469612302545;
57 static const double C7 = 0.773010453362737;
58 static const double C8 = 0.707106781186548;
59 static const double C9 = 0.634393284163646;
60 static const double C10 = 0.555570233019602;
61 static const double C11 = 0.471396736825998;
62 static const double C12 = 0.38268343236509;
63 static const double C13 = 0.290284677254462;
64 static const double C14 = 0.195090322016128;
65 static const double C15 = 0.098017140329561;
66
67 static void butterfly_16x16_dct_1d(double input[16], double output[16]) {
68 double step[16];
69 double intermediate[16];
70 double temp1, temp2;
71
72 // step 1
73 step[ 0] = input[0] + input[15];
74 step[ 1] = input[1] + input[14];
75 step[ 2] = input[2] + input[13];
76 step[ 3] = input[3] + input[12];
77 step[ 4] = input[4] + input[11];
78 step[ 5] = input[5] + input[10];
79 step[ 6] = input[6] + input[ 9];
80 step[ 7] = input[7] + input[ 8];
81 step[ 8] = input[7] - input[ 8];
82 step[ 9] = input[6] - input[ 9];
83 step[10] = input[5] - input[10];
84 step[11] = input[4] - input[11];
85 step[12] = input[3] - input[12];
86 step[13] = input[2] - input[13];
87 step[14] = input[1] - input[14];
88 step[15] = input[0] - input[15];
89
90 // step 2
91 output[0] = step[0] + step[7];
92 output[1] = step[1] + step[6];
93 output[2] = step[2] + step[5];
94 output[3] = step[3] + step[4];
95 output[4] = step[3] - step[4];
96 output[5] = step[2] - step[5];
97 output[6] = step[1] - step[6];
98 output[7] = step[0] - step[7];
99
100 temp1 = step[ 8]*C7;
101 temp2 = step[15]*C9;
102 output[ 8] = temp1 + temp2;
103
104 temp1 = step[ 9]*C11;
105 temp2 = step[14]*C5;
106 output[ 9] = temp1 - temp2;
107
108 temp1 = step[10]*C3;
109 temp2 = step[13]*C13;
110 output[10] = temp1 + temp2;
111
112 temp1 = step[11]*C15;
113 temp2 = step[12]*C1;
114 output[11] = temp1 - temp2;
115
116 temp1 = step[11]*C1;
117 temp2 = step[12]*C15;
118 output[12] = temp2 + temp1;
119
120 temp1 = step[10]*C13;
121 temp2 = step[13]*C3;
122 output[13] = temp2 - temp1;
123
124 temp1 = step[ 9]*C5;
125 temp2 = step[14]*C11;
126 output[14] = temp2 + temp1;
127
128 temp1 = step[ 8]*C9;
129 temp2 = step[15]*C7;
130 output[15] = temp2 - temp1;
131
132 // step 3
133 step[ 0] = output[0] + output[3];
134 step[ 1] = output[1] + output[2];
135 step[ 2] = output[1] - output[2];
136 step[ 3] = output[0] - output[3];
137
138 temp1 = output[4]*C14;
139 temp2 = output[7]*C2;
140 step[ 4] = temp1 + temp2;
141
142 temp1 = output[5]*C10;
143 temp2 = output[6]*C6;
144 step[ 5] = temp1 + temp2;
145
146 temp1 = output[5]*C6;
147 temp2 = output[6]*C10;
148 step[ 6] = temp2 - temp1;
149
150 temp1 = output[4]*C2;
151 temp2 = output[7]*C14;
152 step[ 7] = temp2 - temp1;
153
154 step[ 8] = output[ 8] + output[11];
155 step[ 9] = output[ 9] + output[10];
156 step[10] = output[ 9] - output[10];
157 step[11] = output[ 8] - output[11];
158
159 step[12] = output[12] + output[15];
160 step[13] = output[13] + output[14];
161 step[14] = output[13] - output[14];
162 step[15] = output[12] - output[15];
163
164 // step 4
165 output[ 0] = (step[ 0] + step[ 1]);
166 output[ 8] = (step[ 0] - step[ 1]);
167
168 temp1 = step[2]*C12;
169 temp2 = step[3]*C4;
170 temp1 = temp1 + temp2;
171 output[ 4] = 2*(temp1*C8);
172
173 temp1 = step[2]*C4;
174 temp2 = step[3]*C12;
175 temp1 = temp2 - temp1;
176 output[12] = 2*(temp1*C8);
177
178 output[ 2] = 2*((step[4] + step[ 5])*C8);
179 output[14] = 2*((step[7] - step[ 6])*C8);
180
181 temp1 = step[4] - step[5];
182 temp2 = step[6] + step[7];
183 output[ 6] = (temp1 + temp2);
184 output[10] = (temp1 - temp2);
185
186 intermediate[8] = step[8] + step[14];
187 intermediate[9] = step[9] + step[15];
188
189 temp1 = intermediate[8]*C12;
190 temp2 = intermediate[9]*C4;
191 temp1 = temp1 - temp2;
192 output[3] = 2*(temp1*C8);
193
194 temp1 = intermediate[8]*C4;
195 temp2 = intermediate[9]*C12;
196 temp1 = temp2 + temp1;
197 output[13] = 2*(temp1*C8);
198
199 output[ 9] = 2*((step[10] + step[11])*C8);
200
201 intermediate[11] = step[10] - step[11];
202 intermediate[12] = step[12] + step[13];
203 intermediate[13] = step[12] - step[13];
204 intermediate[14] = step[ 8] - step[14];
205 intermediate[15] = step[ 9] - step[15];
206
207 output[15] = (intermediate[11] + intermediate[12]);
208 output[ 1] = -(intermediate[11] - intermediate[12]);
209
210 output[ 7] = 2*(intermediate[13]*C8);
211
212 temp1 = intermediate[14]*C12;
213 temp2 = intermediate[15]*C4;
214 temp1 = temp1 - temp2;
215 output[11] = -2*(temp1*C8);
216
217 temp1 = intermediate[14]*C4;
218 temp2 = intermediate[15]*C12;
219 temp1 = temp2 + temp1;
220 output[ 5] = 2*(temp1*C8);
221 }
222
223 static void reference_16x16_dct_1d(double in[16], double out[16]) {
224 const double kPi = 3.141592653589793238462643383279502884;
225 const double kInvSqrt2 = 0.707106781186547524400844362104;
226 for (int k = 0; k < 16; k++) {
227 out[k] = 0.0;
228 for (int n = 0; n < 16; n++)
229 out[k] += in[n]*cos(kPi*(2*n+1)*k/32.0);
230 if (k == 0)
231 out[k] = out[k]*kInvSqrt2;
232 }
233 }
234
235 void reference_16x16_dct_2d(int16_t input[16*16], double output[16*16]) {
236 // First transform columns
237 for (int i = 0; i < 16; ++i) {
238 double temp_in[16], temp_out[16];
239 for (int j = 0; j < 16; ++j)
240 temp_in[j] = input[j*16 + i];
241 butterfly_16x16_dct_1d(temp_in, temp_out);
242 for (int j = 0; j < 16; ++j)
243 output[j*16 + i] = temp_out[j];
244 }
245 // Then transform rows
246 for (int i = 0; i < 16; ++i) {
247 double temp_in[16], temp_out[16];
248 for (int j = 0; j < 16; ++j)
249 temp_in[j] = output[j + i*16];
250 butterfly_16x16_dct_1d(temp_in, temp_out);
251 // Scale by some magic number
252 for (int j = 0; j < 16; ++j)
253 output[j + i*16] = temp_out[j]/2;
254 }
255 }
256
257
258 TEST(VP9Idct16x16Test, AccuracyCheck) {
259 ACMRandom rnd(ACMRandom::DeterministicSeed());
260 const int count_test_block = 1000;
261 for (int i = 0; i < count_test_block; ++i) {
262 int16_t in[256], coeff[256];
263 int16_t out_c[256];
264 double out_r[256];
265
266 // Initialize a test block with input range [-255, 255].
267 for (int j = 0; j < 256; ++j)
268 in[j] = rnd.Rand8() - rnd.Rand8();
269
270 reference_16x16_dct_2d(in, out_r);
271 for (int j = 0; j < 256; j++)
272 coeff[j] = round(out_r[j]);
273 vp9_short_idct16x16_c(coeff, out_c, 32);
274 for (int j = 0; j < 256; ++j) {
275 const int diff = out_c[j] - in[j];
276 const int error = diff * diff;
277 EXPECT_GE(1, error)
278 << "Error: 16x16 IDCT has error " << error
279 << " at index " << j;
280 }
281
282 vp9_short_fdct16x16_c(in, out_c, 32);
283 for (int j = 0; j < 256; ++j) {
284 const double diff = coeff[j] - out_c[j];
285 const double error = diff * diff;
286 EXPECT_GE(1.0, error)
287 << "Error: 16x16 FDCT has error " << error
288 << " at index " << j;
289 }
290 }
291 }
292
293 TEST(VP9Fdct16x16Test, AccuracyCheck) {
294 ACMRandom rnd(ACMRandom::DeterministicSeed());
295 int max_error = 0;
296 double total_error = 0;
297 const int count_test_block = 1000;
298 for (int i = 0; i < count_test_block; ++i) {
299 int16_t test_input_block[256];
300 int16_t test_temp_block[256];
301 int16_t test_output_block[256];
302
303 // Initialize a test block with input range [-255, 255].
304 for (int j = 0; j < 256; ++j)
305 test_input_block[j] = rnd.Rand8() - rnd.Rand8();
306
307 const int pitch = 32;
308 vp9_short_fdct16x16_c(test_input_block, test_temp_block, pitch);
309 vp9_short_idct16x16_c(test_temp_block, test_output_block, pitch);
310
311 for (int j = 0; j < 256; ++j) {
312 const int diff = test_input_block[j] - test_output_block[j];
313 const int error = diff * diff;
314 if (max_error < error)
315 max_error = error;
316 total_error += error;
317 }
318 }
319
320 EXPECT_GE(1, max_error)
321 << "Error: 16x16 FDCT/IDCT has an individual roundtrip error > 1";
322
323 EXPECT_GE(count_test_block/10, total_error)
324 << "Error: 16x16 FDCT/IDCT has average roundtrip error > 1/10 per block";
325 }
326
327 TEST(VP9Fdct16x16Test, CoeffSizeCheck) {
328 ACMRandom rnd(ACMRandom::DeterministicSeed());
329 const int count_test_block = 1000;
330 for (int i = 0; i < count_test_block; ++i) {
331 int16_t input_block[256], input_extreme_block[256];
332 int16_t output_block[256], output_extreme_block[256];
333
334 // Initialize a test block with input range [-255, 255].
335 for (int j = 0; j < 256; ++j) {
336 input_block[j] = rnd.Rand8() - rnd.Rand8();
337 input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255;
338 }
339 if (i == 0)
340 for (int j = 0; j < 256; ++j)
341 input_extreme_block[j] = 255;
342
343 const int pitch = 32;
344 vp9_short_fdct16x16_c(input_block, output_block, pitch);
345 vp9_short_fdct16x16_c(input_extreme_block, output_extreme_block, pitch);
346
347 // The minimum quant value is 4.
348 for (int j = 0; j < 256; ++j) {
349 EXPECT_GE(4*DCT_MAX_VALUE, abs(output_block[j]))
350 << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE";
351 EXPECT_GE(4*DCT_MAX_VALUE, abs(output_extreme_block[j]))
352 << "Error: 16x16 FDCT extreme has coefficient larger than 4*DCT_MAX_VA LUE";
353 }
354 }
355 }
356 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698