[FFmpeg-devel] [PATCH] lavfi: use libswr in af_aresample.
Clément Bœsch
ubitux at gmail.com
Sat Jan 21 21:10:39 CET 2012
---
Question: is there any need of flushing? (is the number of output samples exact
enough?)
---
configure | 1 +
libavfilter/af_aresample.c | 272 ++++----------------------------------------
2 files changed, 23 insertions(+), 250 deletions(-)
diff --git a/configure b/configure
index 3bace2b..18e617d 100755
--- a/configure
+++ b/configure
@@ -1639,6 +1639,7 @@ udp_protocol_deps="network"
# filters
amovie_filter_deps="avcodec avformat"
+aresample_filter_deps="swresample"
ass_filter_deps="libass"
blackframe_filter_deps="gpl"
boxblur_filter_deps="gpl"
diff --git a/libavfilter/af_aresample.c b/libavfilter/af_aresample.c
index cd9d80e..0fdc1dd 100644
--- a/libavfilter/af_aresample.c
+++ b/libavfilter/af_aresample.c
@@ -24,20 +24,14 @@
* resampling audio filter
*/
-#include "libavutil/eval.h"
-#include "libavcodec/avcodec.h"
+#include "libswresample/swresample.h"
#include "avfilter.h"
#include "internal.h"
typedef struct {
- struct AVResampleContext *resample;
int out_rate;
double ratio;
- AVFilterBufferRef *outsamplesref;
- int unconsumed_nb_samples,
- max_cached_nb_samples;
- int16_t *cached_data[8],
- *resampled_data[8];
+ struct SwrContext *swr;
} AResampleContext;
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)
static av_cold void uninit(AVFilterContext *ctx)
{
AResampleContext *aresample = ctx->priv;
- if (aresample->outsamplesref) {
- int nb_channels =
- av_get_channel_layout_nb_channels(
- aresample->outsamplesref->audio->channel_layout);
- avfilter_unref_buffer(aresample->outsamplesref);
- while (nb_channels--) {
- av_freep(&(aresample->cached_data[nb_channels]));
- av_freep(&(aresample->resampled_data[nb_channels]));
- }
- }
-
- if (aresample->resample)
- av_resample_close(aresample->resample);
+ swr_free(&aresample->swr);
}
static int config_output(AVFilterLink *outlink)
{
+ int ret;
AVFilterContext *ctx = outlink->src;
AVFilterLink *inlink = ctx->inputs[0];
AResampleContext *aresample = ctx->priv;
@@ -85,9 +68,16 @@ static int config_output(AVFilterLink *outlink)
outlink->sample_rate = aresample->out_rate;
outlink->time_base = (AVRational) {1, aresample->out_rate};
- //TODO: make the resampling parameters configurable
- aresample->resample = av_resample_init(aresample->out_rate, inlink->sample_rate,
- 16, 10, 0, 0.8);
+ //TODO: make the resampling parameters (filter size, phrase shift, linear, cutoff) configurable
+ aresample->swr = swr_alloc_set_opts(aresample->swr,
+ inlink->channel_layout, inlink->format, aresample->out_rate,
+ inlink->channel_layout, inlink->format, inlink->sample_rate,
+ 0, ctx);
+ if (!aresample->swr)
+ return AVERROR(ENOMEM);
+ ret = swr_init(aresample->swr);
+ if (ret < 0)
+ return ret;
aresample->ratio = (double)outlink->sample_rate / inlink->sample_rate;
@@ -96,235 +86,18 @@ static int config_output(AVFilterLink *outlink)
return 0;
}
-static int query_formats(AVFilterContext *ctx)
-{
- AVFilterFormats *formats = NULL;
-
- avfilter_add_format(&formats, AV_SAMPLE_FMT_S16);
- if (!formats)
- return AVERROR(ENOMEM);
- avfilter_set_common_sample_formats(ctx, formats);
-
- formats = avfilter_make_all_channel_layouts();
- if (!formats)
- return AVERROR(ENOMEM);
- avfilter_set_common_channel_layouts(ctx, formats);
-
- formats = avfilter_make_all_packing_formats();
- if (!formats)
- return AVERROR(ENOMEM);
- avfilter_set_common_packing_formats(ctx, formats);
-
- return 0;
-}
-
-static void deinterleave(int16_t **outp, int16_t *in,
- int nb_channels, int nb_samples)
-{
- int16_t *out[8];
- memcpy(out, outp, nb_channels * sizeof(int16_t*));
-
- switch (nb_channels) {
- case 2:
- while (nb_samples--) {
- *out[0]++ = *in++;
- *out[1]++ = *in++;
- }
- break;
- case 3:
- while (nb_samples--) {
- *out[0]++ = *in++;
- *out[1]++ = *in++;
- *out[2]++ = *in++;
- }
- break;
- case 4:
- while (nb_samples--) {
- *out[0]++ = *in++;
- *out[1]++ = *in++;
- *out[2]++ = *in++;
- *out[3]++ = *in++;
- }
- break;
- case 5:
- while (nb_samples--) {
- *out[0]++ = *in++;
- *out[1]++ = *in++;
- *out[2]++ = *in++;
- *out[3]++ = *in++;
- *out[4]++ = *in++;
- }
- break;
- case 6:
- while (nb_samples--) {
- *out[0]++ = *in++;
- *out[1]++ = *in++;
- *out[2]++ = *in++;
- *out[3]++ = *in++;
- *out[4]++ = *in++;
- *out[5]++ = *in++;
- }
- break;
- case 8:
- while (nb_samples--) {
- *out[0]++ = *in++;
- *out[1]++ = *in++;
- *out[2]++ = *in++;
- *out[3]++ = *in++;
- *out[4]++ = *in++;
- *out[5]++ = *in++;
- *out[6]++ = *in++;
- *out[7]++ = *in++;
- }
- break;
- }
-}
-
-static void interleave(int16_t *out, int16_t **inp,
- int nb_channels, int nb_samples)
-{
- int16_t *in[8];
- memcpy(in, inp, nb_channels * sizeof(int16_t*));
-
- switch (nb_channels) {
- case 2:
- while (nb_samples--) {
- *out++ = *in[0]++;
- *out++ = *in[1]++;
- }
- break;
- case 3:
- while (nb_samples--) {
- *out++ = *in[0]++;
- *out++ = *in[1]++;
- *out++ = *in[2]++;
- }
- break;
- case 4:
- while (nb_samples--) {
- *out++ = *in[0]++;
- *out++ = *in[1]++;
- *out++ = *in[2]++;
- *out++ = *in[3]++;
- }
- break;
- case 5:
- while (nb_samples--) {
- *out++ = *in[0]++;
- *out++ = *in[1]++;
- *out++ = *in[2]++;
- *out++ = *in[3]++;
- *out++ = *in[4]++;
- }
- break;
- case 6:
- while (nb_samples--) {
- *out++ = *in[0]++;
- *out++ = *in[1]++;
- *out++ = *in[2]++;
- *out++ = *in[3]++;
- *out++ = *in[4]++;
- *out++ = *in[5]++;
- }
- break;
- case 8:
- while (nb_samples--) {
- *out++ = *in[0]++;
- *out++ = *in[1]++;
- *out++ = *in[2]++;
- *out++ = *in[3]++;
- *out++ = *in[4]++;
- *out++ = *in[5]++;
- *out++ = *in[6]++;
- *out++ = *in[7]++;
- }
- break;
- }
-}
-
static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref)
{
- AResampleContext *aresample = inlink->dst->priv;
- AVFilterLink * const outlink = inlink->dst->outputs[0];
- int i,
- in_nb_samples = insamplesref->audio->nb_samples,
- cached_nb_samples = in_nb_samples + aresample->unconsumed_nb_samples,
- requested_out_nb_samples = aresample->ratio * cached_nb_samples,
- nb_channels =
- av_get_channel_layout_nb_channels(inlink->channel_layout);
-
- if (cached_nb_samples > aresample->max_cached_nb_samples) {
- for (i = 0; i < nb_channels; i++) {
- aresample->cached_data[i] =
- av_realloc(aresample->cached_data[i], cached_nb_samples * sizeof(int16_t));
- aresample->resampled_data[i] =
- av_realloc(aresample->resampled_data[i],
- FFALIGN(sizeof(int16_t) * requested_out_nb_samples, 16));
-
- if (aresample->cached_data[i] == NULL || aresample->resampled_data[i] == NULL)
- return;
- }
- aresample->max_cached_nb_samples = cached_nb_samples;
-
- if (aresample->outsamplesref)
- avfilter_unref_buffer(aresample->outsamplesref);
-
- aresample->outsamplesref =
- avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, requested_out_nb_samples);
- outlink->out_buf = aresample->outsamplesref;
- }
-
- avfilter_copy_buffer_ref_props(aresample->outsamplesref, insamplesref);
- aresample->outsamplesref->audio->sample_rate = outlink->sample_rate;
- aresample->outsamplesref->pts =
- av_rescale(outlink->sample_rate, insamplesref->pts, inlink->sample_rate);
-
- /* av_resample() works with planar audio buffers */
- if (!inlink->planar && nb_channels > 1) {
- int16_t *out[8];
- for (i = 0; i < nb_channels; i++)
- out[i] = aresample->cached_data[i] + aresample->unconsumed_nb_samples;
+ AResampleContext *aresample = inlink->dst->priv;
+ const int n_in = insamplesref->audio->nb_samples;
+ const int n_out = n_in * aresample->ratio;
+ AVFilterLink *const outlink = inlink->dst->outputs[0];
+ AVFilterBufferRef *outsamplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, n_out);
- deinterleave(out, (int16_t *)insamplesref->data[0],
- nb_channels, in_nb_samples);
- } else {
- for (i = 0; i < nb_channels; i++)
- memcpy(aresample->cached_data[i] + aresample->unconsumed_nb_samples,
- insamplesref->data[i],
- in_nb_samples * sizeof(int16_t));
- }
-
- for (i = 0; i < nb_channels; i++) {
- int consumed_nb_samples;
- const int is_last = i+1 == nb_channels;
-
- aresample->outsamplesref->audio->nb_samples =
- av_resample(aresample->resample,
- aresample->resampled_data[i], aresample->cached_data[i],
- &consumed_nb_samples,
- cached_nb_samples,
- requested_out_nb_samples, is_last);
-
- /* move unconsumed data back to the beginning of the cache */
- aresample->unconsumed_nb_samples = cached_nb_samples - consumed_nb_samples;
- memmove(aresample->cached_data[i],
- aresample->cached_data[i] + consumed_nb_samples,
- aresample->unconsumed_nb_samples * sizeof(int16_t));
- }
-
-
- /* copy resampled data to the output samplesref */
- if (!inlink->planar && nb_channels > 1) {
- interleave((int16_t *)aresample->outsamplesref->data[0],
- aresample->resampled_data,
- nb_channels, aresample->outsamplesref->audio->nb_samples);
- } else {
- for (i = 0; i < nb_channels; i++)
- memcpy(aresample->outsamplesref->data[i], aresample->resampled_data[i],
- aresample->outsamplesref->audio->nb_samples * sizeof(int16_t));
- }
+ swr_convert(aresample->swr, outsamplesref->data, n_out,
+ (void *)insamplesref->data, n_in);
- avfilter_filter_samples(outlink, avfilter_ref_buffer(aresample->outsamplesref, ~0));
+ avfilter_filter_samples(outlink, outsamplesref);
avfilter_unref_buffer(insamplesref);
}
@@ -333,7 +106,6 @@ AVFilter avfilter_af_aresample = {
.description = NULL_IF_CONFIG_SMALL("Resample audio data."),
.init = init,
.uninit = uninit,
- .query_formats = query_formats,
.priv_size = sizeof(AResampleContext),
.inputs = (const AVFilterPad[]) {{ .name = "default",
--
1.7.8.4
More information about the ffmpeg-devel
mailing list