[FFmpeg-devel] [PATCH] lavfi: add aconcat variant for the concat filter

Stefano Sabatini stefasab at gmail.com
Thu Sep 6 17:35:58 CEST 2012


It can be useful to specify aconcat rather than concat=a=1:v=0.

This is consistent with amovie/asplit and other filter variants
specialized on audio.

It is perfectly equivalent to concat otherwise.
---
 doc/filters.texi         |   14 ++++++------
 libavfilter/Makefile     |    1 +
 libavfilter/allfilters.c |    1 +
 libavfilter/avf_concat.c |   49 ++++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 52 insertions(+), 13 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 685a3e2..0b57eed 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -4328,16 +4328,16 @@ settb=AVTB
 @end example
 @end itemize
 
- at section concat
+ at section aconcat, concat
 
 Concatenate audio and video streams, joining them together one after the
 other.
 
-The filter works on segments of synchronized video and audio streams. All
+These filter work on segments of synchronized video and audio streams. All
 segments must have the same number of streams of each type, and that will
 also be the number of streams at output.
 
-The filter accepts the following named parameters:
+These filter accept the following named parameters:
 @table @option
 
 @item n
@@ -4345,15 +4345,15 @@ Set the number of segments. Default is 2.
 
 @item v
 Set the number of output video streams, that is also the number of video
-streams in each segment. Default is 1.
+streams in each segment. Default is 1 for @code{concat}, 0 for @code{aconcat}.
 
 @item a
 Set the number of output audio streams, that is also the number of video
-streams in each segment. Default is 0.
+streams in each segment. Default is 1 for @code{aconcat}, 0 for @code{concat}.
 
 @end table
 
-The filter has @var{v}+ at var{a} outputs: first @var{v} video outputs, then
+These filter have @var{v}+ at var{a} outputs: first @var{v} video outputs, then
 @var{a} audio outputs.
 
 There are @var{n}×(@var{v}+ at var{a}) inputs: first the inputs for the first
@@ -4367,7 +4367,7 @@ concatenated at once. The concat filter will use the duration of the longest
 stream in each segment (except the last one), and if necessary pad shorter
 audio streams with silence.
 
-For this filter to work correctly, all segments must start at timestamp 0.
+For these filters to work correctly, all segments must start at timestamp 0.
 
 All corresponding streams must have the same parameters in all segments; the
 filtering system will automatically select a common pixel format for video
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 82d39e4..5cb0ce1 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -204,6 +204,7 @@ OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/vf_yvu9.o
 OBJS-$(CONFIG_MP_FILTER) += libmpcodecs/pullup.o
 
 # multimedia filters
+OBJS-$(CONFIG_ACONCAT_FILTER)                += avf_concat.o
 OBJS-$(CONFIG_CONCAT_FILTER)                 += avf_concat.o
 OBJS-$(CONFIG_SHOWSPECTRUM_FILTER)           += avf_showspectrum.o
 OBJS-$(CONFIG_SHOWWAVES_FILTER)              += avf_showwaves.o
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index 6842ec9..f141628 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -150,6 +150,7 @@ void avfilter_register_all(void)
     REGISTER_FILTER (NULLSINK,    nullsink,    vsink);
 
     /* multimedia filters */
+    REGISTER_FILTER (ACONCAT,     aconcat,     avf);
     REGISTER_FILTER (CONCAT,      concat,      avf);
     REGISTER_FILTER (SHOWSPECTRUM,showspectrum,avf);
     REGISTER_FILTER (SHOWWAVES,   showwaves,   avf);
diff --git a/libavfilter/avf_concat.c b/libavfilter/avf_concat.c
index c0bd621..1b1d70f 100644
--- a/libavfilter/avf_concat.c
+++ b/libavfilter/avf_concat.c
@@ -60,15 +60,13 @@ static const AVOption concat_options[] = {
       AV_OPT_TYPE_INT, { .i64 = 2 }, 2, INT_MAX, V|A|F},
     { "v", "specify the number of video streams",
       OFFSET(nb_streams[AVMEDIA_TYPE_VIDEO]),
-      AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, V|F },
+      AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, V|F },
     { "a", "specify the number of audio streams",
       OFFSET(nb_streams[AVMEDIA_TYPE_AUDIO]),
       AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, A|F},
     { 0 }
 };
 
-AVFILTER_DEFINE_CLASS(concat);
-
 static int query_formats(AVFilterContext *ctx)
 {
     ConcatContext *cat = ctx->priv;
@@ -360,15 +358,19 @@ static int request_frame(AVFilterLink *outlink)
     }
 }
 
-static av_cold int init(AVFilterContext *ctx, const char *args)
+static av_cold int common_init(AVFilterContext *ctx, const char *args, const AVClass *class)
 {
     ConcatContext *cat = ctx->priv;
     int ret;
     unsigned seg, type, str;
     char name[32];
 
-    cat->class = &concat_class;
+    cat->class = class;
     av_opt_set_defaults(cat);
+
+    if (!strcmp(ctx->filter->name, "concat"))  cat->nb_streams[AVMEDIA_TYPE_VIDEO] = 1;
+    if (!strcmp(ctx->filter->name, "aconcat")) cat->nb_streams[AVMEDIA_TYPE_AUDIO] = 1;
+
     ret = av_set_options_string(cat, args, "=", ":");
     if (ret < 0) {
         av_log(ctx, AV_LOG_ERROR, "Error parsing options: '%s'\n", args);
@@ -433,10 +435,43 @@ static av_cold void uninit(AVFilterContext *ctx)
     av_free(cat->in);
 }
 
+#if CONFIG_CONCAT_FILTER
+
+AVFILTER_DEFINE_CLASS(concat);
+
+static av_cold int concat_init(AVFilterContext *ctx, const char *args)
+{
+    return common_init(ctx, args, &concat_class);
+}
+
 AVFilter avfilter_avf_concat = {
     .name          = "concat",
     .description   = NULL_IF_CONFIG_SMALL("Concatenate audio and video streams."),
-    .init          = init,
+    .init          = concat_init,
+    .uninit        = uninit,
+    .query_formats = query_formats,
+    .priv_size     = sizeof(ConcatContext),
+    .inputs        = (const AVFilterPad[]) { { .name = NULL } },
+    .outputs       = (const AVFilterPad[]) { { .name = NULL } },
+    .priv_class    = &concat_class,
+};
+
+#endif // CONFIG_CONCAT_FILTER
+
+#if CONFIG_ACONCAT_FILTER
+
+#define aconcat_options concat_options
+AVFILTER_DEFINE_CLASS(aconcat);
+
+static av_cold int aconcat_init(AVFilterContext *ctx, const char *args)
+{
+    return common_init(ctx, args, &aconcat_class);
+}
+
+AVFilter avfilter_avf_aconcat = {
+    .name          = "aconcat",
+    .description   = NULL_IF_CONFIG_SMALL("Concatenate audio and video streams."),
+    .init          = aconcat_init,
     .uninit        = uninit,
     .query_formats = query_formats,
     .priv_size     = sizeof(ConcatContext),
@@ -444,3 +479,5 @@ AVFilter avfilter_avf_concat = {
     .outputs       = (const AVFilterPad[]) { { .name = NULL } },
     .priv_class    = &concat_class,
 };
+
+#endif // CONFIG_ACONCAT_FILTER
-- 
1.7.5.4



More information about the ffmpeg-devel mailing list