1 /*
2 * (c) 2001 Fabrice Bellard
3 * 2007 Marc Hoffman <marc.hoffman@analog.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * DCT test (c) 2001 Fabrice Bellard
25 * Started from sample code by Juan J. Sierralta P.
26 */
27
28 #include "config.h"
29 #include "config_components.h"
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #if HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #include <math.h>
37
45
55
62 };
63
68 #if CONFIG_FAANDCT
70 #endif /* CONFIG_FAANDCT */
71 };
72
76
79 }
83 }
84 }
85
93 #if CONFIG_FAANIDCT
95 #endif /* CONFIG_FAANIDCT */
96 #if CONFIG_MPEG4_DECODER
98 #endif /* CONFIG_MPEG4_DECODER */
99 };
100
101 #if ARCH_AARCH64
103 #elif ARCH_ARM
105 #elif ARCH_PPC
107 #elif ARCH_X86
109 #else
112 #endif
113
114 #define AANSCALE_BITS 12
115
117 #define NB_ITS_SPEED 50000
118
121
123 {
125
127
129 case 0:
130 for (
i = 0;
i < 64;
i++)
132 if (is_idct) {
134 for (
i = 0;
i < 64;
i++)
136 }
137 break;
138 case 1:
140 for (
i = 0;
i < j;
i++) {
143 }
144 break;
145 case 2:
148 break;
149 }
150 }
151
154 {
156
157 #if ARCH_X86
159 return;
160 #endif
161
164 for (
i = 0;
i < 64;
i++)
165 dst[(
i & 0x38) | ((
i & 6) >> 1) | ((
i & 1) << 2)] =
src[
i];
166 break;
168 for (
i = 0;
i < 64;
i++)
169 dst[(
i & 0x24) | ((
i & 3) << 3) | ((
i >> 3) & 3)] =
src[
i];
170 break;
172 for (
i = 0;
i < 64;
i++)
174 break;
175 default:
176 for (
i = 0;
i < 64;
i++)
178 break;
179 }
180 }
181
183 {
186 int err_inf, v;
187 int64_t err2, ti, ti1, it1, err_sum = 0;
188 int64_t sysErr[64], sysErrMax = 0;
189 int64_t err2_matrix[64], err2_max = 0;
190 int maxout = 0;
191 int blockSumErrMax = 0, blockSumErr;
193 const int vals=1<<
bits;
194 double omse, ome;
195 int spec_err;
196
198
199 err_inf = 0;
200 err2 = 0;
201 for (
i = 0;
i < 64;
i++)
202 err2_matrix[
i] = sysErr[
i] = 0;
206
209
210 if (!strcmp(
dct->name,
"IJG-AAN-INT")) {
211 for (
i = 0;
i < 64;
i++) {
214 }
215 }
216
218 if (!strcmp(
dct->name,
"PR-SSE2"))
219 for (
i = 0;
i < 64;
i++)
221
222 blockSumErr = 0;
223 for (
i = 0;
i < 64;
i++) {
225 err_sum += err;
227 if (v > err_inf)
228 err_inf = v;
232 blockSumErr += v;
235 }
236 if (blockSumErrMax < blockSumErr)
237 blockSumErrMax = blockSumErr;
238 }
239 for (
i = 0;
i < 64;
i++) {
241 err2_max =
FFMAX(err2_max ,
FFABS(err2_matrix[
i]));
242 }
243
244 for (
i = 0;
i < 64;
i++) {
247 printf(
"%7d ", (
int) sysErr[
i]);
248 }
250
253
254 spec_err = is_idct && (err_inf > 1 || omse > 0.02 ||
fabs(ome) > 0.0015);
256 spec_err = is_idct && ((
double) err2_max /
NB_ITS > 0.06 || (
double) sysErrMax /
NB_ITS > 0.015);
257
258 printf(
"%s %s: max_err=%d omse=%0.8f ome=%0.8f syserr=%0.8f maxout=%d blockSumErr=%d\n",
259 is_idct ?
"IDCT" :
"DCT",
dct->name, err_inf,
260 omse, ome, (
double) sysErrMax /
NB_ITS,
261 maxout, blockSumErrMax);
262
263 if (spec_err && !
dct->nonspec) {
265 return 1;
266 }
267
268 if (!speed)
269 return 0;
270
271 /* speed test */
272
275
277 it1 = 0;
278 do {
282 }
286 } while (ti1 < 1000000);
287
288 printf(
"%s %s: %0.1f kdct/s\n", is_idct ?
"IDCT" :
"DCT",
dct->name,
289 (double) it1 * 1000.0 / (double) ti1);
290
291 return 0;
292 }
293
296
298 {
300 static double c8[8][8];
301 static double c4[4][4];
302 double block1[64], block2[64], block3[64];
305
308
309 for (
i = 0;
i < 8;
i++) {
310 sum = 0;
311 for (j = 0; j < 8; j++) {
312 s = (
i == 0) ? sqrt(1.0 / 8.0) : sqrt(1.0 / 4.0);
313 c8[
i][j] =
s * cos(
M_PI *
i * (j + 0.5) / 8.0);
314 sum += c8[
i][j] * c8[
i][j];
315 }
316 }
317
318 for (
i = 0;
i < 4;
i++) {
319 sum = 0;
320 for (j = 0; j < 4; j++) {
321 s = (
i == 0) ? sqrt(1.0 / 4.0) : sqrt(1.0 / 2.0);
322 c4[
i][j] =
s * cos(
M_PI *
i * (j + 0.5) / 4.0);
323 sum += c4[
i][j] * c4[
i][j];
324 }
325 }
326 }
327
328 /* butterfly */
330 for (
i = 0;
i < 4;
i++) {
331 for (j = 0; j < 8; j++) {
336 }
337 }
338
339 /* idct8 on lines */
340 for (
i = 0;
i < 8;
i++) {
341 for (j = 0; j < 8; j++) {
342 sum = 0;
343 for (k = 0; k < 8; k++)
344 sum += c8[k][j] *
block1[8 *
i + k];
345 block2[8 *
i + j] = sum;
346 }
347 }
348
349 /* idct4 */
350 for (
i = 0;
i < 8;
i++) {
351 for (j = 0; j < 4; j++) {
352 /* top */
353 sum = 0;
354 for (k = 0; k < 4; k++)
355 sum += c4[k][j] * block2[8 * (2 * k) +
i];
356 block3[8 * (2 * j) +
i] = sum;
357
358 /* bottom */
359 sum = 0;
360 for (k = 0; k < 4; k++)
361 sum += c4[k][j] * block2[8 * (2 * k + 1) +
i];
362 block3[8 * (2 * j + 1) +
i] = sum;
363 }
364 }
365
366 /* clamp and store the result */
367 for (
i = 0;
i < 8;
i++) {
368 for (j = 0; j < 8; j++) {
369 v = block3[8 *
i + j];
370 if (v < 0) v = 0;
371 else if (v > 255) v = 255;
372 dest[
i * linesize + j] = (int)
rint(v);
373 }
374 }
375 }
376
378 void (*idct248_put)(uint8_t *dest,
379 ptrdiff_t line_size,
381 int speed)
382 {
383 int it,
i, it1, ti, ti1, err_max, v;
385
387
388 /* just one test to see if code is correct (precision is less
389 important here) */
390 err_max = 0;
392 /* XXX: use forward transform to generate values */
393 for (
i = 0;
i < 64;
i++)
396
397 for (
i = 0;
i < 64;
i++)
400
401 for (
i = 0;
i < 64;
i++)
404
405 for (
i = 0;
i < 64;
i++) {
407 if (v == 255)
409 if (v > err_max)
410 err_max = v;
411 }
412 #if 0
415 int j;
416 for(j=0;j<8;j++) {
418 }
420 }
421
424 int j;
425 for(j=0;j<8;j++) {
427 }
429 }
430 #endif
431 }
432 printf(
"%s %s: err_inf=%d\n", 1 ?
"IDCT248" :
"DCT248",
name, err_max);
433
434 if (!speed)
435 return;
436
438 it1 = 0;
439 do {
441 for (
i = 0;
i < 64;
i++)
444 }
448 } while (ti1 < 1000000);
449
450 printf(
"%s %s: %0.1f kdct/s\n", 1 ?
"IDCT248" :
"DCT248",
name,
451 (double) it1 * 1000.0 / (double) ti1);
452 }
453
455 {
456 printf(
"dct-test [-i] [<test-number>] [<bits>]\n"
457 "test-number 0 -> test with random matrixes\n"
458 " 1 -> test with random sparse matrixes\n"
459 " 2 -> do 3. test from MPEG-4 std\n"
460 "bits Number of time domain bits to use, 8 is default\n"
461 "-i test IDCT implementations\n"
462 "-4 test IDCT248 implementations\n"
463 "-t speed test\n");
464 }
465
466 #if !HAVE_GETOPT
468 #endif
469
470 int main(
int argc,
char **argv)
471 {
472 int test_idct = 0, test_248_dct = 0;
475 int speed = 0;
476 int err = 0;
478
480
481 for (;;) {
482 c =
getopt(argc, argv,
"ih4t");
484 break;
486 case 'i':
487 test_idct = 1;
488 break;
489 case '4':
490 test_248_dct = 1;
491 break;
492 case 't':
493 speed = 1;
494 break;
495 default:
496 case 'h':
498 return 0;
499 }
500 }
501
505
506 printf(
"ffmpeg DCT/IDCT test\n");
507
508 if (test_248_dct) {
510 } else {
512 if (test_idct) {
515
519 }
520 #if CONFIG_FDCTDSP
521 else {
524
528 }
529 #endif /* CONFIG_FDCTDSP */
530 }
531
532 if (err)
533 printf(
"Error: %d.\n", err);
534
535 return !!err;
536 }