diff --git a/libavfilter/graphparser.c b/libavfilter/graphparser.c index d54f97d5e8..be61c27081 100644 --- a/libavfilter/graphparser.c +++ b/libavfilter/graphparser.c @@ -41,8 +41,8 @@ static const AVClass filter_parser_class = { static const AVClass *log_ctx = &filter_parser_class; -static int create_filter(AVFilterGraph *ctx, int index, char *name, - char *args) +static AVFilterContext *create_filter(AVFilterGraph *ctx, int index, + char *name, char *args) { AVFilterContext *filt; @@ -54,46 +54,34 @@ static int create_filter(AVFilterGraph *ctx, int index, char *name, if(!(filterdef = avfilter_get_by_name(name))) { av_log(&log_ctx, AV_LOG_ERROR, "no such filter: '%s'\n", name); - return -1; + return NULL; } if(!(filt = avfilter_open(filterdef, tmp))) { av_log(&log_ctx, AV_LOG_ERROR, "error creating filter '%s'\n", name); - return -1; + return NULL; } if (avfilter_graph_add_filter(ctx, filt) < 0) - return -1; + return NULL; if(avfilter_init_filter(filt, args, NULL)) { av_log(&log_ctx, AV_LOG_ERROR, "error initializing filter '%s' with args '%s'\n", name, args); - return -1; + return NULL; } - return 0; + return filt; } -static int link_filter(AVFilterGraph *ctx, int src, int srcpad, - int dst, int dstpad) +static int link_filter(AVFilterContext *src, int srcpad, + AVFilterContext *dst, int dstpad) { - AVFilterContext *filt, *filtb; - - char tmp[20]; - - snprintf(tmp, 20, "%d", src); - if(!(filt = avfilter_graph_get_filter(ctx, tmp))) { - av_log(&log_ctx, AV_LOG_ERROR, "link source does not exist in graph\n"); - return -1; - } - snprintf(tmp, 20, "%d", dst); - if(!(filtb = avfilter_graph_get_filter(ctx, tmp))) { - av_log(&log_ctx, AV_LOG_ERROR, "link destination does not exist in graph\n"); - return -1; - } - if(avfilter_link(filt, srcpad, filtb, dstpad)) { - av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); + if(avfilter_link(src, srcpad, dst, dstpad)) { + av_log(&log_ctx, AV_LOG_ERROR, + "cannot create the link %s:%d -> %s:%d\n", + src->filter->name, srcpad, dst->filter->name, dstpad); return -1; } @@ -201,7 +189,7 @@ static void parse_link_name(const char **buf, char **name) * @arg ars a pointer (that need to be free'd after use) to the args of the * filter */ -static int parse_filter(const char **buf, AVFilterGraph *graph, int index) +static AVFilterContext *parse_filter(const char **buf, AVFilterGraph *graph, int index) { char *name, *opts; name = consume_string(buf); @@ -227,7 +215,7 @@ enum LinkType { typedef struct AVFilterInOut { enum LinkType type; char *name; - int instance; + AVFilterContext *instance; int pad_idx; struct AVFilterInOut *next; @@ -247,7 +235,7 @@ static void free_inout(AVFilterInOut *head) * Parse "(a1)(link2) ... (etc)" */ static int parse_inouts(const char **buf, AVFilterInOut **inout, int firstpad, - enum LinkType type, int instance) + enum LinkType type, AVFilterContext *instance) { int pad = firstpad; while (**buf == '(') { @@ -262,6 +250,16 @@ static int parse_inouts(const char **buf, AVFilterInOut **inout, int firstpad, return pad; } +static const char *skip_inouts(const char *buf) +{ + while (*buf == '(') { + buf += strcspn(buf, ")"); + buf++; + } + return buf; +} + + /** * Parse a string describing a filter graph. */ @@ -275,70 +273,61 @@ int avfilter_graph_parse_chain(AVFilterGraph *graph, const char *filters, AVFilt int pad = 0; int has_out = 0; - char tmp[20]; - AVFilterContext *filt; + AVFilterContext *last_filt = NULL; consume_whitespace(&filters); do { + AVFilterContext *filter; int oldpad = pad; + const char *inouts = filters; - pad = parse_inouts(&filters, &inout, chr == ',', LinkTypeIn, index); + // We need to parse the inputs of the filter after we create it, so + // skip it by now + filters = skip_inouts(filters); - if (parse_filter(&filters, graph, index) < 0) + if (!(filter = parse_filter(&filters, graph, index))) goto fail; + pad = parse_inouts(&inouts, &inout, chr == ',', LinkTypeIn, filter); + // If the first filter has an input and none was given, it is // implicitly the input of the whole graph. if (pad == 0 && graph->filters[graph->filter_count-1]->input_count == 1) { - snprintf(tmp, 20, "%d", index); - if(!(filt = avfilter_graph_get_filter(graph, tmp))) { - av_log(&log_ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n"); - goto fail; - } - if(avfilter_link(in, inpad, filt, 0)) { + if(avfilter_link(in, inpad, filter, 0)) { av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); goto fail; } } if(chr == ',') { - if (link_filter(graph, index-1, oldpad, index, 0) < 0) + if (link_filter(last_filt, oldpad, filter, 0) < 0) goto fail; } - pad = parse_inouts(&filters, &inout, 0, LinkTypeOut, index); + pad = parse_inouts(&filters, &inout, 0, LinkTypeOut, filter); chr = *filters++; index++; + last_filt = filter; } while (chr == ',' || chr == ';'); head = inout; for (; inout != NULL; inout = inout->next) { - if (inout->instance == -1) + if (inout->instance == NULL) continue; // Already processed if (!strcmp(inout->name, "in")) { - snprintf(tmp, 20, "%d", inout->instance); - if(!(filt = avfilter_graph_get_filter(graph, tmp))) { - av_log(&log_ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n"); - goto fail; - } - if(avfilter_link(in, inpad, filt, inout->pad_idx)) { + if(avfilter_link(in, inpad, inout->instance, inout->pad_idx)) { av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); goto fail; } } else if (!strcmp(inout->name, "out")) { has_out = 1; - snprintf(tmp, 20, "%d", inout->instance); - if(!(filt = avfilter_graph_get_filter(graph, tmp))) { - av_log(&log_ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n"); - goto fail; - } - if(avfilter_link(filt, inout->pad_idx, out, outpad)) { + if(avfilter_link(inout->instance, inout->pad_idx, out, outpad)) { av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); goto fail; - } + } } else { AVFilterInOut *p, *src, *dst; @@ -363,24 +352,18 @@ int avfilter_graph_parse_chain(AVFilterGraph *graph, const char *filters, AVFilt goto fail; } - if (link_filter(graph, src->instance, src->pad_idx, dst->instance, dst->pad_idx) < 0) + if (link_filter(src->instance, src->pad_idx, dst->instance, dst->pad_idx) < 0) goto fail; - src->instance = -1; - dst->instance = -1; + src->instance = NULL; + dst->instance = NULL; } } free_inout(head); if (!has_out) { - snprintf(tmp, 20, "%d", index-1); - if(!(filt = avfilter_graph_get_filter(graph, tmp))) { - av_log(&log_ctx, AV_LOG_ERROR, "filter owning exported pad does not exist\n"); - goto fail; - } - - if(avfilter_link(filt, pad, out, outpad)) { + if(avfilter_link(last_filt, pad, out, outpad)) { av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); goto fail; }