On Mon, May 25, 2020 at 07:50:24AM +0800, lance.lmw...@gmail.com wrote: > From: Limin Wang <lance.lmw...@gmail.com> > > Signed-off-by: Limin Wang <lance.lmw...@gmail.com> > --- > libavfilter/Makefile | 1 - > libavfilter/graphdump.c | 89 +++++++++++++++++++++ > tools/graph2dot.c | 204 > ------------------------------------------------ > 3 files changed, 89 insertions(+), 205 deletions(-) > delete mode 100644 tools/graph2dot.c > > diff --git a/libavfilter/Makefile b/libavfilter/Makefile > index 4d07bb6..291126e 100644 > --- a/libavfilter/Makefile > +++ b/libavfilter/Makefile > @@ -526,7 +526,6 @@ SKIPHEADERS-$(CONFIG_VULKAN) += vulkan.h > > OBJS-$(CONFIG_LIBGLSLANG) += glslang.o > > -TOOLS = graph2dot > TESTPROGS = drawutils filtfmts formats integral > > TOOLS-$(CONFIG_LIBZMQ) += zmqsend > diff --git a/libavfilter/graphdump.c b/libavfilter/graphdump.c > index 79ef1a7..97d4f39 100644 > --- a/libavfilter/graphdump.c > +++ b/libavfilter/graphdump.c > @@ -151,15 +151,104 @@ static void avfilter_graph_dump_to_buf(AVBPrint *buf, > AVFilterGraph *graph) > } > } > > +static void avfilter_graph2dot_to_buf(AVBPrint *buf, AVFilterGraph *graph) > +{ > + int i, j; > + > + av_bprintf(buf, "digraph G {\n"); > + av_bprintf(buf, "node [shape=box]\n"); > + av_bprintf(buf, "rankdir=LR\n"); > + > + for (i = 0; i < graph->nb_filters; i++) { > + char filter_ctx_label[128]; > + const AVFilterContext *filter_ctx = graph->filters[i]; > + > + snprintf(filter_ctx_label, sizeof(filter_ctx_label), "%s\\n(%s)", > + filter_ctx->name, > + filter_ctx->filter->name); > + > + for (j = 0; j < filter_ctx->nb_outputs; 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\\n(%s)", > + dst_filter_ctx->name, > + dst_filter_ctx->filter->name); > + > + av_bprintf(buf, "\"%s\" -> \"%s\" [ label= \"inpad:%s -> > outpad:%s\\n", > + filter_ctx_label, dst_filter_ctx_label, > + avfilter_pad_get_name(link->srcpad, 0), > + avfilter_pad_get_name(link->dstpad, 0)); > + > + if (link->type == AVMEDIA_TYPE_VIDEO) { > + const AVPixFmtDescriptor *desc = > av_pix_fmt_desc_get(link->format); > + av_bprintf(buf, > + "fmt:%s w:%d h:%d tb:%d/%d", > + desc->name, > + link->w, link->h, > + link->time_base.num, link->time_base.den); > + } else if (link->type == AVMEDIA_TYPE_AUDIO) { > + char audio_buf[255]; > + av_get_channel_layout_string(audio_buf, > sizeof(audio_buf), -1, > + link->channel_layout); > + av_bprintf(buf, > + "fmt:%s sr:%d cl:%s tb:%d/%d", > + av_get_sample_fmt_name(link->format), > + link->sample_rate, audio_buf, > + link->time_base.num, link->time_base.den); > + } > + av_bprintf(buf, "\" ];\n"); > + } > + } > + } > + av_bprintf(buf, "}\n"); > +} > + > char *avfilter_graph_dump(AVFilterGraph *graph, const char *options) > { > AVBPrint buf; > char *dump = NULL; > + int ret; > + AVDictionary *dict = NULL; > + AVDictionaryEntry *format = NULL; > + AVDictionaryEntry *filename = NULL; > + > + ret = av_dict_parse_string(&dict, options, "=", ":", 0); > + if (ret < 0) { > + av_dict_free(&dict); > + return NULL; > + } > + format = av_dict_get(dict, "fmt", NULL, 0); > > + if (format && !av_strcasecmp(format->value, "DOT")) { > + av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); > + avfilter_graph2dot_to_buf(&buf, graph); > + av_bprint_finalize(&buf, &dump); > + } else { > av_bprint_init(&buf, 0, AV_BPRINT_SIZE_COUNT_ONLY); > avfilter_graph_dump_to_buf(&buf, graph); > av_bprint_init(&buf, buf.len + 1, buf.len + 1); > avfilter_graph_dump_to_buf(&buf, graph); > av_bprint_finalize(&buf, &dump); > + } > + > + if (filename = av_dict_get(dict, "filename", NULL, 0)) { > + FILE* file = fopen(filename->value, "w"); > + if (!file) { > + av_log(graph, AV_LOG_ERROR, "failed to open: %s \n", > filename->value); > + av_freep(&dump); > + return NULL; > + } > + if (dump) { > + fputs(dump, file); > + fflush(file); > + } > + fclose(file); > + } > + > + av_dict_free(&dict); > return dump; > } > diff --git a/tools/graph2dot.c b/tools/graph2dot.c > deleted file mode 100644 > index d5c1e4e..0000000 > --- a/tools/graph2dot.c > +++ /dev/null > @@ -1,204 +0,0 @@ > -/* > - * 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 "config.h" > -#if HAVE_UNISTD_H > -#include <unistd.h> /* getopt */ > -#endif > -#include <stdio.h> > -#include <string.h> > - > -#include "libavutil/channel_layout.h" > -#include "libavutil/mem.h" > -#include "libavutil/pixdesc.h" > -#include "libavfilter/avfilter.h" > - > -#if !HAVE_GETOPT > -#include "compat/getopt.c" > -#endif > - > -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->nb_filters; i++) { > - char filter_ctx_label[128]; > - const AVFilterContext *filter_ctx = graph->filters[i]; > - > - snprintf(filter_ctx_label, sizeof(filter_ctx_label), "%s\\n(%s)", > - filter_ctx->name, > - filter_ctx->filter->name); > - > - for (j = 0; j < filter_ctx->nb_outputs; 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\\n(%s)", > - dst_filter_ctx->name, > - dst_filter_ctx->filter->name); > - > - fprintf(outfile, "\"%s\" -> \"%s\" [ label= \"inpad:%s -> > outpad:%s\\n", > - filter_ctx_label, dst_filter_ctx_label, > - avfilter_pad_get_name(link->srcpad, 0), > - avfilter_pad_get_name(link->dstpad, 0)); > - > - if (link->type == AVMEDIA_TYPE_VIDEO) { > - const AVPixFmtDescriptor *desc = > av_pix_fmt_desc_get(link->format); > - fprintf(outfile, > - "fmt:%s w:%d h:%d tb:%d/%d", > - desc->name, > - link->w, link->h, > - link->time_base.num, link->time_base.den); > - } else if (link->type == AVMEDIA_TYPE_AUDIO) { > - char buf[255]; > - av_get_channel_layout_string(buf, sizeof(buf), -1, > - link->channel_layout); > - fprintf(outfile, > - "fmt:%s sr:%d cl:%s tb:%d/%d", > - av_get_sample_fmt_name(link->format), > - link->sample_rate, buf, > - link->time_base.num, link->time_base.den); > - } > - fprintf(outfile, "\" ];\n"); > - } > - } > - } > - 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, "Failed 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, "Failed to open output file '%s': %s\n", > - outfilename, strerror(errno)); > - return 1; > - } > - > - /* read from infile and put it in a buffer */ > - { > - int64_t count = 0; > - struct line *line, *last_line, *first_line; > - char *p; > - last_line = first_line = av_malloc(sizeof(struct line)); > - if (!last_line) { > - fprintf(stderr, "Memory allocation failure\n"); > - return 1; > - } > - > - while (fgets(last_line->data, sizeof(last_line->data), infile)) { > - struct line *new_line = av_malloc(sizeof(struct line)); > - if (!new_line) { > - fprintf(stderr, "Memory allocation failure\n"); > - return 1; > - } > - count += strlen(last_line->data); > - last_line->next = new_line; > - last_line = new_line; > - } > - last_line->next = NULL; > - > - graph_string = av_malloc(count + 1); > - if (!graph_string) { > - fprintf(stderr, "Memory allocation failure\n"); > - return 1; > - } > - p = graph_string; > - for (line = first_line; line->next; line = line->next) { > - size_t l = strlen(line->data); > - memcpy(p, line->data, l); > - p += l; > - } > - *p = '\0'; > - } > - > - if (avfilter_graph_parse(graph, graph_string, NULL, NULL, NULL) < 0) { > - fprintf(stderr, "Failed to parse the graph description\n"); > - return 1; > - } > - > - if (avfilter_graph_config(graph, NULL) < 0) > - return 1; > - > - print_digraph(outfile, graph); > - fflush(outfile); > - > - return 0; > -} > -- > 2.6.4 >
will apply the patchset tomorrow if no further comments. -- Thanks, Limin Wang _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".