Browse code

ffprobe: implement subsection field selection through the -show_entries option

Stefano Sabatini authored on 2012/09/18 04:08:09
Showing 3 changed files
... ...
@@ -27,6 +27,7 @@ version <next>:
27 27
 - AST demuxer
28 28
 - new expansion syntax for drawtext
29 29
 - BRender PIX image decoder
30
+- ffprobe -show_entries option
30 31
 
31 32
 
32 33
 version 1.0:
... ...
@@ -133,6 +133,59 @@ Like @option{-show_format}, but only prints the specified entry of the
133 133
 container format information, rather than all. This option may be given more
134 134
 than once, then all specified entries will be shown.
135 135
 
136
+This option is deprecated, use @code{show_entries} instead.
137
+
138
+@item -show_entries @var{section_entries}
139
+Set list of entries to show.
140
+
141
+Entries are specified according to the following
142
+syntax. @var{section_entries} contains a list of section entries
143
+separated by @code{:}. Each section entry is composed by a section
144
+name (or unique name), optionally followed by a list of entries local
145
+to that section, separated by @code{,}.
146
+
147
+If section name is specified but is followed by no @code{=}, all
148
+entries are printed to output, together with all the contained
149
+sections. Otherwise only the entries specified in the local section
150
+entries list are printed. In particular, if @code{=} is specified but
151
+the list of local entries is empty, then no entries will be shown for
152
+that section.
153
+
154
+Note that the order of specification of the local section entries is
155
+not honored in the output, and the usual display order will be
156
+retained.
157
+
158
+The formal syntax is given by:
159
+@example
160
+@var{LOCAL_SECTION_ENTRIES} ::= @var{SECTION_ENTRY_NAME}[,@var{LOCAL_SECTION_ENTRIES}]
161
+@var{SECTION_ENTRY}         ::= @var{SECTION_NAME}[=[@var{LOCAL_SECTION_ENTRIES}]]
162
+@var{SECTION_ENTRIES}       ::= @var{SECTION_ENTRY}[:@var{SECTION_ENTRIES}]
163
+@end example
164
+
165
+For example, to show only the index and type of each stream, and the PTS
166
+time, duration time, and stream index of the packets, you can specify
167
+the argument:
168
+@example
169
+packet=pts_time,duration_time,stream_index : stream=index,codec_type
170
+@end example
171
+
172
+To show all the entries in the section "format", but only the codec
173
+type in the section "stream", specify the argument:
174
+@example
175
+format : stream=codec_type
176
+@end example
177
+
178
+To show all the tags in the stream and format sections:
179
+@example
180
+format_tags : format_tags
181
+@end example
182
+
183
+To show only the @code{title} tag (if available) in the stream
184
+sections:
185
+@example
186
+stream_tags=title
187
+@end example
188
+
136 189
 @item -show_packets
137 190
 Show information about each packet contained in the input multimedia
138 191
 stream.
... ...
@@ -55,9 +55,9 @@ static int do_read_packets = 0;
55 55
 static int do_show_error   = 0;
56 56
 static int do_show_format  = 0;
57 57
 static int do_show_frames  = 0;
58
-static AVDictionary *fmt_entries_to_show = NULL;
59 58
 static int do_show_packets = 0;
60 59
 static int do_show_streams = 0;
60
+static int do_show_stream_disposition = 0;
61 61
 static int do_show_data    = 0;
62 62
 static int do_show_program_version  = 0;
63 63
 static int do_show_library_versions = 0;
... ...
@@ -73,6 +73,8 @@ static char *stream_specifier;
73 73
 
74 74
 /* section structure definition */
75 75
 
76
+#define SECTION_MAX_NB_CHILDREN 10
77
+
76 78
 struct section {
77 79
     int id;             ///< unique id identifying a section
78 80
     const char *name;
... ...
@@ -82,7 +84,11 @@ struct section {
82 82
 #define SECTION_FLAG_HAS_VARIABLE_FIELDS 4 ///< the section may contain a variable number of fields with variable keys.
83 83
                                            ///  For these sections the element_name field is mandatory.
84 84
     int flags;
85
+    int children_ids[SECTION_MAX_NB_CHILDREN+1]; ///< list of children section IDS, terminated by -1
85 86
     const char *element_name; ///< name of the contained element, if provided
87
+    const char *unique_name;  ///< unique section name, in case the name is ambiguous
88
+    AVDictionary *entries_to_show;
89
+    int show_all_entries;
86 90
 };
87 91
 
88 92
 typedef enum {
... ...
@@ -106,24 +112,26 @@ typedef enum {
106 106
     SECTION_ID_STREAM_TAGS,
107 107
 } SectionID;
108 108
 
109
-static const struct section sections[] = {
110
-    [SECTION_ID_ERROR] =              { SECTION_ID_ERROR,              "error" },
111
-    [SECTION_ID_FORMAT] =             { SECTION_ID_FORMAT,             "format" },
112
-    [SECTION_ID_FORMAT_TAGS] =        { SECTION_ID_FORMAT_TAGS,        "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, .element_name = "tag" },
113
-    [SECTION_ID_FRAME] =              { SECTION_ID_FRAME,              "frame" },
114
-    [SECTION_ID_FRAMES] =             { SECTION_ID_FRAMES,             "frames", SECTION_FLAG_IS_ARRAY },
115
-    [SECTION_ID_FRAME_TAGS] =         { SECTION_ID_FRAME_TAGS,         "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, .element_name = "tag" },
116
-    [SECTION_ID_LIBRARY_VERSION] =    { SECTION_ID_LIBRARY_VERSION,    "library_version" },
117
-    [SECTION_ID_LIBRARY_VERSIONS] =   { SECTION_ID_LIBRARY_VERSIONS,   "library_versions", SECTION_FLAG_IS_ARRAY },
118
-    [SECTION_ID_PACKET] =             { SECTION_ID_PACKET,             "packet" },
119
-    [SECTION_ID_PACKETS] =            { SECTION_ID_PACKETS,            "packets", SECTION_FLAG_IS_ARRAY },
120
-    [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", SECTION_FLAG_IS_ARRAY },
121
-    [SECTION_ID_PROGRAM_VERSION] =    { SECTION_ID_PROGRAM_VERSION,    "program_version" },
122
-    [SECTION_ID_ROOT] =               { SECTION_ID_ROOT,               "root", SECTION_FLAG_IS_WRAPPER },
123
-    [SECTION_ID_STREAM] =             { SECTION_ID_STREAM,             "stream" },
124
-    [SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition" },
125
-    [SECTION_ID_STREAMS] =            { SECTION_ID_STREAMS,            "streams", SECTION_FLAG_IS_ARRAY },
126
-    [SECTION_ID_STREAM_TAGS] =        { SECTION_ID_STREAM_TAGS,        "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, .element_name = "tag" },
109
+static struct section sections[] = {
110
+    [SECTION_ID_ERROR] =              { SECTION_ID_ERROR, "error", 0, { -1 } },
111
+    [SECTION_ID_FORMAT] =             { SECTION_ID_FORMAT, "format", 0, { SECTION_ID_FORMAT_TAGS, -1 } },
112
+    [SECTION_ID_FORMAT_TAGS] =        { SECTION_ID_FORMAT_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "format_tags" },
113
+    [SECTION_ID_FRAMES] =             { SECTION_ID_FRAMES, "frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME, -1 } },
114
+    [SECTION_ID_FRAME] =              { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, -1 } },
115
+    [SECTION_ID_FRAME_TAGS] =         { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
116
+    [SECTION_ID_LIBRARY_VERSIONS] =   { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
117
+    [SECTION_ID_LIBRARY_VERSION] =    { SECTION_ID_LIBRARY_VERSION, "library_version", 0, { -1 } },
118
+    [SECTION_ID_PACKETS] =            { SECTION_ID_PACKETS, "packets", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
119
+    [SECTION_ID_PACKETS_AND_FRAMES] = { SECTION_ID_PACKETS_AND_FRAMES, "packets_and_frames", SECTION_FLAG_IS_ARRAY, { SECTION_ID_PACKET, -1} },
120
+    [SECTION_ID_PACKET] =             { SECTION_ID_PACKET, "packet", 0, { -1 } },
121
+    [SECTION_ID_PROGRAM_VERSION] =    { SECTION_ID_PROGRAM_VERSION, "program_version", 0, { -1 } },
122
+    [SECTION_ID_ROOT] =               { SECTION_ID_ROOT, "root", SECTION_FLAG_IS_WRAPPER,
123
+                                        { SECTION_ID_FORMAT, SECTION_ID_FRAMES, SECTION_ID_STREAMS, SECTION_ID_PACKETS,
124
+                                          SECTION_ID_ERROR, SECTION_ID_PROGRAM_VERSION, SECTION_ID_LIBRARY_VERSIONS, -1} },
125
+    [SECTION_ID_STREAMS] =            { SECTION_ID_STREAMS, "streams", SECTION_FLAG_IS_ARRAY, { SECTION_ID_STREAM, -1 } },
126
+    [SECTION_ID_STREAM] =             { SECTION_ID_STREAM, "stream", 0, { SECTION_ID_STREAM_DISPOSITION, SECTION_ID_STREAM_TAGS, -1 } },
127
+    [SECTION_ID_STREAM_DISPOSITION] = { SECTION_ID_STREAM_DISPOSITION, "disposition", 0, { -1 }, .unique_name = "stream_disposition" },
128
+    [SECTION_ID_STREAM_TAGS] =        { SECTION_ID_STREAM_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "stream_tags" },
127 129
 };
128 130
 
129 131
 static const OptionDef *options;
... ...
@@ -146,7 +154,9 @@ static int *selected_streams;
146 146
 
147 147
 static void exit_program(void)
148 148
 {
149
-    av_dict_free(&fmt_entries_to_show);
149
+    int i;
150
+    for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
151
+        av_dict_free(&(sections[i].entries_to_show));
150 152
 }
151 153
 
152 154
 struct unit_value {
... ...
@@ -375,9 +385,9 @@ static inline void writer_print_section_footer(WriterContext *wctx)
375 375
 static inline void writer_print_integer(WriterContext *wctx,
376 376
                                         const char *key, long long int val)
377 377
 {
378
-    if ((wctx->section[wctx->level]->id != SECTION_ID_FORMAT
379
-         && wctx->section[wctx->level]->id != SECTION_ID_FORMAT_TAGS) ||
380
-        !fmt_entries_to_show || av_dict_get(fmt_entries_to_show, key, NULL, 0)) {
378
+    const struct section *section = wctx->section[wctx->level];
379
+
380
+    if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
381 381
         wctx->writer->print_integer(wctx, key, val);
382 382
         wctx->nb_item[wctx->level]++;
383 383
     }
... ...
@@ -386,11 +396,12 @@ static inline void writer_print_integer(WriterContext *wctx,
386 386
 static inline void writer_print_string(WriterContext *wctx,
387 387
                                        const char *key, const char *val, int opt)
388 388
 {
389
+    const struct section *section = wctx->section[wctx->level];
390
+
389 391
     if (opt && !(wctx->writer->flags & WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS))
390 392
         return;
391
-    if ((wctx->section[wctx->level]->id != SECTION_ID_FORMAT
392
-         && wctx->section[wctx->level]->id != SECTION_ID_FORMAT_TAGS) ||
393
-        !fmt_entries_to_show || av_dict_get(fmt_entries_to_show, key, NULL, 0)) {
393
+
394
+    if (section->show_all_entries || av_dict_get(section->entries_to_show, key, NULL, 0)) {
394 395
         wctx->writer->print_string(wctx, key, val);
395 396
         wctx->nb_item[wctx->level]++;
396 397
     }
... ...
@@ -1706,6 +1717,7 @@ static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_i
1706 1706
         print_int(name, !!(stream->disposition & AV_DISPOSITION_##flagname)); \
1707 1707
     } while (0)
1708 1708
 
1709
+    if (do_show_stream_disposition) {
1709 1710
     writer_print_section_header(w, SECTION_ID_STREAM_DISPOSITION);
1710 1711
     PRINT_DISPOSITION(DEFAULT,          "default");
1711 1712
     PRINT_DISPOSITION(DUB,              "dub");
... ...
@@ -1719,6 +1731,7 @@ static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_i
1719 1719
     PRINT_DISPOSITION(CLEAN_EFFECTS,    "clean_effects");
1720 1720
     PRINT_DISPOSITION(ATTACHED_PIC,     "attached_pic");
1721 1721
     writer_print_section_footer(w);
1722
+    }
1722 1723
 
1723 1724
     show_tags(w, stream->metadata, SECTION_ID_STREAM_TAGS);
1724 1725
 
... ...
@@ -1958,11 +1971,100 @@ static int opt_format(void *optctx, const char *opt, const char *arg)
1958 1958
     return 0;
1959 1959
 }
1960 1960
 
1961
+static inline void mark_section_show_entries(SectionID section_id,
1962
+                                             int show_all_entries, AVDictionary *entries)
1963
+{
1964
+    struct section *section = &sections[section_id];
1965
+
1966
+    section->show_all_entries = show_all_entries;
1967
+    if (show_all_entries) {
1968
+        SectionID *id;
1969
+        for (id = section->children_ids; *id != -1; id++)
1970
+            mark_section_show_entries(*id, show_all_entries, entries);
1971
+    } else {
1972
+        av_dict_copy(&section->entries_to_show, entries, 0);
1973
+    }
1974
+}
1975
+
1976
+static int match_section(const char *section_name,
1977
+                         int show_all_entries, AVDictionary *entries)
1978
+{
1979
+    int i, ret = 0;
1980
+
1981
+    for (i = 0; i < FF_ARRAY_ELEMS(sections); i++) {
1982
+        const struct section *section = &sections[i];
1983
+        if (!strcmp(section_name, section->name) ||
1984
+            (section->unique_name && !strcmp(section_name, section->unique_name))) {
1985
+            av_log(NULL, AV_LOG_DEBUG,
1986
+                   "'%s' matches section with unique name '%s'\n", section_name,
1987
+                   (char *)av_x_if_null(section->unique_name, section->name));
1988
+            ret++;
1989
+            mark_section_show_entries(section->id, show_all_entries, entries);
1990
+        }
1991
+    }
1992
+    return ret;
1993
+}
1994
+
1995
+static int opt_show_entries(void *optctx, const char *opt, const char *arg)
1996
+{
1997
+    const char *p = arg;
1998
+    int ret = 0;
1999
+
2000
+    while (*p) {
2001
+        AVDictionary *entries = NULL;
2002
+        char *section_name = av_get_token(&p, "=:");
2003
+        int show_all_entries = 0;
2004
+
2005
+        if (!section_name) {
2006
+            av_log(NULL, AV_LOG_ERROR,
2007
+                   "Missing section name for option '%s'\n", opt);
2008
+            return AVERROR(EINVAL);
2009
+        }
2010
+
2011
+        if (*p == '=') {
2012
+            p++;
2013
+            while (*p && *p != ':') {
2014
+                char *entry = av_get_token(&p, ",:");
2015
+                if (!entry)
2016
+                    break;
2017
+                av_log(NULL, AV_LOG_VERBOSE,
2018
+                       "Adding '%s' to the entries to show in section '%s'\n",
2019
+                       entry, section_name);
2020
+                av_dict_set(&entries, entry, "", AV_DICT_DONT_STRDUP_KEY);
2021
+                if (*p == ',')
2022
+                    p++;
2023
+            }
2024
+        } else {
2025
+            show_all_entries = 1;
2026
+        }
2027
+
2028
+        ret = match_section(section_name, show_all_entries, entries);
2029
+        if (ret == 0) {
2030
+            av_log(NULL, AV_LOG_ERROR, "No match for section '%s'\n", section_name);
2031
+            ret = AVERROR(EINVAL);
2032
+        }
2033
+        av_free(section_name);
2034
+
2035
+        if (ret <= 0)
2036
+            break;
2037
+        if (*p)
2038
+            p++;
2039
+    }
2040
+
2041
+    return ret;
2042
+}
2043
+
1961 2044
 static int opt_show_format_entry(void *optctx, const char *opt, const char *arg)
1962 2045
 {
1963
-    do_show_format = 1;
1964
-    av_dict_set(&fmt_entries_to_show, arg, "", 0);
1965
-    return 0;
2046
+    char *buf = av_asprintf("format=%s", arg);
2047
+    int ret;
2048
+
2049
+    av_log(NULL, AV_LOG_WARNING,
2050
+           "Option '%s' is deprecated, use '-show_entries format=%s' instead\n",
2051
+           opt, arg);
2052
+    ret = opt_show_entries(optctx, opt, buf);
2053
+    av_free(buf);
2054
+    return ret;
1966 2055
 }
1967 2056
 
1968 2057
 static void opt_input_file(void *optctx, const char *arg)
... ...
@@ -2005,11 +2107,26 @@ static int opt_pretty(void *optctx, const char *opt, const char *arg)
2005 2005
 
2006 2006
 static int opt_show_versions(const char *opt, const char *arg)
2007 2007
 {
2008
-    do_show_program_version  = 1;
2009
-    do_show_library_versions = 1;
2008
+    mark_section_show_entries(SECTION_ID_PROGRAM_VERSION, 1, NULL);
2009
+    mark_section_show_entries(SECTION_ID_LIBRARY_VERSION, 1, NULL);
2010 2010
     return 0;
2011 2011
 }
2012 2012
 
2013
+#define DEFINE_OPT_SHOW_SECTION(section, target_section_id)             \
2014
+    static int opt_show_##section(const char *opt, const char *arg)     \
2015
+    {                                                                   \
2016
+        mark_section_show_entries(SECTION_ID_##target_section_id, 1, NULL); \
2017
+        return 0;                                                       \
2018
+    }
2019
+
2020
+DEFINE_OPT_SHOW_SECTION(error,            ERROR);
2021
+DEFINE_OPT_SHOW_SECTION(format,           FORMAT);
2022
+DEFINE_OPT_SHOW_SECTION(frames,           FRAMES);
2023
+DEFINE_OPT_SHOW_SECTION(library_versions, LIBRARY_VERSIONS);
2024
+DEFINE_OPT_SHOW_SECTION(packets,          PACKETS);
2025
+DEFINE_OPT_SHOW_SECTION(program_version,  PROGRAM_VERSION);
2026
+DEFINE_OPT_SHOW_SECTION(streams,          STREAMS);
2027
+
2013 2028
 static const OptionDef real_options[] = {
2014 2029
 #include "cmdutils_common_opts.h"
2015 2030
     { "f", HAS_ARG, {.func_arg = opt_format}, "force format", "format" },
... ...
@@ -2026,17 +2143,19 @@ static const OptionDef real_options[] = {
2026 2026
     { "of", OPT_STRING | HAS_ARG, {(void*)&print_format}, "alias for -print_format", "format" },
2027 2027
     { "select_streams", OPT_STRING | HAS_ARG, {(void*)&stream_specifier}, "select the specified streams", "stream_specifier" },
2028 2028
     { "show_data",    OPT_BOOL, {(void*)&do_show_data}, "show packets data" },
2029
-    { "show_error",   OPT_BOOL, {(void*)&do_show_error} ,  "show probing error" },
2030
-    { "show_format",  OPT_BOOL, {&do_show_format} , "show format/container info" },
2031
-    { "show_frames",  OPT_BOOL, {(void*)&do_show_frames} , "show frames info" },
2029
+    { "show_error",   0, {(void*)&opt_show_error},  "show probing error" },
2030
+    { "show_format",  0, {(void*)&opt_show_format}, "show format/container info" },
2031
+    { "show_frames",  0, {(void*)&opt_show_frames}, "show frames info" },
2032 2032
     { "show_format_entry", HAS_ARG, {.func_arg = opt_show_format_entry},
2033 2033
       "show a particular entry from the format/container info", "entry" },
2034
-    { "show_packets", OPT_BOOL, {&do_show_packets}, "show packets info" },
2035
-    { "show_streams", OPT_BOOL, {&do_show_streams}, "show streams info" },
2034
+    { "show_entries", HAS_ARG, {.func_arg = opt_show_entries},
2035
+      "show a set of specified entries", "entry_list" },
2036
+    { "show_packets", 0, {(void*)&opt_show_packets}, "show packets info" },
2037
+    { "show_streams", 0, {(void*)&opt_show_streams}, "show streams info" },
2036 2038
     { "count_frames", OPT_BOOL, {(void*)&do_count_frames}, "count the number of frames per stream" },
2037 2039
     { "count_packets", OPT_BOOL, {(void*)&do_count_packets}, "count the number of packets per stream" },
2038
-    { "show_program_version",  OPT_BOOL, {(void*)&do_show_program_version},  "show ffprobe version" },
2039
-    { "show_library_versions", OPT_BOOL, {(void*)&do_show_library_versions}, "show library versions" },
2040
+    { "show_program_version",  0, {(void*)&opt_show_program_version},  "show ffprobe version" },
2041
+    { "show_library_versions", 0, {(void*)&opt_show_library_versions}, "show library versions" },
2040 2042
     { "show_versions",         0, {(void*)&opt_show_versions}, "show program and library versions" },
2041 2043
     { "show_private_data", OPT_BOOL, {(void*)&show_private_data}, "show private data" },
2042 2044
     { "private",           OPT_BOOL, {(void*)&show_private_data}, "same as show_private_data" },
... ...
@@ -2046,13 +2165,30 @@ static const OptionDef real_options[] = {
2046 2046
     { NULL, },
2047 2047
 };
2048 2048
 
2049
+static inline int check_section_show_entries(int section_id)
2050
+{
2051
+    int *id;
2052
+    struct section *section = &sections[section_id];
2053
+    if (sections[section_id].show_all_entries || sections[section_id].entries_to_show)
2054
+        return 1;
2055
+    for (id = section->children_ids; *id != -1; id++)
2056
+        if (check_section_show_entries(*id))
2057
+            return 1;
2058
+    return 0;
2059
+}
2060
+
2061
+#define SET_DO_SHOW(id, varname) do {                                   \
2062
+        if (check_section_show_entries(SECTION_ID_##id))                \
2063
+            do_show_##varname = 1;                                      \
2064
+    } while (0)
2065
+
2049 2066
 int main(int argc, char **argv)
2050 2067
 {
2051 2068
     const Writer *w;
2052 2069
     WriterContext *wctx;
2053 2070
     char *buf;
2054 2071
     char *w_name = NULL, *w_args = NULL;
2055
-    int ret;
2072
+    int ret, i;
2056 2073
 
2057 2074
     av_log_set_flags(AV_LOG_SKIP_REPEATED);
2058 2075
     atexit(exit_program);
... ...
@@ -2069,6 +2205,16 @@ int main(int argc, char **argv)
2069 2069
     show_banner(argc, argv, options);
2070 2070
     parse_options(NULL, argc, argv, options, opt_input_file);
2071 2071
 
2072
+    /* mark things to show, based on -show_entries */
2073
+    SET_DO_SHOW(ERROR, error);
2074
+    SET_DO_SHOW(FORMAT, format);
2075
+    SET_DO_SHOW(FRAMES, frames);
2076
+    SET_DO_SHOW(LIBRARY_VERSIONS, library_versions);
2077
+    SET_DO_SHOW(PACKETS, packets);
2078
+    SET_DO_SHOW(PROGRAM_VERSION, program_version);
2079
+    SET_DO_SHOW(STREAMS, streams);
2080
+    SET_DO_SHOW(STREAM_DISPOSITION, stream_disposition);
2081
+
2072 2082
     if (do_bitexact && (do_show_program_version || do_show_library_versions)) {
2073 2083
         av_log(NULL, AV_LOG_ERROR,
2074 2084
                "-bitexact and -show_program_version or -show_library_versions "
... ...
@@ -2125,7 +2271,8 @@ end:
2125 2125
     av_freep(&print_format);
2126 2126
 
2127 2127
     uninit_opts();
2128
-    av_dict_free(&fmt_entries_to_show);
2128
+    for (i = 0; i < FF_ARRAY_ELEMS(sections); i++)
2129
+        av_dict_free(&(sections[i].entries_to_show));
2129 2130
 
2130 2131
     avformat_network_deinit();
2131 2132