Originally committed as revision 21338 to svn://svn.ffmpeg.org/ffmpeg/trunk
Vitor Sessak authored on 2010/01/20 09:39:47... | ... |
@@ -99,6 +99,7 @@ Configuration options: |
99 | 99 |
--disable-fastdiv disable table-based division |
100 | 100 |
--enable-small optimize for size instead of speed |
101 | 101 |
--disable-aandct disable AAN DCT code |
102 |
+ --disable-dct disable DCT code |
|
102 | 103 |
--disable-fft disable FFT code |
103 | 104 |
--disable-golomb disable Golomb code |
104 | 105 |
--disable-lpc disable LPC code |
... | ... |
@@ -862,6 +863,7 @@ CONFIG_LIST=" |
862 | 862 |
avisynth |
863 | 863 |
beos_netserver |
864 | 864 |
bzlib |
865 |
+ dct |
|
865 | 866 |
doc |
866 | 867 |
fastdiv |
867 | 868 |
ffmpeg |
... | ... |
@@ -27,6 +27,7 @@ OBJS = allcodecs.o \ |
27 | 27 |
# parts needed for many different codecs |
28 | 28 |
OBJS-$(CONFIG_AANDCT) += aandcttab.o |
29 | 29 |
OBJS-$(CONFIG_ENCODERS) += faandct.o jfdctfst.o jfdctint.o |
30 |
+OBJS-$(CONFIG_DCT) += dct.o |
|
30 | 31 |
FFT-OBJS-$(CONFIG_HARDCODED_TABLES) += cos_tables.o |
31 | 32 |
OBJS-$(CONFIG_FFT) += fft.o $(FFT-OBJS-yes) |
32 | 33 |
OBJS-$(CONFIG_GOLOMB) += golomb.o |
33 | 34 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,139 @@ |
0 |
+/* |
|
1 |
+ * (I)DCT Transforms |
|
2 |
+ * Copyright (c) 2009 Peter Ross <pross@xvid.org> |
|
3 |
+ * Copyright (c) 2010 Alex Converse <alex.converse@gmail.com> |
|
4 |
+ * Copyright (c) 2010 Vitor Sessak |
|
5 |
+ * |
|
6 |
+ * This file is part of FFmpeg. |
|
7 |
+ * |
|
8 |
+ * FFmpeg is free software; you can redistribute it and/or |
|
9 |
+ * modify it under the terms of the GNU Lesser General Public |
|
10 |
+ * License as published by the Free Software Foundation; either |
|
11 |
+ * version 2.1 of the License, or (at your option) any later version. |
|
12 |
+ * |
|
13 |
+ * FFmpeg is distributed in the hope that it will be useful, |
|
14 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
15 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
16 |
+ * Lesser General Public License for more details. |
|
17 |
+ * |
|
18 |
+ * You should have received a copy of the GNU Lesser General Public |
|
19 |
+ * License along with FFmpeg; if not, write to the Free Software |
|
20 |
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
|
21 |
+ */ |
|
22 |
+ |
|
23 |
+/** |
|
24 |
+ * @file libavcodec/dct.c |
|
25 |
+ * (Inverse) Discrete Cosine Transforms. These are also known as the |
|
26 |
+ * type II and type III DCTs respectively. |
|
27 |
+ */ |
|
28 |
+ |
|
29 |
+#include <math.h> |
|
30 |
+#include "dsputil.h" |
|
31 |
+ |
|
32 |
+av_cold int ff_dct_init(DCTContext *s, int nbits, int inverse) |
|
33 |
+{ |
|
34 |
+ int n = 1 << nbits; |
|
35 |
+ int i; |
|
36 |
+ |
|
37 |
+ s->nbits = nbits; |
|
38 |
+ s->inverse = inverse; |
|
39 |
+ |
|
40 |
+ ff_init_ff_cos_tabs(nbits+2); |
|
41 |
+ |
|
42 |
+ s->costab = ff_cos_tabs[nbits+2]; |
|
43 |
+ |
|
44 |
+ s->csc2 = av_malloc(n/2 * sizeof(FFTSample)); |
|
45 |
+ |
|
46 |
+ if (ff_rdft_init(&s->rdft, nbits, inverse) < 0) { |
|
47 |
+ av_free(s->csc2); |
|
48 |
+ return -1; |
|
49 |
+ } |
|
50 |
+ |
|
51 |
+ for (i = 0; i < n/2; i++) |
|
52 |
+ s->csc2[i] = 0.5 / sin((M_PI / (2*n) * (2*i + 1))); |
|
53 |
+ |
|
54 |
+ return 0; |
|
55 |
+} |
|
56 |
+ |
|
57 |
+/* sin((M_PI * x / (2*n)) */ |
|
58 |
+#define SIN(s,n,x) (s->costab[(n) - (x)]) |
|
59 |
+ |
|
60 |
+/* cos((M_PI * x / (2*n)) */ |
|
61 |
+#define COS(s,n,x) (s->costab[x]) |
|
62 |
+ |
|
63 |
+static void ff_dct_calc_c(DCTContext *ctx, FFTSample *data) |
|
64 |
+{ |
|
65 |
+ int n = 1 << ctx->nbits; |
|
66 |
+ int i; |
|
67 |
+ |
|
68 |
+ if (ctx->inverse) { |
|
69 |
+ float next = data[n - 1]; |
|
70 |
+ float inv_n = 1.0f / n; |
|
71 |
+ |
|
72 |
+ for (i = n - 2; i >= 2; i -= 2) { |
|
73 |
+ float val1 = data[i ]; |
|
74 |
+ float val2 = data[i - 1] - data[i + 1]; |
|
75 |
+ float c = COS(ctx, n, i); |
|
76 |
+ float s = SIN(ctx, n, i); |
|
77 |
+ |
|
78 |
+ data[i ] = c * val1 + s * val2; |
|
79 |
+ data[i + 1] = s * val1 - c * val2; |
|
80 |
+ } |
|
81 |
+ |
|
82 |
+ data[1] = 2 * next; |
|
83 |
+ |
|
84 |
+ ff_rdft_calc(&ctx->rdft, data); |
|
85 |
+ |
|
86 |
+ for (i = 0; i < n / 2; i++) { |
|
87 |
+ float tmp1 = data[i ] * inv_n; |
|
88 |
+ float tmp2 = data[n - i - 1] * inv_n; |
|
89 |
+ float csc = ctx->csc2[i] * (tmp1 - tmp2); |
|
90 |
+ |
|
91 |
+ tmp1 += tmp2; |
|
92 |
+ data[i ] = tmp1 + csc; |
|
93 |
+ data[n - i - 1] = tmp1 - csc; |
|
94 |
+ } |
|
95 |
+ } else { |
|
96 |
+ float next; |
|
97 |
+ for (i=0; i < n/2; i++) { |
|
98 |
+ float tmp1 = data[i ]; |
|
99 |
+ float tmp2 = data[n - i - 1]; |
|
100 |
+ float s = SIN(ctx, n, 2*i + 1); |
|
101 |
+ |
|
102 |
+ s *= tmp1 - tmp2; |
|
103 |
+ tmp1 = (tmp1 + tmp2) * 0.5f; |
|
104 |
+ |
|
105 |
+ data[i ] = tmp1 + s; |
|
106 |
+ data[n-i-1] = tmp1 - s; |
|
107 |
+ } |
|
108 |
+ |
|
109 |
+ ff_rdft_calc(&ctx->rdft, data); |
|
110 |
+ |
|
111 |
+ next = data[1] * 0.5; |
|
112 |
+ data[1] *= -1; |
|
113 |
+ |
|
114 |
+ for (i = n - 2; i >= 0; i -= 2) { |
|
115 |
+ float inr = data[i ]; |
|
116 |
+ float ini = data[i + 1]; |
|
117 |
+ float c = COS(ctx, n, i); |
|
118 |
+ float s = SIN(ctx, n, i); |
|
119 |
+ |
|
120 |
+ data[i ] = c * inr + s * ini; |
|
121 |
+ |
|
122 |
+ data[i+1] = next; |
|
123 |
+ |
|
124 |
+ next += s * inr - c * ini; |
|
125 |
+ } |
|
126 |
+ } |
|
127 |
+} |
|
128 |
+ |
|
129 |
+void ff_dct_calc(DCTContext *s, FFTSample *data) |
|
130 |
+{ |
|
131 |
+ ff_dct_calc_c(s, data); |
|
132 |
+} |
|
133 |
+ |
|
134 |
+av_cold void ff_dct_end(DCTContext *s) |
|
135 |
+{ |
|
136 |
+ ff_rdft_end(&s->rdft); |
|
137 |
+ av_free(s->csc2); |
|
138 |
+} |
... | ... |
@@ -899,6 +899,26 @@ int ff_rdft_init(RDFTContext *s, int nbits, enum RDFTransformType trans); |
899 | 899 |
void ff_rdft_calc(RDFTContext *s, FFTSample *data); |
900 | 900 |
void ff_rdft_end(RDFTContext *s); |
901 | 901 |
|
902 |
+/* Discrete Cosine Transform */ |
|
903 |
+ |
|
904 |
+typedef struct { |
|
905 |
+ int nbits; |
|
906 |
+ int inverse; |
|
907 |
+ FFTSample *data; |
|
908 |
+ RDFTContext rdft; |
|
909 |
+ const float *costab; |
|
910 |
+ FFTSample *csc2; |
|
911 |
+} DCTContext; |
|
912 |
+ |
|
913 |
+/** |
|
914 |
+ * Sets up (Inverse)DCT. |
|
915 |
+ * @param nbits log2 of the length of the input array |
|
916 |
+ * @param inverse >0 forward transform, <0 inverse transform |
|
917 |
+ */ |
|
918 |
+int ff_dct_init(DCTContext *s, int nbits, int inverse); |
|
919 |
+void ff_dct_calc(DCTContext *s, FFTSample *data); |
|
920 |
+void ff_dct_end (DCTContext *s); |
|
921 |
+ |
|
902 | 922 |
#define WRAPPER8_16(name8, name16)\ |
903 | 923 |
static int name16(void /*MpegEncContext*/ *s, uint8_t *dst, uint8_t *src, int stride, int h){\ |
904 | 924 |
return name8(s, dst , src , stride, h)\ |
... | ... |
@@ -128,6 +128,39 @@ static void mdct_ref(float *output, float *input, int nbits) |
128 | 128 |
} |
129 | 129 |
} |
130 | 130 |
|
131 |
+static void idct_ref(float *output, float *input, int nbits) |
|
132 |
+{ |
|
133 |
+ int n = 1<<nbits; |
|
134 |
+ int k, i; |
|
135 |
+ double a, s; |
|
136 |
+ |
|
137 |
+ /* do it by hand */ |
|
138 |
+ for (i = 0; i < n; i++) { |
|
139 |
+ s = 0.5 * input[0]; |
|
140 |
+ for (k = 1; k < n; k++) { |
|
141 |
+ a = M_PI*k*(i+0.5) / n; |
|
142 |
+ s += input[k] * cos(a); |
|
143 |
+ } |
|
144 |
+ output[i] = 2 * s / n; |
|
145 |
+ } |
|
146 |
+} |
|
147 |
+static void dct_ref(float *output, float *input, int nbits) |
|
148 |
+{ |
|
149 |
+ int n = 1<<nbits; |
|
150 |
+ int k, i; |
|
151 |
+ double a, s; |
|
152 |
+ |
|
153 |
+ /* do it by hand */ |
|
154 |
+ for (k = 0; k < n; k++) { |
|
155 |
+ s = 0; |
|
156 |
+ for (i = 0; i < n; i++) { |
|
157 |
+ a = M_PI*k*(i+0.5) / n; |
|
158 |
+ s += input[i] * cos(a); |
|
159 |
+ } |
|
160 |
+ output[k] = s; |
|
161 |
+ } |
|
162 |
+} |
|
163 |
+ |
|
131 | 164 |
|
132 | 165 |
static float frandom(AVLFG *prng) |
133 | 166 |
{ |
... | ... |
@@ -166,6 +199,7 @@ static void help(void) |
166 | 166 |
"-h print this help\n" |
167 | 167 |
"-s speed test\n" |
168 | 168 |
"-m (I)MDCT test\n" |
169 |
+ "-d (I)DCT test\n" |
|
169 | 170 |
"-i inverse transform test\n" |
170 | 171 |
"-n b set the transform size to 2^b\n" |
171 | 172 |
"-f x set scale factor for output data of (I)MDCT to x\n" |
... | ... |
@@ -177,6 +211,7 @@ enum tf_transform { |
177 | 177 |
TRANSFORM_FFT, |
178 | 178 |
TRANSFORM_MDCT, |
179 | 179 |
TRANSFORM_RDFT, |
180 |
+ TRANSFORM_DCT, |
|
180 | 181 |
}; |
181 | 182 |
|
182 | 183 |
int main(int argc, char **argv) |
... | ... |
@@ -190,6 +225,7 @@ int main(int argc, char **argv) |
190 | 190 |
FFTContext s1, *s = &s1; |
191 | 191 |
FFTContext m1, *m = &m1; |
192 | 192 |
RDFTContext r1, *r = &r1; |
193 |
+ DCTContext d1, *d = &d1; |
|
193 | 194 |
int fft_nbits, fft_size, fft_size_2; |
194 | 195 |
double scale = 1.0; |
195 | 196 |
AVLFG prng; |
... | ... |
@@ -197,7 +233,7 @@ int main(int argc, char **argv) |
197 | 197 |
|
198 | 198 |
fft_nbits = 9; |
199 | 199 |
for(;;) { |
200 |
- c = getopt(argc, argv, "hsimrn:f:"); |
|
200 |
+ c = getopt(argc, argv, "hsimrdn:f:"); |
|
201 | 201 |
if (c == -1) |
202 | 202 |
break; |
203 | 203 |
switch(c) { |
... | ... |
@@ -216,6 +252,9 @@ int main(int argc, char **argv) |
216 | 216 |
case 'r': |
217 | 217 |
transform = TRANSFORM_RDFT; |
218 | 218 |
break; |
219 |
+ case 'd': |
|
220 |
+ transform = TRANSFORM_DCT; |
|
221 |
+ break; |
|
219 | 222 |
case 'n': |
220 | 223 |
fft_nbits = atoi(optarg); |
221 | 224 |
break; |
... | ... |
@@ -257,6 +296,13 @@ int main(int argc, char **argv) |
257 | 257 |
ff_rdft_init(r, fft_nbits, do_inverse ? IRDFT : RDFT); |
258 | 258 |
fft_ref_init(fft_nbits, do_inverse); |
259 | 259 |
break; |
260 |
+ case TRANSFORM_DCT: |
|
261 |
+ if (do_inverse) |
|
262 |
+ av_log(NULL, AV_LOG_INFO,"IDCT"); |
|
263 |
+ else |
|
264 |
+ av_log(NULL, AV_LOG_INFO,"DCT"); |
|
265 |
+ ff_dct_init(d, fft_nbits, do_inverse); |
|
266 |
+ break; |
|
260 | 267 |
} |
261 | 268 |
av_log(NULL, AV_LOG_INFO," %d test\n", fft_size); |
262 | 269 |
|
... | ... |
@@ -321,6 +367,17 @@ int main(int argc, char **argv) |
321 | 321 |
tab_ref[0].im = tab_ref[fft_size_2].re; |
322 | 322 |
check_diff((float *)tab_ref, (float *)tab2, fft_size, 1.0); |
323 | 323 |
} |
324 |
+ break; |
|
325 |
+ case TRANSFORM_DCT: |
|
326 |
+ memcpy(tab, tab1, fft_size * sizeof(FFTComplex)); |
|
327 |
+ ff_dct_calc(d, tab); |
|
328 |
+ if (do_inverse) { |
|
329 |
+ idct_ref(tab_ref, tab1, fft_nbits); |
|
330 |
+ } else { |
|
331 |
+ dct_ref(tab_ref, tab1, fft_nbits); |
|
332 |
+ } |
|
333 |
+ check_diff((float *)tab_ref, (float *)tab, fft_size, 1.0); |
|
334 |
+ break; |
|
324 | 335 |
} |
325 | 336 |
|
326 | 337 |
/* do a speed test */ |
... | ... |
@@ -351,6 +408,10 @@ int main(int argc, char **argv) |
351 | 351 |
memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); |
352 | 352 |
ff_rdft_calc(r, tab2); |
353 | 353 |
break; |
354 |
+ case TRANSFORM_DCT: |
|
355 |
+ memcpy(tab2, tab1, fft_size * sizeof(FFTSample)); |
|
356 |
+ ff_dct_calc(d, tab2); |
|
357 |
+ break; |
|
354 | 358 |
} |
355 | 359 |
} |
356 | 360 |
duration = gettime() - time_start; |
... | ... |
@@ -374,6 +435,9 @@ int main(int argc, char **argv) |
374 | 374 |
case TRANSFORM_RDFT: |
375 | 375 |
ff_rdft_end(r); |
376 | 376 |
break; |
377 |
+ case TRANSFORM_DCT: |
|
378 |
+ ff_dct_end(d); |
|
379 |
+ break; |
|
377 | 380 |
} |
378 | 381 |
return 0; |
379 | 382 |
} |