annotate rdft.c @ 12530:63edd10ad4bc libavcodec tip

Try to fix crashes introduced by r25218 r25218 made assumptions about the existence of past reference frames that weren't necessarily true.
author darkshikari
date Tue, 28 Sep 2010 09:06:22 +0000
parents 7dd2a45249a9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
8694
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
1 /*
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
2 * (I)RDFT transforms
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
3 * Copyright (c) 2009 Alex Converse <alex dot converse at gmail dot com>
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
4 *
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
5 * This file is part of FFmpeg.
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
6 *
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
11 *
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
15 * Lesser General Public License for more details.
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
16 *
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
20 */
11444
6f1697664bf2 Replace many includes of libavutil/common.h with what is actually needed
mru
parents: 11391
diff changeset
21 #include <stdlib.h>
8694
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
22 #include <math.h>
11370
4b3da727d832 Move FFT parts from dsputil.h to fft.h
mru
parents: 10496
diff changeset
23 #include "libavutil/mathematics.h"
4b3da727d832 Move FFT parts from dsputil.h to fft.h
mru
parents: 10496
diff changeset
24 #include "fft.h"
8694
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
25
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
26 /**
11644
7dd2a45249a9 Remove explicit filename from Doxygen @file commands.
diego
parents: 11532
diff changeset
27 * @file
8694
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
28 * (Inverse) Real Discrete Fourier Transforms.
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
29 */
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
30
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
31 /* sin(2*pi*x/n) for 0<=x<n/4, followed by n/2<=x<3n/4 */
10408
8fd8f6c1cdcc Add support for hardcoded ff_sin_* tables.
reimar
parents: 10407
diff changeset
32 #if !CONFIG_HARDCODED_TABLES
10407
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
33 SINTABLE(16);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
34 SINTABLE(32);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
35 SINTABLE(64);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
36 SINTABLE(128);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
37 SINTABLE(256);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
38 SINTABLE(512);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
39 SINTABLE(1024);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
40 SINTABLE(2048);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
41 SINTABLE(4096);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
42 SINTABLE(8192);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
43 SINTABLE(16384);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
44 SINTABLE(32768);
57acce8b1380 Move/add COSTABLE/SINTABLE macros to dsputil to add extern definitions
reimar
parents: 10402
diff changeset
45 SINTABLE(65536);
10408
8fd8f6c1cdcc Add support for hardcoded ff_sin_* tables.
reimar
parents: 10407
diff changeset
46 #endif
8fd8f6c1cdcc Add support for hardcoded ff_sin_* tables.
reimar
parents: 10407
diff changeset
47 SINTABLE_CONST FFTSample * const ff_sin_tabs[] = {
10492
63910f7ba293 Pad ff_cos_tabs and ff_sin_tabs so that index n points to the table for n bits.
reimar
parents: 10408
diff changeset
48 NULL, NULL, NULL, NULL,
8694
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
49 ff_sin_16, ff_sin_32, ff_sin_64, ff_sin_128, ff_sin_256, ff_sin_512, ff_sin_1024,
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
50 ff_sin_2048, ff_sin_4096, ff_sin_8192, ff_sin_16384, ff_sin_32768, ff_sin_65536,
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
51 };
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
52
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
53 /** Map one real FFT into two parallel real even and odd FFTs. Then interleave
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
54 * the two real FFTs into one complex FFT. Unmangle the results.
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
55 * ref: http://www.engineeringproductivitytools.com/stuff/T0001/PT10.HTM
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
56 */
11374
1cd8731bbe7f Make some functions static
mru
parents: 11370
diff changeset
57 static void ff_rdft_calc_c(RDFTContext* s, FFTSample* data)
8694
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
58 {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
59 int i, i1, i2;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
60 FFTComplex ev, od;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
61 const int n = 1 << s->nbits;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
62 const float k1 = 0.5;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
63 const float k2 = 0.5 - s->inverse;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
64 const FFTSample *tcos = s->tcos;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
65 const FFTSample *tsin = s->tsin;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
66
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
67 if (!s->inverse) {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
68 ff_fft_permute(&s->fft, (FFTComplex*)data);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
69 ff_fft_calc(&s->fft, (FFTComplex*)data);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
70 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
71 /* i=0 is a special case because of packing, the DC term is real, so we
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
72 are going to throw the N/2 term (also real) in with it. */
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
73 ev.re = data[0];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
74 data[0] = ev.re+data[1];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
75 data[1] = ev.re-data[1];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
76 for (i = 1; i < (n>>2); i++) {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
77 i1 = 2*i;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
78 i2 = n-i1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
79 /* Separate even and odd FFTs */
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
80 ev.re = k1*(data[i1 ]+data[i2 ]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
81 od.im = -k2*(data[i1 ]-data[i2 ]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
82 ev.im = k1*(data[i1+1]-data[i2+1]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
83 od.re = k2*(data[i1+1]+data[i2+1]);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
84 /* Apply twiddle factors to the odd FFT and add to the even FFT */
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
85 data[i1 ] = ev.re + od.re*tcos[i] - od.im*tsin[i];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
86 data[i1+1] = ev.im + od.im*tcos[i] + od.re*tsin[i];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
87 data[i2 ] = ev.re - od.re*tcos[i] + od.im*tsin[i];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
88 data[i2+1] = -ev.im + od.im*tcos[i] + od.re*tsin[i];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
89 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
90 data[2*i+1]=s->sign_convention*data[2*i+1];
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
91 if (s->inverse) {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
92 data[0] *= k1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
93 data[1] *= k1;
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
94 ff_fft_permute(&s->fft, (FFTComplex*)data);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
95 ff_fft_calc(&s->fft, (FFTComplex*)data);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
96 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
97 }
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
98
11513
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
99 av_cold int ff_rdft_init(RDFTContext *s, int nbits, enum RDFTransformType trans)
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
100 {
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
101 int n = 1 << nbits;
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
102 int i;
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
103 const double theta = (trans == DFT_R2C || trans == DFT_C2R ? -1 : 1)*2*M_PI/n;
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
104
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
105 s->nbits = nbits;
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
106 s->inverse = trans == IDFT_C2R || trans == DFT_C2R;
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
107 s->sign_convention = trans == IDFT_R2C || trans == DFT_C2R ? 1 : -1;
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
108
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
109 if (nbits < 4 || nbits > 16)
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
110 return -1;
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
111
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
112 if (ff_fft_init(&s->fft, nbits-1, trans == IDFT_C2R || trans == IDFT_R2C) < 0)
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
113 return -1;
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
114
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
115 ff_init_ff_cos_tabs(nbits);
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
116 s->tcos = ff_cos_tabs[nbits];
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
117 s->tsin = ff_sin_tabs[nbits]+(trans == DFT_R2C || trans == DFT_C2R)*(n>>2);
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
118 #if !CONFIG_HARDCODED_TABLES
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
119 for (i = 0; i < (n>>2); i++) {
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
120 s->tsin[i] = sin(i*theta);
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
121 }
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
122 #endif
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
123 s->rdft_calc = ff_rdft_calc_c;
11532
e011e73a902b ARM: NEON optimised RDFT
mru
parents: 11513
diff changeset
124
e011e73a902b ARM: NEON optimised RDFT
mru
parents: 11513
diff changeset
125 if (ARCH_ARM) ff_rdft_init_arm(s);
e011e73a902b ARM: NEON optimised RDFT
mru
parents: 11513
diff changeset
126
11513
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
127 return 0;
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
128 }
66da6ffd7ed5 rdft: reorder functions to avoid static prototype
mru
parents: 11512
diff changeset
129
8694
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
130 av_cold void ff_rdft_end(RDFTContext *s)
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
131 {
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
132 ff_fft_end(&s->fft);
68fd157bab48 Add the rdft family of transforms (fft/ifft of an all real sequence) to dsputil.
alexc
parents:
diff changeset
133 }