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) V3 == * Fixed all "new warnings" * Fixed out-of-tree building (thanks, Michael) V4 == * Resolved merge conflict * Fixed build on MinGW (missing include due to WIN32_LEAN_AND_MEAN being defined) (thanks, Michael) V5 == * Applied changes as per review from Stefano (thanks!) * Introduced AVTextFormatOptions struct for options in avtext_context_open() V6 == * Fix "new warning" in 2nd last commit * Squash patches 04 and 05 (they weren't truely independent) * Applied changes as per review from Stefano (thanks!) V7 == * Bitten by OOT builds once again (thanks, Michael) V8 == * New commit Remove void (*print_rational) from AVTextFormatter (unused) * New commit fftools/textformat: Rename name param to key for API consistency * print_int Extend existing function instead of adding print_int_flags * Fix registered_formatters[] array size * avtextwriters.h: Remove unused includes * graphprint.c: Make BPrint inits consistent * tf_json: Check nesting level for value printing * And other review suggestions by Stefano (thanks!) . softworkz (15): fftools/textformat: Formatting and whitespace changes fftools/textformat: Apply quality improvements fftools/textformat: Remove unused print_rational() pointer from AVTextFormatter fftools/textformat: Rename name param to key for API consistency fftools/avtextformat: Re-use BPrint in loop fftools/textformat: Introduce AVTextFormatOptions for avtext_context_open() fftools/textformat: Introduce common header and deduplicate code fftools/tf_internal: Use av_default_item_name fftools/textformat: Add flags param to function avtext_print_integer() 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/ffmpeg_mux: Make ms_from_ost() inline 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 | 22 +- fftools/ffmpeg.c | 4 + fftools/ffmpeg.h | 4 + fftools/ffmpeg_filter.c | 195 +---- fftools/ffmpeg_filter.h | 234 ++++++ fftools/ffmpeg_mux.h | 2 +- fftools/ffmpeg_opt.c | 17 + fftools/ffprobe.c | 15 +- fftools/graph/filelauncher.c | 205 +++++ fftools/graph/graphprint.c | 1148 ++++++++++++++++++++++++++++ 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 | 242 +++--- fftools/textformat/avtextformat.h | 78 +- fftools/textformat/avtextwriters.h | 16 +- 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 | 64 +- fftools/textformat/tf_mermaid.c | 658 ++++++++++++++++ fftools/textformat/tf_mermaid.h | 41 + fftools/textformat/tf_xml.c | 68 +- fftools/textformat/tw_avio.c | 18 +- fftools/textformat/tw_buffer.c | 9 +- fftools/textformat/tw_stdout.c | 10 +- libavfilter/avfilter.c | 9 + libavfilter/avfilter.h | 12 + 37 files changed, 3701 insertions(+), 580 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: 25b0a8e295749a60a238ba0d6fe7a3742937b6bb Published-As: https://github.com/ffstaging/FFmpeg/releases/tag/pr-ffstaging-66%2Fsoftworkz%2Fsubmit_print_execution_graph-v8 Fetch-It-Via: git fetch https://github.com/ffstaging/FFmpeg pr-ffstaging-66/softworkz/submit_print_execution_graph-v8 Pull-Request: https://github.com/ffstaging/FFmpeg/pull/66 Range-diff vs v7: 1: b4bb8cdcc6 ! 1: ad156d4853 fftools/textformat: Formatting and whitespace changes @@ fftools/textformat/avtextformat.c: int avtext_context_open(AVTextFormatContext * AVBPrint bp; av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC); - bprint_bytes(&bp, p0, p-p0), -+ 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); +- av_log(tctx, AV_LOG_ERROR, +- "Invalid UTF8 sequence %s found in string validation replace '%s'\n", +- bp.str, tctx->string_validation_replacement); ++ 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; + } + } @@ fftools/textformat/avtextformat.c: fail: } @@ fftools/textformat/avtextformat.c: fail: } -static const AVTextFormatter *registered_formatters[7+1]; -+static const AVTextFormatter *registered_formatters[10 + 1]; ++static const AVTextFormatter *registered_formatters[7 + 1]; + static void formatters_register_all(void) { static int initialized; ## fftools/textformat/avtextformat.h ## +@@ fftools/textformat/avtextformat.h: typedef struct AVTextFormatSection { + #define AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE 16 ///< the items in this array section should be numbered individually by type + + int flags; +- const int children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1 ++ const int children_ids[SECTION_MAX_NB_CHILDREN + 1]; ///< list of children section IDS, terminated by -1 + const char *element_name; ///< name of the contained element, if provided + const char *unique_name; ///< unique section name, in case the name is ambiguous + AVDictionary *entries_to_show; +- const char *(* get_type)(const void *data); ///< function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined ++ const char *(*get_type)(const void *data); ///< function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined + int show_all_entries; + } AVTextFormatSection; + @@ fftools/textformat/avtextformat.h: typedef struct AVTextFormatter { #define SECTION_MAX_NB_SECTIONS 100 2: 1a4044ba23 ! 2: fd59be673d fftools/textformat: Apply quality improvements @@ fftools/textformat/avtextformat.c: int avtext_context_open(AVTextFormatContext * AVTextFormatContext *tctx; int i, ret = 0; -+ if (!ptctx || !formatter) -+ return AVERROR(EINVAL); ++ av_assert0(ptctx && formatter); + if (!(tctx = av_mallocz(sizeof(AVTextFormatContext)))) { ret = AVERROR(ENOMEM); @@ fftools/textformat/avtextformat.c: int avtext_context_open(AVTextFormatContext * while (*p) { const uint8_t *p0 = p; int32_t code; - ret = av_utf8_decode(&code, &p, endp, tctx->string_validation_utf8_flags); - if (ret < 0) { - AVBPrint bp; -- av_bprint_init(&bp, 0, AV_BPRINT_SIZE_AUTOMATIC); -+ av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED); - 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); +@@ fftools/textformat/avtextformat.c: int avtext_context_open(AVTextFormatContext **ptctx, const AVTextFormatter *form + "Invalid UTF8 sequence %s found in string validation replace '%s'\n", + bp.str, tctx->string_validation_replacement); + return ret; + goto fail; } } @@ fftools/textformat/avtextformat.c: static const char unit_bit_per_second_str[] = void avtext_print_section_header(AVTextFormatContext *tctx, const void *data, int section_id) { -+ if (section_id < 0 || section_id >= tctx->nb_sections) ++ if (section_id < 0 || section_id >= tctx->nb_sections) { ++ av_log(tctx, AV_LOG_ERROR, "Invalid section_id for section_header: %d\n", section_id); + return; ++ } + tctx->level++; av_assert0(tctx->level < SECTION_MAX_NB_LEVELS); @@ fftools/textformat/avtextformat.c: void avtext_print_section_header(AVTextFormat void avtext_print_section_footer(AVTextFormatContext *tctx) { -+ if (tctx->level < 0 || tctx->level >= SECTION_MAX_NB_LEVELS) ++ if (tctx->level < 0 || tctx->level >= SECTION_MAX_NB_LEVELS) { ++ av_log(tctx, AV_LOG_ERROR, "Invalid level for section_footer: %d\n", tctx->level); + return; ++ } + int section_id = tctx->section[tctx->level]->id; int parent_section_id = tctx->level @@ 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 = { +@@ fftools/textformat/tw_avio.c: int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_fil + IOWriterContext *ctx; + int ret; - int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_filename) - { + if (!output_filename || !output_filename[0]) { + av_log(NULL, AV_LOG_ERROR, "The output_filename cannot be NULL or empty\n"); + return AVERROR(EINVAL); + } -+ - IOWriterContext *ctx; - int ret; -- ret = avtextwriter_context_open(pwctx, &avtextwriter_avio); if (ret < 0) - return ret; -@@ fftools/textformat/tw_avio.c: int avtextwriter_create_file(AVTextWriterContext **pwctx, const char *output_fil - - int avtextwriter_create_avio(AVTextWriterContext **pwctx, AVIOContext *avio_ctx, int close_on_uninit) - { -+ av_assert0(avio_ctx); -+ +@@ fftools/textformat/tw_avio.c: int avtextwriter_create_avio(AVTextWriterContext **pwctx, AVIOContext *avio_ctx, IOWriterContext *ctx; int ret; ++ av_assert0(avio_ctx); ++ + ret = avtextwriter_context_open(pwctx, &avtextwriter_avio); + if (ret < 0) + return ret; -: ---------- > 3: 4727f424d3 fftools/textformat: Remove unused print_rational() pointer from AVTextFormatter -: ---------- > 4: 43d00310c4 fftools/textformat: Rename name param to key for API consistency 3: 5972ecf213 = 5: 606fa7866a fftools/avtextformat: Re-use BPrint in loop 4: 97ab9e0426 = 6: 95ef1f0919 fftools/textformat: Introduce AVTextFormatOptions for avtext_context_open() 5: 6d1cf2b3fd ! 7: dafd10253d fftools/textformat: Introduce common header and deduplicate code @@ fftools/textformat/tf_json.c: static inline void json_print_item_str(AVTextForma static void json_print_str(AVTextFormatContext *wctx, const char *key, const char *value) { ++ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level); + const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level); JSONContext *json = wctx->priv; - const struct AVTextFormatSection *parent_section = wctx->level ? - wctx->section[wctx->level-1] : NULL; ++ ++ if (!section) ++ return; if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE)) writer_put_str(wctx, json->item_sep); @@ fftools/textformat/tf_json.c: static void json_print_str(AVTextFormatContext *wc static void json_print_int(AVTextFormatContext *wctx, const char *key, int64_t value) { ++ const AVTextFormatSection *section = tf_get_section(wctx, wctx->level); + const AVTextFormatSection *parent_section = tf_get_parent_section(wctx, wctx->level); JSONContext *json = wctx->priv; - const AVTextFormatSection *parent_section = wctx->level ? wctx->section[wctx->level - 1] : NULL; AVBPrint buf; ++ if (!section) ++ return; ++ if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & AV_TEXTFORMAT_SECTION_FLAG_NUMBERING_BY_TYPE)) + writer_put_str(wctx, json->item_sep); + if (!json->compact) @@ fftools/textformat/tf_json.c: const AVTextFormatter avtextformatter_json = { .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT, .priv_class = &json_class, 6: fa22ead3ef = 8: a4b1fb9cc0 fftools/tf_internal: Use av_default_item_name 7: 59dfd3ded6 ! 9: a18ccba001 fftools/textformat: Add function avtext_print_integer_flags() @@ Metadata Author: softworkz <softwo...@hotmail.com> ## Commit message ## - fftools/textformat: Add function avtext_print_integer_flags() + fftools/textformat: Add flags param to function avtext_print_integer() - This function works analog to the avtext_print_string() which already + Make this function work analog to avtext_print_string() which already has a flags parameter. Signed-off-by: softworkz <softwo...@hotmail.com> + ## fftools/ffprobe.c ## +@@ fftools/ffprobe.c: static void log_callback(void *ptr, int level, const char *fmt, va_list vl) + avtext_print_string(tfc, k, pbuf.str, 0); \ + } while (0) + +-#define print_int(k, v) avtext_print_integer(tfc, k, v) ++#define print_int(k, v) avtext_print_integer(tfc, k, v, 0) + #define print_q(k, v, s) avtext_print_rational(tfc, k, v, s) + #define print_str(k, v) avtext_print_string(tfc, k, v, 0) + #define print_str_opt(k, v) avtext_print_string(tfc, k, v, AV_TEXTFORMAT_PRINT_STRING_OPTIONAL) + ## fftools/textformat/avtextformat.c ## -@@ fftools/textformat/avtextformat.c: void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t va - } +@@ fftools/textformat/avtextformat.c: void avtext_print_section_footer(AVTextFormatContext *tctx) + tctx->level--; } -+void avtext_print_integer_flags(AVTextFormatContext *tctx, const char *key, int64_t val, int flags) -+{ +-void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t val) ++void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t val, int flags) + { + const AVTextFormatSection *section; + + av_assert0(tctx); + + if (tctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_NEVER) @@ fftools/textformat/avtextformat.c: void avtext_print_integer(AVTextFormatContext + && !(tctx->formatter->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS)) + return; + -+ avtext_print_integer(tctx, key, val); -+} -+ - static inline int validate_string(AVTextFormatContext *tctx, char **dstp, const char *src) - { - const uint8_t *p, *endp, *srcp = (const uint8_t *)src; + av_assert0(key && tctx->level >= 0 && tctx->level < SECTION_MAX_NB_LEVELS); + + section = tctx->section[tctx->level]; @@ fftools/textformat/avtextformat.c: int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char * section = tctx->section[tctx->level]; @@ fftools/textformat/avtextformat.c: int avtext_print_string(AVTextFormatContext * return 0; if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) { +@@ fftools/textformat/avtextformat.c: void avtext_print_ts(AVTextFormatContext *tctx, const char *key, int64_t ts, int + if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) + avtext_print_string(tctx, key, "N/A", AV_TEXTFORMAT_PRINT_STRING_OPTIONAL); + else +- avtext_print_integer(tctx, key, ts); ++ avtext_print_integer(tctx, key, ts, 0); + } + + void avtext_print_data(AVTextFormatContext *tctx, const char *key, ## fftools/textformat/avtextformat.h ## -@@ fftools/textformat/avtextformat.h: void avtext_print_section_footer(AVTextFormatContext *tctx); +@@ fftools/textformat/avtextformat.h: void avtext_print_section_header(AVTextFormatContext *tctx, const void *data, in - void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t val); + void avtext_print_section_footer(AVTextFormatContext *tctx); + +-void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t val); ++void avtext_print_integer(AVTextFormatContext *tctx, const char *key, int64_t val, int flags); -+void avtext_print_integer_flags(AVTextFormatContext *tctx, const char *key, int64_t val, int flags); -+ int avtext_print_string(AVTextFormatContext *tctx, const char *key, const char *val, int flags); - void avtext_print_unit_int(AVTextFormatContext *tctx, const char *key, int value, const char *unit); 8: 55a704faa5 = 10: 456423f436 fftools/ffmpeg_filter: Move some declaration to new header file 9: b6320cab8c = 11: 07c0d5b09b avfilter/avfilter: Add avfilter_link_get_hw_frames_ctx() 10: 48d36d9df0 = 12: 249899886e fftools/resources: Add resource manager files 11: c4c7340c1d = 13: 58c7b1c142 fftools/ffmpeg_mux: Make ms_from_ost() inline 12: 9cc44e3690 ! 14: 3a090c9e60 fftools/graphprint: Add execution graph printing @@ fftools/graph/graphprint.c (new) +/* Text Format API Shortcuts */ +#define print_id(k, v) print_sanizied_id(gpc, k, v, 0) +#define print_id_noprefix(k, v) print_sanizied_id(gpc, k, v, 1) -+#define print_int(k, v) avtext_print_integer(tfc, k, v) -+#define print_int_opt(k, v) avtext_print_integer_flags(tfc, k, v, gpc->opt_flags) ++#define print_int(k, v) avtext_print_integer(tfc, k, v, 0) ++#define print_int_opt(k, v) avtext_print_integer(tfc, k, v, gpc->opt_flags) +#define print_q(k, v, s) avtext_print_rational(tfc, k, v, s) +#define print_str(k, v) avtext_print_string(tfc, k, v, 0) +#define print_str_opt(k, v) avtext_print_string(tfc, k, v, gpc->opt_flags) @@ fftools/graph/graphprint.c (new) + AVBPrint buf; + AVTextFormatSectionContext sec_ctx = { 0 }; + -+ av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC); ++ av_bprint_init(&buf, 0, AV_BPRINT_SIZE_UNLIMITED); + + print_section_header_id(gpc, SECTION_ID_INPUTFILES, "Inputs", 0); + @@ fftools/graph/graphprint.c (new) + + avtext_print_section_footer(tfc); // SECTION_ID_STREAMLINKS + ++ av_bprint_finalize(&buf, NULL); + return 0; +} + @@ fftools/graph/graphprint.h (new) +#endif /* FFTOOLS_GRAPH_GRAPHPRINT_H */ ## fftools/textformat/avtextformat.c ## +@@ fftools/textformat/avtextformat.c: fail: + return ret; + } + +-static const AVTextFormatter *registered_formatters[7 + 1]; ++static const AVTextFormatter *registered_formatters[9 + 1]; + + static void formatters_register_all(void) + { @@ fftools/textformat/avtextformat.c: static void formatters_register_all(void) registered_formatters[4] = &avtextformatter_ini; registered_formatters[5] = &avtextformatter_json; @@ fftools/textformat/avtextformat.h: typedef struct AVTextFormatSection { +#define AV_TEXTFORMAT_SECTION_FLAG_IS_SUBGRAPH 256 ///< ... int flags; - const int children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1 + const int children_ids[SECTION_MAX_NB_CHILDREN + 1]; ///< list of children section IDS, terminated by -1 @@ fftools/textformat/avtextformat.h: typedef struct AVTextFormatSection { AVDictionary *entries_to_show; - const char *(* get_type)(const void *data); ///< function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined + const char *(*get_type)(const void *data); ///< function returning a type if defined, must be defined when SECTION_FLAG_HAS_TYPE is defined int show_all_entries; -+ const char *id_key; ///< name of the key to be used as the id ++ const char *id_key; ///< name of the key to be used as the id + const char *src_id_key; ///< name of the key to be used as the source id for diagram connections + const char *dest_id_key; ///< name of the key to be used as the target id for diagram connections + const char *linktype_key; ///< name of the key to be used as the link type for diagram connections (AVTextFormatLinkType) 13: 1cb17c6e3b = 15: 578373f8c2 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".