ffmpeg / libavcodec / resample.c @ 5509bffa
History | View | Annotate | Download (6.86 KB)
1 |
/*
|
---|---|
2 |
* Sample rate convertion for both audio and video
|
3 |
* Copyright (c) 2000 Fabrice Bellard.
|
4 |
*
|
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.
|
9 |
*
|
10 |
* This library is distributed in the hope that it will be useful,
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13 |
* Lesser General Public License for more details.
|
14 |
*
|
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18 |
*/
|
19 |
|
20 |
/**
|
21 |
* @file resample.c
|
22 |
* Sample rate convertion for both audio and video.
|
23 |
*/
|
24 |
|
25 |
#include "avcodec.h" |
26 |
|
27 |
struct AVResampleContext;
|
28 |
|
29 |
struct ReSampleContext {
|
30 |
struct AVResampleContext *resample_context;
|
31 |
short *temp[2]; |
32 |
int temp_len;
|
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 |
|
110 |
static void ac3_5p1_mux(short *output, short *input1, short *input2, int n) |
111 |
{ |
112 |
int i;
|
113 |
short l,r;
|
114 |
|
115 |
for(i=0;i<n;i++) { |
116 |
l=*input1++; |
117 |
r=*input2++; |
118 |
*output++ = l; /* left */
|
119 |
*output++ = (l/2)+(r/2); /* center */ |
120 |
*output++ = r; /* right */
|
121 |
*output++ = 0; /* left surround */ |
122 |
*output++ = 0; /* right surroud */ |
123 |
*output++ = 0; /* low freq */ |
124 |
} |
125 |
} |
126 |
|
127 |
ReSampleContext *audio_resample_init(int output_channels, int input_channels, |
128 |
int output_rate, int input_rate) |
129 |
{ |
130 |
ReSampleContext *s; |
131 |
|
132 |
if ( input_channels > 2) |
133 |
{ |
134 |
av_log(NULL, AV_LOG_ERROR, "Resampling with input channels greater than 2 unsupported."); |
135 |
return NULL; |
136 |
} |
137 |
|
138 |
s = av_mallocz(sizeof(ReSampleContext));
|
139 |
if (!s)
|
140 |
{ |
141 |
av_log(NULL, AV_LOG_ERROR, "Can't allocate memory for resample context."); |
142 |
return NULL; |
143 |
} |
144 |
|
145 |
s->ratio = (float)output_rate / (float)input_rate; |
146 |
|
147 |
s->input_channels = input_channels; |
148 |
s->output_channels = output_channels; |
149 |
|
150 |
s->filter_channels = s->input_channels; |
151 |
if (s->output_channels < s->filter_channels)
|
152 |
s->filter_channels = s->output_channels; |
153 |
|
154 |
/*
|
155 |
* ac3 output is the only case where filter_channels could be greater than 2.
|
156 |
* input channels can't be greater than 2, so resample the 2 channels and then
|
157 |
* expand to 6 channels after the resampling.
|
158 |
*/
|
159 |
if(s->filter_channels>2) |
160 |
s->filter_channels = 2;
|
161 |
|
162 |
s->resample_context= av_resample_init(output_rate, input_rate, 16, 10, 0, 1.0); |
163 |
|
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;
|
172 |
short *bufin[2]; |
173 |
short *bufout[2]; |
174 |
short *buftmp2[2], *buftmp3[2]; |
175 |
int lenout;
|
176 |
|
177 |
if (s->input_channels == s->output_channels && s->ratio == 1.0 && 0) { |
178 |
/* nothing to do */
|
179 |
memcpy(output, input, nb_samples * s->input_channels * sizeof(short)); |
180 |
return nb_samples;
|
181 |
} |
182 |
|
183 |
/* XXX: move those malloc to resample init code */
|
184 |
for(i=0; i<s->filter_channels; i++){ |
185 |
bufin[i]= (short*) av_malloc( (nb_samples + s->temp_len) * sizeof(short) ); |
186 |
memcpy(bufin[i], s->temp[i], s->temp_len * sizeof(short)); |
187 |
buftmp2[i] = bufin[i] + s->temp_len; |
188 |
} |
189 |
|
190 |
/* make some zoom to avoid round pb */
|
191 |
lenout= (int)(nb_samples * s->ratio) + 16; |
192 |
bufout[0]= (short*) av_malloc( lenout * sizeof(short) ); |
193 |
bufout[1]= (short*) av_malloc( lenout * sizeof(short) ); |
194 |
|
195 |
if (s->input_channels == 2 && |
196 |
s->output_channels == 1) {
|
197 |
buftmp3[0] = output;
|
198 |
stereo_to_mono(buftmp2[0], input, nb_samples);
|
199 |
} else if (s->output_channels >= 2 && s->input_channels == 1) { |
200 |
buftmp3[0] = bufout[0]; |
201 |
memcpy(buftmp2[0], input, nb_samples*sizeof(short)); |
202 |
} else if (s->output_channels >= 2) { |
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;
|
208 |
memcpy(buftmp2[0], input, nb_samples*sizeof(short)); |
209 |
} |
210 |
|
211 |
nb_samples += s->temp_len; |
212 |
|
213 |
/* resample each channel */
|
214 |
nb_samples1 = 0; /* avoid warning */ |
215 |
for(i=0;i<s->filter_channels;i++) { |
216 |
int consumed;
|
217 |
int is_last= i+1 == s->filter_channels; |
218 |
|
219 |
nb_samples1 = av_resample(s->resample_context, buftmp3[i], bufin[i], &consumed, nb_samples, lenout, is_last); |
220 |
s->temp_len= nb_samples - consumed; |
221 |
s->temp[i]= av_realloc(s->temp[i], s->temp_len*sizeof(short)); |
222 |
memcpy(s->temp[i], bufin[i] + consumed, s->temp_len*sizeof(short)); |
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); |
229 |
} else if (s->output_channels == 6) { |
230 |
ac3_5p1_mux(output, buftmp3[0], buftmp3[1], nb_samples1); |
231 |
} |
232 |
|
233 |
for(i=0; i<s->filter_channels; i++) |
234 |
av_free(bufin[i]); |
235 |
|
236 |
av_free(bufout[0]);
|
237 |
av_free(bufout[1]);
|
238 |
return nb_samples1;
|
239 |
} |
240 |
|
241 |
void audio_resample_close(ReSampleContext *s)
|
242 |
{ |
243 |
av_resample_close(s->resample_context); |
244 |
av_freep(&s->temp[0]);
|
245 |
av_freep(&s->temp[1]);
|
246 |
av_free(s); |
247 |
} |