00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #include <stdio.h>
00027
00028 #include "libavutil/internal.h"
00029 #include "libavutil/mem.h"
00030 #include "avfilter.h"
00031 #include "audio.h"
00032 #include "internal.h"
00033 #include "video.h"
00034
00035 static int split_init(AVFilterContext *ctx, const char *args)
00036 {
00037 int i, nb_outputs = 2;
00038
00039 if (args) {
00040 nb_outputs = strtol(args, NULL, 0);
00041 if (nb_outputs <= 0) {
00042 av_log(ctx, AV_LOG_ERROR, "Invalid number of outputs specified: %d.\n",
00043 nb_outputs);
00044 return AVERROR(EINVAL);
00045 }
00046 }
00047
00048 for (i = 0; i < nb_outputs; i++) {
00049 char name[32];
00050 AVFilterPad pad = { 0 };
00051
00052 snprintf(name, sizeof(name), "output%d", i);
00053 pad.type = ctx->filter->inputs[0].type;
00054 pad.name = av_strdup(name);
00055 pad.rej_perms = AV_PERM_WRITE;
00056
00057 ff_insert_outpad(ctx, i, &pad);
00058 }
00059
00060 return 0;
00061 }
00062
00063 static void split_uninit(AVFilterContext *ctx)
00064 {
00065 int i;
00066
00067 for (i = 0; i < ctx->nb_outputs; i++)
00068 av_freep(&ctx->output_pads[i].name);
00069 }
00070
00071 static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
00072 {
00073 AVFilterContext *ctx = inlink->dst;
00074 int i, ret = AVERROR_EOF;
00075
00076 for (i = 0; i < ctx->nb_outputs; i++) {
00077 AVFilterBufferRef *buf_out;
00078
00079 if (ctx->outputs[i]->closed)
00080 continue;
00081 buf_out = avfilter_ref_buffer(picref, ~AV_PERM_WRITE);
00082 if (!buf_out)
00083 return AVERROR(ENOMEM);
00084
00085 ret = ff_start_frame(ctx->outputs[i], buf_out);
00086 if (ret < 0)
00087 break;
00088 }
00089 return ret;
00090 }
00091
00092 static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
00093 {
00094 AVFilterContext *ctx = inlink->dst;
00095 int i, ret = AVERROR_EOF;
00096
00097 for (i = 0; i < ctx->nb_outputs; i++) {
00098 if (ctx->outputs[i]->closed)
00099 continue;
00100 ret = ff_draw_slice(ctx->outputs[i], y, h, slice_dir);
00101 if (ret < 0)
00102 break;
00103 }
00104 return ret;
00105 }
00106
00107 static int end_frame(AVFilterLink *inlink)
00108 {
00109 AVFilterContext *ctx = inlink->dst;
00110 int i, ret = AVERROR_EOF;
00111
00112 for (i = 0; i < ctx->nb_outputs; i++) {
00113 if (ctx->outputs[i]->closed)
00114 continue;
00115 ret = ff_end_frame(ctx->outputs[i]);
00116 if (ret < 0)
00117 break;
00118 }
00119 return ret;
00120 }
00121
00122 AVFilter avfilter_vf_split = {
00123 .name = "split",
00124 .description = NULL_IF_CONFIG_SMALL("Pass on the input video to N outputs."),
00125
00126 .init = split_init,
00127 .uninit = split_uninit,
00128
00129 .inputs = (const AVFilterPad[]) {{ .name = "default",
00130 .type = AVMEDIA_TYPE_VIDEO,
00131 .get_video_buffer= ff_null_get_video_buffer,
00132 .start_frame = start_frame,
00133 .draw_slice = draw_slice,
00134 .end_frame = end_frame, },
00135 { .name = NULL}},
00136 .outputs = NULL,
00137 };
00138
00139 static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
00140 {
00141 AVFilterContext *ctx = inlink->dst;
00142 int i, ret = 0;
00143
00144 for (i = 0; i < ctx->nb_outputs; i++) {
00145 AVFilterBufferRef *buf_out = avfilter_ref_buffer(samplesref,
00146 ~AV_PERM_WRITE);
00147 if (!buf_out) {
00148 ret = AVERROR(ENOMEM);
00149 break;
00150 }
00151
00152 ret = ff_filter_samples(inlink->dst->outputs[i], buf_out);
00153 if (ret < 0)
00154 break;
00155 }
00156 avfilter_unref_buffer(samplesref);
00157 return ret;
00158 }
00159
00160 AVFilter avfilter_af_asplit = {
00161 .name = "asplit",
00162 .description = NULL_IF_CONFIG_SMALL("Pass on the audio input to N audio outputs."),
00163
00164 .init = split_init,
00165 .uninit = split_uninit,
00166
00167 .inputs = (const AVFilterPad[]) {{ .name = "default",
00168 .type = AVMEDIA_TYPE_AUDIO,
00169 .get_audio_buffer = ff_null_get_audio_buffer,
00170 .filter_samples = filter_samples },
00171 { .name = NULL }},
00172 .outputs = NULL,
00173 };