This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 60684932fbc76dc4651d788f27e5e7b6ccfc2621
Author:     Andreas Rheinhardt <[email protected]>
AuthorDate: Sun Jun 1 00:13:54 2025 +0200
Commit:     Andreas Rheinhardt <[email protected]>
CommitDate: Wed Jan 7 16:36:07 2026 +0100

    fftools/textformat/avtextformat: Separate mutable and immutable data
    
    Only two fields of AVTextFormatSection are ever modified:
    entries_to_show and show_all_entries (they are only used
    by ffprobe; the graph printing code always prints everything).
    These fields do not belong into AVTextFormatSection, they are
    more ffprobe-internal (and if the graph printing code ever
    made use of them, these fields could very well be
    per GraphPrintContext).
    
    This commit therefore moves them out of AVTextFormatSection
    and adds a callback to AVTextFormatContext to decide which
    elements to discard. This also allows to make the AVTextFormatSections
    const.
    
    This also fixes a race when initializing the sections
    for graphprint.
    
    Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 fftools/ffprobe.c                 | 38 +++++++++++++++++++++++++++++---------
 fftools/graph/graphprint.c        |  9 +--------
 fftools/textformat/avtextformat.c |  9 +++------
 fftools/textformat/avtextformat.h | 13 +++++++++++--
 4 files changed, 44 insertions(+), 25 deletions(-)

diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index ddd5654796..814e591e3c 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -252,7 +252,7 @@ static const char *get_stream_group_type(const void *data)
     return av_x_if_null(avformat_stream_group_name(stg->type), "unknown");
 }
 
-static struct AVTextFormatSection sections[] = {
+static const AVTextFormatSection sections[] = {
     [SECTION_ID_CHAPTERS] =           { SECTION_ID_CHAPTERS, "chapters", 
AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_CHAPTER, -1 } },
     [SECTION_ID_CHAPTER] =            { SECTION_ID_CHAPTER, "chapter", 0, { 
SECTION_ID_CHAPTER_TAGS, -1 } },
     [SECTION_ID_CHAPTER_TAGS] =       { SECTION_ID_CHAPTER_TAGS, "tags", 
AV_TEXTFORMAT_SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", 
.unique_name = "chapter_tags" },
@@ -324,6 +324,13 @@ static struct AVTextFormatSection sections[] = {
     [SECTION_ID_SUBTITLE] =           { SECTION_ID_SUBTITLE, "subtitle", 0, { 
-1 } },
 };
 
+typedef struct EntrySelection {
+    int show_all_entries;
+    AVDictionary *entries_to_show;
+} EntrySelection;
+
+static EntrySelection selected_entries[FF_ARRAY_ELEMS(sections)] = { 0 };
+
 static const OptionDef *options;
 
 /* FFprobe context */
@@ -358,6 +365,14 @@ typedef struct LogBuffer {
 static LogBuffer *log_buffer;
 static int log_buffer_size;
 
+static int is_key_selected_callback(AVTextFormatContext *tctx, const char *key)
+{
+    const AVTextFormatSection *section = tctx->section[tctx->level];
+    const EntrySelection *selection = &selected_entries[section - sections];
+
+    return selection->show_all_entries || 
av_dict_get(selection->entries_to_show, key, NULL, 0);
+}
+
 static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
 {
     AVClass* avc = ptr ? *(AVClass **) ptr : NULL;
@@ -2737,14 +2752,15 @@ static int opt_format(void *optctx, const char *opt, 
const char *arg)
 static inline void mark_section_show_entries(SectionID section_id,
                                              int show_all_entries, 
AVDictionary *entries)
 {
-    struct AVTextFormatSection *section = &sections[section_id];
+    EntrySelection *selection = &selected_entries[section_id];
 
-    section->show_all_entries = show_all_entries;
+    selection->show_all_entries = show_all_entries;
     if (show_all_entries) {
+        const AVTextFormatSection *section = &sections[section_id];
         for (const int *id = section->children_ids; *id != -1; id++)
             mark_section_show_entries(*id, show_all_entries, entries);
     } else {
-        av_dict_copy(&section->entries_to_show, entries, 0);
+        av_dict_copy(&selection->entries_to_show, entries, 0);
     }
 }
 
@@ -3167,9 +3183,12 @@ static const OptionDef real_options[] = {
 
 static inline int check_section_show_entries(int section_id)
 {
-    struct AVTextFormatSection *section = &sections[section_id];
-    if (sections[section_id].show_all_entries || 
sections[section_id].entries_to_show)
+    const EntrySelection *selection = &selected_entries[section_id];
+
+    if (selection->show_all_entries || selection->entries_to_show)
         return 1;
+
+    const AVTextFormatSection *section = &sections[section_id];
     for (const int *id = section->children_ids; *id != -1; id++)
         if (check_section_show_entries(*id))
             return 1;
@@ -3188,7 +3207,7 @@ int main(int argc, char **argv)
     AVTextWriterContext *wctx;
     char *buf;
     char *f_name = NULL, *f_args = NULL;
-    int ret, input_ret, i;
+    int ret, input_ret;
 
     init_dynload();
 
@@ -3282,6 +3301,7 @@ int main(int argc, char **argv)
         goto end;
 
     AVTextFormatOptions tf_options = {
+        .is_key_selected              = is_key_selected_callback,
         .show_optional_fields = show_optional_fields,
         .show_value_unit = show_value_unit,
         .use_value_prefix = use_value_prefix,
@@ -3338,8 +3358,8 @@ end:
     av_freep(&read_intervals);
 
     uninit_opts();
-    for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
-        av_dict_free(&(sections[i].entries_to_show));
+    for (size_t i = 0; i < FF_ARRAY_ELEMS(selected_entries); ++i)
+        av_dict_free(&selected_entries[i].entries_to_show);
 
     avformat_network_deinit();
 
diff --git a/fftools/graph/graphprint.c b/fftools/graph/graphprint.c
index 242eaf8ba1..502632acb3 100644
--- a/fftools/graph/graphprint.c
+++ b/fftools/graph/graphprint.c
@@ -74,7 +74,7 @@ typedef enum {
     SECTION_ID_ENCODER,
 } SectionID;
 
-static struct AVTextFormatSection sections[] = {
+static const AVTextFormatSection sections[] = {
     [SECTION_ID_ROOT]            = { SECTION_ID_ROOT, "root", 
AV_TEXTFORMAT_SECTION_FLAG_IS_WRAPPER, { SECTION_ID_FILTERGRAPHS, 
SECTION_ID_INPUTFILES, SECTION_ID_OUTPUTFILES, SECTION_ID_DECODERS, 
SECTION_ID_ENCODERS, SECTION_ID_STREAMLINKS, -1 } },
 
     [SECTION_ID_FILTERGRAPHS]    = { SECTION_ID_FILTERGRAPHS, "graphs", 
AV_TEXTFORMAT_SECTION_FLAG_IS_ARRAY, { SECTION_ID_FILTERGRAPH, -1 } },
@@ -470,12 +470,6 @@ static void print_filter(GraphPrintContext *gpc, const 
AVFilterContext *filter,
     avtext_print_section_footer(tfc); // SECTION_ID_FILTER
 }
 
-static void init_sections(void)
-{
-    for (unsigned i = 0; i < FF_ARRAY_ELEMS(sections); i++)
-        sections[i].show_all_entries = 1;
-}
-
 static void print_filtergraph_single(GraphPrintContext *gpc, FilterGraph *fg, 
AVFilterGraph *graph)
 {
     AVTextFormatContext *tfc = gpc->tfc;
@@ -876,7 +870,6 @@ static int init_graphprint(GraphPrintContext **pgpc, 
AVBPrint *target_buf)
     GraphPrintContext *gpc = NULL;
     int ret;
 
-    init_sections();
     *pgpc = NULL;
 
     av_bprint_init(target_buf, 0, AV_BPRINT_SIZE_UNLIMITED);
diff --git a/fftools/textformat/avtextformat.c 
b/fftools/textformat/avtextformat.c
index 651a84578c..ac067a2045 100644
--- a/fftools/textformat/avtextformat.c
+++ b/fftools/textformat/avtextformat.c
@@ -147,6 +147,7 @@ int avtext_context_open(AVTextFormatContext **ptctx, const 
AVTextFormatter *form
         goto fail;
     }
 
+    tctx->is_key_selected = options.is_key_selected;
     tctx->show_value_unit = options.show_value_unit;
     tctx->use_value_prefix = options.use_value_prefix;
     tctx->use_byte_value_binary_prefix = options.use_byte_value_binary_prefix;
@@ -289,8 +290,6 @@ void avtext_print_section_footer(AVTextFormatContext *tctx)
 
 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)
@@ -303,9 +302,7 @@ void avtext_print_integer(AVTextFormatContext *tctx, const 
char *key, int64_t va
 
     av_assert0(key && tctx->level >= 0 && tctx->level < SECTION_MAX_NB_LEVELS);
 
-    section = tctx->section[tctx->level];
-
-    if (section->show_all_entries || av_dict_get(section->entries_to_show, 
key, NULL, 0)) {
+    if (!tctx->is_key_selected || tctx->is_key_selected(tctx, key)) {
         tctx->formatter->print_integer(tctx, key, val);
         tctx->nb_item[tctx->level]++;
     }
@@ -460,7 +457,7 @@ int avtext_print_string(AVTextFormatContext *tctx, const 
char *key, const char *
         && !(tctx->formatter->flags & 
AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS))
         return 0;
 
-    if (section->show_all_entries || av_dict_get(section->entries_to_show, 
key, NULL, 0)) {
+    if (!tctx->is_key_selected || tctx->is_key_selected(tctx, key)) {
         if (flags & AV_TEXTFORMAT_PRINT_STRING_VALIDATE) {
             char *key1 = NULL, *val1 = NULL;
             ret = validate_string(tctx, &key1, key);
diff --git a/fftools/textformat/avtextformat.h 
b/fftools/textformat/avtextformat.h
index d9c14069eb..33b06ca360 100644
--- a/fftools/textformat/avtextformat.h
+++ b/fftools/textformat/avtextformat.h
@@ -57,9 +57,7 @@ typedef struct AVTextFormatSection {
     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
-    int show_all_entries;
     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
@@ -131,6 +129,16 @@ struct AVTextFormatContext {
     AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer 
dedicated to each section,
                                                   ///  used by various 
formatters
 
+    /**
+     * Callback to discard certain elements based upon the key used.
+     * It is called before any element with a key is printed.
+     * If this callback is unset, all elements are printed.
+     *
+     * @retval 1 if the element is supposed to be printed
+     * @retval 0 if the element is supposed to be discarded
+     */
+    int (*is_key_selected)(struct AVTextFormatContext *tctx, const char *key);
+
     int show_optional_fields;
     int show_value_unit;
     int use_value_prefix;
@@ -145,6 +153,7 @@ struct AVTextFormatContext {
 };
 
 typedef struct AVTextFormatOptions {
+    int (*is_key_selected)(struct AVTextFormatContext *tctx, const char *key);
     int show_optional_fields;
     int show_value_unit;
     int use_value_prefix;

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to