[FFmpeg-devel] [PATCH 2/3] avfilter: add audio upsample filter

Paul B Mahol onemda at gmail.com
Fri Apr 19 00:17:33 EEST 2019


Signed-off-by: Paul B Mahol <onemda at gmail.com>
---
 libavfilter/Makefile       |   1 +
 libavfilter/af_aupsample.c | 159 +++++++++++++++++++++++++++++++++++++
 libavfilter/allfilters.c   |   1 +
 3 files changed, 161 insertions(+)
 create mode 100644 libavfilter/af_aupsample.c

diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 682df45ef5..a38bc35231 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -86,6 +86,7 @@ OBJS-$(CONFIG_ASTATS_FILTER)                 += af_astats.o
 OBJS-$(CONFIG_ASTREAMSELECT_FILTER)          += f_streamselect.o framesync.o
 OBJS-$(CONFIG_ATEMPO_FILTER)                 += af_atempo.o
 OBJS-$(CONFIG_ATRIM_FILTER)                  += trim.o
+OBJS-$(CONFIG_AUPSAMPLE_FILTER)              += af_aupsample.o
 OBJS-$(CONFIG_AZMQ_FILTER)                   += f_zmq.o
 OBJS-$(CONFIG_BANDPASS_FILTER)               += af_biquads.o
 OBJS-$(CONFIG_BANDREJECT_FILTER)             += af_biquads.o
diff --git a/libavfilter/af_aupsample.c b/libavfilter/af_aupsample.c
new file mode 100644
index 0000000000..ee35b9c0c6
--- /dev/null
+++ b/libavfilter/af_aupsample.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2019 Paul B Mahol
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/opt.h"
+#include "libavutil/samplefmt.h"
+#include "avfilter.h"
+#include "audio.h"
+#include "filters.h"
+#include "internal.h"
+
+typedef struct AudioUpSampleContext {
+    const AVClass *class;
+    int factor;
+
+    int64_t next_pts;
+} AudioUpSampleContext;
+
+#define OFFSET(x) offsetof(AudioUpSampleContext, x)
+#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+
+static const AVOption aupsample_options[] = {
+    { "factor", "set upsampling factor", OFFSET(factor), AV_OPT_TYPE_INT, {.i64=1}, 1, 64, A },
+    { NULL }
+};
+
+AVFILTER_DEFINE_CLASS(aupsample);
+
+static int query_formats(AVFilterContext *ctx)
+{
+    AudioUpSampleContext *s = ctx->priv;
+    AVFilterChannelLayouts *layouts;
+    AVFilterFormats *formats;
+    int sample_rates[] = { 44100, -1 };
+    static const enum AVSampleFormat sample_fmts[] = {
+        AV_SAMPLE_FMT_DBLP,
+        AV_SAMPLE_FMT_NONE
+    };
+    AVFilterFormats *avff;
+    int ret;
+
+    if (!ctx->inputs[0]->in_samplerates ||
+        !ctx->inputs[0]->in_samplerates->nb_formats) {
+        return AVERROR(EAGAIN);
+    }
+
+    layouts = ff_all_channel_counts();
+    if (!layouts)
+        return AVERROR(ENOMEM);
+    ret = ff_set_common_channel_layouts(ctx, layouts);
+    if (ret < 0)
+        return ret;
+
+    formats = ff_make_format_list(sample_fmts);
+    if (!formats)
+        return AVERROR(ENOMEM);
+    ret = ff_set_common_formats(ctx, formats);
+    if (ret < 0)
+        return ret;
+
+    avff = ctx->inputs[0]->in_samplerates;
+    sample_rates[0] = avff->formats[0];
+    if (!ctx->inputs[0]->out_samplerates)
+        if ((ret = ff_formats_ref(ff_make_format_list(sample_rates),
+                                  &ctx->inputs[0]->out_samplerates)) < 0)
+            return ret;
+
+    sample_rates[0] = avff->formats[0] * s->factor;
+    return ff_formats_ref(ff_make_format_list(sample_rates),
+                         &ctx->outputs[0]->in_samplerates);
+}
+
+static int config_input(AVFilterLink *inlink)
+{
+    AVFilterContext *ctx = inlink->dst;
+    AudioUpSampleContext *s = ctx->priv;
+
+    s->next_pts = AV_NOPTS_VALUE;
+
+    return 0;
+}
+
+static int filter_frame(AVFilterLink *inlink, AVFrame *in)
+{
+    AVFilterContext *ctx = inlink->dst;
+    AVFilterLink *outlink = ctx->outputs[0];
+    AudioUpSampleContext *s = ctx->priv;
+    const int factor = s->factor;
+    AVFrame *out;
+
+    if (s->factor == 1)
+        return ff_filter_frame(outlink, in);
+
+    out = ff_get_audio_buffer(outlink, in->nb_samples * s->factor);
+    if (!out) {
+        av_frame_free(&in);
+        return AVERROR(ENOMEM);
+    }
+
+    if (s->next_pts == AV_NOPTS_VALUE)
+        s->next_pts = in->pts;
+
+    for (int c = 0; c < in->channels; c++) {
+        const double *src = (const double *)in->extended_data[c];
+        double *dst = (double *)out->extended_data[c];
+
+        for (int n = 0; n < in->nb_samples; n++)
+            dst[n*factor] = src[n];
+    }
+
+    out->pts = s->next_pts;
+    s->next_pts += av_rescale_q(out->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base);
+    av_frame_free(&in);
+    return ff_filter_frame(ctx->outputs[0], out);
+}
+
+static const AVFilterPad aupsample_inputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_AUDIO,
+        .filter_frame = filter_frame,
+        .config_props = config_input,
+    },
+    { NULL }
+};
+
+static const AVFilterPad aupsample_outputs[] = {
+    {
+        .name         = "default",
+        .type         = AVMEDIA_TYPE_AUDIO,
+    },
+    { NULL }
+};
+
+AVFilter ff_af_aupsample = {
+    .name          = "aupsample",
+    .description   = NULL_IF_CONFIG_SMALL("Upsample audio by integer factor."),
+    .query_formats = query_formats,
+    .priv_size     = sizeof(AudioUpSampleContext),
+    .priv_class    = &aupsample_class,
+    .inputs        = aupsample_inputs,
+    .outputs       = aupsample_outputs,
+};
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index 4d3039d6ba..29b372a1db 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -78,6 +78,7 @@ extern AVFilter ff_af_astats;
 extern AVFilter ff_af_astreamselect;
 extern AVFilter ff_af_atempo;
 extern AVFilter ff_af_atrim;
+extern AVFilter ff_af_aupsample;
 extern AVFilter ff_af_azmq;
 extern AVFilter ff_af_bandpass;
 extern AVFilter ff_af_bandreject;
-- 
2.17.1



More information about the ffmpeg-devel mailing list