... | ... |
@@ -5,7 +5,7 @@ FFLIBS = avutil |
5 | 5 |
|
6 | 6 |
FFLIBS-$(CONFIG_ACONVERT_FILTER) += avcodec |
7 | 7 |
FFLIBS-$(CONFIG_AMOVIE_FILTER) += avformat avcodec |
8 |
-FFLIBS-$(CONFIG_ARESAMPLE_FILTER) += avcodec |
|
8 |
+FFLIBS-$(CONFIG_ARESAMPLE_FILTER) += swresample |
|
9 | 9 |
FFLIBS-$(CONFIG_MOVIE_FILTER) += avformat avcodec |
10 | 10 |
FFLIBS-$(CONFIG_PAN_FILTER) += swresample |
11 | 11 |
FFLIBS-$(CONFIG_SCALE_FILTER) += swscale |
... | ... |
@@ -24,20 +24,14 @@ |
24 | 24 |
* resampling audio filter |
25 | 25 |
*/ |
26 | 26 |
|
27 |
-#include "libavutil/eval.h" |
|
28 |
-#include "libavcodec/avcodec.h" |
|
27 |
+#include "libswresample/swresample.h" |
|
29 | 28 |
#include "avfilter.h" |
30 | 29 |
#include "internal.h" |
31 | 30 |
|
32 | 31 |
typedef struct { |
33 |
- struct AVResampleContext *resample; |
|
34 | 32 |
int out_rate; |
35 | 33 |
double ratio; |
36 |
- AVFilterBufferRef *outsamplesref; |
|
37 |
- int unconsumed_nb_samples, |
|
38 |
- max_cached_nb_samples; |
|
39 |
- int16_t *cached_data[8], |
|
40 |
- *resampled_data[8]; |
|
34 |
+ struct SwrContext *swr; |
|
41 | 35 |
} AResampleContext; |
42 | 36 |
|
43 | 37 |
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) |
... | ... |
@@ -58,23 +52,12 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) |
58 | 58 |
static av_cold void uninit(AVFilterContext *ctx) |
59 | 59 |
{ |
60 | 60 |
AResampleContext *aresample = ctx->priv; |
61 |
- if (aresample->outsamplesref) { |
|
62 |
- int nb_channels = |
|
63 |
- av_get_channel_layout_nb_channels( |
|
64 |
- aresample->outsamplesref->audio->channel_layout); |
|
65 |
- avfilter_unref_buffer(aresample->outsamplesref); |
|
66 |
- while (nb_channels--) { |
|
67 |
- av_freep(&(aresample->cached_data[nb_channels])); |
|
68 |
- av_freep(&(aresample->resampled_data[nb_channels])); |
|
69 |
- } |
|
70 |
- } |
|
71 |
- |
|
72 |
- if (aresample->resample) |
|
73 |
- av_resample_close(aresample->resample); |
|
61 |
+ swr_free(&aresample->swr); |
|
74 | 62 |
} |
75 | 63 |
|
76 | 64 |
static int config_output(AVFilterLink *outlink) |
77 | 65 |
{ |
66 |
+ int ret; |
|
78 | 67 |
AVFilterContext *ctx = outlink->src; |
79 | 68 |
AVFilterLink *inlink = ctx->inputs[0]; |
80 | 69 |
AResampleContext *aresample = ctx->priv; |
... | ... |
@@ -85,9 +68,16 @@ static int config_output(AVFilterLink *outlink) |
85 | 85 |
outlink->sample_rate = aresample->out_rate; |
86 | 86 |
outlink->time_base = (AVRational) {1, aresample->out_rate}; |
87 | 87 |
|
88 |
- //TODO: make the resampling parameters configurable |
|
89 |
- aresample->resample = av_resample_init(aresample->out_rate, inlink->sample_rate, |
|
90 |
- 16, 10, 0, 0.8); |
|
88 |
+ //TODO: make the resampling parameters (filter size, phrase shift, linear, cutoff) configurable |
|
89 |
+ aresample->swr = swr_alloc_set_opts(aresample->swr, |
|
90 |
+ inlink->channel_layout, inlink->format, aresample->out_rate, |
|
91 |
+ inlink->channel_layout, inlink->format, inlink->sample_rate, |
|
92 |
+ 0, ctx); |
|
93 |
+ if (!aresample->swr) |
|
94 |
+ return AVERROR(ENOMEM); |
|
95 |
+ ret = swr_init(aresample->swr); |
|
96 |
+ if (ret < 0) |
|
97 |
+ return ret; |
|
91 | 98 |
|
92 | 99 |
aresample->ratio = (double)outlink->sample_rate / inlink->sample_rate; |
93 | 100 |
|
... | ... |
@@ -96,235 +86,24 @@ static int config_output(AVFilterLink *outlink) |
96 | 96 |
return 0; |
97 | 97 |
} |
98 | 98 |
|
99 |
-static int query_formats(AVFilterContext *ctx) |
|
100 |
-{ |
|
101 |
- AVFilterFormats *formats = NULL; |
|
102 |
- |
|
103 |
- avfilter_add_format(&formats, AV_SAMPLE_FMT_S16); |
|
104 |
- if (!formats) |
|
105 |
- return AVERROR(ENOMEM); |
|
106 |
- avfilter_set_common_sample_formats(ctx, formats); |
|
107 |
- |
|
108 |
- formats = avfilter_make_all_channel_layouts(); |
|
109 |
- if (!formats) |
|
110 |
- return AVERROR(ENOMEM); |
|
111 |
- avfilter_set_common_channel_layouts(ctx, formats); |
|
112 |
- |
|
113 |
- formats = avfilter_make_all_packing_formats(); |
|
114 |
- if (!formats) |
|
115 |
- return AVERROR(ENOMEM); |
|
116 |
- avfilter_set_common_packing_formats(ctx, formats); |
|
117 |
- |
|
118 |
- return 0; |
|
119 |
-} |
|
120 |
- |
|
121 |
-static void deinterleave(int16_t **outp, int16_t *in, |
|
122 |
- int nb_channels, int nb_samples) |
|
123 |
-{ |
|
124 |
- int16_t *out[8]; |
|
125 |
- memcpy(out, outp, nb_channels * sizeof(int16_t*)); |
|
126 |
- |
|
127 |
- switch (nb_channels) { |
|
128 |
- case 2: |
|
129 |
- while (nb_samples--) { |
|
130 |
- *out[0]++ = *in++; |
|
131 |
- *out[1]++ = *in++; |
|
132 |
- } |
|
133 |
- break; |
|
134 |
- case 3: |
|
135 |
- while (nb_samples--) { |
|
136 |
- *out[0]++ = *in++; |
|
137 |
- *out[1]++ = *in++; |
|
138 |
- *out[2]++ = *in++; |
|
139 |
- } |
|
140 |
- break; |
|
141 |
- case 4: |
|
142 |
- while (nb_samples--) { |
|
143 |
- *out[0]++ = *in++; |
|
144 |
- *out[1]++ = *in++; |
|
145 |
- *out[2]++ = *in++; |
|
146 |
- *out[3]++ = *in++; |
|
147 |
- } |
|
148 |
- break; |
|
149 |
- case 5: |
|
150 |
- while (nb_samples--) { |
|
151 |
- *out[0]++ = *in++; |
|
152 |
- *out[1]++ = *in++; |
|
153 |
- *out[2]++ = *in++; |
|
154 |
- *out[3]++ = *in++; |
|
155 |
- *out[4]++ = *in++; |
|
156 |
- } |
|
157 |
- break; |
|
158 |
- case 6: |
|
159 |
- while (nb_samples--) { |
|
160 |
- *out[0]++ = *in++; |
|
161 |
- *out[1]++ = *in++; |
|
162 |
- *out[2]++ = *in++; |
|
163 |
- *out[3]++ = *in++; |
|
164 |
- *out[4]++ = *in++; |
|
165 |
- *out[5]++ = *in++; |
|
166 |
- } |
|
167 |
- break; |
|
168 |
- case 8: |
|
169 |
- while (nb_samples--) { |
|
170 |
- *out[0]++ = *in++; |
|
171 |
- *out[1]++ = *in++; |
|
172 |
- *out[2]++ = *in++; |
|
173 |
- *out[3]++ = *in++; |
|
174 |
- *out[4]++ = *in++; |
|
175 |
- *out[5]++ = *in++; |
|
176 |
- *out[6]++ = *in++; |
|
177 |
- *out[7]++ = *in++; |
|
178 |
- } |
|
179 |
- break; |
|
180 |
- } |
|
181 |
-} |
|
182 |
- |
|
183 |
-static void interleave(int16_t *out, int16_t **inp, |
|
184 |
- int nb_channels, int nb_samples) |
|
185 |
-{ |
|
186 |
- int16_t *in[8]; |
|
187 |
- memcpy(in, inp, nb_channels * sizeof(int16_t*)); |
|
188 |
- |
|
189 |
- switch (nb_channels) { |
|
190 |
- case 2: |
|
191 |
- while (nb_samples--) { |
|
192 |
- *out++ = *in[0]++; |
|
193 |
- *out++ = *in[1]++; |
|
194 |
- } |
|
195 |
- break; |
|
196 |
- case 3: |
|
197 |
- while (nb_samples--) { |
|
198 |
- *out++ = *in[0]++; |
|
199 |
- *out++ = *in[1]++; |
|
200 |
- *out++ = *in[2]++; |
|
201 |
- } |
|
202 |
- break; |
|
203 |
- case 4: |
|
204 |
- while (nb_samples--) { |
|
205 |
- *out++ = *in[0]++; |
|
206 |
- *out++ = *in[1]++; |
|
207 |
- *out++ = *in[2]++; |
|
208 |
- *out++ = *in[3]++; |
|
209 |
- } |
|
210 |
- break; |
|
211 |
- case 5: |
|
212 |
- while (nb_samples--) { |
|
213 |
- *out++ = *in[0]++; |
|
214 |
- *out++ = *in[1]++; |
|
215 |
- *out++ = *in[2]++; |
|
216 |
- *out++ = *in[3]++; |
|
217 |
- *out++ = *in[4]++; |
|
218 |
- } |
|
219 |
- break; |
|
220 |
- case 6: |
|
221 |
- while (nb_samples--) { |
|
222 |
- *out++ = *in[0]++; |
|
223 |
- *out++ = *in[1]++; |
|
224 |
- *out++ = *in[2]++; |
|
225 |
- *out++ = *in[3]++; |
|
226 |
- *out++ = *in[4]++; |
|
227 |
- *out++ = *in[5]++; |
|
228 |
- } |
|
229 |
- break; |
|
230 |
- case 8: |
|
231 |
- while (nb_samples--) { |
|
232 |
- *out++ = *in[0]++; |
|
233 |
- *out++ = *in[1]++; |
|
234 |
- *out++ = *in[2]++; |
|
235 |
- *out++ = *in[3]++; |
|
236 |
- *out++ = *in[4]++; |
|
237 |
- *out++ = *in[5]++; |
|
238 |
- *out++ = *in[6]++; |
|
239 |
- *out++ = *in[7]++; |
|
240 |
- } |
|
241 |
- break; |
|
242 |
- } |
|
243 |
-} |
|
244 |
- |
|
245 | 99 |
static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref) |
246 | 100 |
{ |
247 |
- AResampleContext *aresample = inlink->dst->priv; |
|
248 |
- AVFilterLink * const outlink = inlink->dst->outputs[0]; |
|
249 |
- int i, |
|
250 |
- in_nb_samples = insamplesref->audio->nb_samples, |
|
251 |
- cached_nb_samples = in_nb_samples + aresample->unconsumed_nb_samples, |
|
252 |
- requested_out_nb_samples = aresample->ratio * cached_nb_samples, |
|
253 |
- nb_channels = |
|
254 |
- av_get_channel_layout_nb_channels(inlink->channel_layout); |
|
255 |
- |
|
256 |
- if (cached_nb_samples > aresample->max_cached_nb_samples) { |
|
257 |
- for (i = 0; i < nb_channels; i++) { |
|
258 |
- aresample->cached_data[i] = |
|
259 |
- av_realloc(aresample->cached_data[i], cached_nb_samples * sizeof(int16_t)); |
|
260 |
- aresample->resampled_data[i] = |
|
261 |
- av_realloc(aresample->resampled_data[i], |
|
262 |
- FFALIGN(sizeof(int16_t) * requested_out_nb_samples, 16)); |
|
263 |
- |
|
264 |
- if (aresample->cached_data[i] == NULL || aresample->resampled_data[i] == NULL) |
|
265 |
- return; |
|
266 |
- } |
|
267 |
- aresample->max_cached_nb_samples = cached_nb_samples; |
|
268 |
- |
|
269 |
- if (aresample->outsamplesref) |
|
270 |
- avfilter_unref_buffer(aresample->outsamplesref); |
|
271 |
- |
|
272 |
- aresample->outsamplesref = |
|
273 |
- avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, requested_out_nb_samples); |
|
274 |
- outlink->out_buf = aresample->outsamplesref; |
|
275 |
- } |
|
276 |
- |
|
277 |
- avfilter_copy_buffer_ref_props(aresample->outsamplesref, insamplesref); |
|
278 |
- aresample->outsamplesref->audio->sample_rate = outlink->sample_rate; |
|
279 |
- aresample->outsamplesref->pts = |
|
280 |
- av_rescale(outlink->sample_rate, insamplesref->pts, inlink->sample_rate); |
|
281 |
- |
|
282 |
- /* av_resample() works with planar audio buffers */ |
|
283 |
- if (!inlink->planar && nb_channels > 1) { |
|
284 |
- int16_t *out[8]; |
|
285 |
- for (i = 0; i < nb_channels; i++) |
|
286 |
- out[i] = aresample->cached_data[i] + aresample->unconsumed_nb_samples; |
|
287 |
- |
|
288 |
- deinterleave(out, (int16_t *)insamplesref->data[0], |
|
289 |
- nb_channels, in_nb_samples); |
|
290 |
- } else { |
|
291 |
- for (i = 0; i < nb_channels; i++) |
|
292 |
- memcpy(aresample->cached_data[i] + aresample->unconsumed_nb_samples, |
|
293 |
- insamplesref->data[i], |
|
294 |
- in_nb_samples * sizeof(int16_t)); |
|
295 |
- } |
|
296 |
- |
|
297 |
- for (i = 0; i < nb_channels; i++) { |
|
298 |
- int consumed_nb_samples; |
|
299 |
- const int is_last = i+1 == nb_channels; |
|
300 |
- |
|
301 |
- aresample->outsamplesref->audio->nb_samples = |
|
302 |
- av_resample(aresample->resample, |
|
303 |
- aresample->resampled_data[i], aresample->cached_data[i], |
|
304 |
- &consumed_nb_samples, |
|
305 |
- cached_nb_samples, |
|
306 |
- requested_out_nb_samples, is_last); |
|
307 |
- |
|
308 |
- /* move unconsumed data back to the beginning of the cache */ |
|
309 |
- aresample->unconsumed_nb_samples = cached_nb_samples - consumed_nb_samples; |
|
310 |
- memmove(aresample->cached_data[i], |
|
311 |
- aresample->cached_data[i] + consumed_nb_samples, |
|
312 |
- aresample->unconsumed_nb_samples * sizeof(int16_t)); |
|
313 |
- } |
|
314 |
- |
|
315 |
- |
|
316 |
- /* copy resampled data to the output samplesref */ |
|
317 |
- if (!inlink->planar && nb_channels > 1) { |
|
318 |
- interleave((int16_t *)aresample->outsamplesref->data[0], |
|
319 |
- aresample->resampled_data, |
|
320 |
- nb_channels, aresample->outsamplesref->audio->nb_samples); |
|
321 |
- } else { |
|
322 |
- for (i = 0; i < nb_channels; i++) |
|
323 |
- memcpy(aresample->outsamplesref->data[i], aresample->resampled_data[i], |
|
324 |
- aresample->outsamplesref->audio->nb_samples * sizeof(int16_t)); |
|
325 |
- } |
|
326 |
- |
|
327 |
- avfilter_filter_samples(outlink, avfilter_ref_buffer(aresample->outsamplesref, ~0)); |
|
101 |
+ AResampleContext *aresample = inlink->dst->priv; |
|
102 |
+ const int n_in = insamplesref->audio->nb_samples; |
|
103 |
+ int n_out = n_in * aresample->ratio; |
|
104 |
+ AVFilterLink *const outlink = inlink->dst->outputs[0]; |
|
105 |
+ AVFilterBufferRef *outsamplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, n_out); |
|
106 |
+ |
|
107 |
+ n_out = swr_convert(aresample->swr, outsamplesref->data, n_out, |
|
108 |
+ (void *)insamplesref->data, n_in); |
|
109 |
+ |
|
110 |
+ avfilter_copy_buffer_ref_props(outsamplesref, insamplesref); |
|
111 |
+ outsamplesref->audio->sample_rate = outlink->sample_rate; |
|
112 |
+ outsamplesref->audio->nb_samples = n_out; |
|
113 |
+ outsamplesref->pts = av_rescale(outlink->sample_rate, insamplesref->pts, |
|
114 |
+ inlink ->sample_rate); |
|
115 |
+ |
|
116 |
+ avfilter_filter_samples(outlink, outsamplesref); |
|
328 | 117 |
avfilter_unref_buffer(insamplesref); |
329 | 118 |
} |
330 | 119 |
|
... | ... |
@@ -333,7 +112,6 @@ AVFilter avfilter_af_aresample = { |
333 | 333 |
.description = NULL_IF_CONFIG_SMALL("Resample audio data."), |
334 | 334 |
.init = init, |
335 | 335 |
.uninit = uninit, |
336 |
- .query_formats = query_formats, |
|
337 | 336 |
.priv_size = sizeof(AResampleContext), |
338 | 337 |
|
339 | 338 |
.inputs = (const AVFilterPad[]) {{ .name = "default", |