diff options
author | Anton Khirnov <anton@khirnov.net> | 2012-04-27 07:41:32 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2012-05-06 16:21:00 +0200 |
commit | fd18ee0ff659fc73e56bd43f5b93ed82934c6c7f (patch) | |
tree | bdf01303451839c6a2312ac55526b9ef0ce2e6e7 | |
parent | dce415e7f1aa5a8ac8bf6371b861162444f239c8 (diff) | |
download | ffmpeg-fd18ee0ff659fc73e56bd43f5b93ed82934c6c7f.tar.gz |
vf_split: support user-specifiable number of outputs.
-rw-r--r-- | doc/filters.texi | 13 | ||||
-rw-r--r-- | libavfilter/vf_split.c | 68 |
2 files changed, 68 insertions, 13 deletions
diff --git a/doc/filters.texi b/doc/filters.texi index b012dc791f..c5a56f49f6 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. +@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 +@example +avconv -i INPUT -filter_complex split=5 OUTPUT +@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 54fdd21588..da6b3ff320 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}}, }; |