From 0c9fe2b232682b0ff21b15a721005d00dd9d3d37 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sun, 15 Sep 2024 22:03:26 +0200 Subject: [PATCH] fftools/cmdutils: extend stream specifiers to match by disposition --- Changelog | 1 + doc/fftools-common-opts.texi | 4 +++ fftools/cmdutils.c | 41 ++++++++++++++++++++++++++ fftools/cmdutils.h | 2 ++ tests/fate/ffmpeg.mak | 4 +++ tests/ref/fate/ffmpeg-spec-disposition | 7 +++++ 6 files changed, 59 insertions(+) create mode 100644 tests/ref/fate/ffmpeg-spec-disposition diff --git a/Changelog b/Changelog index 4c9c2c6878..fbc76db862 100644 --- a/Changelog +++ b/Changelog @@ -23,6 +23,7 @@ version : YUVJ pixel format - Vulkan H.264 encoder - Vulkan H.265 encoder +- stream specifiers in fftools can now match by stream disposition version 7.0: diff --git a/doc/fftools-common-opts.texi b/doc/fftools-common-opts.texi index 1974d79a4c..4e48789def 100644 --- a/doc/fftools-common-opts.texi +++ b/doc/fftools-common-opts.texi @@ -79,6 +79,10 @@ Match the stream by stream id (e.g. PID in MPEG-TS container). Matches streams with the metadata tag @var{key} having the specified value. If @var{value} is not given, matches streams that contain the given tag with any value. +@item disp:@var{dispositions}[:@var{additional_stream_specifier}] +Matches streams with the given disposition(s). @var{dispositions} is a list of +one or more dispositions (as printed by the @option{-dispositions} option) +joined with '+'. @item u Matches streams with usable configuration, the codec must be defined and the essential information such as video dimension or audio sample rate must be present. diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c index 1573106d8b..8d06358cac 100644 --- a/fftools/cmdutils.c +++ b/fftools/cmdutils.c @@ -1091,6 +1091,43 @@ int stream_specifier_parse(StreamSpecifier *ss, const char *spec, av_log(logctx, AV_LOG_TRACE, "Parsed program ID: %"PRId64"; remainder: %s\n", ss->list_id, spec); + } else if (!strncmp(spec, "disp:", 5)) { + const AVClass *st_class = av_stream_get_class(); + const AVOption *o = av_opt_find(&st_class, "disposition", NULL, 0, AV_OPT_SEARCH_FAKE_OBJ); + char *disp = NULL; + size_t len; + + av_assert0(o); + + if (ss->disposition) { + av_log(logctx, AV_LOG_ERROR, "Multiple disposition specifiers\n"); + ret = AVERROR(EINVAL); + goto fail; + } + + spec += 5; + + for (len = 0; cmdutils_isalnum(spec[len]) || + spec[len] == '_' || spec[len] == '+'; len++) + continue; + + disp = av_strndup(spec, len); + if (!disp) { + ret = AVERROR(ENOMEM); + goto fail; + } + + ret = av_opt_eval_flags(&st_class, o, disp, &ss->disposition); + av_freep(&disp); + if (ret < 0) { + av_log(logctx, AV_LOG_ERROR, "Invalid disposition specifier\n"); + goto fail; + } + + spec += len; + + av_log(logctx, AV_LOG_TRACE, + "Parsed disposition: 0x%x; remainder: %s\n", ss->disposition, spec); } else if (*spec == '#' || (*spec == 'i' && *(spec + 1) == ':')) { if (ss->stream_list != STREAM_LIST_ALL) @@ -1281,6 +1318,10 @@ unsigned stream_specifier_match(const StreamSpecifier *ss, } } + if (ss->disposition && + (candidate->disposition & ss->disposition) != ss->disposition) + continue; + if (st == candidate) return ss->idx < 0 || ss->idx == nb_matched; diff --git a/fftools/cmdutils.h b/fftools/cmdutils.h index 9441d5726b..e74aa2a98d 100644 --- a/fftools/cmdutils.h +++ b/fftools/cmdutils.h @@ -130,6 +130,8 @@ typedef struct StreamSpecifier { uint8_t usable_only; + int disposition; + char *meta_key; char *meta_val; diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index 3ffaaeb295..869376dd18 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -263,3 +263,7 @@ fate-ffmpeg-loopback-decoding: CMD = transcode \ "rawvideo -s 352x288 -pix_fmt yuv420p" $(TARGET_PATH)/tests/data/vsynth1.yuv nut \ "-map 0:v:0 -c:v mpeg2video -f null - -flags +bitexact -idct simple -threads $$threads -dec 0:0 -filter_complex '[0:v][dec:0]hstack[stack]' -map '[stack]' -c:v ffv1" "" FATE_FFMPEG-$(call ENCDEC2, MPEG2VIDEO, FFV1, NUT, HSTACK_FILTER PIPE_PROTOCOL FRAMECRC_MUXER) += fate-ffmpeg-loopback-decoding + +# test matching by stream disposition +fate-ffmpeg-spec-disposition: CMD = framecrc -i $(TARGET_SAMPLES)/mpegts/pmtchange.ts -map '0:disp:visual_impaired+descriptions:1' -c copy +FATE_FFMPEG-$(call FRAMECRC, MPEGTS,,) += fate-ffmpeg-spec-disposition diff --git a/tests/ref/fate/ffmpeg-spec-disposition b/tests/ref/fate/ffmpeg-spec-disposition new file mode 100644 index 0000000000..4f24619d2b --- /dev/null +++ b/tests/ref/fate/ffmpeg-spec-disposition @@ -0,0 +1,7 @@ +#tb 0: 1/90000 +#media_type 0: audio +#codec_id 0: ac3 +#sample_rate 0: 48000 +#channel_layout_name 0: stereo +0, 0, 0, 2880, 768, 0x72b37931, F=0x3, S=1, 1 +0, 2880, 2880, 2880, 690, 0xa84a4ea2