X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;ds=inline;f=libavcodec%2Ffft-test.c;h=83b5546f0826e98594a82776898889fb70fc79cd;hb=7ca3e5203f133eb41a0b5c3a1d753a7427ba72e7;hp=0313154ecf4a6098077dfde0c136ba653bc544ee;hpb=2912e87a6c9264d556734e2bf94a99c64cf9b102;p=ffmpeg diff --git a/libavcodec/fft-test.c b/libavcodec/fft-test.c index 0313154ecf4..83b5546f082 100644 --- a/libavcodec/fft-test.c +++ b/libavcodec/fft-test.c @@ -23,63 +23,83 @@ * FFT and MDCT tests. */ -#include "libavutil/mathematics.h" -#include "libavutil/lfg.h" -#include "libavutil/log.h" -#include "fft.h" +#include "config.h" + #include +#if HAVE_UNISTD_H #include -#include +#endif +#include #include #include -#undef exit +#include "libavutil/cpu.h" +#include "libavutil/lfg.h" +#include "libavutil/log.h" +#include "libavutil/mathematics.h" +#include "libavutil/time.h" -/* reference fft */ +#include "fft.h" +#if FFT_FLOAT +#include "dct.h" +#include "rdft.h" +#endif -#define MUL16(a,b) ((a) * (b)) +/* reference fft */ -#define CMAC(pre, pim, are, aim, bre, bim) \ -{\ - pre += (MUL16(are, bre) - MUL16(aim, bim));\ - pim += (MUL16(are, bim) + MUL16(bre, aim));\ -} +#define MUL16(a, b) ((a) * (b)) -FFTComplex *exptab; +#define CMAC(pre, pim, are, aim, bre, bim) \ + { \ + pre += (MUL16(are, bre) - MUL16(aim, bim)); \ + pim += (MUL16(are, bim) + MUL16(bre, aim)); \ + } -static void fft_ref_init(int nbits, int inverse) +#if FFT_FLOAT +#define RANGE 1.0 +#define REF_SCALE(x, bits) (x) +#define FMT "%10.6f" +#else +#define RANGE 16384 +#define REF_SCALE(x, bits) ((x) / (1 << (bits))) +#define FMT "%6d" +#endif + +static struct { + float re, im; +} *exptab; + +static int fft_ref_init(int nbits, int inverse) { - int n, i; - double c1, s1, alpha; + int i, n = 1 << nbits; - n = 1 << nbits; - exptab = av_malloc((n / 2) * sizeof(FFTComplex)); + exptab = av_malloc((n / 2) * sizeof(*exptab)); + if (!exptab) + return AVERROR(ENOMEM); - for (i = 0; i < (n/2); i++) { - alpha = 2 * M_PI * (float)i / (float)n; - c1 = cos(alpha); - s1 = sin(alpha); + for (i = 0; i < (n / 2); i++) { + double alpha = 2 * M_PI * (float) i / (float) n; + double c1 = cos(alpha), s1 = sin(alpha); if (!inverse) s1 = -s1; exptab[i].re = c1; exptab[i].im = s1; } + return 0; } static void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits) { - int n, i, j, k, n2; - double tmp_re, tmp_im, s, c; - FFTComplex *q; + int i, j; + int n = 1 << nbits; + int n2 = n >> 1; - n = 1 << nbits; - n2 = n >> 1; for (i = 0; i < n; i++) { - tmp_re = 0; - tmp_im = 0; - q = tab; + double tmp_re = 0, tmp_im = 0; + FFTComplex *q = tab; for (j = 0; j < n; j++) { - k = (i * j) & (n - 1); + double s, c; + int k = (i * j) & (n - 1); if (k >= n2) { c = -exptab[k - n2].re; s = -exptab[k - n2].im; @@ -90,117 +110,107 @@ static void fft_ref(FFTComplex *tabr, FFTComplex *tab, int nbits) CMAC(tmp_re, tmp_im, c, s, q->re, q->im); q++; } - tabr[i].re = tmp_re; - tabr[i].im = tmp_im; + tabr[i].re = REF_SCALE(tmp_re, nbits); + tabr[i].im = REF_SCALE(tmp_im, nbits); } } -static void imdct_ref(float *out, float *in, int nbits) +#if CONFIG_MDCT +static void imdct_ref(FFTSample *out, FFTSample *in, int nbits) { - int n = 1<= 1e-3) { - av_log(NULL, AV_LOG_ERROR, "ERROR %5d: %10.6f %10.6f\n", + av_log(NULL, AV_LOG_ERROR, "ERROR %5d: "FMT" "FMT"\n", i, tab1[i], tab2[i]); err = 1; } - error+= e*e; - if(e>max) max= e; + error += e * e; + if (e > max) + max = e; } - av_log(NULL, AV_LOG_INFO, "max:%f e:%g\n", max, sqrt(error)/n); + av_log(NULL, AV_LOG_INFO, "max:%f e:%g\n", max, sqrt(error) / n); return err; } - static void help(void) { - av_log(NULL, AV_LOG_INFO,"usage: fft-test [-h] [-s] [-i] [-n b]\n" + av_log(NULL, AV_LOG_INFO, + "usage: fft-test [-h] [-s] [-i] [-n b]\n" "-h print this help\n" "-s speed test\n" "-m (I)MDCT test\n" @@ -208,9 +218,7 @@ static void help(void) "-r (I)RDFT test\n" "-i inverse transform test\n" "-n b set the transform size to 2^b\n" - "-f x set scale factor for output data of (I)MDCT to x\n" - ); - exit(1); + "-f x set scale factor for output data of (I)MDCT to x\n"); } enum tf_transform { @@ -220,33 +228,36 @@ enum tf_transform { TRANSFORM_DCT, }; +#if !HAVE_GETOPT +#include "compat/getopt.c" +#endif + int main(int argc, char **argv) { FFTComplex *tab, *tab1, *tab_ref; FFTSample *tab2; - int it, i, c; - int do_speed = 0; - int err = 1; enum tf_transform transform = TRANSFORM_FFT; - int do_inverse = 0; - FFTContext s1, *s = &s1; - FFTContext m1, *m = &m1; - RDFTContext r1, *r = &r1; - DCTContext d1, *d = &d1; - int fft_nbits, fft_size, fft_size_2; + FFTContext m, s; +#if FFT_FLOAT + RDFTContext r; + DCTContext d; +#endif /* FFT_FLOAT */ + int it, i, err = 1; + int do_speed = 0, do_inverse = 0; + int fft_nbits = 9, fft_size; double scale = 1.0; AVLFG prng; + av_lfg_init(&prng, 1); - fft_nbits = 9; - for(;;) { - c = getopt(argc, argv, "hsimrdn:f:"); + for (;;) { + int c = getopt(argc, argv, "hsimrdn:f:c:"); if (c == -1) break; - switch(c) { + switch (c) { case 'h': help(); - break; + return 1; case 's': do_speed = 1; break; @@ -268,50 +279,73 @@ int main(int argc, char **argv) case 'f': scale = atof(optarg); break; + case 'c': + { + int cpuflags = av_parse_cpu_flags(optarg); + if (cpuflags < 0) + return 1; + av_set_cpu_flags_mask(cpuflags); + break; + } } } fft_size = 1 << fft_nbits; - fft_size_2 = fft_size >> 1; - tab = av_malloc(fft_size * sizeof(FFTComplex)); - tab1 = av_malloc(fft_size * sizeof(FFTComplex)); - tab_ref = av_malloc(fft_size * sizeof(FFTComplex)); - tab2 = av_malloc(fft_size * sizeof(FFTSample)); + tab = av_malloc(fft_size * sizeof(FFTComplex)); + tab1 = av_malloc(fft_size * sizeof(FFTComplex)); + tab_ref = av_malloc(fft_size * sizeof(FFTComplex)); + tab2 = av_malloc(fft_size * sizeof(FFTSample)); + + if (!(tab && tab1 && tab_ref && tab2)) + goto cleanup; switch (transform) { +#if CONFIG_MDCT case TRANSFORM_MDCT: - av_log(NULL, AV_LOG_INFO,"Scale factor is set to %f\n", scale); + av_log(NULL, AV_LOG_INFO, "Scale factor is set to %f\n", scale); if (do_inverse) - av_log(NULL, AV_LOG_INFO,"IMDCT"); + av_log(NULL, AV_LOG_INFO, "IMDCT"); else - av_log(NULL, AV_LOG_INFO,"MDCT"); - ff_mdct_init(m, fft_nbits, do_inverse, scale); + av_log(NULL, AV_LOG_INFO, "MDCT"); + ff_mdct_init(&m, fft_nbits, do_inverse, scale); break; +#endif /* CONFIG_MDCT */ case TRANSFORM_FFT: if (do_inverse) - av_log(NULL, AV_LOG_INFO,"IFFT"); + av_log(NULL, AV_LOG_INFO, "IFFT"); else - av_log(NULL, AV_LOG_INFO,"FFT"); - ff_fft_init(s, fft_nbits, do_inverse); - fft_ref_init(fft_nbits, do_inverse); + av_log(NULL, AV_LOG_INFO, "FFT"); + ff_fft_init(&s, fft_nbits, do_inverse); + if (err = fft_ref_init(fft_nbits, do_inverse) < 0) + goto cleanup; break; +#if FFT_FLOAT +#if CONFIG_RDFT case TRANSFORM_RDFT: if (do_inverse) - av_log(NULL, AV_LOG_INFO,"IDFT_C2R"); + av_log(NULL, AV_LOG_INFO, "IDFT_C2R"); else - av_log(NULL, AV_LOG_INFO,"DFT_R2C"); - ff_rdft_init(r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C); - fft_ref_init(fft_nbits, do_inverse); + av_log(NULL, AV_LOG_INFO, "DFT_R2C"); + ff_rdft_init(&r, fft_nbits, do_inverse ? IDFT_C2R : DFT_R2C); + if (err = fft_ref_init(fft_nbits, do_inverse) < 0) + goto cleanup; break; +#endif /* CONFIG_RDFT */ +#if CONFIG_DCT case TRANSFORM_DCT: if (do_inverse) - av_log(NULL, AV_LOG_INFO,"DCT_III"); + av_log(NULL, AV_LOG_INFO, "DCT_III"); else - av_log(NULL, AV_LOG_INFO,"DCT_II"); - ff_dct_init(d, fft_nbits, do_inverse ? DCT_III : DCT_II); + av_log(NULL, AV_LOG_INFO, "DCT_II"); + ff_dct_init(&d, fft_nbits, do_inverse ? DCT_III : DCT_II); break; +#endif /* CONFIG_DCT */ +#endif /* FFT_FLOAT */ + default: + av_log(NULL, AV_LOG_ERROR, "Requested transform not supported\n"); + goto cleanup; } - av_log(NULL, AV_LOG_INFO," %d test\n", fft_size); + av_log(NULL, AV_LOG_INFO, " %d test\n", fft_size); /* generate random data */ @@ -321,70 +355,78 @@ int main(int argc, char **argv) } /* checking result */ - av_log(NULL, AV_LOG_INFO,"Checking...\n"); + av_log(NULL, AV_LOG_INFO, "Checking...\n"); switch (transform) { +#if CONFIG_MDCT case TRANSFORM_MDCT: if (do_inverse) { - imdct_ref((float *)tab_ref, (float *)tab1, fft_nbits); - ff_imdct_calc(m, tab2, (float *)tab1); - err = check_diff((float *)tab_ref, tab2, fft_size, scale); + imdct_ref(&tab_ref->re, &tab1->re, fft_nbits); + m.imdct_calc(&m, tab2, &tab1->re); + err = check_diff(&tab_ref->re, tab2, fft_size, scale); } else { - mdct_ref((float *)tab_ref, (float *)tab1, fft_nbits); - - ff_mdct_calc(m, tab2, (float *)tab1); - - err = check_diff((float *)tab_ref, tab2, fft_size / 2, scale); + mdct_ref(&tab_ref->re, &tab1->re, fft_nbits); + m.mdct_calc(&m, tab2, &tab1->re); + err = check_diff(&tab_ref->re, tab2, fft_size / 2, scale); } break; +#endif /* CONFIG_MDCT */ case TRANSFORM_FFT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); - ff_fft_permute(s, tab); - ff_fft_calc(s, tab); + s.fft_permute(&s, tab); + s.fft_calc(&s, tab); fft_ref(tab_ref, tab1, fft_nbits); - err = check_diff((float *)tab_ref, (float *)tab, fft_size * 2, 1.0); + err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 1.0); break; +#if FFT_FLOAT +#if CONFIG_RDFT case TRANSFORM_RDFT: + { + int fft_size_2 = fft_size >> 1; if (do_inverse) { - tab1[ 0].im = 0; + tab1[0].im = 0; tab1[fft_size_2].im = 0; for (i = 1; i < fft_size_2; i++) { - tab1[fft_size_2+i].re = tab1[fft_size_2-i].re; - tab1[fft_size_2+i].im = -tab1[fft_size_2-i].im; + tab1[fft_size_2 + i].re = tab1[fft_size_2 - i].re; + tab1[fft_size_2 + i].im = -tab1[fft_size_2 - i].im; } memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); tab2[1] = tab1[fft_size_2].re; - ff_rdft_calc(r, tab2); + r.rdft_calc(&r, tab2); fft_ref(tab_ref, tab1, fft_nbits); for (i = 0; i < fft_size; i++) { tab[i].re = tab2[i]; tab[i].im = 0; } - err = check_diff((float *)tab_ref, (float *)tab, fft_size * 2, 0.5); + err = check_diff(&tab_ref->re, &tab->re, fft_size * 2, 0.5); } else { for (i = 0; i < fft_size; i++) { tab2[i] = tab1[i].re; tab1[i].im = 0; } - ff_rdft_calc(r, tab2); + r.rdft_calc(&r, tab2); fft_ref(tab_ref, tab1, fft_nbits); tab_ref[0].im = tab_ref[fft_size_2].re; - err = check_diff((float *)tab_ref, (float *)tab2, fft_size, 1.0); + err = check_diff(&tab_ref->re, tab2, fft_size, 1.0); } break; + } +#endif /* CONFIG_RDFT */ +#if CONFIG_DCT case TRANSFORM_DCT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); - ff_dct_calc(d, tab); - if (do_inverse) { - idct_ref(tab_ref, tab1, fft_nbits); - } else { - dct_ref(tab_ref, tab1, fft_nbits); - } - err = check_diff((float *)tab_ref, (float *)tab, fft_size, 1.0); + d.dct_calc(&d, &tab->re); + if (do_inverse) + idct_ref(&tab_ref->re, &tab1->re, fft_nbits); + else + dct_ref(&tab_ref->re, &tab1->re, fft_nbits); + err = check_diff(&tab_ref->re, &tab->re, fft_size, 1.0); break; +#endif /* CONFIG_DCT */ +#endif /* FFT_FLOAT */ } /* do a speed test */ @@ -393,65 +435,79 @@ int main(int argc, char **argv) int64_t time_start, duration; int nb_its; - av_log(NULL, AV_LOG_INFO,"Speed test...\n"); + av_log(NULL, AV_LOG_INFO, "Speed test...\n"); /* we measure during about 1 seconds */ nb_its = 1; - for(;;) { - time_start = gettime(); + for (;;) { + time_start = av_gettime_relative(); for (it = 0; it < nb_its; it++) { switch (transform) { case TRANSFORM_MDCT: - if (do_inverse) { - ff_imdct_calc(m, (float *)tab, (float *)tab1); - } else { - ff_mdct_calc(m, (float *)tab, (float *)tab1); - } + if (do_inverse) + m.imdct_calc(&m, &tab->re, &tab1->re); + else + m.mdct_calc(&m, &tab->re, &tab1->re); break; case TRANSFORM_FFT: memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); - ff_fft_calc(s, tab); + s.fft_calc(&s, tab); break; +#if FFT_FLOAT case TRANSFORM_RDFT: memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); - ff_rdft_calc(r, tab2); + r.rdft_calc(&r, tab2); break; case TRANSFORM_DCT: memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); - ff_dct_calc(d, tab2); + d.dct_calc(&d, tab2); break; +#endif /* FFT_FLOAT */ } } - duration = gettime() - time_start; + duration = av_gettime_relative() - time_start; if (duration >= 1000000) break; nb_its *= 2; } - av_log(NULL, AV_LOG_INFO,"time: %0.1f us/transform [total time=%0.2f s its=%d]\n", - (double)duration / nb_its, - (double)duration / 1000000.0, + av_log(NULL, AV_LOG_INFO, + "time: %0.1f us/transform [total time=%0.2f s its=%d]\n", + (double) duration / nb_its, + (double) duration / 1000000.0, nb_its); } switch (transform) { +#if CONFIG_MDCT case TRANSFORM_MDCT: - ff_mdct_end(m); + ff_mdct_end(&m); break; +#endif /* CONFIG_MDCT */ case TRANSFORM_FFT: - ff_fft_end(s); + ff_fft_end(&s); break; +#if FFT_FLOAT +#if CONFIG_RDFT case TRANSFORM_RDFT: - ff_rdft_end(r); + ff_rdft_end(&r); break; +#endif /* CONFIG_RDFT */ +#if CONFIG_DCT case TRANSFORM_DCT: - ff_dct_end(d); + ff_dct_end(&d); break; +#endif /* CONFIG_DCT */ +#endif /* FFT_FLOAT */ } +cleanup: av_free(tab); av_free(tab1); av_free(tab2); av_free(tab_ref); av_free(exptab); - return err; + if (err) + printf("Error: %d.\n", err); + + return !!err; }