From: Stefano Sabatini Date: Thu, 25 Feb 2010 19:55:01 +0000 (+0000) Subject: Add the graph2dot tools and document it. X-Git-Tag: android-x86-4.4-r1~23113 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=11ab237e31860435816bc70739dc5a35c3078cc4;p=android-x86%2Fexternal-ffmpeg.git Add the graph2dot tools and document it. Also link avfiltergraph.o and graphparser.o against libavfilter, as it uses them. Originally committed as revision 22063 to svn://svn.ffmpeg.org/ffmpeg/trunk --- diff --git a/doc/libavfilter.texi b/doc/libavfilter.texi index 5bb5235898..32bf10fd9a 100644 --- a/doc/libavfilter.texi +++ b/doc/libavfilter.texi @@ -71,6 +71,34 @@ There exist so-called @var{source filters} that do not have a video input, and we expect in the future some @var{sink filters} that will not have video output. +@chapter graph2dot + +The @file{graph2dot} program included in the FFmpeg @file{tools} +directory can be used to parse a filter graph description and issue a +corresponding textual representation in the dot language. + +Invoke the command: +@example +graph2dot -h +@end example + +to see how to use @file{graph2dot}. + +You can then pass the dot description to the @file{dot} program (from +the graphviz suite of programs) and obtain a graphical representation +of the filter graph. + +For example the sequence of commands: +@example +echo @var{GRAPH_DESCRIPTION} | \ +tools/graph2dot -o graph.tmp && \ +dot -Tpng graph.tmp -o graph.png && \ +display graph.png +@end example + +can be used to create and display an image representing the graph +described by the @var{GRAPH_DESCRIPTION} string. + @chapter Available video filters When you configure your FFmpeg build, you can disable any of the diff --git a/libavfilter/Makefile b/libavfilter/Makefile index fd95e35c80..904cceffd0 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -8,8 +8,10 @@ HEADERS = avfilter.h OBJS = allfilters.o \ avfilter.o \ + avfiltergraph.o \ defaults.o \ formats.o \ + graphparser.o \ parseutils.o \ OBJS-$(CONFIG_CROP_FILTER) += vf_crop.o diff --git a/tools/graph2dot.c b/tools/graph2dot.c new file mode 100644 index 0000000000..57a25a73cb --- /dev/null +++ b/tools/graph2dot.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2008-2010 Stefano Sabatini + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include /* getopt */ + +#undef HAVE_AV_CONFIG_H +#include "libavutil/pixdesc.h" +#include "libavfilter/graphparser.h" + +static void usage(void) +{ + printf("Convert a libavfilter graph to a dot file\n"); + printf("Usage: graph2dot [OPTIONS]\n"); + printf("\n" + "Options:\n" + "-i INFILE set INFILE as input file, stdin if omitted\n" + "-o OUTFILE set OUTFILE as output file, stdout if omitted\n" + "-h print this help\n"); +} + +struct line { + char data[256]; + struct line *next; +}; + +static void print_digraph(FILE *outfile, AVFilterGraph *graph) +{ + int i, j; + + fprintf(outfile, "digraph G {\n"); + fprintf(outfile, "node [shape=box]\n"); + fprintf(outfile, "rankdir=LR\n"); + + for (i = 0; i < graph->filter_count; i++) { + char filter_ctx_label[128]; + const AVFilterContext *filter_ctx = graph->filters[i]; + + snprintf(filter_ctx_label, sizeof(filter_ctx_label), "%s (%s)", + filter_ctx->name, + filter_ctx->filter->name); + + for (j = 0; j < filter_ctx->output_count; j++) { + AVFilterLink *link = filter_ctx->outputs[j]; + if (link) { + char dst_filter_ctx_label[128]; + const AVFilterContext *dst_filter_ctx = link->dst; + + snprintf(dst_filter_ctx_label, sizeof(dst_filter_ctx_label), "%s (%s)", + dst_filter_ctx->name, + dst_filter_ctx->filter->name); + + fprintf(outfile, "\"%s\" -> \"%s\"", filter_ctx_label, dst_filter_ctx_label); + fprintf(outfile, " [ label= \"fmt:%s w:%d h:%d\"];\n", + av_pix_fmt_descriptors[link->format].name, link->w, link->h); + } + } + } + fprintf(outfile, "}\n"); +} + +int main(int argc, char **argv) +{ + const char *outfilename = NULL; + const char *infilename = NULL; + FILE *outfile = NULL; + FILE *infile = NULL; + char *graph_string = NULL; + AVFilterGraph *graph = av_mallocz(sizeof(AVFilterGraph)); + char c; + + av_log_set_level(AV_LOG_DEBUG); + + while ((c = getopt(argc, argv, "hi:o:")) != -1) { + switch(c) { + case 'h': + usage(); + return 0; + case 'i': + infilename = optarg; + break; + case 'o': + outfilename = optarg; + break; + case '?': + return 1; + } + } + + if (!infilename || !strcmp(infilename, "-")) + infilename = "/dev/stdin"; + infile = fopen(infilename, "r"); + if (!infile) { + fprintf(stderr, "Impossible to open input file '%s': %s\n", infilename, strerror(errno)); + return 1; + } + + if (!outfilename || !strcmp(outfilename, "-")) + outfilename = "/dev/stdout"; + outfile = fopen(outfilename, "w"); + if (!outfile) { + fprintf(stderr, "Impossible to open output file '%s': %s\n", outfilename, strerror(errno)); + return 1; + } + + /* read from infile and put it in a buffer */ + { + unsigned int count = 0; + struct line *line, *last_line, *first_line; + char *p; + last_line = first_line = av_malloc(sizeof(struct line)); + + while (fgets(last_line->data, sizeof(last_line->data), infile)) { + struct line *new_line = av_malloc(sizeof(struct line)); + count += strlen(last_line->data); + last_line->next = new_line; + last_line = new_line; + } + last_line->next = NULL; + + graph_string = av_malloc(count + 1); + p = graph_string; + for (line = first_line; line->next; line = line->next) { + unsigned int l = strlen(line->data); + memcpy(p, line->data, l); + p += l; + } + *p = '\0'; + } + + avfilter_register_all(); + + if (avfilter_graph_parse(graph, graph_string, NULL, NULL, NULL) < 0) { + fprintf(stderr, "Impossible to parse the graph description\n"); + return 1; + } + + if (avfilter_graph_check_validity(graph, NULL) || + avfilter_graph_config_formats(graph, NULL) || + avfilter_graph_config_links (graph, NULL)) + return 1; + + print_digraph(outfile, graph); + fflush(outfile); + + return 0; +}