Mercurial > libavcodec.hg
annotate resample.c @ 3198:6b9f0c4fbdbe libavcodec
First part of a series of speed-enchancing patches.
This one sets up a snow.h and makes snow use the dsputil function pointer
framework to access the three functions that will be implemented in asm
in the other parts of the patchset.
Patch by Robert Edele < yartrebo AH earthlink POIS net>
Original thread:
Subject: [Ffmpeg-devel] [PATCH] Snow mmx+sse2 asm optimizations
Date: Sun, 05 Feb 2006 12:47:14 -0500
| author | gpoirier |
|---|---|
| date | Thu, 16 Mar 2006 19:18:18 +0000 |
| parents | 0b546eab515d |
| children | c8c591fe26f8 |
| 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 | |
|
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2979
diff
changeset
|
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 |
|
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
27 struct AVResampleContext; |
| 0 | 28 |
| 29 struct ReSampleContext { | |
|
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
30 struct AVResampleContext *resample_context; |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
31 short *temp[2]; |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
32 int temp_len; |
| 0 | 33 float ratio; |
| 34 /* channel convert */ | |
| 35 int input_channels, output_channels, filter_channels; | |
| 36 }; | |
| 37 | |
| 38 /* n1: number of samples */ | |
| 39 static void stereo_to_mono(short *output, short *input, int n1) | |
| 40 { | |
| 41 short *p, *q; | |
| 42 int n = n1; | |
| 43 | |
| 44 p = input; | |
| 45 q = output; | |
| 46 while (n >= 4) { | |
| 47 q[0] = (p[0] + p[1]) >> 1; | |
| 48 q[1] = (p[2] + p[3]) >> 1; | |
| 49 q[2] = (p[4] + p[5]) >> 1; | |
| 50 q[3] = (p[6] + p[7]) >> 1; | |
| 51 q += 4; | |
| 52 p += 8; | |
| 53 n -= 4; | |
| 54 } | |
| 55 while (n > 0) { | |
| 56 q[0] = (p[0] + p[1]) >> 1; | |
| 57 q++; | |
| 58 p += 2; | |
| 59 n--; | |
| 60 } | |
| 61 } | |
| 62 | |
| 63 /* n1: number of samples */ | |
| 64 static void mono_to_stereo(short *output, short *input, int n1) | |
| 65 { | |
| 66 short *p, *q; | |
| 67 int n = n1; | |
| 68 int v; | |
| 69 | |
| 70 p = input; | |
| 71 q = output; | |
| 72 while (n >= 4) { | |
| 73 v = p[0]; q[0] = v; q[1] = v; | |
| 74 v = p[1]; q[2] = v; q[3] = v; | |
| 75 v = p[2]; q[4] = v; q[5] = v; | |
| 76 v = p[3]; q[6] = v; q[7] = v; | |
| 77 q += 8; | |
| 78 p += 4; | |
| 79 n -= 4; | |
| 80 } | |
| 81 while (n > 0) { | |
| 82 v = p[0]; q[0] = v; q[1] = v; | |
| 83 q += 2; | |
| 84 p += 1; | |
| 85 n--; | |
| 86 } | |
| 87 } | |
| 88 | |
| 89 /* XXX: should use more abstract 'N' channels system */ | |
| 90 static void stereo_split(short *output1, short *output2, short *input, int n) | |
| 91 { | |
| 92 int i; | |
| 93 | |
| 94 for(i=0;i<n;i++) { | |
| 95 *output1++ = *input++; | |
| 96 *output2++ = *input++; | |
| 97 } | |
| 98 } | |
| 99 | |
| 100 static void stereo_mux(short *output, short *input1, short *input2, int n) | |
| 101 { | |
| 102 int i; | |
| 103 | |
| 104 for(i=0;i<n;i++) { | |
| 105 *output++ = *input1++; | |
| 106 *output++ = *input2++; | |
| 107 } | |
| 108 } | |
| 109 | |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
110 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
|
111 { |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
112 int i; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
113 short l,r; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
114 |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
115 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
|
116 l=*input1++; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
117 r=*input2++; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
118 *output++ = l; /* left */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
119 *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
|
120 *output++ = r; /* right */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
121 *output++ = 0; /* left surround */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
122 *output++ = 0; /* right surroud */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
123 *output++ = 0; /* low freq */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
124 } |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
125 } |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
126 |
| 2967 | 127 ReSampleContext *audio_resample_init(int output_channels, int input_channels, |
| 0 | 128 int output_rate, int input_rate) |
| 129 { | |
| 130 ReSampleContext *s; | |
| 2967 | 131 |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
132 if ( input_channels > 2) |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
133 { |
| 2979 | 134 av_log(NULL, AV_LOG_ERROR, "Resampling with input channels greater than 2 unsupported."); |
| 135 return NULL; | |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
136 } |
| 0 | 137 |
| 138 s = av_mallocz(sizeof(ReSampleContext)); | |
| 139 if (!s) | |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
140 { |
| 2979 | 141 av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for resample context."); |
| 142 return NULL; | |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
143 } |
| 0 | 144 |
| 145 s->ratio = (float)output_rate / (float)input_rate; | |
| 2967 | 146 |
| 0 | 147 s->input_channels = input_channels; |
| 148 s->output_channels = output_channels; | |
| 2967 | 149 |
| 0 | 150 s->filter_channels = s->input_channels; |
| 151 if (s->output_channels < s->filter_channels) | |
| 152 s->filter_channels = s->output_channels; | |
| 153 | |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
154 /* |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
155 * 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
|
156 * 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
|
157 * 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
|
158 */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
159 if(s->filter_channels>2) |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
160 s->filter_channels = 2; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
161 |
| 2308 | 162 s->resample_context= av_resample_init(output_rate, input_rate, 16, 10, 0, 1.0); |
| 2967 | 163 |
| 0 | 164 return s; |
| 165 } | |
| 166 | |
| 167 /* resample audio. 'nb_samples' is the number of input samples */ | |
| 168 /* XXX: optimize it ! */ | |
| 169 int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples) | |
| 170 { | |
| 171 int i, nb_samples1; | |
| 64 | 172 short *bufin[2]; |
| 173 short *bufout[2]; | |
| 0 | 174 short *buftmp2[2], *buftmp3[2]; |
| 64 | 175 int lenout; |
| 0 | 176 |
| 2109 | 177 if (s->input_channels == s->output_channels && s->ratio == 1.0 && 0) { |
| 0 | 178 /* nothing to do */ |
| 179 memcpy(output, input, nb_samples * s->input_channels * sizeof(short)); | |
| 180 return nb_samples; | |
| 181 } | |
| 182 | |
| 64 | 183 /* 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
|
184 for(i=0; i<s->filter_channels; i++){ |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
185 bufin[i]= (short*) av_malloc( (nb_samples + s->temp_len) * sizeof(short) ); |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
186 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
|
187 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
|
188 } |
| 2967 | 189 |
| 64 | 190 /* make some zoom to avoid round pb */ |
| 191 lenout= (int)(nb_samples * s->ratio) + 16; | |
|
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
192 bufout[0]= (short*) av_malloc( lenout * sizeof(short) ); |
|
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
193 bufout[1]= (short*) av_malloc( lenout * sizeof(short) ); |
| 64 | 194 |
| 0 | 195 if (s->input_channels == 2 && |
| 196 s->output_channels == 1) { | |
| 197 buftmp3[0] = output; | |
| 198 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
|
199 } else if (s->output_channels >= 2 && s->input_channels == 1) { |
| 0 | 200 buftmp3[0] = bufout[0]; |
|
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
201 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
|
202 } else if (s->output_channels >= 2) { |
| 0 | 203 buftmp3[0] = bufout[0]; |
| 204 buftmp3[1] = bufout[1]; | |
| 205 stereo_split(buftmp2[0], buftmp2[1], input, nb_samples); | |
| 206 } else { | |
| 207 buftmp3[0] = output; | |
|
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
208 memcpy(buftmp2[0], input, nb_samples*sizeof(short)); |
| 0 | 209 } |
| 210 | |
|
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
211 nb_samples += s->temp_len; |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
212 |
| 0 | 213 /* resample each channel */ |
| 214 nb_samples1 = 0; /* avoid warning */ | |
| 215 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
|
216 int consumed; |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
217 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
|
218 |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
219 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
|
220 s->temp_len= nb_samples - consumed; |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
221 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
|
222 memcpy(s->temp[i], bufin[i] + consumed, s->temp_len*sizeof(short)); |
| 0 | 223 } |
| 224 | |
| 225 if (s->output_channels == 2 && s->input_channels == 1) { | |
| 226 mono_to_stereo(output, buftmp3[0], nb_samples1); | |
| 227 } else if (s->output_channels == 2) { | |
| 228 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
|
229 } 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
|
230 ac3_5p1_mux(output, buftmp3[0], buftmp3[1], nb_samples1); |
| 0 | 231 } |
| 232 | |
| 2084 | 233 for(i=0; i<s->filter_channels; i++) |
| 234 av_free(bufin[i]); | |
| 64 | 235 |
|
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
236 av_free(bufout[0]); |
|
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
237 av_free(bufout[1]); |
| 0 | 238 return nb_samples1; |
| 239 } | |
| 240 | |
| 241 void audio_resample_close(ReSampleContext *s) | |
| 242 { | |
|
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
243 av_resample_close(s->resample_context); |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
244 av_freep(&s->temp[0]); |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
245 av_freep(&s->temp[1]); |
|
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
246 av_free(s); |
| 0 | 247 } |
