[libav-commits] lavfi: add aformat filter

Anton Khirnov git at libav.org
Mon May 14 21:38:40 CEST 2012


Module: libav
Branch: master
Commit: fb604ae8500d4ee7de6af61387c11618b3dea25b

Author:    Anton Khirnov <anton at khirnov.net>
Committer: Anton Khirnov <anton at khirnov.net>
Date:      Sun May  6 09:00:53 2012 +0200

lavfi: add aformat filter

Based on a patch by Mina Nagy Zaki <mnzaki at gmail.com>

---

 doc/filters.texi         |   26 ++++++++
 libavfilter/Makefile     |    1 +
 libavfilter/af_aformat.c |  148 ++++++++++++++++++++++++++++++++++++++++++++++
 libavfilter/allfilters.c |    1 +
 4 files changed, 176 insertions(+), 0 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 0314bfa..f066657 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -107,6 +107,32 @@ build.
 
 Below is a description of the currently available audio filters.
 
+ at section aformat
+
+Convert the input audio to one of the specified formats. The framework will
+negotiate the most appropriate format to minimize conversions.
+
+The filter accepts the following named parameters:
+ at table @option
+
+ at item sample_fmts
+A comma-separated list of requested sample formats.
+
+ at item sample_rates
+A comma-separated list of requested sample rates.
+
+ at item channel_layouts
+A comma-separated list of requested channel layouts.
+
+ at end table
+
+If a parameter is omitted, all values are allowed.
+
+For example to force the output to either unsigned 8-bit or signed 16-bit stereo:
+ at example
+aformat=sample_fmts\=u8\,s16:channel_layouts\=stereo
+ at end example
+
 @section anull
 
 Pass the audio source unchanged to the output.
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 6a6bfd6..df75bd5 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -22,6 +22,7 @@ OBJS = allfilters.o                                                     \
        graphparser.o                                                    \
        vf_scale.o                                                       \
 
+OBJS-$(CONFIG_AFORMAT_FILTER)                += af_aformat.o
 OBJS-$(CONFIG_ANULL_FILTER)                  += af_anull.o
 OBJS-$(CONFIG_RESAMPLE_FILTER)               += af_resample.o
 
diff --git a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c
new file mode 100644
index 0000000..84442d3
--- /dev/null
+++ b/libavfilter/af_aformat.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2011 Mina Nagy Zaki
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * format audio filter
+ */
+
+#include "libavutil/audioconvert.h"
+#include "libavutil/avstring.h"
+#include "libavutil/opt.h"
+
+#include "audio.h"
+#include "avfilter.h"
+#include "formats.h"
+#include "internal.h"
+
+typedef struct AFormatContext {
+    const AVClass   *class;
+
+    AVFilterFormats *formats;
+    AVFilterFormats *sample_rates;
+    AVFilterChannelLayouts *channel_layouts;
+
+    char *formats_str;
+    char *sample_rates_str;
+    char *channel_layouts_str;
+} AFormatContext;
+
+#define OFFSET(x) offsetof(AFormatContext, x)
+#define A AV_OPT_FLAG_AUDIO_PARAM
+static const AVOption options[] = {
+    { "sample_fmts",     "A comma-separated list of sample formats.",  OFFSET(formats_str),         AV_OPT_TYPE_STRING, .flags = A },
+    { "sample_rates",    "A comma-separated list of sample rates.",    OFFSET(sample_rates_str),    AV_OPT_TYPE_STRING, .flags = A },
+    { "channel_layouts", "A comma-separated list of channel layouts.", OFFSET(channel_layouts_str), AV_OPT_TYPE_STRING, .flags = A },
+    { NULL },
+};
+
+static const AVClass aformat_class = {
+    .class_name = "aformat filter",
+    .item_name  = av_default_item_name,
+    .option     = options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+#define PARSE_FORMATS(str, type, list, add_to_list, get_fmt, none, desc)    \
+do {                                                                        \
+    char *next, *cur = str;                                                 \
+    while (cur) {                                                           \
+        type fmt;                                                           \
+        next = strchr(cur, ',');                                            \
+        if (next)                                                           \
+            *next++ = 0;                                                    \
+                                                                            \
+        if ((fmt = get_fmt(cur)) == none) {                                 \
+            av_log(ctx, AV_LOG_ERROR, "Error parsing " desc ": %s.\n", cur);\
+            ret = AVERROR(EINVAL);                                          \
+            goto fail;                                                      \
+        }                                                                   \
+        add_to_list(&list, fmt);                                            \
+                                                                            \
+        cur = next;                                                         \
+    }                                                                       \
+} while (0)
+
+static int get_sample_rate(const char *samplerate)
+{
+    int ret = strtol(samplerate, NULL, 0);
+    return FFMAX(ret, 0);
+}
+
+static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
+{
+    AFormatContext *s = ctx->priv;
+    int ret;
+
+    if (!args) {
+        av_log(ctx, AV_LOG_ERROR, "No parameters supplied.\n");
+        return AVERROR(EINVAL);
+    }
+
+    s->class = &aformat_class;
+    av_opt_set_defaults(s);
+
+    if ((ret = av_set_options_string(s, args, "=", ":")) < 0) {
+        av_log(ctx, AV_LOG_ERROR, "Error parsing options string '%s'.\n", args);
+        return ret;
+    }
+
+    PARSE_FORMATS(s->formats_str, enum AVSampleFormat, s->formats,
+                  avfilter_add_format, av_get_sample_fmt, AV_SAMPLE_FMT_NONE, "sample format");
+    PARSE_FORMATS(s->sample_rates_str, int, s->sample_rates, avfilter_add_format,
+                  get_sample_rate, 0, "sample rate");
+    PARSE_FORMATS(s->channel_layouts_str, uint64_t, s->channel_layouts,
+                  ff_add_channel_layout, av_get_channel_layout, 0,
+                  "channel layout");
+
+fail:
+    av_opt_free(s);
+    return ret;
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+    AFormatContext *s = ctx->priv;
+
+    avfilter_set_common_formats(ctx, s->formats ? s->formats :
+                                                  avfilter_all_formats(AVMEDIA_TYPE_AUDIO));
+    ff_set_common_samplerates(ctx, s->sample_rates ? s->sample_rates :
+                                                     ff_all_samplerates());
+    ff_set_common_channel_layouts(ctx, s->channel_layouts ? s->channel_layouts :
+                                                            ff_all_channel_layouts());
+
+    return 0;
+}
+
+AVFilter avfilter_af_aformat = {
+    .name          = "aformat",
+    .description   = NULL_IF_CONFIG_SMALL("Convert the input audio to one of the specified formats."),
+    .init          = init,
+    .query_formats = query_formats,
+    .priv_size     = sizeof(AFormatContext),
+
+    .inputs        = (AVFilterPad[]) {{ .name            = "default",
+                                        .type            = AVMEDIA_TYPE_AUDIO,
+                                        .filter_samples  = ff_null_filter_samples },
+                                      { .name = NULL}},
+    .outputs       = (AVFilterPad[]) {{ .name            = "default",
+                                        .type            = AVMEDIA_TYPE_AUDIO},
+                                      { .name = NULL}},
+};
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index c84b3f2..4f5f852 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -34,6 +34,7 @@ void avfilter_register_all(void)
         return;
     initialized = 1;
 
+    REGISTER_FILTER (AFORMAT,     aformat,     af);
     REGISTER_FILTER (ANULL,       anull,       af);
     REGISTER_FILTER (RESAMPLE,    resample,    af);
 



More information about the libav-commits mailing list