[FFmpeg-devel] [PATCH 3/8] ffprobe/avtextformat: Generalize ffprobe specifics

softworkz ffmpegagent at gmail.com
Thu Feb 27 16:01:35 EET 2025


From: softworkz <softworkz at hotmail.com>

Signed-off-by: softworkz <softworkz at hotmail.com>
---
 fftools/ffprobe.c                   | 34 +++++++++++++++--------------
 libavutil/avtextformat.h            | 13 +++++------
 libavutil/textformat/avtextformat.c | 30 ++++++++++---------------
 3 files changed, 35 insertions(+), 42 deletions(-)

diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 837e21c0e2..5560f6b87e 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -272,7 +272,7 @@ static struct AVTextFormatSection sections[] = {
     [SECTION_ID_LIBRARY_VERSIONS] =   { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
     [SECTION_ID_LIBRARY_VERSION] =    { SECTION_ID_LIBRARY_VERSION, "library_version", 0, { -1 } },
     [SECTION_ID_PACKETS] =            { SECTION_ID_PACKETS, "packets", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
-    [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
+    [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", SECTION_FLAG_IS_ARRAY | SECTION_FLAG_NUMBERING_BY_TYPE, { SECTION_ID_PACKET, -1} },
     [SECTION_ID_PACKET] =             { SECTION_ID_PACKET, "packet", 0, { SECTION_ID_PACKET_TAGS, SECTION_ID_PACKET_SIDE_DATA_LIST, -1 } },
     [SECTION_ID_PACKET_TAGS] =        { SECTION_ID_PACKET_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "packet_tags" },
     [SECTION_ID_PACKET_SIDE_DATA_LIST] ={ SECTION_ID_PACKET_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "packet_side_data_list" },
@@ -547,7 +547,7 @@ static const AVTextFormatter default_formatter = {
     .print_section_footer  = default_print_section_footer,
     .print_integer         = default_print_int,
     .print_string          = default_print_str,
-    .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
+    .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
     .priv_class            = &default_class,
 };
 
@@ -747,7 +747,7 @@ static const AVTextFormatter compact_formatter = {
     .print_section_footer = compact_print_section_footer,
     .print_integer        = compact_print_int,
     .print_string         = compact_print_str,
-    .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
+    .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
     .priv_class           = &compact_class,
 };
 
@@ -778,7 +778,7 @@ static const AVTextFormatter csv_formatter = {
     .print_section_footer = compact_print_section_footer,
     .print_integer        = compact_print_int,
     .print_string         = compact_print_str,
-    .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
+    .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS,
     .priv_class           = &csv_class,
 };
 
@@ -870,8 +870,9 @@ static void flat_print_section_header(AVTextFormatContext *wctx, const void *dat
         av_bprintf(buf, "%s%s", wctx->section[wctx->level]->name, flat->sep_str);
 
         if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
-            int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
-                wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
+            int n = parent_section->flags & SECTION_FLAG_NUMBERING_BY_TYPE ?
+                wctx->nb_item_type[wctx->level-1][section->id] :
+                wctx->nb_item[wctx->level-1];
             av_bprintf(buf, "%d%s", n, flat->sep_str);
         }
     }
@@ -902,7 +903,7 @@ static const AVTextFormatter flat_formatter = {
     .print_section_header  = flat_print_section_header,
     .print_integer         = flat_print_int,
     .print_string          = flat_print_str,
-    .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
+    .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS|AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
     .priv_class            = &flat_class,
 };
 
@@ -974,8 +975,9 @@ static void ini_print_section_header(AVTextFormatContext *wctx, const void *data
         av_bprintf(buf, "%s%s", buf->str[0] ? "." : "", wctx->section[wctx->level]->name);
 
         if (parent_section->flags & SECTION_FLAG_IS_ARRAY) {
-            int n = parent_section->id == SECTION_ID_PACKETS_AND_FRAMES ?
-                wctx->nb_section_packet_frame : wctx->nb_item[wctx->level-1];
+            int n = parent_section->flags & SECTION_FLAG_NUMBERING_BY_TYPE ?
+                wctx->nb_item_type[wctx->level-1][section->id] :
+                wctx->nb_item[wctx->level-1];
             av_bprintf(buf, ".%d", n);
         }
     }
@@ -1006,7 +1008,7 @@ static const AVTextFormatter ini_formatter = {
     .print_section_header  = ini_print_section_header,
     .print_integer         = ini_print_int,
     .print_string          = ini_print_str,
-    .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
+    .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS|AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
     .priv_class            = &ini_class,
 };
 
@@ -1090,7 +1092,7 @@ static void json_print_section_header(AVTextFormatContext *wctx, const void *dat
             writer_printf(wctx, "{%s", json->item_start_end);
 
             /* this is required so the parser can distinguish between packets and frames */
-            if (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES) {
+            if (parent_section && parent_section->flags & SECTION_FLAG_NUMBERING_BY_TYPE) {
                 if (!json->compact)
                     JSON_INDENT();
                 writer_printf(wctx, "\"type\": \"%s\"", section->name);
@@ -1141,7 +1143,7 @@ static void json_print_str(AVTextFormatContext *wctx, const char *key, const cha
     const struct AVTextFormatSection *parent_section = wctx->level ?
         wctx->section[wctx->level-1] : NULL;
 
-    if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
+    if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & SECTION_FLAG_NUMBERING_BY_TYPE))
         writer_put_str(wctx, json->item_sep);
     if (!json->compact)
         JSON_INDENT();
@@ -1155,7 +1157,7 @@ static void json_print_int(AVTextFormatContext *wctx, const char *key, int64_t v
         wctx->section[wctx->level-1] : NULL;
     AVBPrint buf;
 
-    if (wctx->nb_item[wctx->level] || (parent_section && parent_section->id == SECTION_ID_PACKETS_AND_FRAMES))
+    if (wctx->nb_item[wctx->level] || (parent_section && parent_section->flags & SECTION_FLAG_NUMBERING_BY_TYPE))
         writer_put_str(wctx, json->item_sep);
     if (!json->compact)
         JSON_INDENT();
@@ -1173,7 +1175,7 @@ static const AVTextFormatter json_formatter = {
     .print_section_footer = json_print_section_footer,
     .print_integer        = json_print_int,
     .print_string         = json_print_str,
-    .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
+    .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
     .priv_class           = &json_class,
 };
 
@@ -1345,7 +1347,7 @@ static AVTextFormatter xml_formatter = {
     .print_section_footer = xml_print_section_footer,
     .print_integer        = xml_print_int,
     .print_string         = xml_print_str,
-    .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
+    .flags = AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT,
     .priv_class           = &xml_class,
 };
 
@@ -3421,7 +3423,7 @@ static int probe_file(AVTextFormatContext *wctx, const char *filename,
 
     if (do_read_frames || do_read_packets) {
         if (do_show_frames && do_show_packets &&
-            wctx->writer->flags & WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER)
+            wctx->writer->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT)
             section_id = SECTION_ID_PACKETS_AND_FRAMES;
         else if (do_show_packets && !do_show_frames)
             section_id = SECTION_ID_PACKETS;
diff --git a/libavutil/avtextformat.h b/libavutil/avtextformat.h
index e1aa227aff..a7f8055783 100644
--- a/libavutil/avtextformat.h
+++ b/libavutil/avtextformat.h
@@ -42,6 +42,7 @@ struct AVTextFormatSection {
 #define SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
                                            ///  For these sections the element_name field is mandatory.
 #define SECTION_FLAG_HAS_TYPE        8 ///< the section contains a type to distinguish multiple nested elements
+#define 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
@@ -54,8 +55,8 @@ struct AVTextFormatSection {
 
 typedef struct AVTextFormatContext AVTextFormatContext;
 
-#define WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS 1
-#define WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER 2
+#define AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS 1
+#define AV_TEXTFORMAT_FLAG_SUPPORTS_MIXED_ARRAY_CONTENT 2
 
 typedef enum {
     WRITER_STRING_VALIDATION_FAIL,
@@ -80,7 +81,8 @@ typedef struct AVTextFormatter {
     int flags;                  ///< a combination or WRITER_FLAG_*
 } AVTextFormatter;
 
-#define SECTION_MAX_NB_LEVELS 12
+#define SECTION_MAX_NB_LEVELS    12
+#define SECTION_MAX_NB_SECTIONS 100
 
 struct AVTextFormatContext {
     const AVClass *class;           ///< class of the writer
@@ -101,16 +103,13 @@ struct AVTextFormatContext {
 
     /** number of the item printed in the given section, starting from 0 */
     unsigned int nb_item[SECTION_MAX_NB_LEVELS];
+    unsigned int nb_item_type[SECTION_MAX_NB_LEVELS][SECTION_MAX_NB_SECTIONS];
 
     /** section per each level */
     const struct AVTextFormatSection *section[SECTION_MAX_NB_LEVELS];
     AVBPrint section_pbuf[SECTION_MAX_NB_LEVELS]; ///< generic print buffer dedicated to each section,
                                                   ///  used by various writers
 
-    unsigned int nb_section_packet; ///< number of the packet section in case we are in "packets_and_frames" section
-    unsigned int nb_section_frame;  ///< number of the frame  section in case we are in "packets_and_frames" section
-    unsigned int nb_section_packet_frame; ///< nb_section_packet or nb_section_frame according if is_packets_and_frames
-
     int show_optional_fields;
     int show_value_unit;
     int use_value_prefix;
diff --git a/libavutil/textformat/avtextformat.c b/libavutil/textformat/avtextformat.c
index 2b67acae65..a2d87e8d42 100644
--- a/libavutil/textformat/avtextformat.c
+++ b/libavutil/textformat/avtextformat.c
@@ -189,6 +189,11 @@ int avtext_context_open(AVTextFormatContext **pwctx, const AVTextFormatter *writ
     wctx->use_byte_value_binary_prefix = use_byte_value_binary_prefix;
     wctx->use_value_sexagesimal_format = use_value_sexagesimal_format;
     wctx->show_optional_fields = show_optional_fields;
+    
+    if (nb_sections > SECTION_MAX_NB_SECTIONS) {
+        av_log(wctx, AV_LOG_ERROR, "The number of section definitions (%d) is larger than the maximum allowed (%d)\n", nb_sections, SECTION_MAX_NB_SECTIONS);
+        goto fail;
+    }
 
     wctx->class = &textcontext_class;
     wctx->writer = writer;
@@ -293,8 +298,6 @@ fail:
 }
 
 /* Temporary definitions during refactoring */
-#define SECTION_ID_PACKETS_AND_FRAMES     24
-#define SECTION_ID_PACKET                 21
 static const char unit_second_str[]         = "s"    ;
 static const char unit_hertz_str[]          = "Hz"   ;
 static const char unit_byte_str[]           = "byte" ;
@@ -305,23 +308,13 @@ void avtext_print_section_header(AVTextFormatContext *wctx,
                                                const void *data,
                                                int section_id)
 {
-    int parent_section_id;
     wctx->level++;
     av_assert0(wctx->level < SECTION_MAX_NB_LEVELS);
-    parent_section_id = wctx->level ?
-        (wctx->section[wctx->level-1])->id : SECTION_ID_NONE;
 
     wctx->nb_item[wctx->level] = 0;
+    memset(wctx->nb_item_type[wctx->level], 0, sizeof(wctx->nb_item_type[wctx->level]));
     wctx->section[wctx->level] = &wctx->sections[section_id];
 
-    if (section_id == SECTION_ID_PACKETS_AND_FRAMES) {
-        wctx->nb_section_packet = wctx->nb_section_frame =
-        wctx->nb_section_packet_frame = 0;
-    } else if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
-        wctx->nb_section_packet_frame = section_id == SECTION_ID_PACKET ?
-            wctx->nb_section_packet : wctx->nb_section_frame;
-    }
-
     if (wctx->writer->print_section_header)
         wctx->writer->print_section_header(wctx, data);
 }
@@ -332,12 +325,11 @@ void avtext_print_section_footer(AVTextFormatContext *wctx)
     int parent_section_id = wctx->level ?
         wctx->section[wctx->level-1]->id : SECTION_ID_NONE;
 
-    if (parent_section_id != SECTION_ID_NONE)
-        wctx->nb_item[wctx->level-1]++;
-    if (parent_section_id == SECTION_ID_PACKETS_AND_FRAMES) {
-        if (section_id == SECTION_ID_PACKET) wctx->nb_section_packet++;
-        else                                     wctx->nb_section_frame++;
+    if (parent_section_id != SECTION_ID_NONE) {
+        wctx->nb_item[wctx->level - 1]++;
+        wctx->nb_item_type[wctx->level - 1][section_id]++;
     }
+
     if (wctx->writer->print_section_footer)
         wctx->writer->print_section_footer(wctx);
     wctx->level--;
@@ -486,7 +478,7 @@ int avtext_print_string(AVTextFormatContext *wctx, const char *key, const char *
     if (wctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_NEVER ||
         (wctx->show_optional_fields == SHOW_OPTIONAL_FIELDS_AUTO
         && (flags & PRINT_STRING_OPT)
-        && !(wctx->writer->flags & WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS)))
+        && !(wctx->writer->flags & AV_TEXTFORMAT_FLAG_SUPPORTS_OPTIONAL_FIELDS)))
         return 0;
 
     if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
-- 
ffmpeg-codebot



More information about the ffmpeg-devel mailing list