Mercurial > libavcodec.hg
annotate fft-test.c @ 9830:bd0879f752e6 libavcodec
Express the H.264 parser dependency on the golomb code in configure instead of
in the Makefile as it is done for all other parts that depend on golomb.
author | diego |
---|---|
date | Tue, 09 Jun 2009 20:29:52 +0000 |
parents | dac20d8df581 |
children | c4a83f3a5c9f |
rev | line source |
---|---|
3699
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
1 /* |
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
2 * (c) 2002 Fabrice Bellard |
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
3 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3699
diff
changeset
|
4 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3699
diff
changeset
|
5 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3699
diff
changeset
|
6 * FFmpeg is free software; you can redistribute it and/or |
3699
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
7 * modify it under the terms of the GNU Lesser General Public |
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
8 * License as published by the Free Software Foundation; either |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3699
diff
changeset
|
9 * version 2.1 of the License, or (at your option) any later version. |
3699
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
10 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3699
diff
changeset
|
11 * FFmpeg is distributed in the hope that it will be useful, |
3699
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
14 * Lesser General Public License for more details. |
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
15 * |
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
16 * You should have received a copy of the GNU Lesser General Public |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3699
diff
changeset
|
17 * License along with FFmpeg; if not, write to the Free Software |
3699
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
19 */ |
c537a97eec66
Add official LGPL license headers to the files that were missing them.
diego
parents:
2967
diff
changeset
|
20 |
1106 | 21 /** |
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
7546
diff
changeset
|
22 * @file libavcodec/fft-test.c |
1106 | 23 * FFT and MDCT tests. |
24 */ | |
25 | |
9199
ea0e5e9a520f
Replace random() usage in test programs by av_lfg_*().
diego
parents:
8718
diff
changeset
|
26 #include "libavutil/lfg.h" |
781 | 27 #include "dsputil.h" |
28 #include <math.h> | |
980 | 29 #include <unistd.h> |
781 | 30 #include <sys/time.h> |
5118
3b190bc34546
Add some #includes to allow compilation without HAVE_AV_CONFIG_H.
diego
parents:
4760
diff
changeset
|
31 #include <stdlib.h> |
3b190bc34546
Add some #includes to allow compilation without HAVE_AV_CONFIG_H.
diego
parents:
4760
diff
changeset
|
32 #include <string.h> |
781 | 33 |
4760 | 34 #undef exit |
35 | |
781 | 36 /* reference fft */ |
37 | |
38 #define MUL16(a,b) ((a) * (b)) | |
39 | |
40 #define CMAC(pre, pim, are, aim, bre, bim) \ | |
41 {\ | |
42 pre += (MUL16(are, bre) - MUL16(aim, bim));\ | |
43 pim += (MUL16(are, bim) + MUL16(bre, aim));\ | |
44 } | |
45 | |
46 FFTComplex *exptab; | |
47 | |
9295
b225f51903af
Mark non-exported functions in test and example programs as static.
diego
parents:
9199
diff
changeset
|
48 static void fft_ref_init(int nbits, int inverse) |
781 | 49 { |
50 int n, i; | |
5418
95234f2e0bdd
make the reference code use double instead of float where it is easy
michael
parents:
5417
diff
changeset
|
51 double c1, s1, alpha; |
781 | 52 |
53 n = 1 << nbits; | |
54 exptab = av_malloc((n / 2) * sizeof(FFTComplex)); | |
55 | |
56 for(i=0;i<(n/2);i++) { | |
57 alpha = 2 * M_PI * (float)i / (float)n; | |
58 c1 = cos(alpha); | |
59 s1 = sin(alpha); | |
60 if (!inverse) | |
61 s1 = -s1; | |
62 exptab[i].re = c1; | |
63 exptab[i].im = s1; | |
64 } | |
65 } | |
66 | |
9295
b225f51903af
Mark non-exported functions in test and example programs as static.
diego
parents:
9199
diff
changeset
|
67 static void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits) |
781 | 68 { |
69 int n, i, j, k, n2; | |
5418
95234f2e0bdd
make the reference code use double instead of float where it is easy
michael
parents:
5417
diff
changeset
|
70 double tmp_re, tmp_im, s, c; |
781 | 71 FFTComplex *q; |
72 | |
73 n = 1 << nbits; | |
74 n2 = n >> 1; | |
75 for(i=0;i<n;i++) { | |
76 tmp_re = 0; | |
77 tmp_im = 0; | |
78 q = tab; | |
79 for(j=0;j<n;j++) { | |
80 k = (i * j) & (n - 1); | |
81 if (k >= n2) { | |
82 c = -exptab[k - n2].re; | |
83 s = -exptab[k - n2].im; | |
84 } else { | |
85 c = exptab[k].re; | |
86 s = exptab[k].im; | |
87 } | |
88 CMAC(tmp_re, tmp_im, c, s, q->re, q->im); | |
89 q++; | |
90 } | |
91 tabr[i].re = tmp_re; | |
92 tabr[i].im = tmp_im; | |
93 } | |
94 } | |
95 | |
9295
b225f51903af
Mark non-exported functions in test and example programs as static.
diego
parents:
9199
diff
changeset
|
96 static void imdct_ref(float *out, float *in, int nbits) |
781 | 97 { |
5442 | 98 int n = 1<<nbits; |
781 | 99 int k, i, a; |
5418
95234f2e0bdd
make the reference code use double instead of float where it is easy
michael
parents:
5417
diff
changeset
|
100 double sum, f; |
781 | 101 |
102 for(i=0;i<n;i++) { | |
103 sum = 0; | |
104 for(k=0;k<n/2;k++) { | |
105 a = (2 * i + 1 + (n / 2)) * (2 * k + 1); | |
106 f = cos(M_PI * a / (double)(2 * n)); | |
107 sum += f * in[k]; | |
108 } | |
109 out[i] = -sum; | |
110 } | |
111 } | |
112 | |
113 /* NOTE: no normalisation by 1 / N is done */ | |
9295
b225f51903af
Mark non-exported functions in test and example programs as static.
diego
parents:
9199
diff
changeset
|
114 static void mdct_ref(float *output, float *input, int nbits) |
781 | 115 { |
5442 | 116 int n = 1<<nbits; |
781 | 117 int k, i; |
5418
95234f2e0bdd
make the reference code use double instead of float where it is easy
michael
parents:
5417
diff
changeset
|
118 double a, s; |
781 | 119 |
120 /* do it by hand */ | |
121 for(k=0;k<n/2;k++) { | |
122 s = 0; | |
123 for(i=0;i<n;i++) { | |
124 a = (2*M_PI*(2*i+1+n/2)*(2*k+1) / (4 * n)); | |
125 s += input[i] * cos(a); | |
126 } | |
127 output[k] = s; | |
128 } | |
129 } | |
130 | |
131 | |
9295
b225f51903af
Mark non-exported functions in test and example programs as static.
diego
parents:
9199
diff
changeset
|
132 static float frandom(void) |
781 | 133 { |
9388
2313bf51945b
cosmetics: Rename prn variable to prng (Pseudo Random Number Generator).
diego
parents:
9295
diff
changeset
|
134 AVLFG prng; |
2313bf51945b
cosmetics: Rename prn variable to prng (Pseudo Random Number Generator).
diego
parents:
9295
diff
changeset
|
135 av_lfg_init(&prng, 1); |
2313bf51945b
cosmetics: Rename prn variable to prng (Pseudo Random Number Generator).
diego
parents:
9295
diff
changeset
|
136 return (float)((av_lfg_get(&prng) & 0xffff) - 32768) / 32768.0; |
781 | 137 } |
138 | |
9295
b225f51903af
Mark non-exported functions in test and example programs as static.
diego
parents:
9199
diff
changeset
|
139 static int64_t gettime(void) |
781 | 140 { |
141 struct timeval tv; | |
142 gettimeofday(&tv,NULL); | |
1064 | 143 return (int64_t)tv.tv_sec * 1000000 + tv.tv_usec; |
781 | 144 } |
145 | |
9674
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
146 static void check_diff(float *tab1, float *tab2, int n, double scale) |
781 | 147 { |
148 int i; | |
5417 | 149 double max= 0; |
150 double error= 0; | |
781 | 151 |
152 for(i=0;i<n;i++) { | |
9674
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
153 double e= fabsf(tab1[i] - (tab2[i] / scale)); |
5417 | 154 if (e >= 1e-3) { |
2967 | 155 av_log(NULL, AV_LOG_ERROR, "ERROR %d: %f %f\n", |
781 | 156 i, tab1[i], tab2[i]); |
157 } | |
5417 | 158 error+= e*e; |
159 if(e>max) max= e; | |
781 | 160 } |
5417 | 161 av_log(NULL, AV_LOG_INFO, "max:%f e:%g\n", max, sqrt(error)/n); |
781 | 162 } |
163 | |
164 | |
9295
b225f51903af
Mark non-exported functions in test and example programs as static.
diego
parents:
9199
diff
changeset
|
165 static void help(void) |
781 | 166 { |
2593
786ccf72ccd5
printf -> av_log patch by (Benjamin Larsson <>banan student.ltu se)
michael
parents:
1879
diff
changeset
|
167 av_log(NULL, AV_LOG_INFO,"usage: fft-test [-h] [-s] [-i] [-n b]\n" |
781 | 168 "-h print this help\n" |
169 "-s speed test\n" | |
170 "-m (I)MDCT test\n" | |
171 "-i inverse transform test\n" | |
172 "-n b set the transform size to 2^b\n" | |
9674
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
173 "-f x set scale factor for output data of (I)MDCT to x\n" |
781 | 174 ); |
175 exit(1); | |
176 } | |
177 | |
178 | |
179 | |
180 int main(int argc, char **argv) | |
181 { | |
182 FFTComplex *tab, *tab1, *tab_ref; | |
7546 | 183 FFTSample *tab2; |
781 | 184 int it, i, c; |
185 int do_speed = 0; | |
186 int do_mdct = 0; | |
187 int do_inverse = 0; | |
188 FFTContext s1, *s = &s1; | |
189 MDCTContext m1, *m = &m1; | |
190 int fft_nbits, fft_size; | |
9674
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
191 double scale = 1.0; |
781 | 192 |
193 fft_nbits = 9; | |
194 for(;;) { | |
9674
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
195 c = getopt(argc, argv, "hsimn:f:"); |
781 | 196 if (c == -1) |
197 break; | |
198 switch(c) { | |
199 case 'h': | |
200 help(); | |
201 break; | |
202 case 's': | |
203 do_speed = 1; | |
204 break; | |
205 case 'i': | |
206 do_inverse = 1; | |
207 break; | |
208 case 'm': | |
209 do_mdct = 1; | |
210 break; | |
211 case 'n': | |
212 fft_nbits = atoi(optarg); | |
213 break; | |
9674
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
214 case 'f': |
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
215 scale = atof(optarg); |
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
216 break; |
781 | 217 } |
218 } | |
219 | |
220 fft_size = 1 << fft_nbits; | |
221 tab = av_malloc(fft_size * sizeof(FFTComplex)); | |
222 tab1 = av_malloc(fft_size * sizeof(FFTComplex)); | |
223 tab_ref = av_malloc(fft_size * sizeof(FFTComplex)); | |
224 tab2 = av_malloc(fft_size * sizeof(FFTSample)); | |
225 | |
226 if (do_mdct) { | |
9674
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
227 av_log(NULL, AV_LOG_INFO,"Scale factor is set to %f\n", scale); |
781 | 228 if (do_inverse) |
2593
786ccf72ccd5
printf -> av_log patch by (Benjamin Larsson <>banan student.ltu se)
michael
parents:
1879
diff
changeset
|
229 av_log(NULL, AV_LOG_INFO,"IMDCT"); |
781 | 230 else |
2593
786ccf72ccd5
printf -> av_log patch by (Benjamin Larsson <>banan student.ltu se)
michael
parents:
1879
diff
changeset
|
231 av_log(NULL, AV_LOG_INFO,"MDCT"); |
9674
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
232 ff_mdct_init(m, fft_nbits, do_inverse, scale); |
781 | 233 } else { |
234 if (do_inverse) | |
2593
786ccf72ccd5
printf -> av_log patch by (Benjamin Larsson <>banan student.ltu se)
michael
parents:
1879
diff
changeset
|
235 av_log(NULL, AV_LOG_INFO,"IFFT"); |
781 | 236 else |
2593
786ccf72ccd5
printf -> av_log patch by (Benjamin Larsson <>banan student.ltu se)
michael
parents:
1879
diff
changeset
|
237 av_log(NULL, AV_LOG_INFO,"FFT"); |
1879
dd63cb7e5080
fft_*() renamed into ff_fft_*() patch by (Gildas Bazin <gbazin at altern dot org>)
michael
parents:
1106
diff
changeset
|
238 ff_fft_init(s, fft_nbits, do_inverse); |
781 | 239 fft_ref_init(fft_nbits, do_inverse); |
240 } | |
2593
786ccf72ccd5
printf -> av_log patch by (Benjamin Larsson <>banan student.ltu se)
michael
parents:
1879
diff
changeset
|
241 av_log(NULL, AV_LOG_INFO," %d test\n", fft_size); |
781 | 242 |
243 /* generate random data */ | |
244 | |
245 for(i=0;i<fft_size;i++) { | |
246 tab1[i].re = frandom(); | |
247 tab1[i].im = frandom(); | |
248 } | |
249 | |
250 /* checking result */ | |
2593
786ccf72ccd5
printf -> av_log patch by (Benjamin Larsson <>banan student.ltu se)
michael
parents:
1879
diff
changeset
|
251 av_log(NULL, AV_LOG_INFO,"Checking...\n"); |
781 | 252 |
253 if (do_mdct) { | |
254 if (do_inverse) { | |
5442 | 255 imdct_ref((float *)tab_ref, (float *)tab1, fft_nbits); |
7546 | 256 ff_imdct_calc(m, tab2, (float *)tab1); |
9674
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
257 check_diff((float *)tab_ref, tab2, fft_size, scale); |
781 | 258 } else { |
5442 | 259 mdct_ref((float *)tab_ref, (float *)tab1, fft_nbits); |
2967 | 260 |
7546 | 261 ff_mdct_calc(m, tab2, (float *)tab1); |
781 | 262 |
9674
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
263 check_diff((float *)tab_ref, tab2, fft_size / 2, scale); |
781 | 264 } |
265 } else { | |
266 memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); | |
1879
dd63cb7e5080
fft_*() renamed into ff_fft_*() patch by (Gildas Bazin <gbazin at altern dot org>)
michael
parents:
1106
diff
changeset
|
267 ff_fft_permute(s, tab); |
dd63cb7e5080
fft_*() renamed into ff_fft_*() patch by (Gildas Bazin <gbazin at altern dot org>)
michael
parents:
1106
diff
changeset
|
268 ff_fft_calc(s, tab); |
2967 | 269 |
781 | 270 fft_ref(tab_ref, tab1, fft_nbits); |
9674
dac20d8df581
Support for testing (i)MDCT output scale factor in fft-test tool.
serge
parents:
9658
diff
changeset
|
271 check_diff((float *)tab_ref, (float *)tab, fft_size * 2, 1.0); |
781 | 272 } |
273 | |
274 /* do a speed test */ | |
275 | |
276 if (do_speed) { | |
1064 | 277 int64_t time_start, duration; |
781 | 278 int nb_its; |
279 | |
2593
786ccf72ccd5
printf -> av_log patch by (Benjamin Larsson <>banan student.ltu se)
michael
parents:
1879
diff
changeset
|
280 av_log(NULL, AV_LOG_INFO,"Speed test...\n"); |
781 | 281 /* we measure during about 1 seconds */ |
282 nb_its = 1; | |
283 for(;;) { | |
284 time_start = gettime(); | |
285 for(it=0;it<nb_its;it++) { | |
286 if (do_mdct) { | |
287 if (do_inverse) { | |
7546 | 288 ff_imdct_calc(m, (float *)tab, (float *)tab1); |
781 | 289 } else { |
7546 | 290 ff_mdct_calc(m, (float *)tab, (float *)tab1); |
781 | 291 } |
292 } else { | |
293 memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); | |
1879
dd63cb7e5080
fft_*() renamed into ff_fft_*() patch by (Gildas Bazin <gbazin at altern dot org>)
michael
parents:
1106
diff
changeset
|
294 ff_fft_calc(s, tab); |
781 | 295 } |
296 } | |
297 duration = gettime() - time_start; | |
298 if (duration >= 1000000) | |
299 break; | |
300 nb_its *= 2; | |
301 } | |
2967 | 302 av_log(NULL, AV_LOG_INFO,"time: %0.1f us/transform [total time=%0.2f s its=%d]\n", |
303 (double)duration / nb_its, | |
781 | 304 (double)duration / 1000000.0, |
305 nb_its); | |
306 } | |
2967 | 307 |
781 | 308 if (do_mdct) { |
969 | 309 ff_mdct_end(m); |
781 | 310 } else { |
1879
dd63cb7e5080
fft_*() renamed into ff_fft_*() patch by (Gildas Bazin <gbazin at altern dot org>)
michael
parents:
1106
diff
changeset
|
311 ff_fft_end(s); |
781 | 312 } |
313 return 0; | |
314 } |