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