FFmpeg
Loading...
Searching...
No Matches
graphprint.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018-2025 - softworkz
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21/**
22 * @file
23 * output writers for filtergraph details
24 */
25
26#include <string.h>
27#include <stdatomic.h>
28
29#include "graphprint.h"
30
31#include "fftools/ffmpeg.h"
32#include "fftools/ffmpeg_mux.h"
33
34#include "libavutil/avassert.h"
35#include "libavutil/avstring.h"
36#include "libavutil/mem.h"
37#include "libavutil/pixdesc.h"
38#include "libavutil/dict.h"
39#include "libavutil/common.h"
41#include "libavutil/buffer.h"
42#include "libavutil/hwcontext.h"
46
77
78static const AVTextFormatSection sections[] = {
80
83
85 [SECTION_ID_GRAPH_INPUT] = { SECTION_ID_GRAPH_INPUT, "graph_input", 0, { -1 }, .id_key = "filter_id" },
86
88 [SECTION_ID_GRAPH_OUTPUT] = { SECTION_ID_GRAPH_OUTPUT, "graph_output", 0, { -1 }, .id_key = "filter_id" },
89
92
94 [SECTION_ID_FILTER_INPUT] = { SECTION_ID_FILTER_INPUT, "filter_input", AV_TEXTFORMAT_SECTION_FLAG_HAS_LINKS, { SECTION_ID_HWFRAMESCONTEXT, -1 }, .id_key = "filter_id", .src_id_key = "source_filter_id", .dest_id_key = "filter_id" },
95
97 [SECTION_ID_FILTER_OUTPUT] = { SECTION_ID_FILTER_OUTPUT, "filter_output", AV_TEXTFORMAT_SECTION_FLAG_HAS_LINKS, { SECTION_ID_HWFRAMESCONTEXT, -1 }, .id_key = "filter_id", .src_id_key = "filter_id", .dest_id_key = "dest_filter_id" },
98
99 [SECTION_ID_HWFRAMESCONTEXT] = { SECTION_ID_HWFRAMESCONTEXT, "hw_frames_context", 0, { -1 }, },
100
103
106
109
112
114 [SECTION_ID_STREAMLINK] = { SECTION_ID_STREAMLINK, "streamlink", AV_TEXTFORMAT_SECTION_FLAG_HAS_LINKS, { -1 }, .src_id_key = "source_stream_id", .dest_id_key = "dest_stream_id" },
115
117 [SECTION_ID_DECODER] = { SECTION_ID_DECODER, "decoder", AV_TEXTFORMAT_SECTION_FLAG_IS_SHAPE | AV_TEXTFORMAT_SECTION_PRINT_TAGS | AV_TEXTFORMAT_SECTION_FLAG_HAS_LINKS, { -1 }, .id_key = "id", .src_id_key = "source_id", .dest_id_key = "id" },
118
120 [SECTION_ID_ENCODER] = { SECTION_ID_ENCODER, "encoder", AV_TEXTFORMAT_SECTION_FLAG_IS_SHAPE | AV_TEXTFORMAT_SECTION_PRINT_TAGS | AV_TEXTFORMAT_SECTION_FLAG_HAS_LINKS, { -1 }, .id_key = "id", .src_id_key = "id", .dest_id_key = "dest_id" },
121};
122
123typedef struct GraphPrintContext {
127 /** record of the print calls, used instead of a formatter context */
128 AVBPrint *rec;
129
135 AVBPrint pbuf;
136
138
146
147static void rec_write(AVBPrint *rec, const void *data, size_t size)
148{
150}
151
152static void rec_write_str(AVBPrint *rec, const char *str)
153{
154 uint32_t len = str ? strlen(str) + 1 : 0;
155
156 rec_write(rec, &len, sizeof(len));
157 if (len)
158 rec_write(rec, str, len);
159}
160
161static int rec_read(const uint8_t **p, const uint8_t *end, void *data, size_t size)
162{
163 if ((size_t)(end - *p) < size)
164 return AVERROR_INVALIDDATA;
165 memcpy(data, *p, size);
166 *p += size;
167 return 0;
168}
169
170static int rec_read_str(const uint8_t **p, const uint8_t *end, const char **str)
171{
172 uint32_t len;
173 int ret = rec_read(p, end, &len, sizeof(len));
174
175 if (ret < 0)
176 return ret;
177 if ((size_t)(end - *p) < len || (len && (*p)[len - 1]))
178 return AVERROR_INVALIDDATA;
179 *str = len ? (const char *)*p : NULL;
180 *p += len;
181 return 0;
182}
183
184static void gp_section_header(const GraphPrintContext *gpc, const AVTextFormatSectionContext *sec_ctx, int section_id)
185{
186 if (gpc->rec) {
187 uint8_t op = GP_OP_SECTION_HEADER, has_ctx = !!sec_ctx;
188 int32_t id = section_id;
189
190 rec_write(gpc->rec, &op, sizeof(op));
191 rec_write(gpc->rec, &id, sizeof(id));
192 rec_write(gpc->rec, &has_ctx, sizeof(has_ctx));
193 if (sec_ctx) {
194 int32_t flags = sec_ctx->context_flags;
195
196 rec_write_str(gpc->rec, sec_ctx->context_id);
197 rec_write_str(gpc->rec, sec_ctx->context_type);
198 rec_write(gpc->rec, &flags, sizeof(flags));
199 }
200 return;
201 }
202 avtext_print_section_header(gpc->tfc, sec_ctx, section_id);
203}
204
206{
207 if (gpc->rec) {
208 uint8_t op = GP_OP_SECTION_FOOTER;
209
210 rec_write(gpc->rec, &op, sizeof(op));
211 return;
212 }
214}
215
216static void gp_print_string(const GraphPrintContext *gpc, const char *key, const char *value, int flags)
217{
218 if (gpc->rec) {
219 uint8_t op = GP_OP_STRING;
220 int32_t f = flags;
221
222 rec_write(gpc->rec, &op, sizeof(op));
223 rec_write(gpc->rec, &f, sizeof(f));
224 rec_write_str(gpc->rec, key);
225 rec_write_str(gpc->rec, value);
226 return;
227 }
229}
230
231static void gp_print_integer(const GraphPrintContext *gpc, const char *key, int64_t value, int flags)
232{
233 if (gpc->rec) {
234 uint8_t op = GP_OP_INTEGER;
235 int32_t f = flags;
236
237 rec_write(gpc->rec, &op, sizeof(op));
238 rec_write(gpc->rec, &f, sizeof(f));
239 rec_write_str(gpc->rec, key);
240 rec_write(gpc->rec, &value, sizeof(value));
241 return;
242 }
244}
245
246static void gp_print_unit_integer(const GraphPrintContext *gpc, const char *key, int64_t value, const char *unit)
247{
248 if (gpc->rec) {
249 uint8_t op = GP_OP_UNIT_INTEGER;
250
251 rec_write(gpc->rec, &op, sizeof(op));
252 rec_write_str(gpc->rec, key);
253 rec_write(gpc->rec, &value, sizeof(value));
254 rec_write_str(gpc->rec, unit);
255 return;
256 }
258}
259
260static void gp_print_rational(const GraphPrintContext *gpc, const char *key, AVRational q, char sep)
261{
262 char buf[44];
263
264 snprintf(buf, sizeof(buf), "%d%c%d", q.num, sep, q.den);
265 gp_print_string(gpc, key, buf, 0);
266}
267
268static int gp_replay(const GraphPrintContext *gpc, const AVBPrint *rec)
269{
270 const uint8_t *p = (const uint8_t *)rec->str;
271 const uint8_t *end = p + FFMIN(rec->len, rec->size - 1);
272 int ret;
273
274 while (p < end) {
275 AVTextFormatSectionContext sec_ctx = { 0 };
276 const char *key, *str;
277 uint8_t op, has_ctx;
280
281 if ((ret = rec_read(&p, end, &op, sizeof(op))) < 0)
282 return ret;
283
284 switch (op) {
286 if ((ret = rec_read(&p, end, &id, sizeof(id))) < 0 ||
287 (ret = rec_read(&p, end, &has_ctx, sizeof(has_ctx))) < 0)
288 return ret;
289 if (has_ctx) {
290 if ((ret = rec_read_str(&p, end, &str)) < 0 ||
291 (ret = rec_read_str(&p, end, &sec_ctx.context_type)) < 0 ||
292 (ret = rec_read(&p, end, &flags, sizeof(flags))) < 0)
293 return ret;
294 sec_ctx.context_id = (char *)str;
295 sec_ctx.context_flags = flags;
296 }
297 avtext_print_section_header(gpc->tfc, has_ctx ? &sec_ctx : NULL, id);
298 break;
301 break;
302 case GP_OP_STRING:
303 if ((ret = rec_read(&p, end, &flags, sizeof(flags))) < 0 ||
304 (ret = rec_read_str(&p, end, &key)) < 0 ||
305 (ret = rec_read_str(&p, end, &str)) < 0)
306 return ret;
307 avtext_print_string(gpc->tfc, key, str, flags);
308 break;
309 case GP_OP_INTEGER:
310 if ((ret = rec_read(&p, end, &flags, sizeof(flags))) < 0 ||
311 (ret = rec_read_str(&p, end, &key)) < 0 ||
312 (ret = rec_read(&p, end, &value, sizeof(value))) < 0)
313 return ret;
315 break;
317 if ((ret = rec_read_str(&p, end, &key)) < 0 ||
318 (ret = rec_read(&p, end, &value, sizeof(value))) < 0 ||
319 (ret = rec_read_str(&p, end, &str)) < 0)
320 return ret;
322 break;
323 default:
324 return AVERROR_INVALIDDATA;
325 }
326 }
327
328 return 0;
329}
330
331/* Text Format API Shortcuts */
332#define print_id(k, v) print_sanizied_id(gpc, k, v, 0)
333#define print_id_noprefix(k, v) print_sanizied_id(gpc, k, v, 1)
334#define print_int(k, v) gp_print_integer(gpc, k, v, 0)
335#define print_int_opt(k, v) gp_print_integer(gpc, k, v, gpc->opt_flags)
336#define print_q(k, v, s) gp_print_rational(gpc, k, v, s)
337#define print_str(k, v) gp_print_string(gpc, k, v, 0)
338#define print_str_opt(k, v) gp_print_string(gpc, k, v, gpc->opt_flags)
339#define print_val(k, v, u) gp_print_unit_integer(gpc, k, v, u)
340
341#define print_fmt(k, f, ...) do { \
342 av_bprint_clear(&gpc->pbuf); \
343 av_bprintf(&gpc->pbuf, f, __VA_ARGS__); \
344 gp_print_string(gpc, k, gpc->pbuf.str, 0); \
345} while (0)
346
347#define print_fmt_opt(k, f, ...) do { \
348 av_bprint_clear(&gpc->pbuf); \
349 av_bprintf(&gpc->pbuf, f, __VA_ARGS__); \
350 gp_print_string(gpc, k, gpc->pbuf.str, gpc->opt_flags); \
351} while (0)
352
353
355
356static inline char *upcase_string(char *dst, size_t dst_size, const char *src)
357{
358 unsigned i;
359 for (i = 0; src[i] && i < dst_size - 1; i++)
360 dst[i] = (char)av_toupper(src[i]);
361 dst[i] = 0;
362 return dst;
363}
364
365static char *get_extension(const char *url)
366{
367 const char *dot = NULL;
368 const char *sep = NULL;
369 const char *end;
370
371 if (!url)
372 return NULL;
373
374 /* Stop at the first query ('?') or fragment ('#') delimiter so they
375 * are not considered part of the path. */
376 end = strpbrk(url, "?#");
377 if (!end)
378 end = url + strlen(url);
379
380 /* Scan the path component only. */
381 for (const char *p = url; p < end; p++) {
382 if (*p == '.')
383 dot = p;
384 else if (*p == '/' || *p == '\\')
385 sep = p;
386 }
387
388 /* Validate that we have a proper extension. */
389 if (dot && dot != url && (!sep || dot > sep + 1) && (dot + 1) < end) {
390 /* Use FFmpeg helper to duplicate the substring. */
391 return av_strndup(dot + 1, end - (dot + 1));
392 }
393
394 return NULL;
395}
396
397static void print_hwdevicecontext(const GraphPrintContext *gpc, const AVHWDeviceContext *hw_device_context)
398{
399
400 if (!hw_device_context)
401 return;
402
403 print_int_opt("has_hw_device_context", 1);
404 print_str_opt("hw_device_type", av_hwdevice_get_type_name(hw_device_context->type));
405}
406
407static void print_hwframescontext(const GraphPrintContext *gpc, const AVHWFramesContext *hw_frames_context)
408{
409 const AVPixFmtDescriptor *pix_desc_hw;
410 const AVPixFmtDescriptor *pix_desc_sw;
411
412 if (!hw_frames_context || !hw_frames_context->device_ctx)
413 return;
414
416
417 print_int_opt("has_hw_frames_context", 1);
418 print_str("hw_device_type", av_hwdevice_get_type_name(hw_frames_context->device_ctx->type));
419
420 pix_desc_hw = av_pix_fmt_desc_get(hw_frames_context->format);
421 if (pix_desc_hw) {
422 print_str("hw_pixel_format", pix_desc_hw->name);
423 if (pix_desc_hw->alias)
424 print_str_opt("hw_pixel_format_alias", pix_desc_hw->alias);
425 }
426
427 pix_desc_sw = av_pix_fmt_desc_get(hw_frames_context->sw_format);
428 if (pix_desc_sw) {
429 print_str("sw_pixel_format", pix_desc_sw->name);
430 if (pix_desc_sw->alias)
431 print_str_opt("sw_pixel_format_alias", pix_desc_sw->alias);
432 }
433
434 print_int_opt("width", hw_frames_context->width);
435 print_int_opt("height", hw_frames_context->height);
436 print_int_opt("initial_pool_size", hw_frames_context->initial_pool_size);
437
438 gp_section_footer(gpc); // SECTION_ID_HWFRAMESCONTEXT
439}
440
442{
443 AVBufferRef *hw_frames_ctx;
444 char layout_string[64];
445
446 if (!link)
447 return;
448
449 hw_frames_ctx = avfilter_link_get_hw_frames_ctx(link);
450
451 print_str_opt("media_type", av_get_media_type_string(link->type));
452
453 switch (link->type) {
455
456 if (hw_frames_ctx && hw_frames_ctx->data) {
457 AVHWFramesContext * hwfctx = (AVHWFramesContext *)hw_frames_ctx->data;
458 const AVPixFmtDescriptor *pix_desc_hw = av_pix_fmt_desc_get(hwfctx->format);
459 const AVPixFmtDescriptor *pix_desc_sw = av_pix_fmt_desc_get(hwfctx->sw_format);
460 if (pix_desc_hw && pix_desc_sw)
461 print_fmt("format", "%s | %s", pix_desc_hw->name, pix_desc_sw->name);
462 } else {
463 print_str("format", av_x_if_null(av_get_pix_fmt_name(link->format), "?"));
464 }
465
466 if (link->w && link->h) {
467 if (gpc->show_value_unit) {
468 print_fmt("size", "%dx%d", link->w, link->h);
469 } else {
470 print_int("width", link->w);
471 print_int("height", link->h);
472 }
473 }
474
475 print_q("sar", link->sample_aspect_ratio, ':');
476
478 print_str_opt("color_range", av_color_range_name(link->color_range));
479
481 print_str("color_space", av_color_space_name(link->colorspace));
482 break;
483
485 ////print_str("format", av_x_if_null(av_get_subtitle_fmt_name(link->format), "?"));
486
487 if (link->w && link->h) {
488 if (gpc->show_value_unit) {
489 print_fmt("size", "%dx%d", link->w, link->h);
490 } else {
491 print_int("width", link->w);
492 print_int("height", link->h);
493 }
494 }
495
496 break;
497
499 av_channel_layout_describe(&link->ch_layout, layout_string, sizeof(layout_string));
500 print_str("channel_layout", layout_string);
501 print_val("channels", link->ch_layout.nb_channels, "ch");
502 if (gpc->show_value_unit)
503 print_fmt("sample_rate", "%d.1 kHz", link->sample_rate / 1000);
504 else
505 print_val("sample_rate", link->sample_rate, "Hz");
506
507 break;
508 }
509
510 print_fmt_opt("sample_rate", "%d/%d", link->time_base.num, link->time_base.den);
511
512 if (hw_frames_ctx && hw_frames_ctx->data)
513 print_hwframescontext(gpc, (AVHWFramesContext *)hw_frames_ctx->data);
514 av_buffer_unref(&hw_frames_ctx);
515}
516
517static char sanitize_char(const char c)
518{
519 if ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
520 return c;
521 return '_';
522}
523
524static void print_sanizied_id(const GraphPrintContext *gpc, const char *key, const char *id_str, int skip_prefix)
525{
526 AVBPrint buf;
527
528 if (!key || !id_str)
529 return;
530
532
533 if (!skip_prefix)
534 av_bprintf(&buf, "G%d_", gpc->id_prefix_num);
535
536 // sanizize section id
537 for (const char *p = id_str; *p; p++)
538 av_bprint_chars(&buf, sanitize_char(*p), 1);
539
540 print_str(key, buf.str);
541
543}
544
545static void print_section_header_id(const GraphPrintContext *gpc, int section_id, const char *id_str, int skip_prefix)
546{
547 AVTextFormatSectionContext sec_ctx = { 0 };
548 AVBPrint buf;
549
550 if (!id_str)
551 return;
552
554
555 if (!skip_prefix)
556 av_bprintf(&buf, "G%d_", gpc->id_prefix_num);
557
558 // sanizize section id
559 for (const char *p = id_str; *p; p++)
560 av_bprint_chars(&buf, sanitize_char(*p), 1);
561
562 sec_ctx.context_id = buf.str;
563
564 gp_section_header(gpc, &sec_ctx, section_id);
565
567}
568
569static const char *get_filterpad_name(const AVFilterPad *pad)
570{
571 return pad ? avfilter_pad_get_name(pad, 0) : "pad";
572}
573
574static void print_filter(GraphPrintContext *gpc, const AVFilterContext *filter, AVDictionary *input_map, AVDictionary *output_map)
575{
576 AVTextFormatSectionContext sec_ctx = { 0 };
577
579
580 ////print_id("filter_id", filter->name);
581
582 if (filter->filter) {
583 print_str("filter_name", filter->filter->name);
584 print_str_opt("description", filter->filter->description);
585 print_int_opt("nb_inputs", filter->nb_inputs);
586 print_int_opt("nb_outputs", filter->nb_outputs);
587 }
588
589 if (filter->hw_device_ctx) {
590 AVHWDeviceContext *device_context = (AVHWDeviceContext *)filter->hw_device_ctx->data;
591 print_hwdevicecontext(gpc, device_context);
592 if (filter->extra_hw_frames > 0)
593 print_int("extra_hw_frames", filter->extra_hw_frames);
594 }
595
597
598 for (unsigned i = 0; i < filter->nb_inputs; i++) {
599 AVDictionaryEntry *dic_entry;
600 AVFilterLink *link = filter->inputs[i];
601
604 sec_ctx.context_type = NULL;
605
606 print_int_opt("input_index", i);
607 print_str_opt("pad_name", get_filterpad_name(link->dstpad));;
608
609 dic_entry = av_dict_get(input_map, link->src->name, NULL, 0);
610 if (dic_entry) {
611 char buf[256];
612 (void)snprintf(buf, sizeof(buf), "in_%s", dic_entry->value);
613 print_id_noprefix("source_filter_id", buf);
614 } else {
615 print_id("source_filter_id", link->src->name);
616 }
617
618 print_str_opt("source_pad_name", get_filterpad_name(link->srcpad));
619 print_id("filter_id", filter->name);
620
621 print_link(gpc, link);
622
623 gp_section_footer(gpc); // SECTION_ID_FILTER_INPUT
624 }
625
626 gp_section_footer(gpc); // SECTION_ID_FILTER_INPUTS
627
629
630 for (unsigned i = 0; i < filter->nb_outputs; i++) {
631 AVDictionaryEntry *dic_entry;
632 AVFilterLink *link = filter->outputs[i];
633 char buf[256];
634
637 sec_ctx.context_type = NULL;
638
639 dic_entry = av_dict_get(output_map, link->dst->name, NULL, 0);
640 if (dic_entry) {
641 (void)snprintf(buf, sizeof(buf), "out_%s", dic_entry->value);
642 print_id_noprefix("dest_filter_id", buf);
643 } else {
644 print_id("dest_filter_id", link->dst->name);
645 }
646
647 print_int_opt("output_index", i);
648 print_str_opt("pad_name", get_filterpad_name(link->srcpad));
649 ////print_id("dest_filter_id", link->dst->name);
650 print_str_opt("dest_pad_name", get_filterpad_name(link->dstpad));
651 print_id("filter_id", filter->name);
652
653 print_link(gpc, link);
654
655 gp_section_footer(gpc); // SECTION_ID_FILTER_OUTPUT
656 }
657
658 gp_section_footer(gpc); // SECTION_ID_FILTER_OUTPUTS
659
660 gp_section_footer(gpc); // SECTION_ID_FILTER
661}
662
664{
665 AVDictionary *input_map = NULL;
666 AVDictionary *output_map = NULL;
667
668 print_int("graph_index", fg->index);
669 print_fmt("name", "Graph %d.%d", gpc->id_prefix_num, fg->index);
670 print_fmt("id", "Graph_%d_%d", gpc->id_prefix_num, fg->index);
671 print_str("description", fg->graph_desc);
672
674
675 for (int i = 0; i < fg->nb_inputs; i++) {
676 InputFilter *ifilter = fg->inputs[i];
677 enum AVMediaType media_type = ifilter->type;
678
680
681 print_int("input_index", ifilter->index);
682
683 if (ifilter->linklabel)
684 print_str("link_label", (const char*)ifilter->linklabel);
685
686 if (ifilter->filter) {
687 print_id("filter_id", ifilter->filter->name);
688 print_str("filter_name", ifilter->filter->filter->name);
689 }
690
691 if (ifilter->linklabel && ifilter->filter)
692 av_dict_set(&input_map, ifilter->filter->name, (const char *)ifilter->linklabel, 0);
693 else if (ifilter->input_name && ifilter->filter)
694 av_dict_set(&input_map, ifilter->filter->name, (const char *)ifilter->input_name, 0);
695
696 print_str("media_type", av_get_media_type_string(media_type));
697
698 gp_section_footer(gpc); // SECTION_ID_GRAPH_INPUT
699 }
700
701 gp_section_footer(gpc); // SECTION_ID_GRAPH_INPUTS
702
704
705 for (int i = 0; i < fg->nb_outputs; i++) {
706 OutputFilter *ofilter = fg->outputs[i];
707
709
710 print_int("output_index", ofilter->index);
711
712 print_str("name", ofilter->output_name);
713
714 if (fg->outputs[i]->linklabel)
715 print_str("link_label", (const char*)fg->outputs[i]->linklabel);
716
717 if (ofilter->filter) {
718 print_id("filter_id", ofilter->filter->name);
719 print_str("filter_name", ofilter->filter->filter->name);
720 }
721
722 if (ofilter->output_name && ofilter->filter)
723 av_dict_set(&output_map, ofilter->filter->name, ofilter->output_name, 0);
724
725
726 print_str("media_type", av_get_media_type_string(ofilter->type));
727
728 gp_section_footer(gpc); // SECTION_ID_GRAPH_OUTPUT
729 }
730
731 gp_section_footer(gpc); // SECTION_ID_GRAPH_OUTPUTS
732
733 if (graph) {
734 AVTextFormatSectionContext sec_ctx = { 0 };
735
736 sec_ctx.context_id = av_asprintf("Graph_%d_%d", gpc->id_prefix_num, fg->index);
737
739
740 if (gpc->is_diagram) {
741 print_fmt("name", "Graph %d.%d", gpc->id_prefix_num, fg->index);
742 print_str("description", fg->graph_desc);
743 print_str("id", sec_ctx.context_id);
744 }
745
746 av_freep(&sec_ctx.context_id);
747
748 for (unsigned i = 0; i < graph->nb_filters; i++) {
749 AVFilterContext *filter = graph->filters[i];
750
751 if (gpc->skip_buffer_filters) {
752 if (av_dict_get(input_map, filter->name, NULL, 0))
753 continue;
754 if (av_dict_get(output_map, filter->name, NULL, 0))
755 continue;
756 }
757
758 sec_ctx.context_id = filter->name;
759
760 print_filter(gpc, filter, input_map, output_map);
761 }
762
763 gp_section_footer(gpc); // SECTION_ID_FILTERS
764 }
765
766 // Clean up dictionaries
767 av_dict_free(&input_map);
768 av_dict_free(&output_map);
769}
770
771static int print_streams(GraphPrintContext *gpc, InputFile **ifiles, int nb_ifiles, OutputFile **ofiles, int nb_ofiles)
772{
773 AVBPrint buf;
774 AVTextFormatSectionContext sec_ctx = { 0 };
775
777
779
780 for (int n = nb_ifiles - 1; n >= 0; n--) {
781 InputFile *ifi = ifiles[n];
782 AVFormatContext *fc = ifi->ctx;
783
784 sec_ctx.context_id = av_asprintf("Input_%d", n);
786 av_freep(&sec_ctx.context_id);
787
788 print_fmt("index", "%d", ifi->index);
789
790 if (fc) {
791 print_str("demuxer_name", fc->iformat->name);
792 if (fc->url) {
793 char *extension = get_extension(fc->url);
794 if (extension) {
795 print_str("file_extension", extension);
796 av_freep(&extension);
797 }
798 print_str("url", fc->url);
799 }
800 }
801
802 sec_ctx.context_id = av_asprintf("InputStreams_%d", n);
803
805
806 av_freep(&sec_ctx.context_id);
807
808 for (int i = 0; i < ifi->nb_streams; i++) {
809 InputStream *ist = ifi->streams[i];
810 const AVCodecDescriptor *codec_desc;
811
812 if (!ist || !ist->par)
813 continue;
814
815 codec_desc = avcodec_descriptor_get(ist->par->codec_id);
816
817 sec_ctx.context_id = av_asprintf("r_in_%d_%d", n, i);
818
820
822 av_freep(&sec_ctx.context_id);
823 sec_ctx.context_type = NULL;
824
825 av_bprint_clear(&buf);
826
827 print_fmt("id", "r_in_%d_%d", n, i);
828
829 if (codec_desc && codec_desc->name) {
830 ////av_bprintf(&buf, "%s", upcase_string(char_buf, sizeof(char_buf), codec_desc->long_name));
831 av_bprintf(&buf, "%s", codec_desc->long_name);
832 } else if (ist->dec) {
833 char char_buf[256];
834 av_bprintf(&buf, "%s", upcase_string(char_buf, sizeof(char_buf), ist->dec->name));
835 } else if (ist->par->codec_type == AVMEDIA_TYPE_ATTACHMENT) {
836 av_bprintf(&buf, "%s", "Attachment");
837 } else if (ist->par->codec_type == AVMEDIA_TYPE_DATA) {
838 av_bprintf(&buf, "%s", "Data");
839 }
840
841 print_fmt("name", "%s", buf.str);
842 print_fmt("index", "%d", ist->index);
843
844 if (ist->dec)
846
847 gp_section_footer(gpc); // SECTION_ID_INPUTSTREAM
848 }
849
850 gp_section_footer(gpc); // SECTION_ID_INPUTSTREAMS
851 gp_section_footer(gpc); // SECTION_ID_INPUTFILE
852 }
853
854 gp_section_footer(gpc); // SECTION_ID_INPUTFILES
855
856
857 print_section_header_id(gpc, SECTION_ID_DECODERS, "Decoders", 0);
858
859 for (int n = 0; n < nb_ifiles; n++) {
860 InputFile *ifi = ifiles[n];
861
862 for (int i = 0; i < ifi->nb_streams; i++) {
863 InputStream *ist = ifi->streams[i];
864
865 if (!ist->decoder)
866 continue;
867
868 sec_ctx.context_id = av_asprintf("in_%d_%d", n, i);
870 sec_ctx.context_flags = 2;
871
873 av_freep(&sec_ctx.context_id);
874 sec_ctx.context_type = NULL;
875 sec_ctx.context_flags = 0;
876
877 av_bprint_clear(&buf);
878
879 print_fmt("source_id", "r_in_%d_%d", n, i);
880 print_fmt("id", "in_%d_%d", n, i);
881
882 ////av_bprintf(&buf, "%s", upcase_string(char_buf, sizeof(char_buf), ist->dec->name));
883 print_fmt("name", "%s", ist->dec->name);
884
886
887 gp_section_footer(gpc); // SECTION_ID_DECODER
888 }
889 }
890
891 gp_section_footer(gpc); // SECTION_ID_DECODERS
892
893
894 print_section_header_id(gpc, SECTION_ID_ENCODERS, "Encoders", 0);
895
896 for (int n = 0; n < nb_ofiles; n++) {
897 OutputFile *of = ofiles[n];
898
899 for (int i = 0; i < of->nb_streams; i++) {
900 OutputStream *ost = of->streams[i];
901 ////const AVCodecDescriptor *codec_desc;
902
903 if (!ost || !ost->st || !ost->st->codecpar || !ost->enc)
904 continue;
905
906 ////codec_desc = avcodec_descriptor_get(ost->st->codecpar->codec_id);
907
908 sec_ctx.context_id = av_asprintf("out__%d_%d", n, i);
910 sec_ctx.context_flags = 2;
911
913 av_freep(&sec_ctx.context_id);
914 sec_ctx.context_type = NULL;
915 sec_ctx.context_flags = 0;
916
917 av_bprint_clear(&buf);
918
919 print_fmt("id", "out__%d_%d", n, i);
920 print_fmt("dest_id", "r_out__%d_%d", n, i);
921
922 print_fmt("name", "%s", ost->enc->enc_ctx->av_class->item_name(ost->enc->enc_ctx));
923
924 print_str_opt("media_type", av_get_media_type_string(ost->type));
925
926 gp_section_footer(gpc); // SECTION_ID_ENCODER
927 }
928 }
929
930 gp_section_footer(gpc); // SECTION_ID_ENCODERS
931
932
934
935 for (int n = nb_ofiles - 1; n >= 0; n--) {
936 OutputFile *of = ofiles[n];
937 Muxer *muxer = (Muxer *)of;
938
939 if (!muxer->fc)
940 continue;
941
942 sec_ctx.context_id = av_asprintf("Output_%d", n);
943
945
946 av_freep(&sec_ctx.context_id);
947
948 ////print_str_opt("index", av_get_media_type_string(of->index));
949 print_fmt("index", "%d", of->index);
950 ////print_str("url", of->url);
951 print_str("muxer_name", muxer->fc->oformat->name);
952 if (of->url) {
953 char *extension = get_extension(of->url);
954 if (extension) {
955 print_str("file_extension", extension);
956 av_freep(&extension);
957 }
958 print_str("url", of->url);
959 }
960
961 sec_ctx.context_id = av_asprintf("OutputStreams_%d", n);
962
964
965 av_freep(&sec_ctx.context_id);
966
967 for (int i = 0; i < of->nb_streams; i++) {
968 OutputStream *ost = of->streams[i];
969 const AVCodecDescriptor *codec_desc = avcodec_descriptor_get(ost->st->codecpar->codec_id);
970
971 sec_ctx.context_id = av_asprintf("r_out__%d_%d", n, i);
974 av_freep(&sec_ctx.context_id);
975 sec_ctx.context_type = NULL;
976
977 av_bprint_clear(&buf);
978
979 print_fmt("id", "r_out__%d_%d", n, i);
980
981 if (codec_desc && codec_desc->name) {
982 av_bprintf(&buf, "%s", codec_desc->long_name);
983 } else {
984 av_bprintf(&buf, "%s", "unknown");
985 }
986
987 print_fmt("name", "%s", buf.str);
988 print_fmt("index", "%d", ost->index);
989
990 print_str_opt("media_type", av_get_media_type_string(ost->type));
991
992 gp_section_footer(gpc); // SECTION_ID_OUTPUTSTREAM
993 }
994
995 gp_section_footer(gpc); // SECTION_ID_OUTPUTSTREAMS
996 gp_section_footer(gpc); // SECTION_ID_OUTPUTFILE
997 }
998
999 gp_section_footer(gpc); // SECTION_ID_OUTPUTFILES
1000
1001
1003
1004 for (int n = 0; n < nb_ofiles; n++) {
1005 OutputFile *of = ofiles[n];
1006
1007 for (int i = 0; i < of->nb_streams; i++) {
1008 OutputStream *ost = of->streams[i];
1009
1010 if (ost->ist && !ost->filter) {
1011 sec_ctx.context_type = av_get_media_type_string(ost->type);
1013 sec_ctx.context_type = NULL;
1014
1015 if (ost->enc) {
1016 print_fmt("dest_stream_id", "out__%d_%d", n, i);
1017 print_fmt("source_stream_id", "in_%d_%d", ost->ist->file->index, ost->ist->index);
1018 print_str("operation", "Transcode");
1019 } else {
1020 print_fmt("dest_stream_id", "r_out__%d_%d", n, i);
1021 print_fmt("source_stream_id", "r_in_%d_%d", ost->ist->file->index, ost->ist->index);
1022 print_str("operation", "Stream Copy");
1023 }
1024
1025 print_str_opt("media_type", av_get_media_type_string(ost->type));
1026
1027 gp_section_footer(gpc); // SECTION_ID_STREAMLINK
1028 }
1029 }
1030 }
1031
1032 gp_section_footer(gpc); // SECTION_ID_STREAMLINKS
1033
1034 av_bprint_finalize(&buf, NULL);
1035 return 0;
1036}
1037
1038
1040{
1041 if (gpc->tfc)
1043
1044 if (gpc->wctx)
1046
1047 // Finalize the print buffer if it was initialized
1049
1050 av_freep(&gpc);
1051}
1052
1053static int init_graphprint(GraphPrintContext **pgpc, AVBPrint *target_buf, int record)
1054{
1055 const AVTextFormatter *text_formatter;
1057 AVTextWriterContext *wctx = NULL;
1058 GraphPrintContext *gpc = NULL;
1059 int ret;
1060
1061 *pgpc = NULL;
1062
1064
1065 const char *w_name = print_graphs_format ? print_graphs_format : "json";
1066
1067 text_formatter = avtext_get_formatter_by_name(w_name);
1068 if (!text_formatter) {
1069 av_log(NULL, AV_LOG_ERROR, "Unknown filter graph output format with name '%s'\n", w_name);
1070 ret = AVERROR(EINVAL);
1071 goto fail;
1072 }
1073
1074 if (!record) {
1075 ret = avtextwriter_create_buffer(&wctx, target_buf);
1076 if (ret < 0) {
1077 av_log(NULL, AV_LOG_ERROR, "avtextwriter_create_buffer failed. Error code %d\n", ret);
1078 ret = AVERROR(EINVAL);
1079 goto fail;
1080 }
1081
1082 AVTextFormatOptions tf_options = { .show_optional_fields = -1 };
1083 const char *w_args = print_graphs_format ? strchr(print_graphs_format, '=') : NULL;
1084 if (w_args)
1085 ++w_args; // consume '='
1086 ret = avtext_context_open(&tfc, text_formatter, wctx, w_args, sections, FF_ARRAY_ELEMS(sections), tf_options, NULL);
1087 if (ret < 0) {
1088 goto fail;
1089 }
1090 }
1091
1092 gpc = av_mallocz(sizeof(GraphPrintContext));
1093 if (!gpc) {
1094 ret = AVERROR(ENOMEM);
1095 goto fail;
1096 }
1097
1098 gpc->wctx = wctx;
1099 gpc->tfc = tfc;
1100 gpc->rec = record ? target_buf : NULL;
1102
1104 gpc->is_diagram = !!(text_formatter->flags & AV_TEXTFORMAT_FLAG_IS_DIAGRAM_FORMATTER);
1105 if (gpc->is_diagram) {
1106 gpc->show_value_unit = 1;
1108 gpc->skip_buffer_filters = 1;
1109 if (tfc) {
1110 tfc->opts.show_value_unit = 1;
1111 tfc->opts.show_optional_fields = -1;
1112 }
1113 ////} else {
1114 //// gpc->opt_flags = AV_TEXTFORMAT_PRINT_STRING_OPTIONAL;
1115 }
1116
1117 if (tfc && (!strcmp(text_formatter->name, "mermaid") || !strcmp(text_formatter->name, "mermaidhtml"))) {
1119
1120 if (!strcmp(text_formatter->name, "mermaidhtml"))
1122
1123 av_diagram_init(tfc, &gpc->diagram_config);
1124 }
1125
1126 *pgpc = gpc;
1127
1128 return 0;
1129
1130fail:
1131 if (tfc)
1133 if (wctx && !tfc) // Only free wctx if tfc didn't take ownership of it
1135 av_freep(&gpc);
1136
1137 return ret;
1138}
1139
1140
1142{
1143 av_assert2(fg);
1144
1145 GraphPrintContext *gpc = NULL;
1146 AVBPrint *target_buf = &fg->graph_print_buf;
1147 int ret;
1148
1149 if (target_buf->len)
1150 av_bprint_finalize(target_buf, NULL);
1151
1152 // Due to the threading model each graph needs to print itself from its own
1153 // thread. The actual printing happens short before cleanup in ffmpeg.c
1154 // where all graphs are assembled together, so the print calls are recorded
1155 // here and replayed there.
1156 ret = init_graphprint(&gpc, target_buf, 1);
1157 if (ret)
1158 return ret;
1159
1161 print_filtergraph_single(gpc, fg, graph);
1162 gp_section_footer(gpc); // SECTION_ID_FILTERGRAPH
1163
1164 uninit_graphprint(gpc);
1165
1166 return 0;
1167}
1168
1169static void print_recorded_graph(const GraphPrintContext *gpc, AVBPrint *graph_buf)
1170{
1171 if (graph_buf->len > 0) {
1172 if (!av_bprint_is_complete(graph_buf))
1173 av_log(NULL, AV_LOG_ERROR, "Incomplete record of a filter graph\n");
1174 else if (gp_replay(gpc, graph_buf) < 0)
1175 av_log(NULL, AV_LOG_ERROR, "Invalid record of a filter graph\n");
1176 av_bprint_finalize(graph_buf, NULL);
1177 }
1178}
1179
1180static int print_filtergraphs_priv(FilterGraph **graphs, int nb_graphs, InputFile **ifiles, int nb_ifiles, OutputFile **ofiles, int nb_ofiles)
1181{
1182 GraphPrintContext *gpc = NULL;
1183 AVBPrint target_buf;
1184 int ret;
1185
1186 ret = init_graphprint(&gpc, &target_buf, 0);
1187 if (ret)
1188 goto cleanup;
1189
1192
1193 for (int i = 0; i < nb_graphs; i++)
1194 print_recorded_graph(gpc, &graphs[i]->graph_print_buf);
1195
1196 for (int n = 0; n < nb_ofiles; n++) {
1197 OutputFile *of = ofiles[n];
1198
1199 for (int i = 0; i < of->nb_streams; i++) {
1200 OutputStream *ost = of->streams[i];
1201
1202 if (ost->fg_simple)
1203 print_recorded_graph(gpc, &ost->fg_simple->graph_print_buf);
1204 }
1205 }
1206
1207 gp_section_footer(gpc); // SECTION_ID_FILTERGRAPHS
1208
1209 print_streams(gpc, ifiles, nb_ifiles, ofiles, nb_ofiles);
1210
1211 gp_section_footer(gpc); // SECTION_ID_ROOT
1212
1213 if (print_graphs_file) {
1214 AVIOContext *avio = NULL;
1215
1216 if (!strcmp(print_graphs_file, "-")) {
1217 printf("%s", target_buf.str);
1218 } else {
1220 if (ret < 0) {
1221 av_log(NULL, AV_LOG_ERROR, "Failed to open graph output file, \"%s\": %s\n", print_graphs_file, av_err2str(ret));
1222 goto cleanup;
1223 }
1224
1225 avio_write(avio, (const unsigned char *)target_buf.str, FFMIN(target_buf.len, target_buf.size - 1));
1226
1227 if ((ret = avio_closep(&avio)) < 0)
1228 av_log(NULL, AV_LOG_ERROR, "Error closing graph output file, loss of information possible: %s\n", av_err2str(ret));
1229 }
1230 }
1231
1232 if (print_graphs)
1233 av_log(NULL, AV_LOG_INFO, "%s %c", target_buf.str, '\n');
1234
1235cleanup:
1236 // Properly clean up resources
1237 if (gpc)
1238 uninit_graphprint(gpc);
1239
1240 // Ensure the target buffer is properly finalized
1241 av_bprint_finalize(&target_buf, NULL);
1242
1243 return ret;
1244}
1245
1246int print_filtergraphs(FilterGraph **graphs, int nb_graphs, InputFile **ifiles, int nb_ifiles, OutputFile **ofiles, int nb_ofiles)
1247{
1248 int ret = print_filtergraphs_priv(graphs, nb_graphs, ifiles, nb_ifiles, ofiles, nb_ofiles);
1250 return ret;
1251}
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:97
int32_t
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition avassert.h:68
Main libavfilter public API header.
int avio_closep(AVIOContext **s)
Close the resource accessed by the AVIOContext *s, free it and set the pointer pointing to it to NULL...
Definition avio.c:724
int avio_open2(AVIOContext **s, const char *filename, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options)
Create and initialize a AVIOContext for accessing the resource indicated by url.
Definition avio.c:566
#define AVIO_FLAG_WRITE
write-only
Definition avio.h:618
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition aviobuf.c:206
char * av_asprintf(const char *fmt,...)
Definition avstring.c:115
void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t val, int flags)
void avtext_print_unit_integer(AVTextFormatContext *tctx, const char *key, int64_t val, AVTextFormatValueFormat fmt, const char *unit)
int avtext_context_open(AVTextFormatContext **ptctx, const AVTextFormatter *formatter, AVTextWriterContext *writer_context, const char *args, const AVTextFormatSection *sections, int nb_sections, AVTextFormatOptions options, char *show_data_hash)
int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags)
int avtext_context_close(AVTextFormatContext **ptctx)
void avtext_print_section_header(AVTextFormatContext *tctx, const void *data, int section_id)
void avtext_print_section_footer(AVTextFormatContext *tctx)
const AVTextFormatter * avtext_get_formatter_by_name(const char *name)
int avtextwriter_context_close(AVTextWriterContext **pwctx)
#define AV_TEXTFORMAT_PRINT_STRING_OPTIONAL
#define AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER
the section only contains other sections, but has no data at its own level
#define AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS
the section may contain a variable number of fields with variable keys.
@ AV_TEXTFORMAT_VALUE_FMT_INT
#define AV_TEXTFORMAT_SECTION_FLAG_HAS_LINKS
...
#define AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY
the section contains an array of elements of the same type
#define AV_TEXTFORMAT_SECTION_FLAG_IS_SHAPE
...
#define AV_TEXTFORMAT_SECTION_FLAG_IS_SUBGRAPH
...
#define AV_TEXTFORMAT_FLAG_IS_DIAGRAM_FORMATTER
#define AV_TEXTFORMAT_SECTION_PRINT_TAGS
...
int avtextwriter_create_buffer(AVTextWriterContext **pwctx, AVBPrint *buffer)
Definition tw_buffer.c:76
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition bprint.c:121
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition bprint.c:68
#define AV_BPRINT_SIZE_UNLIMITED
refcounted data buffer API
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define f(width, name)
Definition cbs_vp8.c:236
common internal and external API header
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
__device__ int printf(const char *,...)
static const uint16_t fc[]
Definition dcaenc.h:43
Public dictionary API.
enum AVCodecID id
Definition dts2pts.c:607
double value
Definition eval.c:102
char * print_graphs_format
Definition ffmpeg_opt.c:79
int print_graphs
Definition ffmpeg_opt.c:77
char * print_graphs_file
Definition ffmpeg_opt.c:78
const char * key
SectionID
Definition ffprobe.c:165
@ SECTION_ID_ROOT
Definition ffprobe.c:226
static const AVTextFormatSection sections[]
Definition ffprobe.c:259
static av_cold void cleanup(FlashSV2Context *s)
static void print_filtergraph_single(GraphPrintContext *gpc, FilterGraph *fg, AVFilterGraph *graph)
Definition graphprint.c:663
@ SECTION_ID_FILTERS
Definition graphprint.c:55
@ SECTION_ID_DECODERS
Definition graphprint.c:72
@ SECTION_ID_STREAMLINKS
Definition graphprint.c:70
@ SECTION_ID_FILTERGRAPHS
Definition graphprint.c:49
@ SECTION_ID_OUTPUTSTREAM
Definition graphprint.c:69
@ SECTION_ID_HWFRAMESCONTEXT
Definition graphprint.c:61
@ SECTION_ID_OUTPUTFILES
Definition graphprint.c:66
@ SECTION_ID_ENCODERS
Definition graphprint.c:74
@ SECTION_ID_FILTER_INPUT
Definition graphprint.c:58
@ SECTION_ID_FILTER_OUTPUT
Definition graphprint.c:60
@ SECTION_ID_GRAPH_OUTPUTS
Definition graphprint.c:53
@ SECTION_ID_INPUTFILE
Definition graphprint.c:63
@ SECTION_ID_OUTPUTFILE
Definition graphprint.c:67
@ SECTION_ID_GRAPH_OUTPUT
Definition graphprint.c:54
@ SECTION_ID_INPUTSTREAM
Definition graphprint.c:65
@ SECTION_ID_DECODER
Definition graphprint.c:73
@ SECTION_ID_STREAMLINK
Definition graphprint.c:71
@ SECTION_ID_ENCODER
Definition graphprint.c:75
@ SECTION_ID_FILTER_OUTPUTS
Definition graphprint.c:59
@ SECTION_ID_GRAPH_INPUT
Definition graphprint.c:52
@ SECTION_ID_INPUTSTREAMS
Definition graphprint.c:64
@ SECTION_ID_INPUTFILES
Definition graphprint.c:62
@ SECTION_ID_FILTER_INPUTS
Definition graphprint.c:57
@ SECTION_ID_GRAPH_INPUTS
Definition graphprint.c:51
@ SECTION_ID_FILTERGRAPH
Definition graphprint.c:50
@ SECTION_ID_FILTER
Definition graphprint.c:56
@ SECTION_ID_OUTPUTSTREAMS
Definition graphprint.c:68
static int print_filtergraphs_priv(FilterGraph **graphs, int nb_graphs, InputFile **ifiles, int nb_ifiles, OutputFile **ofiles, int nb_ofiles)
static int rec_read(const uint8_t **p, const uint8_t *end, void *data, size_t size)
Definition graphprint.c:161
static void print_hwframescontext(const GraphPrintContext *gpc, const AVHWFramesContext *hw_frames_context)
Definition graphprint.c:407
static void print_recorded_graph(const GraphPrintContext *gpc, AVBPrint *graph_buf)
static void print_sanizied_id(const GraphPrintContext *gpc, const char *key, const char *id_str, int skip_prefix)
Definition graphprint.c:524
static int print_streams(GraphPrintContext *gpc, InputFile **ifiles, int nb_ifiles, OutputFile **ofiles, int nb_ofiles)
Definition graphprint.c:771
#define print_int(k, v)
Definition graphprint.c:334
static void gp_print_integer(const GraphPrintContext *gpc, const char *key, int64_t value, int flags)
Definition graphprint.c:231
static void gp_print_unit_integer(const GraphPrintContext *gpc, const char *key, int64_t value, const char *unit)
Definition graphprint.c:246
#define print_int_opt(k, v)
Definition graphprint.c:335
static char * get_extension(const char *url)
Definition graphprint.c:365
static void print_hwdevicecontext(const GraphPrintContext *gpc, const AVHWDeviceContext *hw_device_context)
Definition graphprint.c:397
static const char * get_filterpad_name(const AVFilterPad *pad)
Definition graphprint.c:569
static atomic_int prefix_num
Definition graphprint.c:354
#define print_id_noprefix(k, v)
Definition graphprint.c:333
#define print_str(k, v)
Definition graphprint.c:337
int print_filtergraph(FilterGraph *fg, AVFilterGraph *graph)
#define print_str_opt(k, v)
Definition graphprint.c:338
static void rec_write(AVBPrint *rec, const void *data, size_t size)
Definition graphprint.c:147
#define print_id(k, v)
Definition graphprint.c:332
#define print_val(k, v, u)
Definition graphprint.c:339
static void gp_section_header(const GraphPrintContext *gpc, const AVTextFormatSectionContext *sec_ctx, int section_id)
Definition graphprint.c:184
static void print_filter(GraphPrintContext *gpc, const AVFilterContext *filter, AVDictionary *input_map, AVDictionary *output_map)
Definition graphprint.c:574
static void print_section_header_id(const GraphPrintContext *gpc, int section_id, const char *id_str, int skip_prefix)
Definition graphprint.c:545
#define print_q(k, v, s)
Definition graphprint.c:336
static void rec_write_str(AVBPrint *rec, const char *str)
Definition graphprint.c:152
static int gp_replay(const GraphPrintContext *gpc, const AVBPrint *rec)
Definition graphprint.c:268
GraphPrintOp
Definition graphprint.c:139
@ GP_OP_INTEGER
Definition graphprint.c:143
@ GP_OP_SECTION_HEADER
Definition graphprint.c:140
@ GP_OP_STRING
Definition graphprint.c:142
@ GP_OP_SECTION_FOOTER
Definition graphprint.c:141
@ GP_OP_UNIT_INTEGER
Definition graphprint.c:144
static int rec_read_str(const uint8_t **p, const uint8_t *end, const char **str)
Definition graphprint.c:170
static void gp_print_string(const GraphPrintContext *gpc, const char *key, const char *value, int flags)
Definition graphprint.c:216
static void gp_print_rational(const GraphPrintContext *gpc, const char *key, AVRational q, char sep)
Definition graphprint.c:260
static void print_link(GraphPrintContext *gpc, AVFilterLink *link)
Definition graphprint.c:441
static char * upcase_string(char *dst, size_t dst_size, const char *src)
Definition graphprint.c:356
static void uninit_graphprint(GraphPrintContext *gpc)
static char sanitize_char(const char c)
Definition graphprint.c:517
#define print_fmt_opt(k, f,...)
Definition graphprint.c:347
static void gp_section_footer(const GraphPrintContext *gpc)
Definition graphprint.c:205
int print_filtergraphs(FilterGraph **graphs, int nb_graphs, InputFile **ifiles, int nb_ifiles, OutputFile **ofiles, int nb_ofiles)
#define print_fmt(k, f,...)
Definition graphprint.c:341
static int init_graphprint(GraphPrintContext **pgpc, AVBPrint *target_buf, int record)
#define fail
Definition test.h:479
const AVCodecDescriptor * avcodec_descriptor_get(enum AVCodecID id)
const char * avfilter_pad_get_name(const AVFilterPad *pads, int pad_idx)
Get the name of an AVFilterPad.
Definition avfilter.c:993
AVBufferRef * avfilter_link_get_hw_frames_ctx(AVFilterLink *link)
Get the hardware frames context of a filter link.
Definition avfilter.c:1003
int av_channel_layout_describe(const AVChannelLayout *channel_layout, char *buf, size_t buf_size)
Get a human-readable string describing the channel layout properties.
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition bprint.h:218
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition bprint.c:234
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
Append data to a print buffer.
Definition bprint.c:147
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition bprint.c:129
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition bprint.c:226
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:140
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:233
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition dict.c:60
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition dict.c:86
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition error.h:61
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition error.h:122
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_INFO
Standard information.
Definition log.h:221
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition mem.c:390
const char * av_get_media_type_string(enum AVMediaType media_type)
Return a string describing the media_type enum, NULL if media_type is unknown.
Definition utils.c:28
AVMediaType
Definition avutil.h:198
static void * av_x_if_null(const void *p, const void *x)
Return x default pointer in case p is NULL.
Definition avutil.h:311
@ AVMEDIA_TYPE_ATTACHMENT
Opaque data information usually sparse.
Definition avutil.h:204
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_SUBTITLE
Definition avutil.h:203
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
@ AVMEDIA_TYPE_DATA
Opaque data information usually continuous.
Definition avutil.h:202
static av_const int av_toupper(int c)
Locale-independent conversion of ASCII characters to uppercase.
Definition avstring.h:227
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
Definition hwcontext.c:120
static int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize)
Perform decode operation.
Definition anm.c:76
#define FFMIN(a, b)
Definition macros.h:49
Memory handling functions.
const char data[16]
Definition mxf.c:149
const char * av_color_space_name(enum AVColorSpace space)
Definition pixdesc.c:3884
const char * av_color_range_name(enum AVColorRange range)
Definition pixdesc.c:3800
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition pixdesc.c:3404
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3484
@ AVCOL_RANGE_UNSPECIFIED
Definition pixfmt.h:754
@ AVCOL_SPC_UNSPECIFIED
Definition pixfmt.h:714
char * ff_resman_get_string(FFResourceId resource_id)
Definition resman.c:130
void ff_resman_uninit(void)
Definition resman.c:120
@ FF_RESOURCE_GRAPH_CSS
Definition resman.h:33
@ FF_RESOURCE_GRAPH_HTML
Definition resman.h:34
#define FF_ARRAY_ELEMS(a)
int atomic_int
Definition stdatomic.h:63
#define atomic_fetch_add(object, operand)
Definition stdatomic.h:312
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
int nb_channels
Number of channels in this layout.
This struct describes the properties of a single codec described by an AVCodecID.
Definition codec_desc.h:38
const char * long_name
A more descriptive name for this codec.
Definition codec_desc.h:50
const char * name
Name of the codec described by this descriptor.
Definition codec_desc.h:46
enum AVMediaType codec_type
General type of the encoded data.
Definition codec_par.h:53
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
const char * name
Name of the codec implementation.
Definition codec.h:182
const char * diagram_css
Definition tf_mermaid.h:31
const char * html_template
Definition tf_mermaid.h:32
char * value
Definition dict.h:92
An instance of a filter.
Definition avfilter.h:279
char * name
name of this filter instance
Definition avfilter.h:284
const AVFilter * filter
the AVFilter of which this is an instance
Definition avfilter.h:282
unsigned nb_filters
Definition avfilter.h:575
AVFilterContext ** filters
Definition avfilter.h:574
A filter pad used for either input or output.
Definition filters.h:40
const char * name
Filter name.
Definition avfilter.h:225
Format I/O context.
Definition avformat.h:1337
const struct AVOutputFormat * oformat
The output container format.
Definition avformat.h:1356
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition hwcontext.h:63
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition hwcontext.h:75
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition hwcontext.h:200
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
int initial_pool_size
Initial size of the frame pool.
Definition hwcontext.h:190
int width
The allocated dimensions of the frames in this pool.
Definition hwcontext.h:220
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition hwcontext.h:137
Bytestream IO Context.
Definition avio.h:160
const char * name
Definition avformat.h:529
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
const char * name
Definition pixdesc.h:70
const char * alias
Alternative comma-separated names.
Definition pixdesc.h:110
Rational number (pair of numerator and denominator).
Definition rational.h:58
int num
Numerator.
Definition rational.h:59
int den
Denominator.
Definition rational.h:60
AVTextFormatOptions opts
int flags
a combination or AV_TEXTFORMAT__FLAG_*
const char * name
struct AVBPrint graph_print_buf
Definition ffmpeg.h:417
int index
Definition ffmpeg.h:404
int nb_outputs
Definition ffmpeg.h:409
OutputFilter ** outputs
Definition ffmpeg.h:408
int nb_inputs
Definition ffmpeg.h:407
const char * graph_desc
Definition ffmpeg.h:416
InputFilter ** inputs
Definition ffmpeg.h:406
AVTextWriterContext * wctx
Definition graphprint.c:125
AVBPrint * rec
record of the print calls, used instead of a formatter context
Definition graphprint.c:128
AVTextFormatContext * tfc
Definition graphprint.c:124
AVDiagramConfig diagram_config
Definition graphprint.c:126
AVFormatContext * ctx
Definition ffmpeg.h:516
int index
Definition ffmpeg.h:514
InputStream ** streams
Definition ffmpeg.h:530
int nb_streams
Definition ffmpeg.h:531
AVFilterContext * filter
Definition ffmpeg.h:369
uint8_t * linklabel
Definition ffmpeg.h:375
char * input_name
Definition ffmpeg.h:371
enum AVMediaType type
Definition ffmpeg.h:367
int index
Definition ffmpeg.h:364
int index
Definition ffmpeg.h:474
Decoder * decoder
Definition ffmpeg.h:485
AVCodecParameters * par
Codec parameters - to be used by the decoding/streamcopy code.
Definition ffmpeg.h:484
const AVCodec * dec
Definition ffmpeg.h:486
AVFormatContext * fc
Definition ffmpeg_mux.h:101
int index
Definition ffmpeg.h:693
const char * url
Definition ffmpeg.h:695
OutputStream ** streams
Definition ffmpeg.h:697
int nb_streams
Definition ffmpeg.h:698
AVFilterContext * filter
Definition ffmpeg.h:385
char * output_name
Definition ffmpeg.h:387
uint8_t * linklabel
Definition ffmpeg.h:392
enum AVMediaType type
Definition ffmpeg.h:396
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition h263dsp.c:29
#define src
Definition vp8dsp.c:248
void av_diagram_init(AVTextFormatContext *tfc, AVDiagramConfig *diagram_config)
Definition tf_mermaid.c:170
int size
static AVStream * ost
int len
static double c[64]