From d2027baac5aaf078a4b7abf5d9d7b0dee4ea6b3b Mon Sep 17 00:00:00 2001 From: Vitor Sessak Date: Fri, 4 Apr 2008 20:09:27 +0000 Subject: I should not have merged the graph parser with the graph framework. Split it. Commited in SoC by Vitor Sessak on 2008-04-03 16:29:07 Originally committed as revision 12746 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavfilter/avfiltergraph.c | 367 +------------------------------------------- libavfilter/avfiltergraph.h | 11 +- 2 files changed, 8 insertions(+), 370 deletions(-) diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c index d09500d749..5df3d2e423 100644 --- a/libavfilter/avfiltergraph.c +++ b/libavfilter/avfiltergraph.c @@ -26,21 +26,6 @@ #include "avfilter.h" #include "avfiltergraph.h" -/** - * For use in av_log - */ -static const char *log_name(void *p) -{ - return "Filter parser"; -} - -static const AVClass filter_parser_class = { - "Filter parser", - log_name -}; - -static const AVClass *log_ctx = &filter_parser_class; - void avfilter_destroy_graph(AVFilterGraph *graph) { for(; graph->filter_count > 0; graph->filter_count --) @@ -48,7 +33,9 @@ void avfilter_destroy_graph(AVFilterGraph *graph) av_freep(&graph->filters); } -/* TODO: insert in sorted order */ +/** + * @todo insert in sorted order + */ void avfilter_graph_add_filter(AVFilterGraph *graph, AVFilterContext *filter) { graph->filters = av_realloc(graph->filters, @@ -56,7 +43,9 @@ void avfilter_graph_add_filter(AVFilterGraph *graph, AVFilterContext *filter) graph->filters[graph->filter_count - 1] = filter; } -/* search intelligently, once we insert in order */ +/* + * @todo search intelligently, once we insert in order + */ AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name) { int i; @@ -160,347 +149,3 @@ int avfilter_graph_config_formats(AVFilterGraph *graph) return 0; } -static int create_filter(AVFilterGraph *ctx, int index, char *name, - char *args) -{ - AVFilterContext *filt; - - AVFilter *filterdef; - char tmp[20]; - - snprintf(tmp, 20, "%d", index); - if(!(filterdef = avfilter_get_by_name(name)) || - !(filt = avfilter_open(filterdef, tmp))) { - av_log(&log_ctx, AV_LOG_ERROR, - "error creating filter '%s'\n", name); - return -1; - } - avfilter_graph_add_filter(ctx, filt); - if(avfilter_init_filter(filt, args, NULL)) { - av_log(&log_ctx, AV_LOG_ERROR, - "error initializing filter '%s'\n", name); - return -1; - } - - return 0; -} - -static int link_filter(AVFilterGraph *ctx, int src, int srcpad, - int 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"); - return -1; - } - - return 0; -} - -static void consume_whitespace(const char **buf) -{ - *buf += strspn(*buf, " \n\t"); -} - -/** - * Copy the first size bytes of input string to a null-terminated string, - * removing any control character. Ex: "aaa'bb'c\'c\\" -> "aaabbc'c\" - */ -static void copy_unquoted(char *out, const char *in, int size) -{ - int i; - for (i=0; i < size; i++) { - if (in[i] == '\'') - continue; - else if (in[i] == '\\') { - if (i+1 == size) { - *out = 0; - return; - } - i++; - } - *out++ = in[i]; - } - *out=0; -} - -/** - * Consumes a string from *buf. - * @return a copy of the consumed string, which should be free'd after use - */ -static char *consume_string(const char **buf) -{ - const char *start; - char *ret; - int size; - - consume_whitespace(buf); - - if (!(**buf)) - return av_mallocz(1); - - start = *buf; - - while(1) { - *buf += strcspn(*buf, " ()=,'\\"); - if (**buf == '\\') - *buf+=2; - else - break; - } - - if (**buf == '\'') { - const char *p = *buf; - do { - p++; - p = strchr(p, '\''); - } while (p && p[-1] == '\\'); - if (p) - *buf = p + 1; - else - *buf += strlen(*buf); // Move the pointer to the null end byte - } - - size = *buf - start + 1; - ret = av_malloc(size); - copy_unquoted(ret, start, size-1); - - return ret; -} - -/** - * Parse "(linkname)" - * @arg name a pointer (that need to be free'd after use) to the name between - * parenthesis - */ -static void parse_link_name(const char **buf, char **name) -{ - (*buf)++; - - *name = consume_string(buf); - - if (!*name[0]) - goto fail; - - if (*(*buf)++ != ')') - goto fail; - - return; - fail: - av_freep(name); - av_log(&log_ctx, AV_LOG_ERROR, "Could not parse link name!\n"); -} - -/** - * Parse "filter=params" - * @arg name a pointer (that need to be free'd after use) to the name of the - * filter - * @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) -{ - char *name, *opts; - name = consume_string(buf); - - if (**buf == '=') { - (*buf)++; - opts = consume_string(buf); - } else { - opts = NULL; - } - - return create_filter(graph, index, name, opts); -} - -enum LinkType { - LinkTypeIn, - LinkTypeOut, -}; - -/** - * A linked-list of the inputs/outputs of the filter chain. - */ -typedef struct AVFilterInOut { - enum LinkType type; - char *name; - int instance; - int pad_idx; - - struct AVFilterInOut *next; -} AVFilterInOut; - -static void free_inout(AVFilterInOut *head) -{ - while (head) { - AVFilterInOut *next; - next = head->next; - av_free(head); - head = next; - } -} - -/** - * Parse "(a1)(link2) ... (etc)" - */ -static int parse_inouts(const char **buf, AVFilterInOut **inout, int firstpad, - enum LinkType type, int instance) -{ - int pad = firstpad; - while (**buf == '(') { - AVFilterInOut *inoutn = av_malloc(sizeof(AVFilterInOut)); - parse_link_name(buf, &inoutn->name); - inoutn->type = type; - inoutn->instance = instance; - inoutn->pad_idx = pad++; - inoutn->next = *inout; - *inout = inoutn; - } - return pad; -} - -/** - * Parse a string describing a filter graph. - */ -int avfilter_graph_parse_chain(AVFilterGraph *graph, const char *filters, AVFilterContext *in, int inpad, AVFilterContext *out, int outpad) -{ - AVFilterInOut *inout=NULL; - AVFilterInOut *head=NULL; - - int index = 0; - char chr = 0; - int pad = 0; - int has_out = 0; - - char tmp[20]; - AVFilterContext *filt; - - consume_whitespace(&filters); - - do { - int oldpad = pad; - - pad = parse_inouts(&filters, &inout, chr == ',', LinkTypeIn, index); - - if (parse_filter(&filters, graph, index) < 0) - goto fail; - - // 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)) { - 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) - goto fail; - - } - pad = parse_inouts(&filters, &inout, 0, LinkTypeOut, index); - chr = *filters++; - index++; - } while (chr == ',' || chr == ';'); - - head = inout; - for (; inout != NULL; inout = inout->next) { - if (inout->instance == -1) - 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)) { - 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)) { - av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); - goto fail; - } - - } else { - AVFilterInOut *p, *src, *dst; - for (p = inout->next; - p && strcmp(p->name,inout->name); p = p->next); - - if (!p) { - av_log(&log_ctx, AV_LOG_ERROR, "Unmatched link: %s.\n", - inout->name); - goto fail; - } - - if (p->type == LinkTypeIn && inout->type == LinkTypeOut) { - src = inout; - dst = p; - } else if (p->type == LinkTypeOut && inout->type == LinkTypeIn) { - src = p; - dst = inout; - } else { - av_log(&log_ctx, AV_LOG_ERROR, "Two links named '%s' are either both input or both output\n", - inout->name); - goto fail; - } - - if (link_filter(graph, src->instance, src->pad_idx, dst->instance, dst->pad_idx) < 0) - goto fail; - - src->instance = -1; - dst->instance = -1; - } - } - - 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)) { - av_log(&log_ctx, AV_LOG_ERROR, "cannot create link between source and destination filters\n"); - goto fail; - } - - } - - return 0; - - fail: - free_inout(head); - avfilter_destroy_graph(graph); - return -1; -} diff --git a/libavfilter/avfiltergraph.h b/libavfilter/avfiltergraph.h index f856fbd6b6..58afa04cea 100644 --- a/libavfilter/avfiltergraph.h +++ b/libavfilter/avfiltergraph.h @@ -30,16 +30,9 @@ typedef struct AVFilterGraph { } AVFilterGraph; /** - * Add to a graph a graph described by a string. - * @param graph the filter graph where to link the parsed graph context - * @param filters string to be parsed - * @param in input to the graph to be parsed (TODO: allow several) - * @param inpad pad index of the input - * @param in output to the graph to be parsed (TODO: allow several) - * @param inpad pad index of the output - * @return zero on success, -1 on error + * Get a pointer to a graph by instance name */ -int avfilter_graph_parse_chain(AVFilterGraph *graph, const char *filters, AVFilterContext *in, int inpad, AVFilterContext *out, int outpad); +AVFilterContext *avfilter_graph_get_filter(AVFilterGraph *graph, char *name); /** * Add an existing filter instance to a filter graph. -- cgit v1.2.3