Browse Source

vf_split: support user-specifiable number of outputs.

tags/n0.11
Anton Khirnov 13 years ago
parent
commit
fd18ee0ff6
2 changed files with 68 additions and 13 deletions
  1. +13
    -0
      doc/filters.texi
  2. +55
    -13
      libavfilter/vf_split.c

+ 13
- 0
doc/filters.texi View File

@@ -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.


+ 55
- 13
libavfilter/vf_split.c View File

@@ -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}},
};

Loading…
Cancel
Save