2 * Filter graphs to bad ASCII-art
3 * Copyright (c) 2012 Nicolas George
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include "libavutil/channel_layout.h"
25 #include "libavutil/bprint.h"
26 #include "libavutil/mem.h"
27 #include "libavutil/pixdesc.h"
31 static int print_link_prop(AVBPrint
*buf
, AVFilterLink
*link
)
34 AVBPrint dummy_buffer
;
38 av_bprint_init(buf
, 0, AV_BPRINT_SIZE_COUNT_ONLY
);
41 case AVMEDIA_TYPE_VIDEO
:
42 format
= av_x_if_null(av_get_pix_fmt_name(link
->format
), "?");
43 av_bprintf(buf
, "[%dx%d %d:%d %s]", link
->w
, link
->h
,
44 link
->sample_aspect_ratio
.num
,
45 link
->sample_aspect_ratio
.den
,
49 case AVMEDIA_TYPE_AUDIO
:
50 format
= av_x_if_null(av_get_sample_fmt_name(link
->format
), "?");
51 av_bprintf(buf
, "[%dHz %s:",
52 (int)link
->sample_rate
, format
);
53 av_channel_layout_describe_bprint(&link
->ch_layout
, buf
);
54 av_bprint_chars(buf
, ']', 1);
64 static void avfilter_graph_dump_to_buf(AVBPrint
*buf
, AVFilterGraph
*graph
)
68 for (i
= 0; i
< graph
->nb_filters
; i
++) {
69 AVFilterContext
*filter
= graph
->filters
[i
];
70 unsigned max_src_name
= 0, max_dst_name
= 0;
71 unsigned max_in_name
= 0, max_out_name
= 0;
72 unsigned max_in_fmt
= 0, max_out_fmt
= 0;
73 unsigned width
, height
, in_indent
;
74 unsigned lname
= strlen(filter
->name
);
75 unsigned ltype
= strlen(filter
->filter
->name
);
77 for (j
= 0; j
< filter
->nb_inputs
; j
++) {
78 AVFilterLink
*l
= filter
->inputs
[j
];
79 unsigned ln
= strlen(l
->src
->name
) + 1 + strlen(l
->srcpad
->name
);
80 max_src_name
= FFMAX(max_src_name
, ln
);
81 max_in_name
= FFMAX(max_in_name
, strlen(l
->dstpad
->name
));
82 max_in_fmt
= FFMAX(max_in_fmt
, print_link_prop(NULL
, l
));
84 for (j
= 0; j
< filter
->nb_outputs
; j
++) {
85 AVFilterLink
*l
= filter
->outputs
[j
];
86 unsigned ln
= strlen(l
->dst
->name
) + 1 + strlen(l
->dstpad
->name
);
87 max_dst_name
= FFMAX(max_dst_name
, ln
);
88 max_out_name
= FFMAX(max_out_name
, strlen(l
->srcpad
->name
));
89 max_out_fmt
= FFMAX(max_out_fmt
, print_link_prop(NULL
, l
));
91 in_indent
= max_src_name
+ max_in_name
+ max_in_fmt
;
92 in_indent
+= in_indent
? 4 : 0;
93 width
= FFMAX(lname
+ 2, ltype
+ 4);
94 height
= FFMAX3(2, filter
->nb_inputs
, filter
->nb_outputs
);
95 av_bprint_chars(buf
, ' ', in_indent
);
97 av_bprint_chars(buf
, '-', width
);
98 av_bprintf(buf
, "+\n");
99 for (j
= 0; j
< height
; j
++) {
100 unsigned in_no
= j
- (height
- filter
->nb_inputs
) / 2;
101 unsigned out_no
= j
- (height
- filter
->nb_outputs
) / 2;
104 if (in_no
< filter
->nb_inputs
) {
105 AVFilterLink
*l
= filter
->inputs
[in_no
];
106 e
= buf
->len
+ max_src_name
+ 2;
107 av_bprintf(buf
, "%s:%s", l
->src
->name
, l
->srcpad
->name
);
108 av_bprint_chars(buf
, '-', e
- buf
->len
);
109 e
= buf
->len
+ max_in_fmt
+ 2 +
110 max_in_name
- strlen(l
->dstpad
->name
);
111 print_link_prop(buf
, l
);
112 av_bprint_chars(buf
, '-', e
- buf
->len
);
113 av_bprintf(buf
, "%s", l
->dstpad
->name
);
115 av_bprint_chars(buf
, ' ', in_indent
);
119 av_bprintf(buf
, "|");
120 if (j
== (height
- 2) / 2) {
121 x
= (width
- lname
) / 2;
122 av_bprintf(buf
, "%*s%-*s", x
, "", width
- x
, filter
->name
);
123 } else if (j
== (height
- 2) / 2 + 1) {
124 x
= (width
- ltype
- 2) / 2;
125 av_bprintf(buf
, "%*s(%s)%*s", x
, "", filter
->filter
->name
,
126 width
- ltype
- 2 - x
, "");
128 av_bprint_chars(buf
, ' ', width
);
130 av_bprintf(buf
, "|");
133 if (out_no
< filter
->nb_outputs
) {
134 AVFilterLink
*l
= filter
->outputs
[out_no
];
135 unsigned ln
= strlen(l
->dst
->name
) + 1 +
136 strlen(l
->dstpad
->name
);
137 e
= buf
->len
+ max_out_name
+ 2;
138 av_bprintf(buf
, "%s", l
->srcpad
->name
);
139 av_bprint_chars(buf
, '-', e
- buf
->len
);
140 e
= buf
->len
+ max_out_fmt
+ 2 +
142 print_link_prop(buf
, l
);
143 av_bprint_chars(buf
, '-', e
- buf
->len
);
144 av_bprintf(buf
, "%s:%s", l
->dst
->name
, l
->dstpad
->name
);
146 av_bprintf(buf
, "\n");
148 av_bprint_chars(buf
, ' ', in_indent
);
149 av_bprintf(buf
, "+");
150 av_bprint_chars(buf
, '-', width
);
151 av_bprintf(buf
, "+\n");
152 av_bprintf(buf
, "\n");
156 char *avfilter_graph_dump(AVFilterGraph
*graph
, const char *options
)
161 av_bprint_init(&buf
, 0, AV_BPRINT_SIZE_COUNT_ONLY
);
162 avfilter_graph_dump_to_buf(&buf
, graph
);
163 dump
= av_malloc(buf
.len
+ 1);
166 av_bprint_init_for_buffer(&buf
, dump
, buf
.len
+ 1);
167 avfilter_graph_dump_to_buf(&buf
, graph
);