Shortest cover letter for my longest-running FFmpeg patchset: * Apply * Build * Add the "-sg" switch to any FFmpeg command line * Press 'q' when you don't want to wait
SG = Show Graph Documentation and examples can be found here: https://github.com/softworkz/ffmpeg_output_apis/wiki Version Updates =============== V2 == * Rebased on top of Andreas' improvements * Applied changes from review (thanks, Andreas) softworkz (10): fftools/textformat: Formatting and whitespace changes fftools/textformat: Quality improvements fftools/textformat: Introduce common header and deduplicate code fftools/tf_internal: Use ac_default_item_name fftools/textformat: Add function avtext_print_integer_flags() fftools/ffmpeg_filter: Move some declaration to new header file avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx() fftools/resources: Add resource manager files fftools/graphprint: Add execution graph printing fftools/graphprint: Now, make it a Killer-Feature! doc/APIchanges | 3 + doc/ffmpeg.texi | 14 + ffbuild/common.mak | 28 +- fftools/Makefile | 18 + fftools/ffmpeg.c | 4 + fftools/ffmpeg.h | 4 + fftools/ffmpeg_filter.c | 195 +---- fftools/ffmpeg_filter.h | 234 ++++++ fftools/ffmpeg_opt.c | 17 + fftools/graph/filelauncher.c | 204 +++++ fftools/graph/graphprint.c | 1146 ++++++++++++++++++++++++++++ fftools/graph/graphprint.h | 62 ++ fftools/resources/.gitignore | 4 + fftools/resources/Makefile | 27 + fftools/resources/graph.css | 353 +++++++++ fftools/resources/graph.html | 86 +++ fftools/resources/resman.c | 213 ++++++ fftools/resources/resman.h | 50 ++ fftools/textformat/avtextformat.c | 238 +++--- fftools/textformat/avtextformat.h | 53 +- fftools/textformat/avtextwriters.h | 11 +- fftools/textformat/tf_compact.c | 121 +-- fftools/textformat/tf_default.c | 55 +- fftools/textformat/tf_flat.c | 51 +- fftools/textformat/tf_ini.c | 62 +- fftools/textformat/tf_internal.h | 81 ++ fftools/textformat/tf_json.c | 56 +- fftools/textformat/tf_mermaid.c | 655 ++++++++++++++++ fftools/textformat/tf_mermaid.h | 41 + fftools/textformat/tf_xml.c | 68 +- fftools/textformat/tw_avio.c | 16 +- fftools/textformat/tw_buffer.c | 7 +- fftools/textformat/tw_stdout.c | 8 +- libavfilter/avfilter.c | 9 + libavfilter/avfilter.h | 12 + 35 files changed, 3662 insertions(+), 544 deletions(-) create mode 100644 fftools/ffmpeg_filter.h create mode 100644 fftools/graph/filelauncher.c create mode 100644 fftools/graph/graphprint.c create mode 100644 fftools/graph/graphprint.h create mode 100644 fftools/resources/.gitignore create mode 100644 fftools/resources/Makefile create mode 100644 fftools/resources/graph.css create mode 100644 fftools/resources/graph.html create mode 100644 fftools/resources/resman.c create mode 100644 fftools/resources/resman.h create mode 100644 fftools/textformat/tf_internal.h create mode 100644 fftools/textformat/tf_mermaid.c create mode 100644 fftools/textformat/tf_mermaid.h base-commit: a888975a3c25760027cd59932f5c1ad04368db8b Published-As: https://github.com/ffstaging/FFmpeg/releases/tag/pr-ffstaging-66%2Fsoftworkz%2Fsubmit_print_execution_graph-v2 Fetch-It-Via: git fetch https://github.com/ffstaging/FFmpeg pr-ffstaging-66/softworkz/submit_print_execution_graph-v2 Pull-Request: https://github.com/ffstaging/FFmpeg/pull/66 Range-diff vs v1: 1: 3df2018c81 ! 1: b6468d1a30 fftools/textformat: Formatting and whitespace changes @@ fftools/textformat/avtextformat.c: static const char *textcontext_get_formatter_ { NULL } }; -@@ fftools/textformat/avtextformat.c: int avtext_context_close(AVTextFormatContext **ptctx) +@@ fftools/textformat/avtextformat.c: void avtext_context_close(AVTextFormatContext **ptctx) } @@ fftools/textformat/avtextformat.c: int avtext_print_string(AVTextFormatContext * - const char *key, AVRational q, char sep) +void avtext_print_rational(AVTextFormatContext *tctx, const char *key, AVRational q, char sep) { - AVBPrint buf; - av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC); + char buf[44]; + snprintf(buf, sizeof(buf), "%d%c%d", q.num, sep, q.den); @@ fftools/textformat/avtextformat.c: void avtext_print_rational(AVTextFormatContext *tctx, } 2: 04cce91500 ! 2: 6568269678 fftools/textformat: Quality improvements @@ fftools/textformat/avtextformat.c: static const AVClass textcontext_class = { av_bprintf(bp, "%02X", ubuf[i]); } -@@ fftools/textformat/avtextformat.c: int avtext_context_close(AVTextFormatContext **ptctx) - - av_hash_freep(&tctx->hash); - -- av_hash_freep(&tctx->hash); -- - if (tctx->formatter->uninit) - tctx->formatter->uninit(tctx); - for (i = 0; i < SECTION_MAX_NB_LEVELS; i++) @@ fftools/textformat/avtextformat.c: int avtext_context_open(AVTextFormatContext **ptctx, AVTextFormatContext *tctx; int i, ret = 0; @@ fftools/textformat/avtextformat.c: int avtext_context_open(AVTextFormatContext + if (!ptctx || !formatter) + return AVERROR(EINVAL); + -+ if (!formatter->priv_size && formatter->priv_class) -+ return AVERROR(EINVAL); -+ + if (!((tctx = av_mallocz(sizeof(AVTextFormatContext))))) { ret = AVERROR(ENOMEM); goto fail; } - -- if (!(tctx->priv = av_mallocz(formatter->priv_size))) { -+ if (formatter->priv_size && !((tctx->priv = av_mallocz(formatter->priv_size)))) { - ret = AVERROR(ENOMEM); - goto fail; - } @@ fftools/textformat/avtextformat.c: int avtext_context_open(AVTextFormatContext **ptctx, + av_log(NULL, AV_LOG_ERROR, " %s", n); + av_log(NULL, AV_LOG_ERROR, "\n"); + } +- return ret; ++ goto fail; + } /* validate replace string */ { @@ fftools/textformat/avtextformat.c: int avtext_context_open(AVTextFormatContext bprint_bytes(&bp, p0, p - p0), av_log(tctx, AV_LOG_ERROR, "Invalid UTF8 sequence %s found in string validation replace '%s'\n", + bp.str, tctx->string_validation_replacement); +- return ret; ++ av_bprint_finalize(&bp, NULL); ++ goto fail; + } + } + } @@ fftools/textformat/avtextformat.c: static const char unit_bit_per_second_str[] = "bit/s"; void avtext_print_section_header(AVTextFormatContext *tctx, const void *data, int section_id) { -+ if (!tctx || section_id < 0 || section_id >= tctx->nb_sections) ++ if (section_id < 0 || section_id >= tctx->nb_sections) + return; + tctx->level++; @@ fftools/textformat/avtextformat.c: void avtext_print_section_header(AVTextFormat void avtext_print_section_footer(AVTextFormatContext *tctx) { -+ if (!tctx || tctx->level < 0 || tctx->level >= SECTION_MAX_NB_LEVELS) ++ if (tctx->level < 0 || tctx->level >= SECTION_MAX_NB_LEVELS) + return; + int section_id = tctx->section[tctx->level]->id; @@ fftools/textformat/avtextformat.c: void avtext_print_section_footer(AVTextFormat - const struct AVTextFormatSection *section = tctx->section[tctx->level]; + const AVTextFormatSection *section; + -+ if (!tctx || !key || tctx->level < 0 || tctx->level >= SECTION_MAX_NB_LEVELS) ++ if (!key || tctx->level < 0 || tctx->level >= SECTION_MAX_NB_LEVELS) + return; + + section = tctx->section[tctx->level]; @@ fftools/textformat/avtextformat.c: void avtext_print_integer(AVTextFormatContext + AVBPrint bp; int invalid_chars_nb = 0, ret = 0; -+ if (!tctx || !dstp || !src) -+ return AVERROR(EINVAL); -+ + *dstp = NULL; av_bprint_init(&dstbuf, 0, AV_BPRINT_SIZE_UNLIMITED); + av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); @@ fftools/textformat/avtextformat.c: void avtext_print_unit_int(AVTextFormatContex + const AVTextFormatSection *section; int ret = 0; -+ if (!tctx || !key || !val || tctx->level < 0 || tctx->level >= SECTION_MAX_NB_LEVELS) ++ if (!key || !val || tctx->level < 0 || tctx->level >= SECTION_MAX_NB_LEVELS) + return AVERROR(EINVAL); + + section = tctx->section[tctx->level]; @@ fftools/textformat/avtextformat.c: void avtext_print_unit_int(AVTextFormatContex if (tctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_NEVER || (tctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO && (flags & AV_TEXTFORMAT_PRINT_STRING_OPTIONAL) -@@ fftools/textformat/avtextformat.c: int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char * - void avtext_print_rational(AVTextFormatContext *tctx, const char *key, AVRational q, char sep) - { - AVBPrint buf; -- av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC); -+ av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); - av_bprintf(&buf, "%d%c%d", q.num, sep, q.den); - avtext_print_string(tctx, key, buf.str, 0); - } @@ fftools/textformat/avtextformat.c: void avtext_print_rational(AVTextFormatContext *tctx, const char *key, AVRationa void avtext_print_time(AVTextFormatContext *tctx, const char *key, int64_t ts, const AVRational *time_base, int is_duration) @@ fftools/textformat/avtextformat.c: void avtext_print_rational(AVTextFormatContex } else { - double d = ts * av_q2d(*time_base); + char buf[128]; -+ double d = av_q2d(*time_base) * (double)ts; ++ double d = av_q2d(*time_base) * ts; struct unit_value uv; uv.val.d = d; uv.unit = unit_second_str; @@ fftools/textformat/avtextformat.c: int avtextwriter_context_open(AVTextWriterCon + if (!pwctx || !writer) + return AVERROR(EINVAL); + -+ if (!writer->priv_size && writer->priv_class) -+ return AVERROR(EINVAL); -+ + if (!((wctx = av_mallocz(sizeof(AVTextWriterContext))))) { ret = AVERROR(ENOMEM); goto fail; @@ fftools/textformat/tw_avio.c: static void io_w8(AVTextWriterContext *wctx, int b static void io_printf(AVTextWriterContext *wctx, const char *fmt, ...) @@ fftools/textformat/tw_avio.c: const AVTextWriter avtextwriter_avio = { - int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_filename, int close_on_uninit) + int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_filename) { + if (!pwctx || !output_filename || !output_filename[0]) + return AVERROR(EINVAL); 3: 0bd0ec42f1 ! 3: 9e77a447b8 fftools/textformat: Introduce common header and deduplicate code @@ fftools/textformat/avtextwriters.h: typedef struct AVTextWriter { ## fftools/textformat/tf_compact.c ## @@ - #include <string.h> - - #include "avtextformat.h" -+#include "tf_internal.h" - #include <libavutil/mem.h> - #include <libavutil/avassert.h> - #include <libavutil/bprint.h> -@@ - #include <libavutil/opt.h> - - + #include "libavutil/bprint.h" + #include "libavutil/error.h" + #include "libavutil/opt.h" +- +- -#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_) -#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_) -#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__) @@ fftools/textformat/tf_compact.c - .item_name = name##_get_name, \ - .option = name##_options \ -} -- ++#include "tf_internal.h" - /* Compact output */ + /* Compact output */ @@ fftools/textformat/tf_compact.c: static av_cold int compact_init(AVTextFormatContext *wctx) static void compact_print_section_header(AVTextFormatContext *wctx, const void *data) { @@ fftools/textformat/tf_compact.c: static void compact_print_section_header(AVText ## fftools/textformat/tf_default.c ## @@ - #include <string.h> - #include "avtextformat.h" -+#include "tf_internal.h" - #include <libavutil/mem.h> - #include <libavutil/avassert.h> - #include <libavutil/bprint.h> - #include <libavutil/opt.h> - + #include "libavutil/bprint.h" + #include "libavutil/opt.h" +- -#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_) -#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_) -#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__) @@ fftools/textformat/tf_default.c - .item_name = name##_get_name, \ - .option = name##_options \ -} -- ++#include "tf_internal.h" + /* Default output */ - typedef struct DefaultContext { @@ fftools/textformat/tf_default.c: static void default_print_section_header(AVTextFormatContext *wctx, const void * { DefaultContext *def = wctx->priv; @@ fftools/textformat/tf_default.c: static void default_print_section_header(AVText ## fftools/textformat/tf_flat.c ## @@ - #include <string.h> - - #include "avtextformat.h" -+#include "tf_internal.h" - #include <libavutil/mem.h> - #include <libavutil/avassert.h> - #include <libavutil/bprint.h> -@@ - #include <libavutil/macros.h> - #include <libavutil/opt.h> - + #include "libavutil/bprint.h" + #include "libavutil/error.h" + #include "libavutil/opt.h" +- -#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_) -#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_) -#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__) @@ fftools/textformat/tf_flat.c - .option = name##_options \ -} - -- --/* Flat output */ -+ /* Flat output */ ++#include "tf_internal.h" + + /* Flat output */ - typedef struct FlatContext { - const AVClass *class; @@ fftools/textformat/tf_flat.c: static void flat_print_section_header(AVTextFormatContext *wctx, const void *dat { FlatContext *flat = wctx->priv; @@ fftools/textformat/tf_flat.c: static void flat_print_section_header(AVTextFormat ## fftools/textformat/tf_ini.c ## @@ - #include <string.h> - - #include "avtextformat.h" -+#include "tf_internal.h" - #include <libavutil/mem.h> - #include <libavutil/avassert.h> - #include <libavutil/bprint.h> - #include <libavutil/opt.h> + #include "libavutil/bprint.h" + #include "libavutil/opt.h" +- -#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_) -#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_) -#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__) @@ fftools/textformat/tf_ini.c - .item_name = name##_get_name, \ - .option = name##_options \ -} -- ++#include "tf_internal.h" + /* Default output */ - typedef struct DefaultContext { @@ fftools/textformat/tf_ini.c: static void ini_print_section_header(AVTextFormatContext *wctx, const void *data { INIContext *ini = wctx->priv; @@ fftools/textformat/tf_internal.h (new) ## fftools/textformat/tf_json.c ## @@ - #include <string.h> - #include "avtextformat.h" -+#include "tf_internal.h" - #include <libavutil/mem.h> - #include <libavutil/avassert.h> - #include <libavutil/bprint.h> - #include <libavutil/opt.h> - + #include "libavutil/bprint.h" + #include "libavutil/opt.h" +- -#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_) -#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_) -#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__) @@ fftools/textformat/tf_json.c - .option = name##_options \ -} - -- ++#include "tf_internal.h" + /* JSON output */ - typedef struct JSONContext { @@ fftools/textformat/tf_json.c: static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx static void json_print_section_header(AVTextFormatContext *wctx, const void *data) @@ fftools/textformat/tf_json.c: const AVTextFormatter avtextformatter_json = { ## fftools/textformat/tf_xml.c ## @@ - #include <string.h> - - #include "avtextformat.h" -+#include "tf_internal.h" - #include <libavutil/mem.h> - #include <libavutil/avassert.h> - #include <libavutil/bprint.h> -@@ - #include <libavutil/macros.h> - #include <libavutil/opt.h> - + #include "libavutil/bprint.h" + #include "libavutil/error.h" + #include "libavutil/opt.h" +- -#define writer_w8(wctx_, b_) (wctx_)->writer->writer->writer_w8((wctx_)->writer, b_) -#define writer_put_str(wctx_, str_) (wctx_)->writer->writer->writer_put_str((wctx_)->writer, str_) -#define writer_printf(wctx_, fmt_, ...) (wctx_)->writer->writer->writer_printf((wctx_)->writer, fmt_, __VA_ARGS__) @@ fftools/textformat/tf_xml.c - .item_name = name##_get_name, \ - .option = name##_options \ -} -- ++#include "tf_internal.h" + /* XML output */ - typedef struct XMLContext { @@ fftools/textformat/tf_xml.c: static av_cold int xml_init(AVTextFormatContext *wctx) static void xml_print_section_header(AVTextFormatContext *wctx, const void *data) { @@ fftools/textformat/tw_avio.c: static void io_put_str(AVTextWriterContext *wctx, } +@@ fftools/textformat/tw_avio.c: const AVTextWriter avtextwriter_avio = { + + int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_filename) + { +- if (!pwctx || !output_filename || !output_filename[0]) ++ if (!output_filename || !output_filename[0]) + return AVERROR(EINVAL); + + IOWriterContext *ctx; ## fftools/textformat/tw_buffer.c ## @@ fftools/textformat/tw_buffer.c: static void buffer_put_str(AVTextWriterContext *wctx, const char *str) -: ---------- > 4: a1b358f5c5 fftools/tf_internal: Use ac_default_item_name 4: ce1191411c = 5: 4f6870ed4c fftools/textformat: Add function avtext_print_integer_flags() 5: 5e0f818fd3 = 6: 9c03e66aea fftools/ffmpeg_filter: Move some declaration to new header file 6: 4f3db399c6 = 7: eb54476d00 avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx() 7: 898574385f = 8: dac301adba fftools/resources: Add resource manager files 8: 72aa40edd7 = 9: 128ae47177 fftools/graphprint: Add execution graph printing 9: 3a61edc78d = 10: 0f6fd80b25 fftools/graphprint: Now, make it a Killer-Feature! -- ffmpeg-codebot _______________________________________________ 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".