Mercurial > libavcodec.hg
annotate resample.c @ 1757:3906ddbaffec libavcodec
optimization & bugfix extracted from the 4k line diff between ffmpeg 0.4.7 and http://www.alicestreet.com/ffh263.html
the other parts of the diff where
1. spelling fixes (rejected as only a small part of it could be applied automatically)
2. cosmetics (reindention, function reordering, var renaming, ...) with bugs (rejected)
3. rtp related stuff (rejetced as it breaks several codecs)
4. some changes to the intra/inter decission & scene change detection (quality tests needed first)
| author | michael |
|---|---|
| date | Sat, 24 Jan 2004 23:47:33 +0000 |
| parents | 932d306bf1dc |
| children | 3dc9bbe1b152 |
| rev | line source |
|---|---|
| 0 | 1 /* |
| 2 * Sample rate convertion for both audio and video | |
| 429 | 3 * Copyright (c) 2000 Fabrice Bellard. |
| 0 | 4 * |
| 429 | 5 * This library is free software; you can redistribute it and/or |
| 6 * modify it under the terms of the GNU Lesser General Public | |
| 7 * License as published by the Free Software Foundation; either | |
| 8 * version 2 of the License, or (at your option) any later version. | |
| 0 | 9 * |
| 429 | 10 * This library is distributed in the hope that it will be useful, |
| 0 | 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 429 | 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 13 * Lesser General Public License for more details. | |
| 0 | 14 * |
| 429 | 15 * You should have received a copy of the GNU Lesser General Public |
| 16 * License along with this library; if not, write to the Free Software | |
| 17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 0 | 18 */ |
| 1106 | 19 |
| 20 /** | |
| 21 * @file resample.c | |
| 22 * Sample rate convertion for both audio and video. | |
| 23 */ | |
| 24 | |
| 64 | 25 #include "avcodec.h" |
|
1125
0980ae063f4e
restoring OS/2 compatibility patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
1106
diff
changeset
|
26 |
| 0 | 27 typedef struct { |
| 28 /* fractional resampling */ | |
| 1064 | 29 uint32_t incr; /* fractional increment */ |
| 30 uint32_t frac; | |
| 0 | 31 int last_sample; |
| 32 /* integer down sample */ | |
| 33 int iratio; /* integer divison ratio */ | |
| 34 int icount, isum; | |
| 35 int inv; | |
| 36 } ReSampleChannelContext; | |
| 37 | |
| 38 struct ReSampleContext { | |
| 39 ReSampleChannelContext channel_ctx[2]; | |
| 40 float ratio; | |
| 41 /* channel convert */ | |
| 42 int input_channels, output_channels, filter_channels; | |
| 43 }; | |
| 44 | |
| 45 | |
| 46 #define FRAC_BITS 16 | |
| 47 #define FRAC (1 << FRAC_BITS) | |
| 48 | |
| 49 static void init_mono_resample(ReSampleChannelContext *s, float ratio) | |
| 50 { | |
| 51 ratio = 1.0 / ratio; | |
| 1057 | 52 s->iratio = (int)floorf(ratio); |
| 0 | 53 if (s->iratio == 0) |
| 54 s->iratio = 1; | |
| 55 s->incr = (int)((ratio / s->iratio) * FRAC); | |
|
373
3007abcbc510
* Fix a problem with the first sample when down sampling.
philipjsg
parents:
64
diff
changeset
|
56 s->frac = FRAC; |
| 0 | 57 s->last_sample = 0; |
| 58 s->icount = s->iratio; | |
| 59 s->isum = 0; | |
| 60 s->inv = (FRAC / s->iratio); | |
| 61 } | |
| 62 | |
| 63 /* fractional audio resampling */ | |
| 64 static int fractional_resample(ReSampleChannelContext *s, short *output, short *input, int nb_samples) | |
| 65 { | |
| 66 unsigned int frac, incr; | |
| 67 int l0, l1; | |
| 68 short *q, *p, *pend; | |
| 69 | |
| 70 l0 = s->last_sample; | |
| 71 incr = s->incr; | |
| 72 frac = s->frac; | |
| 73 | |
| 74 p = input; | |
| 75 pend = input + nb_samples; | |
| 76 q = output; | |
| 77 | |
| 78 l1 = *p++; | |
| 79 for(;;) { | |
| 80 /* interpolate */ | |
| 81 *q++ = (l0 * (FRAC - frac) + l1 * frac) >> FRAC_BITS; | |
| 82 frac = frac + s->incr; | |
| 83 while (frac >= FRAC) { | |
| 739 | 84 frac -= FRAC; |
| 0 | 85 if (p >= pend) |
| 86 goto the_end; | |
| 87 l0 = l1; | |
| 88 l1 = *p++; | |
| 89 } | |
| 90 } | |
| 91 the_end: | |
| 92 s->last_sample = l1; | |
| 93 s->frac = frac; | |
| 94 return q - output; | |
| 95 } | |
| 96 | |
| 97 static int integer_downsample(ReSampleChannelContext *s, short *output, short *input, int nb_samples) | |
| 98 { | |
| 99 short *q, *p, *pend; | |
| 100 int c, sum; | |
| 101 | |
| 102 p = input; | |
| 103 pend = input + nb_samples; | |
| 104 q = output; | |
| 105 | |
| 106 c = s->icount; | |
| 107 sum = s->isum; | |
| 108 | |
| 109 for(;;) { | |
| 110 sum += *p++; | |
| 111 if (--c == 0) { | |
| 112 *q++ = (sum * s->inv) >> FRAC_BITS; | |
| 113 c = s->iratio; | |
| 114 sum = 0; | |
| 115 } | |
| 116 if (p >= pend) | |
| 117 break; | |
| 118 } | |
| 119 s->isum = sum; | |
| 120 s->icount = c; | |
| 121 return q - output; | |
| 122 } | |
| 123 | |
| 124 /* n1: number of samples */ | |
| 125 static void stereo_to_mono(short *output, short *input, int n1) | |
| 126 { | |
| 127 short *p, *q; | |
| 128 int n = n1; | |
| 129 | |
| 130 p = input; | |
| 131 q = output; | |
| 132 while (n >= 4) { | |
| 133 q[0] = (p[0] + p[1]) >> 1; | |
| 134 q[1] = (p[2] + p[3]) >> 1; | |
| 135 q[2] = (p[4] + p[5]) >> 1; | |
| 136 q[3] = (p[6] + p[7]) >> 1; | |
| 137 q += 4; | |
| 138 p += 8; | |
| 139 n -= 4; | |
| 140 } | |
| 141 while (n > 0) { | |
| 142 q[0] = (p[0] + p[1]) >> 1; | |
| 143 q++; | |
| 144 p += 2; | |
| 145 n--; | |
| 146 } | |
| 147 } | |
| 148 | |
| 149 /* n1: number of samples */ | |
| 150 static void mono_to_stereo(short *output, short *input, int n1) | |
| 151 { | |
| 152 short *p, *q; | |
| 153 int n = n1; | |
| 154 int v; | |
| 155 | |
| 156 p = input; | |
| 157 q = output; | |
| 158 while (n >= 4) { | |
| 159 v = p[0]; q[0] = v; q[1] = v; | |
| 160 v = p[1]; q[2] = v; q[3] = v; | |
| 161 v = p[2]; q[4] = v; q[5] = v; | |
| 162 v = p[3]; q[6] = v; q[7] = v; | |
| 163 q += 8; | |
| 164 p += 4; | |
| 165 n -= 4; | |
| 166 } | |
| 167 while (n > 0) { | |
| 168 v = p[0]; q[0] = v; q[1] = v; | |
| 169 q += 2; | |
| 170 p += 1; | |
| 171 n--; | |
| 172 } | |
| 173 } | |
| 174 | |
| 175 /* XXX: should use more abstract 'N' channels system */ | |
| 176 static void stereo_split(short *output1, short *output2, short *input, int n) | |
| 177 { | |
| 178 int i; | |
| 179 | |
| 180 for(i=0;i<n;i++) { | |
| 181 *output1++ = *input++; | |
| 182 *output2++ = *input++; | |
| 183 } | |
| 184 } | |
| 185 | |
| 186 static void stereo_mux(short *output, short *input1, short *input2, int n) | |
| 187 { | |
| 188 int i; | |
| 189 | |
| 190 for(i=0;i<n;i++) { | |
| 191 *output++ = *input1++; | |
| 192 *output++ = *input2++; | |
| 193 } | |
| 194 } | |
| 195 | |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
196 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
|
197 { |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
198 int i; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
199 short l,r; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
200 |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
201 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
|
202 l=*input1++; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
203 r=*input2++; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
204 *output++ = l; /* left */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
205 *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
|
206 *output++ = r; /* right */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
207 *output++ = 0; /* left surround */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
208 *output++ = 0; /* right surroud */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
209 *output++ = 0; /* low freq */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
210 } |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
211 } |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
212 |
| 0 | 213 static int mono_resample(ReSampleChannelContext *s, short *output, short *input, int nb_samples) |
| 214 { | |
| 64 | 215 short *buf1; |
| 0 | 216 short *buftmp; |
| 217 | |
|
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
218 buf1= (short*)av_malloc( nb_samples * sizeof(short) ); |
| 64 | 219 |
| 0 | 220 /* first downsample by an integer factor with averaging filter */ |
| 221 if (s->iratio > 1) { | |
| 222 buftmp = buf1; | |
| 223 nb_samples = integer_downsample(s, buftmp, input, nb_samples); | |
| 224 } else { | |
| 225 buftmp = input; | |
| 226 } | |
| 227 | |
| 228 /* then do a fractional resampling with linear interpolation */ | |
| 229 if (s->incr != FRAC) { | |
| 230 nb_samples = fractional_resample(s, output, buftmp, nb_samples); | |
| 231 } else { | |
| 232 memcpy(output, buftmp, nb_samples * sizeof(short)); | |
| 233 } | |
|
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
234 av_free(buf1); |
| 0 | 235 return nb_samples; |
| 236 } | |
| 237 | |
| 238 ReSampleContext *audio_resample_init(int output_channels, int input_channels, | |
| 239 int output_rate, int input_rate) | |
| 240 { | |
| 241 ReSampleContext *s; | |
| 242 int i; | |
| 243 | |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
244 if ( input_channels > 2) |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
245 { |
|
1598
932d306bf1dc
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1446
diff
changeset
|
246 av_log(NULL, AV_LOG_ERROR, "Resampling with input channels greater than 2 unsupported."); |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
247 return NULL; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
248 } |
| 0 | 249 |
| 250 s = av_mallocz(sizeof(ReSampleContext)); | |
| 251 if (!s) | |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
252 { |
|
1598
932d306bf1dc
av_log() patch by (Michel Bardiaux <mbardiaux at peaktime dot be>)
michael
parents:
1446
diff
changeset
|
253 av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for resample context."); |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
254 return NULL; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
255 } |
| 0 | 256 |
| 257 s->ratio = (float)output_rate / (float)input_rate; | |
| 258 | |
| 259 s->input_channels = input_channels; | |
| 260 s->output_channels = output_channels; | |
| 261 | |
| 262 s->filter_channels = s->input_channels; | |
| 263 if (s->output_channels < s->filter_channels) | |
| 264 s->filter_channels = s->output_channels; | |
| 265 | |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
266 /* |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
267 * 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
|
268 * 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
|
269 * 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
|
270 */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
271 if(s->filter_channels>2) |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
272 s->filter_channels = 2; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
273 |
| 0 | 274 for(i=0;i<s->filter_channels;i++) { |
| 275 init_mono_resample(&s->channel_ctx[i], s->ratio); | |
| 276 } | |
| 277 return s; | |
| 278 } | |
| 279 | |
| 280 /* resample audio. 'nb_samples' is the number of input samples */ | |
| 281 /* XXX: optimize it ! */ | |
| 282 /* XXX: do it with polyphase filters, since the quality here is | |
| 283 HORRIBLE. Return the number of samples available in output */ | |
| 284 int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples) | |
| 285 { | |
| 286 int i, nb_samples1; | |
| 64 | 287 short *bufin[2]; |
| 288 short *bufout[2]; | |
| 0 | 289 short *buftmp2[2], *buftmp3[2]; |
| 64 | 290 int lenout; |
| 0 | 291 |
| 292 if (s->input_channels == s->output_channels && s->ratio == 1.0) { | |
| 293 /* nothing to do */ | |
| 294 memcpy(output, input, nb_samples * s->input_channels * sizeof(short)); | |
| 295 return nb_samples; | |
| 296 } | |
| 297 | |
| 64 | 298 /* XXX: move those malloc to resample init code */ |
|
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
299 bufin[0]= (short*) av_malloc( nb_samples * sizeof(short) ); |
|
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
300 bufin[1]= (short*) av_malloc( nb_samples * sizeof(short) ); |
| 64 | 301 |
| 302 /* make some zoom to avoid round pb */ | |
| 303 lenout= (int)(nb_samples * s->ratio) + 16; | |
|
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
304 bufout[0]= (short*) av_malloc( lenout * sizeof(short) ); |
|
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
305 bufout[1]= (short*) av_malloc( lenout * sizeof(short) ); |
| 64 | 306 |
| 0 | 307 if (s->input_channels == 2 && |
| 308 s->output_channels == 1) { | |
| 309 buftmp2[0] = bufin[0]; | |
| 310 buftmp3[0] = output; | |
| 311 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
|
312 } else if (s->output_channels >= 2 && s->input_channels == 1) { |
| 0 | 313 buftmp2[0] = input; |
| 314 buftmp3[0] = bufout[0]; | |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
315 } else if (s->output_channels >= 2) { |
| 0 | 316 buftmp2[0] = bufin[0]; |
| 317 buftmp2[1] = bufin[1]; | |
| 318 buftmp3[0] = bufout[0]; | |
| 319 buftmp3[1] = bufout[1]; | |
| 320 stereo_split(buftmp2[0], buftmp2[1], input, nb_samples); | |
| 321 } else { | |
| 322 buftmp2[0] = input; | |
| 323 buftmp3[0] = output; | |
| 324 } | |
| 325 | |
| 326 /* resample each channel */ | |
| 327 nb_samples1 = 0; /* avoid warning */ | |
| 328 for(i=0;i<s->filter_channels;i++) { | |
| 329 nb_samples1 = mono_resample(&s->channel_ctx[i], buftmp3[i], buftmp2[i], nb_samples); | |
| 330 } | |
| 331 | |
| 332 if (s->output_channels == 2 && s->input_channels == 1) { | |
| 333 mono_to_stereo(output, buftmp3[0], nb_samples1); | |
| 334 } else if (s->output_channels == 2) { | |
| 335 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
|
336 } 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
|
337 ac3_5p1_mux(output, buftmp3[0], buftmp3[1], nb_samples1); |
| 0 | 338 } |
| 339 | |
|
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
340 av_free(bufin[0]); |
|
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
341 av_free(bufin[1]); |
| 64 | 342 |
|
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
343 av_free(bufout[0]); |
|
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
344 av_free(bufout[1]); |
| 0 | 345 return nb_samples1; |
| 346 } | |
| 347 | |
| 348 void audio_resample_close(ReSampleContext *s) | |
| 349 { | |
|
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
350 av_free(s); |
| 0 | 351 } |
