PR #24467 opened by Cuptu URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24467 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24467.patch
`-show_entries stream=...` also matches streams inside groups, enabling group output even when it was not requested. With the MOV timecode groups in `fcp_export8-236.mov`, the selected video stream is printed four times. Require an explicit selection to enable groups through their stream sections. Shared stream names still filter fields when groups are enabled with `-show_stream_groups` or a group section name. Add three FATE tests and update the affected MOV references. Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/24352 Tested with MSYS2/Clang on Windows: all 5,791 local FATE tests pass after rerunning failures with LF source files and relative sample paths. The build uses default components and the external libraries available here. >From 116e96e4319dfac1b32515e8da5a1efd93819f82 Mon Sep 17 00:00:00 2001 From: cuptu <[email protected]> Date: Sun, 13 Sep 2026 10:14:21 +0800 Subject: [PATCH] fftools/ffprobe: avoid implicitly enabling groups for stream entries -show_entries stream=... also matches streams inside groups, enabling group output even when it was not requested. With the MOV timecode groups in fcp_export8-236.mov, the selected video stream is printed four times. Require an explicit selection to enable groups through their stream sections. Shared stream names still filter fields when groups are enabled with -show_stream_groups or a group section name. Add three FATE tests and update the affected MOV references. Fixes: https://code.ffmpeg.org/FFmpeg/FFmpeg/issues/24352 Signed-off-by: cuptu <[email protected]> --- doc/ffprobe.texi | 6 ++++ fftools/ffprobe.c | 30 ++++++++++++------- tests/fate/mov.mak | 12 ++++++++ .../fate/ffprobe-group-stream-entries-tmcd | 6 ++++ tests/ref/fate/ffprobe-show-groups-tmcd | 7 +++++ tests/ref/fate/ffprobe-stream-entries-tmcd | 1 + .../ref/fate/mov-mp4-disposition-mpegts-remux | 3 -- tests/ref/fate/mov-mp4-ttml-dfxp | 3 -- tests/ref/fate/mov-mp4-ttml-stpp | 3 -- tests/ref/fate/mov-mp4-with-mov-in24-ver | 5 ---- 10 files changed, 52 insertions(+), 24 deletions(-) create mode 100644 tests/ref/fate/ffprobe-group-stream-entries-tmcd create mode 100644 tests/ref/fate/ffprobe-show-groups-tmcd create mode 100644 tests/ref/fate/ffprobe-stream-entries-tmcd diff --git a/doc/ffprobe.texi b/doc/ffprobe.texi index 41dbba4656..9b95b82938 100644 --- a/doc/ffprobe.texi +++ b/doc/ffprobe.texi @@ -196,6 +196,12 @@ sections: stream_tags=title @end example +Selecting @code{stream} or @code{streams} does not by itself enable stream +group output. To also show streams within groups, use +@code{-show_stream_groups} or select their unique section name, for example +@code{-show_entries stream_group_stream=index}. The shared names still +select fields within stream groups when group output is enabled. + @item -show_packets Show information about each packet contained in the input multimedia stream. diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c index e918d98cab..8d65586742 100644 --- a/fftools/ffprobe.c +++ b/fftools/ffprobe.c @@ -332,6 +332,7 @@ static const AVTextFormatSection sections[] = { typedef struct EntrySelection { int show_all_entries; + int explicitly_selected; ///< Selected by unique name or through a selected parent. AVDictionary *entries_to_show; } EntrySelection; @@ -2908,15 +2909,17 @@ 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) + int show_all_entries, AVDictionary *entries, + int explicitly_selected) { EntrySelection *selection = &selected_entries[section_id]; selection->show_all_entries = show_all_entries; + selection->explicitly_selected |= explicitly_selected; if (show_all_entries) { const AVTextFormatSection *section = §ions[section_id]; for (const int *id = section->children_ids; *id != -1; id++) - mark_section_show_entries(*id, show_all_entries, entries); + mark_section_show_entries(*id, show_all_entries, entries, explicitly_selected); } else { av_dict_copy(&selection->entries_to_show, entries, 0); } @@ -2935,7 +2938,9 @@ static int match_section(const char *section_name, "'%s' matches section with unique name '%s'\n", section_name, (char *)av_x_if_null(section->unique_name, section->name)); ret++; - mark_section_show_entries(section->id, show_all_entries, entries); + mark_section_show_entries(section->id, show_all_entries, entries, + !section->unique_name || + !strcmp(section_name, section->unique_name)); } } return ret; @@ -3261,15 +3266,15 @@ static int opt_codec(void *optctx, const char *opt, const char *arg) static int opt_show_versions(void *optctx, const char *opt, const char *arg) { - mark_section_show_entries(SECTION_ID_PROGRAM_VERSION, 1, NULL); - mark_section_show_entries(SECTION_ID_LIBRARY_VERSION, 1, NULL); + mark_section_show_entries(SECTION_ID_PROGRAM_VERSION, 1, NULL, 1); + mark_section_show_entries(SECTION_ID_LIBRARY_VERSION, 1, NULL, 1); return 0; } #define DEFINE_OPT_SHOW_SECTION(section, target_section_id) \ static int opt_show_##section(void *optctx, const char *opt, const char *arg) \ { \ - mark_section_show_entries(SECTION_ID_##target_section_id, 1, NULL); \ + mark_section_show_entries(SECTION_ID_##target_section_id, 1, NULL, 1); \ return 0; \ } @@ -3340,22 +3345,27 @@ static const OptionDef real_options[] = { { NULL, }, }; -static inline int check_section_show_entries(int section_id) +static inline int check_section_show_entries(int section_id, int require_explicit) { const EntrySelection *selection = &selected_entries[section_id]; - if (selection->show_all_entries || selection->entries_to_show) + /* Selecting a shared stream section must not implicitly enable groups. */ + if (section_id == SECTION_ID_STREAM_GROUP_STREAMS) + require_explicit = 1; + + if ((!require_explicit || selection->explicitly_selected) && + (selection->show_all_entries || selection->entries_to_show)) return 1; const AVTextFormatSection *section = §ions[section_id]; for (const int *id = section->children_ids; *id != -1; id++) - if (check_section_show_entries(*id)) + if (check_section_show_entries(*id, require_explicit)) return 1; return 0; } #define SET_DO_SHOW(id, varname) do { \ - if (check_section_show_entries(SECTION_ID_##id)) \ + if (check_section_show_entries(SECTION_ID_##id, 0)) \ do_show_##varname = 1; \ } while (0) diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index 3c0ac3ec13..ecbf686814 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -47,6 +47,18 @@ FATE_MOV_FFPROBE-$(call DEMDEC, MOV, HEVC) += fate-mov-dovi-hvce-mp4-read FATE_MOV_FFPROBE-$(call DEMDEC, MOV, H264) += fate-mov-vfr-bframes-duration +FATE_MOV_FFPROBE-$(CONFIG_MOV_DEMUXER) += fate-ffprobe-stream-entries-tmcd \ + fate-ffprobe-group-stream-entries-tmcd \ + fate-ffprobe-show-groups-tmcd + +fate-ffprobe-stream-entries-tmcd: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -v error -select_streams v:0 \ + -show_entries stream=index -of compact $(TARGET_SAMPLES)/mov/fcp_export8-236.mov +fate-ffprobe-group-stream-entries-tmcd: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -v error -select_streams v:0 \ + -show_entries stream_group_stream=index -of compact $(TARGET_SAMPLES)/mov/fcp_export8-236.mov +fate-ffprobe-show-groups-tmcd: CMD = run ffprobe$(PROGSSUF)$(EXESUF) -v error -select_streams v:0 -show_stream_groups \ + -show_entries stream_group=:stream_group_disposition=:stream_group_tags=:stream_group_components=:stream_group_stream_disposition=:stream_group_stream_tags=:stream=index \ + -of compact $(TARGET_SAMPLES)/mov/fcp_export8-236.mov + FATE_MOV_FASTSTART = fate-mov-faststart-4gb-overflow \ FATE_SAMPLES_FFMPEG += $(FATE_MOV-yes) $(FATE_MOV_REMUX-yes) diff --git a/tests/ref/fate/ffprobe-group-stream-entries-tmcd b/tests/ref/fate/ffprobe-group-stream-entries-tmcd new file mode 100644 index 0000000000..6ba54f4200 --- /dev/null +++ b/tests/ref/fate/ffprobe-group-stream-entries-tmcd @@ -0,0 +1,6 @@ +stream_group| +stream|index=0| +stream_group| +stream|index=0| +stream_group| +stream|index=0| diff --git a/tests/ref/fate/ffprobe-show-groups-tmcd b/tests/ref/fate/ffprobe-show-groups-tmcd new file mode 100644 index 0000000000..64b32fe905 --- /dev/null +++ b/tests/ref/fate/ffprobe-show-groups-tmcd @@ -0,0 +1,7 @@ +stream_group| +stream|index=0| +stream_group| +stream|index=0| +stream_group| +stream|index=0| +stream|index=0| diff --git a/tests/ref/fate/ffprobe-stream-entries-tmcd b/tests/ref/fate/ffprobe-stream-entries-tmcd new file mode 100644 index 0000000000..64b0ce91b9 --- /dev/null +++ b/tests/ref/fate/ffprobe-stream-entries-tmcd @@ -0,0 +1 @@ +stream|index=0| diff --git a/tests/ref/fate/mov-mp4-disposition-mpegts-remux b/tests/ref/fate/mov-mp4-disposition-mpegts-remux index bbd9c89fa7..7107bf4497 100644 --- a/tests/ref/fate/mov-mp4-disposition-mpegts-remux +++ b/tests/ref/fate/mov-mp4-disposition-mpegts-remux @@ -19,9 +19,6 @@ { "programs": [ - ], - "stream_groups": [ - ], "streams": [ { diff --git a/tests/ref/fate/mov-mp4-ttml-dfxp b/tests/ref/fate/mov-mp4-ttml-dfxp index b019b3f6cc..2d60f3d964 100644 --- a/tests/ref/fate/mov-mp4-ttml-dfxp +++ b/tests/ref/fate/mov-mp4-ttml-dfxp @@ -22,9 +22,6 @@ ], "programs": [ - ], - "stream_groups": [ - ], "streams": [ { diff --git a/tests/ref/fate/mov-mp4-ttml-stpp b/tests/ref/fate/mov-mp4-ttml-stpp index 827296253e..0a8e423449 100644 --- a/tests/ref/fate/mov-mp4-ttml-stpp +++ b/tests/ref/fate/mov-mp4-ttml-stpp @@ -23,9 +23,6 @@ cbd2c7ff864a663b0d893deac5a0caec *tests/data/fate/mov-mp4-ttml-stpp.mp4 ], "programs": [ - ], - "stream_groups": [ - ], "streams": [ { diff --git a/tests/ref/fate/mov-mp4-with-mov-in24-ver b/tests/ref/fate/mov-mp4-with-mov-in24-ver index 450560b149..b5522454df 100644 --- a/tests/ref/fate/mov-mp4-with-mov-in24-ver +++ b/tests/ref/fate/mov-mp4-with-mov-in24-ver @@ -1,8 +1,3 @@ -[STREAM_GROUP] -[STREAM] -codec_name=pcm_s24le -[/STREAM] -[/STREAM_GROUP] [STREAM] codec_name=pcm_s24le [/STREAM] -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
