Mercurial > libavcodec.hg
annotate resample.c @ 6017:e1404acccac3 libavcodec
Actually return with an error condition if we're being asked to deal with too
many reference frames. Also check max num ref frames against our internal
ref buffer sizes.
Part of fix for roundup issue 281
author | heydowns |
---|---|
date | Fri, 14 Dec 2007 05:48:27 +0000 |
parents | 7d242886f17b |
children | 78b46e3f9df2 |
rev | line source |
---|---|
0 | 1 /* |
5355 | 2 * samplerate conversion for both audio and video |
429 | 3 * Copyright (c) 2000 Fabrice Bellard. |
0 | 4 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
429 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * 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:
3036
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
0 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
0 | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
429 | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 * Lesser General Public License for more details. | |
0 | 16 * |
429 | 17 * 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:
3036
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2979
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 20 */ |
1106 | 21 |
22 /** | |
23 * @file resample.c | |
5355 | 24 * samplerate conversion for both audio and video |
1106 | 25 */ |
26 | |
64 | 27 #include "avcodec.h" |
1125
0980ae063f4e
restoring OS/2 compatibility patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
1106
diff
changeset
|
28 |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
29 struct AVResampleContext; |
0 | 30 |
31 struct ReSampleContext { | |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
32 struct AVResampleContext *resample_context; |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
33 short *temp[2]; |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
34 int temp_len; |
0 | 35 float ratio; |
36 /* channel convert */ | |
37 int input_channels, output_channels, filter_channels; | |
38 }; | |
39 | |
40 /* n1: number of samples */ | |
41 static void stereo_to_mono(short *output, short *input, int n1) | |
42 { | |
43 short *p, *q; | |
44 int n = n1; | |
45 | |
46 p = input; | |
47 q = output; | |
48 while (n >= 4) { | |
49 q[0] = (p[0] + p[1]) >> 1; | |
50 q[1] = (p[2] + p[3]) >> 1; | |
51 q[2] = (p[4] + p[5]) >> 1; | |
52 q[3] = (p[6] + p[7]) >> 1; | |
53 q += 4; | |
54 p += 8; | |
55 n -= 4; | |
56 } | |
57 while (n > 0) { | |
58 q[0] = (p[0] + p[1]) >> 1; | |
59 q++; | |
60 p += 2; | |
61 n--; | |
62 } | |
63 } | |
64 | |
65 /* n1: number of samples */ | |
66 static void mono_to_stereo(short *output, short *input, int n1) | |
67 { | |
68 short *p, *q; | |
69 int n = n1; | |
70 int v; | |
71 | |
72 p = input; | |
73 q = output; | |
74 while (n >= 4) { | |
75 v = p[0]; q[0] = v; q[1] = v; | |
76 v = p[1]; q[2] = v; q[3] = v; | |
77 v = p[2]; q[4] = v; q[5] = v; | |
78 v = p[3]; q[6] = v; q[7] = v; | |
79 q += 8; | |
80 p += 4; | |
81 n -= 4; | |
82 } | |
83 while (n > 0) { | |
84 v = p[0]; q[0] = v; q[1] = v; | |
85 q += 2; | |
86 p += 1; | |
87 n--; | |
88 } | |
89 } | |
90 | |
91 /* XXX: should use more abstract 'N' channels system */ | |
92 static void stereo_split(short *output1, short *output2, short *input, int n) | |
93 { | |
94 int i; | |
95 | |
96 for(i=0;i<n;i++) { | |
97 *output1++ = *input++; | |
98 *output2++ = *input++; | |
99 } | |
100 } | |
101 | |
102 static void stereo_mux(short *output, short *input1, short *input2, int n) | |
103 { | |
104 int i; | |
105 | |
106 for(i=0;i<n;i++) { | |
107 *output++ = *input1++; | |
108 *output++ = *input2++; | |
109 } | |
110 } | |
111 | |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
112 static void ac3_5p1_mux(short *output, short *input1, short *input2, int n) |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
113 { |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
114 int i; |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
115 short l,r; |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
116 |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
117 for(i=0;i<n;i++) { |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
118 l=*input1++; |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
119 r=*input2++; |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
120 *output++ = l; /* left */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
121 *output++ = (l/2)+(r/2); /* center */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
122 *output++ = r; /* right */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
123 *output++ = 0; /* left surround */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
124 *output++ = 0; /* right surroud */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
125 *output++ = 0; /* low freq */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
126 } |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
127 } |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
128 |
2967 | 129 ReSampleContext *audio_resample_init(int output_channels, int input_channels, |
0 | 130 int output_rate, int input_rate) |
131 { | |
132 ReSampleContext *s; | |
2967 | 133 |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
134 if ( input_channels > 2) |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
135 { |
2979 | 136 av_log(NULL, AV_LOG_ERROR, "Resampling with input channels greater than 2 unsupported."); |
137 return NULL; | |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
138 } |
0 | 139 |
140 s = av_mallocz(sizeof(ReSampleContext)); | |
141 if (!s) | |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
142 { |
2979 | 143 av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for resample context."); |
144 return NULL; | |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
145 } |
0 | 146 |
147 s->ratio = (float)output_rate / (float)input_rate; | |
2967 | 148 |
0 | 149 s->input_channels = input_channels; |
150 s->output_channels = output_channels; | |
2967 | 151 |
0 | 152 s->filter_channels = s->input_channels; |
153 if (s->output_channels < s->filter_channels) | |
154 s->filter_channels = s->output_channels; | |
155 | |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
156 /* |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
157 * ac3 output is the only case where filter_channels could be greater than 2. |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
158 * input channels can't be greater than 2, so resample the 2 channels and then |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
159 * expand to 6 channels after the resampling. |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
160 */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
161 if(s->filter_channels>2) |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
162 s->filter_channels = 2; |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
163 |
4712
5c0c96d437f2
set more reasonable cutoff for audio rate conversion
michael
parents:
3947
diff
changeset
|
164 #define TAPS 16 |
5c0c96d437f2
set more reasonable cutoff for audio rate conversion
michael
parents:
3947
diff
changeset
|
165 s->resample_context= av_resample_init(output_rate, input_rate, TAPS, 10, 0, 0.8); |
2967 | 166 |
0 | 167 return s; |
168 } | |
169 | |
170 /* resample audio. 'nb_samples' is the number of input samples */ | |
171 /* XXX: optimize it ! */ | |
172 int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples) | |
173 { | |
174 int i, nb_samples1; | |
64 | 175 short *bufin[2]; |
176 short *bufout[2]; | |
0 | 177 short *buftmp2[2], *buftmp3[2]; |
64 | 178 int lenout; |
0 | 179 |
2109 | 180 if (s->input_channels == s->output_channels && s->ratio == 1.0 && 0) { |
0 | 181 /* nothing to do */ |
182 memcpy(output, input, nb_samples * s->input_channels * sizeof(short)); | |
183 return nb_samples; | |
184 } | |
185 | |
64 | 186 /* XXX: move those malloc to resample init code */ |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
187 for(i=0; i<s->filter_channels; i++){ |
5958
ed05a3d964fa
stupid code (casting of void*) found by checktree.sh
michael
parents:
5502
diff
changeset
|
188 bufin[i]= av_malloc( (nb_samples + s->temp_len) * sizeof(short) ); |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
189 memcpy(bufin[i], s->temp[i], s->temp_len * sizeof(short)); |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
190 buftmp2[i] = bufin[i] + s->temp_len; |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
191 } |
2967 | 192 |
64 | 193 /* make some zoom to avoid round pb */ |
5959 | 194 lenout= 4*nb_samples * s->ratio + 16; |
5958
ed05a3d964fa
stupid code (casting of void*) found by checktree.sh
michael
parents:
5502
diff
changeset
|
195 bufout[0]= av_malloc( lenout * sizeof(short) ); |
ed05a3d964fa
stupid code (casting of void*) found by checktree.sh
michael
parents:
5502
diff
changeset
|
196 bufout[1]= av_malloc( lenout * sizeof(short) ); |
64 | 197 |
0 | 198 if (s->input_channels == 2 && |
199 s->output_channels == 1) { | |
200 buftmp3[0] = output; | |
201 stereo_to_mono(buftmp2[0], input, nb_samples); | |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
202 } else if (s->output_channels >= 2 && s->input_channels == 1) { |
0 | 203 buftmp3[0] = bufout[0]; |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
204 memcpy(buftmp2[0], input, nb_samples*sizeof(short)); |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
205 } else if (s->output_channels >= 2) { |
0 | 206 buftmp3[0] = bufout[0]; |
207 buftmp3[1] = bufout[1]; | |
208 stereo_split(buftmp2[0], buftmp2[1], input, nb_samples); | |
209 } else { | |
210 buftmp3[0] = output; | |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
211 memcpy(buftmp2[0], input, nb_samples*sizeof(short)); |
0 | 212 } |
213 | |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
214 nb_samples += s->temp_len; |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
215 |
0 | 216 /* resample each channel */ |
217 nb_samples1 = 0; /* avoid warning */ | |
218 for(i=0;i<s->filter_channels;i++) { | |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
219 int consumed; |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
220 int is_last= i+1 == s->filter_channels; |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
221 |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
222 nb_samples1 = av_resample(s->resample_context, buftmp3[i], bufin[i], &consumed, nb_samples, lenout, is_last); |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
223 s->temp_len= nb_samples - consumed; |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
224 s->temp[i]= av_realloc(s->temp[i], s->temp_len*sizeof(short)); |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
225 memcpy(s->temp[i], bufin[i] + consumed, s->temp_len*sizeof(short)); |
0 | 226 } |
227 | |
228 if (s->output_channels == 2 && s->input_channels == 1) { | |
229 mono_to_stereo(output, buftmp3[0], nb_samples1); | |
230 } else if (s->output_channels == 2) { | |
231 stereo_mux(output, buftmp3[0], buftmp3[1], nb_samples1); | |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
232 } else if (s->output_channels == 6) { |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
233 ac3_5p1_mux(output, buftmp3[0], buftmp3[1], nb_samples1); |
0 | 234 } |
235 | |
2084 | 236 for(i=0; i<s->filter_channels; i++) |
237 av_free(bufin[i]); | |
64 | 238 |
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
239 av_free(bufout[0]); |
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
240 av_free(bufout[1]); |
0 | 241 return nb_samples1; |
242 } | |
243 | |
244 void audio_resample_close(ReSampleContext *s) | |
245 { | |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
246 av_resample_close(s->resample_context); |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
247 av_freep(&s->temp[0]); |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
248 av_freep(&s->temp[1]); |
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
249 av_free(s); |
0 | 250 } |