Mercurial > libavcodec.hg
annotate resample.c @ 8991:ca768cb2bfb6 libavcodec
Use last decoded SPS as current SPS in order to parse picture timing SEI
correctly. This works around an apparent H.264 standard deficiency.
Patch by Ivan Schreter, schreter gmx net
| author | cehoyos |
|---|---|
| date | Fri, 20 Feb 2009 16:20:01 +0000 |
| parents | 28b706b75b00 |
| children | fff66291d84d |
| rev | line source |
|---|---|
| 0 | 1 /* |
| 5355 | 2 * samplerate conversion for both audio and video |
|
8629
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
7470
diff
changeset
|
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 /** | |
|
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8629
diff
changeset
|
23 * @file libavcodec/resample.c |
| 5355 | 24 * samplerate conversion for both audio and video |
| 1106 | 25 */ |
| 26 | |
| 64 | 27 #include "avcodec.h" |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
28 #include "audioconvert.h" |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
29 #include "opt.h" |
|
1125
0980ae063f4e
restoring OS/2 compatibility patch by ("Slavik Gnatenko" <miracle9 at newmail dot ru>)
michaelni
parents:
1106
diff
changeset
|
30 |
|
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
31 struct AVResampleContext; |
| 0 | 32 |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
33 static const char *context_to_name(void *ptr) |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
34 { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
35 return "audioresample"; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
36 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
37 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
38 static const AVOption options[] = {{NULL}}; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
39 static const AVClass audioresample_context_class = { "ReSampleContext", context_to_name, options }; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
40 |
| 0 | 41 struct ReSampleContext { |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
42 const AVClass *av_class; |
|
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
43 struct AVResampleContext *resample_context; |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
44 short *temp[2]; |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
45 int temp_len; |
| 0 | 46 float ratio; |
| 47 /* channel convert */ | |
| 48 int input_channels, output_channels, filter_channels; | |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
49 AVAudioConvert *convert_ctx[2]; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
50 enum SampleFormat sample_fmt[2]; ///< input and output sample format |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
51 unsigned sample_size[2]; ///< size of one sample in sample_fmt |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
52 short *buffer[2]; ///< buffers used for conversion to S16 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
53 unsigned buffer_size[2]; ///< sizes of allocated buffers |
| 0 | 54 }; |
| 55 | |
| 56 /* n1: number of samples */ | |
| 57 static void stereo_to_mono(short *output, short *input, int n1) | |
| 58 { | |
| 59 short *p, *q; | |
| 60 int n = n1; | |
| 61 | |
| 62 p = input; | |
| 63 q = output; | |
| 64 while (n >= 4) { | |
| 65 q[0] = (p[0] + p[1]) >> 1; | |
| 66 q[1] = (p[2] + p[3]) >> 1; | |
| 67 q[2] = (p[4] + p[5]) >> 1; | |
| 68 q[3] = (p[6] + p[7]) >> 1; | |
| 69 q += 4; | |
| 70 p += 8; | |
| 71 n -= 4; | |
| 72 } | |
| 73 while (n > 0) { | |
| 74 q[0] = (p[0] + p[1]) >> 1; | |
| 75 q++; | |
| 76 p += 2; | |
| 77 n--; | |
| 78 } | |
| 79 } | |
| 80 | |
| 81 /* n1: number of samples */ | |
| 82 static void mono_to_stereo(short *output, short *input, int n1) | |
| 83 { | |
| 84 short *p, *q; | |
| 85 int n = n1; | |
| 86 int v; | |
| 87 | |
| 88 p = input; | |
| 89 q = output; | |
| 90 while (n >= 4) { | |
| 91 v = p[0]; q[0] = v; q[1] = v; | |
| 92 v = p[1]; q[2] = v; q[3] = v; | |
| 93 v = p[2]; q[4] = v; q[5] = v; | |
| 94 v = p[3]; q[6] = v; q[7] = v; | |
| 95 q += 8; | |
| 96 p += 4; | |
| 97 n -= 4; | |
| 98 } | |
| 99 while (n > 0) { | |
| 100 v = p[0]; q[0] = v; q[1] = v; | |
| 101 q += 2; | |
| 102 p += 1; | |
| 103 n--; | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 /* XXX: should use more abstract 'N' channels system */ | |
| 108 static void stereo_split(short *output1, short *output2, short *input, int n) | |
| 109 { | |
| 110 int i; | |
| 111 | |
| 112 for(i=0;i<n;i++) { | |
| 113 *output1++ = *input++; | |
| 114 *output2++ = *input++; | |
| 115 } | |
| 116 } | |
| 117 | |
| 118 static void stereo_mux(short *output, short *input1, short *input2, int n) | |
| 119 { | |
| 120 int i; | |
| 121 | |
| 122 for(i=0;i<n;i++) { | |
| 123 *output++ = *input1++; | |
| 124 *output++ = *input2++; | |
| 125 } | |
| 126 } | |
| 127 | |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
128 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
|
129 { |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
130 int i; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
131 short l,r; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
132 |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
133 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
|
134 l=*input1++; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
135 r=*input2++; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
136 *output++ = l; /* left */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
137 *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
|
138 *output++ = r; /* right */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
139 *output++ = 0; /* left surround */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
140 *output++ = 0; /* right surroud */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
141 *output++ = 0; /* low freq */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
142 } |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
143 } |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
144 |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
145 ReSampleContext *av_audio_resample_init(int output_channels, int input_channels, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
146 int output_rate, int input_rate, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
147 enum SampleFormat sample_fmt_out, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
148 enum SampleFormat sample_fmt_in, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
149 int filter_length, int log2_phase_count, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
150 int linear, double cutoff) |
| 0 | 151 { |
| 152 ReSampleContext *s; | |
| 2967 | 153 |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
154 if ( input_channels > 2) |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
155 { |
| 6023 | 156 av_log(NULL, AV_LOG_ERROR, "Resampling with input channels greater than 2 unsupported.\n"); |
| 2979 | 157 return NULL; |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
158 } |
| 0 | 159 |
| 160 s = av_mallocz(sizeof(ReSampleContext)); | |
| 161 if (!s) | |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
162 { |
| 6023 | 163 av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for resample context.\n"); |
| 2979 | 164 return NULL; |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
165 } |
| 0 | 166 |
| 167 s->ratio = (float)output_rate / (float)input_rate; | |
| 2967 | 168 |
| 0 | 169 s->input_channels = input_channels; |
| 170 s->output_channels = output_channels; | |
| 2967 | 171 |
| 0 | 172 s->filter_channels = s->input_channels; |
| 173 if (s->output_channels < s->filter_channels) | |
| 174 s->filter_channels = s->output_channels; | |
| 175 | |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
176 s->sample_fmt [0] = sample_fmt_in; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
177 s->sample_fmt [1] = sample_fmt_out; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
178 s->sample_size[0] = av_get_bits_per_sample_format(s->sample_fmt[0])>>3; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
179 s->sample_size[1] = av_get_bits_per_sample_format(s->sample_fmt[1])>>3; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
180 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
181 if (s->sample_fmt[0] != SAMPLE_FMT_S16) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
182 if (!(s->convert_ctx[0] = av_audio_convert_alloc(SAMPLE_FMT_S16, 1, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
183 s->sample_fmt[0], 1, NULL, 0))) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
184 av_log(s, AV_LOG_ERROR, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
185 "Cannot convert %s sample format to s16 sample format\n", |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
186 avcodec_get_sample_fmt_name(s->sample_fmt[0])); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
187 av_free(s); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
188 return NULL; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
189 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
190 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
191 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
192 if (s->sample_fmt[1] != SAMPLE_FMT_S16) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
193 if (!(s->convert_ctx[1] = av_audio_convert_alloc(s->sample_fmt[1], 1, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
194 SAMPLE_FMT_S16, 1, NULL, 0))) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
195 av_log(s, AV_LOG_ERROR, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
196 "Cannot convert s16 sample format to %s sample format\n", |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
197 avcodec_get_sample_fmt_name(s->sample_fmt[1])); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
198 av_audio_convert_free(s->convert_ctx[0]); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
199 av_free(s); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
200 return NULL; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
201 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
202 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
203 |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
204 /* |
|
7470
1a93d3bbe3ee
cosmetics: make all references to AC-3 capitalized and hyphenated
jbr
parents:
6023
diff
changeset
|
205 * AC-3 output is the only case where filter_channels could be greater than 2. |
|
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
206 * 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
|
207 * 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
|
208 */ |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
209 if(s->filter_channels>2) |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
210 s->filter_channels = 2; |
|
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
211 |
|
4712
5c0c96d437f2
set more reasonable cutoff for audio rate conversion
michael
parents:
3947
diff
changeset
|
212 #define TAPS 16 |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
213 s->resample_context= av_resample_init(output_rate, input_rate, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
214 filter_length, log2_phase_count, linear, cutoff); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
215 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
216 s->av_class= &audioresample_context_class; |
| 2967 | 217 |
| 0 | 218 return s; |
| 219 } | |
| 220 | |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
221 #if LIBAVCODEC_VERSION_MAJOR < 53 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
222 ReSampleContext *audio_resample_init(int output_channels, int input_channels, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
223 int output_rate, int input_rate) |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
224 { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
225 return av_audio_resample_init(output_channels, input_channels, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
226 output_rate, input_rate, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
227 SAMPLE_FMT_S16, SAMPLE_FMT_S16, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
228 TAPS, 10, 0, 0.8); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
229 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
230 #endif |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
231 |
| 0 | 232 /* resample audio. 'nb_samples' is the number of input samples */ |
| 233 /* XXX: optimize it ! */ | |
| 234 int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples) | |
| 235 { | |
| 236 int i, nb_samples1; | |
| 64 | 237 short *bufin[2]; |
| 238 short *bufout[2]; | |
| 0 | 239 short *buftmp2[2], *buftmp3[2]; |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
240 short *output_bak = NULL; |
| 64 | 241 int lenout; |
| 0 | 242 |
| 2109 | 243 if (s->input_channels == s->output_channels && s->ratio == 1.0 && 0) { |
| 0 | 244 /* nothing to do */ |
| 245 memcpy(output, input, nb_samples * s->input_channels * sizeof(short)); | |
| 246 return nb_samples; | |
| 247 } | |
| 248 | |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
249 if (s->sample_fmt[0] != SAMPLE_FMT_S16) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
250 int istride[1] = { s->sample_size[0] }; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
251 int ostride[1] = { 2 }; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
252 const void *ibuf[1] = { input }; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
253 void *obuf[1]; |
|
8911
28b706b75b00
Prevent heap corruption when resampling 8-bit audio.
pross
parents:
8806
diff
changeset
|
254 unsigned input_size = nb_samples*s->input_channels*2; |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
255 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
256 if (!s->buffer_size[0] || s->buffer_size[0] < input_size) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
257 av_free(s->buffer[0]); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
258 s->buffer_size[0] = input_size; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
259 s->buffer[0] = av_malloc(s->buffer_size[0]); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
260 if (!s->buffer[0]) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
261 av_log(s, AV_LOG_ERROR, "Could not allocate buffer\n"); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
262 return 0; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
263 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
264 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
265 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
266 obuf[0] = s->buffer[0]; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
267 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
268 if (av_audio_convert(s->convert_ctx[0], obuf, ostride, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
269 ibuf, istride, nb_samples*s->input_channels) < 0) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
270 av_log(s, AV_LOG_ERROR, "Audio sample format conversion failed\n"); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
271 return 0; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
272 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
273 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
274 input = s->buffer[0]; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
275 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
276 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
277 lenout= 4*nb_samples * s->ratio + 16; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
278 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
279 if (s->sample_fmt[1] != SAMPLE_FMT_S16) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
280 output_bak = output; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
281 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
282 if (!s->buffer_size[1] || s->buffer_size[1] < lenout) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
283 av_free(s->buffer[1]); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
284 s->buffer_size[1] = lenout; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
285 s->buffer[1] = av_malloc(s->buffer_size[1]); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
286 if (!s->buffer[1]) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
287 av_log(s, AV_LOG_ERROR, "Could not allocate buffer\n"); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
288 return 0; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
289 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
290 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
291 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
292 output = s->buffer[1]; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
293 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
294 |
| 64 | 295 /* 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
|
296 for(i=0; i<s->filter_channels; i++){ |
|
5958
ed05a3d964fa
stupid code (casting of void*) found by checktree.sh
michael
parents:
5502
diff
changeset
|
297 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
|
298 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
|
299 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
|
300 } |
| 2967 | 301 |
| 64 | 302 /* make some zoom to avoid round pb */ |
|
5958
ed05a3d964fa
stupid code (casting of void*) found by checktree.sh
michael
parents:
5502
diff
changeset
|
303 bufout[0]= av_malloc( lenout * sizeof(short) ); |
|
ed05a3d964fa
stupid code (casting of void*) found by checktree.sh
michael
parents:
5502
diff
changeset
|
304 bufout[1]= av_malloc( lenout * sizeof(short) ); |
| 64 | 305 |
| 0 | 306 if (s->input_channels == 2 && |
| 307 s->output_channels == 1) { | |
| 308 buftmp3[0] = output; | |
| 309 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
|
310 } else if (s->output_channels >= 2 && s->input_channels == 1) { |
| 0 | 311 buftmp3[0] = bufout[0]; |
|
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
312 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
|
313 } else if (s->output_channels >= 2) { |
| 0 | 314 buftmp3[0] = bufout[0]; |
| 315 buftmp3[1] = bufout[1]; | |
| 316 stereo_split(buftmp2[0], buftmp2[1], input, nb_samples); | |
| 317 } else { | |
| 318 buftmp3[0] = output; | |
|
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
319 memcpy(buftmp2[0], input, nb_samples*sizeof(short)); |
| 0 | 320 } |
| 321 | |
|
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
322 nb_samples += s->temp_len; |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
323 |
| 0 | 324 /* resample each channel */ |
| 325 nb_samples1 = 0; /* avoid warning */ | |
| 326 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
|
327 int consumed; |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
328 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
|
329 |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
330 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
|
331 s->temp_len= nb_samples - consumed; |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
332 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
|
333 memcpy(s->temp[i], bufin[i] + consumed, s->temp_len*sizeof(short)); |
| 0 | 334 } |
| 335 | |
| 336 if (s->output_channels == 2 && s->input_channels == 1) { | |
| 337 mono_to_stereo(output, buftmp3[0], nb_samples1); | |
| 338 } else if (s->output_channels == 2) { | |
| 339 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
|
340 } 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
|
341 ac3_5p1_mux(output, buftmp3[0], buftmp3[1], nb_samples1); |
| 0 | 342 } |
| 343 | |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
344 if (s->sample_fmt[1] != SAMPLE_FMT_S16) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
345 int istride[1] = { 2 }; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
346 int ostride[1] = { s->sample_size[1] }; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
347 const void *ibuf[1] = { output }; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
348 void *obuf[1] = { output_bak }; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
349 |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
350 if (av_audio_convert(s->convert_ctx[1], obuf, ostride, |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
351 ibuf, istride, nb_samples1*s->output_channels) < 0) { |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
352 av_log(s, AV_LOG_ERROR, "Audio sample format convertion failed\n"); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
353 return 0; |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
354 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
355 } |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
356 |
| 2084 | 357 for(i=0; i<s->filter_channels; i++) |
| 358 av_free(bufin[i]); | |
| 64 | 359 |
|
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
360 av_free(bufout[0]); |
|
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
361 av_free(bufout[1]); |
| 0 | 362 return nb_samples1; |
| 363 } | |
| 364 | |
| 365 void audio_resample_close(ReSampleContext *s) | |
| 366 { | |
|
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
367 av_resample_close(s->resample_context); |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
368 av_freep(&s->temp[0]); |
|
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
369 av_freep(&s->temp[1]); |
|
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
370 av_freep(&s->buffer[0]); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
371 av_freep(&s->buffer[1]); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
372 av_audio_convert_free(s->convert_ctx[0]); |
|
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
373 av_audio_convert_free(s->convert_ctx[1]); |
|
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
374 av_free(s); |
| 0 | 375 } |
