[libav-devel] [PATCH 2/4] vf_split: support user-specifiable number of outputs.

Anton Khirnov anton at khirnov.net
Thu May 3 20:05:06 CEST 2012


---
 doc/filters.texi       |   13 +++++++++
 libavfilter/vf_split.c |   68 +++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 68 insertions(+), 13 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index b012dc7..c5a56f4 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -1666,6 +1666,19 @@ not specified it will use the default value of 16.
 Adding this in the beginning of filter chains should make filtering
 faster due to better use of the memory cache.
 
+ at section split
+
+Split input video into several identical outputs.
+
+The filter accepts a single parameter which specifies the number of outputs. If
+unspecified, it defaults to 2.
+
+For example
+ at example
+avconv -i INPUT -filter_complex split=5 OUTPUT
+ at end example
+will create 5 copies of the input video.
+
 @section transpose
 
 Transpose rows with columns in the input video and optionally flip it.
diff --git a/libavfilter/vf_split.c b/libavfilter/vf_split.c
index 54fdd21..da6b3ff 100644
--- a/libavfilter/vf_split.c
+++ b/libavfilter/vf_split.c
@@ -25,24 +25,67 @@
 
 #include "avfilter.h"
 
+static int split_init(AVFilterContext *ctx, const char *args, void *opaque)
+{
+    int i, nb_outputs = 2;
+
+    if (args) {
+        nb_outputs = strtol(args, NULL, 0);
+        if (nb_outputs <= 0) {
+            av_log(ctx, AV_LOG_ERROR, "Invalid number of outputs specified: %d.\n",
+                   nb_outputs);
+            return AVERROR(EINVAL);
+        }
+    }
+
+    for (i = 0; i < nb_outputs; i++) {
+        char name[32];
+        AVFilterPad pad = { 0 };
+
+        snprintf(name, sizeof(name), "output%d", i);
+        pad.type = AVMEDIA_TYPE_VIDEO;
+        pad.name = av_strdup(name);
+
+        avfilter_insert_outpad(ctx, i, &pad);
+    }
+
+    return 0;
+}
+
+static void split_uninit(AVFilterContext *ctx)
+{
+    int i;
+
+    for (i = 0; i < ctx->output_count; i++)
+        av_freep(&ctx->output_pads[i].name);
+}
+
 static void start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
 {
-    avfilter_start_frame(inlink->dst->outputs[0],
-                         avfilter_ref_buffer(picref, ~AV_PERM_WRITE));
-    avfilter_start_frame(inlink->dst->outputs[1],
-                         avfilter_ref_buffer(picref, ~AV_PERM_WRITE));
+    AVFilterContext *ctx = inlink->dst;
+    int i;
+
+    for (i = 0; i < ctx->output_count; i++)
+        avfilter_start_frame(ctx->outputs[i],
+                             avfilter_ref_buffer(picref, ~AV_PERM_WRITE));
 }
 
 static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
 {
-    avfilter_draw_slice(inlink->dst->outputs[0], y, h, slice_dir);
-    avfilter_draw_slice(inlink->dst->outputs[1], y, h, slice_dir);
+    AVFilterContext *ctx = inlink->dst;
+    int i;
+
+    for (i = 0; i < ctx->output_count; i++)
+        avfilter_draw_slice(ctx->outputs[i], y, h, slice_dir);
 }
 
 static void end_frame(AVFilterLink *inlink)
 {
-    avfilter_end_frame(inlink->dst->outputs[0]);
-    avfilter_end_frame(inlink->dst->outputs[1]);
+    AVFilterContext *ctx = inlink->dst;
+    int i;
+
+    for (i = 0; i < ctx->output_count; i++)
+        avfilter_end_frame(ctx->outputs[i]);
 
     avfilter_unref_buffer(inlink->cur_buf);
 }
@@ -51,6 +94,9 @@ AVFilter avfilter_vf_split = {
     .name      = "split",
     .description = NULL_IF_CONFIG_SMALL("Pass on the input to two outputs."),
 
+    .init   = split_init,
+    .uninit = split_uninit,
+
     .inputs    = (AVFilterPad[]) {{ .name            = "default",
                                     .type            = AVMEDIA_TYPE_VIDEO,
                                     .get_video_buffer= avfilter_null_get_video_buffer,
@@ -58,9 +104,5 @@ AVFilter avfilter_vf_split = {
                                     .draw_slice      = draw_slice,
                                     .end_frame       = end_frame, },
                                   { .name = NULL}},
-    .outputs   = (AVFilterPad[]) {{ .name            = "output1",
-                                    .type            = AVMEDIA_TYPE_VIDEO, },
-                                  { .name            = "output2",
-                                    .type            = AVMEDIA_TYPE_VIDEO, },
-                                  { .name = NULL}},
+    .outputs   = (AVFilterPad[]) {{ .name = NULL}},
 };
-- 
1.7.9.5



More information about the libav-devel mailing list