Mercurial > libavcodec.hg
annotate resample.c @ 12266:48d6738904a9 libavcodec
Fix SPLATB_REG mess. Used to be a if/elseif/elseif/elseif spaghetti, so this
splits it into small optimization-specific macros which are selected for each
DSP function. The advantage of this approach is that the sse4 functions now
use the ssse3 codepath also without needing an explicit sse4 codepath.
author | rbultje |
---|---|
date | Sat, 24 Jul 2010 19:33:05 +0000 |
parents | 3da317f52661 |
children | 776789af0304 |
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 /** | |
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
9835
diff
changeset
|
23 * @file |
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}}; |
11664
3da317f52661
Add version to AVClass so we can add to and use fields of AVClass without ABI issues.
michael
parents:
11644
diff
changeset
|
39 static const AVClass audioresample_context_class = { "ReSampleContext", context_to_name, options, LIBAVUTIL_VERSION_INT }; |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
40 |
0 | 41 struct ReSampleContext { |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
42 struct AVResampleContext *resample_context; |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
43 short *temp[2]; |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
44 int temp_len; |
0 | 45 float ratio; |
46 /* channel convert */ | |
47 int input_channels, output_channels, filter_channels; | |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
48 AVAudioConvert *convert_ctx[2]; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
49 enum SampleFormat sample_fmt[2]; ///< input and output sample format |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
50 unsigned sample_size[2]; ///< size of one sample in sample_fmt |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
51 short *buffer[2]; ///< buffers used for conversion to S16 |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
52 unsigned buffer_size[2]; ///< sizes of allocated buffers |
0 | 53 }; |
54 | |
55 /* n1: number of samples */ | |
56 static void stereo_to_mono(short *output, short *input, int n1) | |
57 { | |
58 short *p, *q; | |
59 int n = n1; | |
60 | |
61 p = input; | |
62 q = output; | |
63 while (n >= 4) { | |
64 q[0] = (p[0] + p[1]) >> 1; | |
65 q[1] = (p[2] + p[3]) >> 1; | |
66 q[2] = (p[4] + p[5]) >> 1; | |
67 q[3] = (p[6] + p[7]) >> 1; | |
68 q += 4; | |
69 p += 8; | |
70 n -= 4; | |
71 } | |
72 while (n > 0) { | |
73 q[0] = (p[0] + p[1]) >> 1; | |
74 q++; | |
75 p += 2; | |
76 n--; | |
77 } | |
78 } | |
79 | |
80 /* n1: number of samples */ | |
81 static void mono_to_stereo(short *output, short *input, int n1) | |
82 { | |
83 short *p, *q; | |
84 int n = n1; | |
85 int v; | |
86 | |
87 p = input; | |
88 q = output; | |
89 while (n >= 4) { | |
90 v = p[0]; q[0] = v; q[1] = v; | |
91 v = p[1]; q[2] = v; q[3] = v; | |
92 v = p[2]; q[4] = v; q[5] = v; | |
93 v = p[3]; q[6] = v; q[7] = v; | |
94 q += 8; | |
95 p += 4; | |
96 n -= 4; | |
97 } | |
98 while (n > 0) { | |
99 v = p[0]; q[0] = v; q[1] = v; | |
100 q += 2; | |
101 p += 1; | |
102 n--; | |
103 } | |
104 } | |
105 | |
106 /* XXX: should use more abstract 'N' channels system */ | |
107 static void stereo_split(short *output1, short *output2, short *input, int n) | |
108 { | |
109 int i; | |
110 | |
111 for(i=0;i<n;i++) { | |
112 *output1++ = *input++; | |
113 *output2++ = *input++; | |
114 } | |
115 } | |
116 | |
117 static void stereo_mux(short *output, short *input1, short *input2, int n) | |
118 { | |
119 int i; | |
120 | |
121 for(i=0;i<n;i++) { | |
122 *output++ = *input1++; | |
123 *output++ = *input2++; | |
124 } | |
125 } | |
126 | |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
127 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
|
128 { |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
129 int i; |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
130 short l,r; |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
131 |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
132 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
|
133 l=*input1++; |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
134 r=*input2++; |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
135 *output++ = l; /* left */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
136 *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
|
137 *output++ = r; /* right */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
138 *output++ = 0; /* left surround */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
139 *output++ = 0; /* right surroud */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
140 *output++ = 0; /* low freq */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
141 } |
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 |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
144 ReSampleContext *av_audio_resample_init(int output_channels, int input_channels, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
145 int output_rate, int input_rate, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
146 enum SampleFormat sample_fmt_out, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
147 enum SampleFormat sample_fmt_in, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
148 int filter_length, int log2_phase_count, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
149 int linear, double cutoff) |
0 | 150 { |
151 ReSampleContext *s; | |
2967 | 152 |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
153 if ( input_channels > 2) |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
154 { |
6023 | 155 av_log(NULL, AV_LOG_ERROR, "Resampling with input channels greater than 2 unsupported.\n"); |
2979 | 156 return NULL; |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
157 } |
0 | 158 |
159 s = av_mallocz(sizeof(ReSampleContext)); | |
160 if (!s) | |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
161 { |
6023 | 162 av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for resample context.\n"); |
2979 | 163 return NULL; |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
164 } |
0 | 165 |
166 s->ratio = (float)output_rate / (float)input_rate; | |
2967 | 167 |
0 | 168 s->input_channels = input_channels; |
169 s->output_channels = output_channels; | |
2967 | 170 |
0 | 171 s->filter_channels = s->input_channels; |
172 if (s->output_channels < s->filter_channels) | |
173 s->filter_channels = s->output_channels; | |
174 | |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
175 s->sample_fmt [0] = sample_fmt_in; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
176 s->sample_fmt [1] = sample_fmt_out; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
177 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
|
178 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
|
179 |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
180 if (s->sample_fmt[0] != SAMPLE_FMT_S16) { |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
181 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
|
182 s->sample_fmt[0], 1, NULL, 0))) { |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
183 av_log(s, AV_LOG_ERROR, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
184 "Cannot convert %s sample format to s16 sample format\n", |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
185 avcodec_get_sample_fmt_name(s->sample_fmt[0])); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
186 av_free(s); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
187 return NULL; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
188 } |
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 if (s->sample_fmt[1] != SAMPLE_FMT_S16) { |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
192 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
|
193 SAMPLE_FMT_S16, 1, NULL, 0))) { |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
194 av_log(s, AV_LOG_ERROR, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
195 "Cannot convert s16 sample format to %s sample format\n", |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
196 avcodec_get_sample_fmt_name(s->sample_fmt[1])); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
197 av_audio_convert_free(s->convert_ctx[0]); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
198 av_free(s); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
199 return NULL; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
200 } |
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 |
1408
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
203 /* |
7470
1a93d3bbe3ee
cosmetics: make all references to AC-3 capitalized and hyphenated
jbr
parents:
6023
diff
changeset
|
204 * 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
|
205 * 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
|
206 * 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
|
207 */ |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
208 if(s->filter_channels>2) |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
209 s->filter_channels = 2; |
4d67eb341a0c
AC3 encoding patch ba (Ross Martin <ffmpeg at ross dot interwrx dot com>)
michaelni
parents:
1128
diff
changeset
|
210 |
4712
5c0c96d437f2
set more reasonable cutoff for audio rate conversion
michael
parents:
3947
diff
changeset
|
211 #define TAPS 16 |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
212 s->resample_context= av_resample_init(output_rate, input_rate, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
213 filter_length, log2_phase_count, linear, cutoff); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
214 |
9835 | 215 *(const AVClass**)s->resample_context = &audioresample_context_class; |
2967 | 216 |
0 | 217 return s; |
218 } | |
219 | |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
220 #if LIBAVCODEC_VERSION_MAJOR < 53 |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
221 ReSampleContext *audio_resample_init(int output_channels, int input_channels, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
222 int output_rate, int input_rate) |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
223 { |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
224 return av_audio_resample_init(output_channels, input_channels, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
225 output_rate, input_rate, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
226 SAMPLE_FMT_S16, SAMPLE_FMT_S16, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
227 TAPS, 10, 0, 0.8); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
228 } |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
229 #endif |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
230 |
0 | 231 /* resample audio. 'nb_samples' is the number of input samples */ |
232 /* XXX: optimize it ! */ | |
233 int audio_resample(ReSampleContext *s, short *output, short *input, int nb_samples) | |
234 { | |
235 int i, nb_samples1; | |
64 | 236 short *bufin[2]; |
237 short *bufout[2]; | |
0 | 238 short *buftmp2[2], *buftmp3[2]; |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
239 short *output_bak = NULL; |
64 | 240 int lenout; |
0 | 241 |
2109 | 242 if (s->input_channels == s->output_channels && s->ratio == 1.0 && 0) { |
0 | 243 /* nothing to do */ |
244 memcpy(output, input, nb_samples * s->input_channels * sizeof(short)); | |
245 return nb_samples; | |
246 } | |
247 | |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
248 if (s->sample_fmt[0] != SAMPLE_FMT_S16) { |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
249 int istride[1] = { s->sample_size[0] }; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
250 int ostride[1] = { 2 }; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
251 const void *ibuf[1] = { input }; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
252 void *obuf[1]; |
8911
28b706b75b00
Prevent heap corruption when resampling 8-bit audio.
pross
parents:
8806
diff
changeset
|
253 unsigned input_size = nb_samples*s->input_channels*2; |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
254 |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
255 if (!s->buffer_size[0] || s->buffer_size[0] < input_size) { |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
256 av_free(s->buffer[0]); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
257 s->buffer_size[0] = input_size; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
258 s->buffer[0] = av_malloc(s->buffer_size[0]); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
259 if (!s->buffer[0]) { |
9834
ce317c75222d
give s->resample_context to avoid segfault, avclass was moved
bcoudurier
parents:
9252
diff
changeset
|
260 av_log(s->resample_context, AV_LOG_ERROR, "Could not allocate buffer\n"); |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
261 return 0; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
262 } |
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 obuf[0] = s->buffer[0]; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
266 |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
267 if (av_audio_convert(s->convert_ctx[0], obuf, ostride, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
268 ibuf, istride, nb_samples*s->input_channels) < 0) { |
9834
ce317c75222d
give s->resample_context to avoid segfault, avclass was moved
bcoudurier
parents:
9252
diff
changeset
|
269 av_log(s->resample_context, AV_LOG_ERROR, "Audio sample format conversion failed\n"); |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
270 return 0; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
271 } |
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 input = s->buffer[0]; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
274 } |
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 lenout= 4*nb_samples * s->ratio + 16; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
277 |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
278 if (s->sample_fmt[1] != SAMPLE_FMT_S16) { |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
279 output_bak = output; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
280 |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
281 if (!s->buffer_size[1] || s->buffer_size[1] < lenout) { |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
282 av_free(s->buffer[1]); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
283 s->buffer_size[1] = lenout; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
284 s->buffer[1] = av_malloc(s->buffer_size[1]); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
285 if (!s->buffer[1]) { |
9834
ce317c75222d
give s->resample_context to avoid segfault, avclass was moved
bcoudurier
parents:
9252
diff
changeset
|
286 av_log(s->resample_context, AV_LOG_ERROR, "Could not allocate buffer\n"); |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
287 return 0; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
288 } |
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 output = s->buffer[1]; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
292 } |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
293 |
64 | 294 /* 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
|
295 for(i=0; i<s->filter_channels; i++){ |
5958
ed05a3d964fa
stupid code (casting of void*) found by checktree.sh
michael
parents:
5502
diff
changeset
|
296 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
|
297 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
|
298 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
|
299 } |
2967 | 300 |
64 | 301 /* make some zoom to avoid round pb */ |
5958
ed05a3d964fa
stupid code (casting of void*) found by checktree.sh
michael
parents:
5502
diff
changeset
|
302 bufout[0]= av_malloc( lenout * sizeof(short) ); |
ed05a3d964fa
stupid code (casting of void*) found by checktree.sh
michael
parents:
5502
diff
changeset
|
303 bufout[1]= av_malloc( lenout * sizeof(short) ); |
64 | 304 |
0 | 305 if (s->input_channels == 2 && |
306 s->output_channels == 1) { | |
307 buftmp3[0] = output; | |
308 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
|
309 } else if (s->output_channels >= 2 && s->input_channels == 1) { |
0 | 310 buftmp3[0] = bufout[0]; |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
311 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
|
312 } else if (s->output_channels >= 2) { |
0 | 313 buftmp3[0] = bufout[0]; |
314 buftmp3[1] = bufout[1]; | |
315 stereo_split(buftmp2[0], buftmp2[1], input, nb_samples); | |
316 } else { | |
317 buftmp3[0] = output; | |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
318 memcpy(buftmp2[0], input, nb_samples*sizeof(short)); |
0 | 319 } |
320 | |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
321 nb_samples += s->temp_len; |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
322 |
0 | 323 /* resample each channel */ |
324 nb_samples1 = 0; /* avoid warning */ | |
325 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
|
326 int consumed; |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
327 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
|
328 |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
329 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
|
330 s->temp_len= nb_samples - consumed; |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
331 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
|
332 memcpy(s->temp[i], bufin[i] + consumed, s->temp_len*sizeof(short)); |
0 | 333 } |
334 | |
335 if (s->output_channels == 2 && s->input_channels == 1) { | |
336 mono_to_stereo(output, buftmp3[0], nb_samples1); | |
337 } else if (s->output_channels == 2) { | |
338 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
|
339 } 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
|
340 ac3_5p1_mux(output, buftmp3[0], buftmp3[1], nb_samples1); |
0 | 341 } |
342 | |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
343 if (s->sample_fmt[1] != SAMPLE_FMT_S16) { |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
344 int istride[1] = { 2 }; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
345 int ostride[1] = { s->sample_size[1] }; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
346 const void *ibuf[1] = { output }; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
347 void *obuf[1] = { output_bak }; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
348 |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
349 if (av_audio_convert(s->convert_ctx[1], obuf, ostride, |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
350 ibuf, istride, nb_samples1*s->output_channels) < 0) { |
9834
ce317c75222d
give s->resample_context to avoid segfault, avclass was moved
bcoudurier
parents:
9252
diff
changeset
|
351 av_log(s->resample_context, AV_LOG_ERROR, "Audio sample format convertion failed\n"); |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
352 return 0; |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
353 } |
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 |
2084 | 356 for(i=0; i<s->filter_channels; i++) |
357 av_free(bufin[i]); | |
64 | 358 |
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
359 av_free(bufout[0]); |
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
360 av_free(bufout[1]); |
0 | 361 return nb_samples1; |
362 } | |
363 | |
364 void audio_resample_close(ReSampleContext *s) | |
365 { | |
2082
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
366 av_resample_close(s->resample_context); |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
367 av_freep(&s->temp[0]); |
3dc9bbe1b152
polyphase kaiser windowed sinc and blackman nuttall windowed sinc audio resample filters
michael
parents:
1598
diff
changeset
|
368 av_freep(&s->temp[1]); |
8806
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
369 av_freep(&s->buffer[0]); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
370 av_freep(&s->buffer[1]); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
371 av_audio_convert_free(s->convert_ctx[0]); |
cbeaa8c0fe4f
extend resampling API, add S16 internal conversion
bcoudurier
parents:
8718
diff
changeset
|
372 av_audio_convert_free(s->convert_ctx[1]); |
396
fce0a2520551
removed useless header includes - use av memory functions
glantau
parents:
373
diff
changeset
|
373 av_free(s); |
0 | 374 } |