PR #21206 opened by mkver URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21206 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21206.patch
Alternative to #21205. >From 6d5108484f151b95b0e31edd58003999a6548cb9 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 15 Dec 2025 15:39:05 +0100 Subject: [PATCH 1/9] avformat/mux: Allow to add list of supported codecs to muxers This allows to check generically for supported codecs in avformat_init_output() and avformat_query_codec(). Notice that using a union of codec_list and query_codec is fine ABI-wise: Given that both members are pointers, the offsets won't be affected (in practice); because the information in which state the union is is given by a flag contained in the FFOutputFormat, it works to even use this for devices without a major ABI bump. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavformat/mux.c | 14 ++++++++++++++ libavformat/mux.h | 37 +++++++++++++++++++++++++++++-------- libavformat/mux_utils.c | 9 ++++++++- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/libavformat/mux.c b/libavformat/mux.c index db3b6c2bfe..d2f6914eac 100644 --- a/libavformat/mux.c +++ b/libavformat/mux.c @@ -294,6 +294,20 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) goto fail; } } + if (of->flags_internal & FF_OFMT_FLAG_CODEC_ID_LIST) { + const enum AVCodecID *codec_list = of->codec_list; + av_assert2(codec_list && *codec_list != AV_CODEC_ID_NONE); + while (1) { + if (par->codec_id == *codec_list) + break; + if (*++codec_list == AV_CODEC_ID_NONE) { + av_log(s, AV_LOG_ERROR, "%s muxer does not support codec %s\n", + of->p.name, avcodec_get_name(par->codec_id)); + ret = AVERROR(EINVAL); + goto fail; + } + } + } desc = avcodec_descriptor_get(par->codec_id); if (desc && desc->props & AV_CODEC_PROP_REORDER) diff --git a/libavformat/mux.h b/libavformat/mux.h index 0b69109174..24cd4d92ac 100644 --- a/libavformat/mux.h +++ b/libavformat/mux.h @@ -57,6 +57,11 @@ struct AVDeviceInfoList; * are disallowed. */ #define FF_OFMT_FLAG_ONLY_DEFAULT_CODECS (1 << 3) +/** + * If this flag is set, it means that FFOutputFormat.codec_list + * is set; otherwise, the union is in query_codec state (which may be NULL). + */ +#define FF_OFMT_FLAG_CODEC_ID_LIST (1 << 4) typedef struct FFOutputFormat { /** @@ -101,14 +106,27 @@ typedef struct FFOutputFormat { */ int (*interleave_packet)(AVFormatContext *s, AVPacket *pkt, int flush, int has_packet); - /** - * Test if the given codec can be stored in this container. - * - * @return 1 if the codec is supported, 0 if it is not. - * A negative number if unknown. - * MKTAG('A', 'P', 'I', 'C') if the codec is only supported as AV_DISPOSITION_ATTACHED_PIC - */ - int (*query_codec)(enum AVCodecID id, int std_compliance); + union { + /** + * Test if the given codec can be stored in this container. + * The union is in this state when the FF_OFMT_FLAG_CODEC_ID_LIST flag + * is not set. + * + * @return 1 if the codec is supported, 0 if it is not. + * A negative number if unknown. + * MKTAG('A', 'P', 'I', 'C') if the codec is only supported as AV_DISPOSITION_ATTACHED_PIC + */ + int (*query_codec)(enum AVCodecID id, int std_compliance); + /** + * A list of supported codecs by this muxer. + * The union is in this state iff the FF_OFMT_FLAG_CODEC_ID_LIST flag + * is set; in this case, any codec not in this list can't be muxed by + * this muxer at all. + * The list is delimited by AV_CODEC_ID_NONE which must never be + * the only entry in this list. + */ + const enum AVCodecID *codec_list; + }; void (*get_output_timestamp)(AVFormatContext *s, int stream, int64_t *dts, int64_t *wall); @@ -169,6 +187,9 @@ static inline const FFOutputFormat *ffofmt(const AVOutputFormat *fmt) return (const FFOutputFormat*)fmt; } +#define OFMT_CODEC_LIST(...) \ + .codec_list = (const enum AVCodecID []){ __VA_ARGS__, AV_CODEC_ID_NONE } + /** * Add packet to an AVFormatContext's packet_buffer list, determining its * interleaved position using compare() function argument. diff --git a/libavformat/mux_utils.c b/libavformat/mux_utils.c index 86d333dbe7..d41bbe4a14 100644 --- a/libavformat/mux_utils.c +++ b/libavformat/mux_utils.c @@ -34,7 +34,14 @@ int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id, { if (ofmt) { unsigned int codec_tag; - if (ffofmt(ofmt)->query_codec) + if (ffofmt(ofmt)->flags_internal & FF_OFMT_FLAG_CODEC_ID_LIST) { + const enum AVCodecID *codec_list = ffofmt(ofmt)->codec_list; + do { + if (codec_id == *codec_list) + return 1; + } while (*++codec_list != AV_CODEC_ID_NONE); + return 0; + } else if (ffofmt(ofmt)->query_codec) return ffofmt(ofmt)->query_codec(codec_id, std_compliance); else if (ofmt->codec_tag) return !!av_codec_get_tag2(ofmt->codec_tag, codec_id, &codec_tag); -- 2.49.1 >From 72464569574ff88bd9014c40915b66307981c065 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 15 Dec 2025 16:20:55 +0100 Subject: [PATCH 2/9] avformat/a64: Check codec ids generically Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavformat/a64.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/a64.c b/libavformat/a64.c index 6e722c7e9f..a4ca4d6817 100644 --- a/libavformat/a64.c +++ b/libavformat/a64.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" #include "libavcodec/codec_id.h" #include "libavcodec/codec_par.h" @@ -54,7 +55,7 @@ static int a64_write_header(AVFormatContext *s) header[4] = 3; break; default: - return AVERROR_INVALIDDATA; + av_unreachable("Already checked via codec_list"); } avio_write(s->pb, header, 2); return 0; @@ -67,7 +68,8 @@ const FFOutputFormat ff_a64_muxer = { .p.video_codec = AV_CODEC_ID_A64_MULTI, .p.audio_codec = AV_CODEC_ID_NONE, .p.subtitle_codec = AV_CODEC_ID_NONE, - .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH | FF_OFMT_FLAG_CODEC_ID_LIST, + OFMT_CODEC_LIST(AV_CODEC_ID_A64_MULTI, AV_CODEC_ID_A64_MULTI5), .write_header = a64_write_header, .write_packet = ff_raw_write_packet, }; -- 2.49.1 >From 581535fc4cb3f0dc5d624344f191c5934677a2bd Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 15 Dec 2025 16:22:48 +0100 Subject: [PATCH 3/9] avformat/amr: Check codec ids generically Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavformat/amr.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/amr.c b/libavformat/amr.c index 9cc61baf55..ad4538aeaa 100644 --- a/libavformat/amr.c +++ b/libavformat/amr.c @@ -25,6 +25,7 @@ Write and read amr data according to RFC3267, http://www.ietf.org/rfc/rfc3267.tx #include "config_components.h" +#include "libavutil/avassert.h" #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "avformat.h" @@ -261,7 +262,7 @@ static int amr_write_header(AVFormatContext *s) } else if (par->codec_id == AV_CODEC_ID_AMR_WB) { avio_write(pb, AMRWB_header, sizeof(AMRWB_header)); /* magic number */ } else { - return -1; + av_unreachable("Already checked via codec_list"); } return 0; } @@ -275,7 +276,8 @@ const FFOutputFormat ff_amr_muxer = { .p.video_codec = AV_CODEC_ID_NONE, .p.subtitle_codec = AV_CODEC_ID_NONE, .p.flags = AVFMT_NOTIMESTAMPS, - .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH | FF_OFMT_FLAG_CODEC_ID_LIST, + OFMT_CODEC_LIST(AV_CODEC_ID_AMR_NB, AV_CODEC_ID_AMR_WB), .write_header = amr_write_header, .write_packet = ff_raw_write_packet, }; -- 2.49.1 >From 1077e0445ef99197613485d30cd848cb2bc721e7 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 15 Dec 2025 16:31:33 +0100 Subject: [PATCH 4/9] avformat/icoenc: Check codec ids generically Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavformat/icoenc.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/icoenc.c b/libavformat/icoenc.c index 9eba9e7926..f7292a5aeb 100644 --- a/libavformat/icoenc.c +++ b/libavformat/icoenc.c @@ -24,6 +24,7 @@ * Microsoft Windows ICO muxer */ +#include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" #include "libavutil/mem.h" @@ -66,8 +67,7 @@ static int ico_check_attributes(AVFormatContext *s, const AVCodecParameters *p) return AVERROR(EINVAL); } } else { - av_log(s, AV_LOG_ERROR, "Unsupported codec %s\n", avcodec_get_name(p->codec_id)); - return AVERROR(EINVAL); + av_unreachable("Already checked via codec_list"); } if (p->width > 256 || @@ -207,4 +207,6 @@ const FFOutputFormat ff_ico_muxer = { .write_trailer = ico_write_trailer, .deinit = ico_deinit, .p.flags = AVFMT_NOTIMESTAMPS, + .flags_internal = FF_OFMT_FLAG_CODEC_ID_LIST, + OFMT_CODEC_LIST(AV_CODEC_ID_BMP, AV_CODEC_ID_PNG), }; -- 2.49.1 >From 5f175d01eeae27d43f92d8bfd5c5b6902e628cd3 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 15 Dec 2025 16:35:16 +0100 Subject: [PATCH 5/9] avformat/latmenc: Check codec ids generically Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavformat/latmenc.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/libavformat/latmenc.c b/libavformat/latmenc.c index 05004048aa..6da7864324 100644 --- a/libavformat/latmenc.c +++ b/libavformat/latmenc.c @@ -93,10 +93,6 @@ static int latm_write_header(AVFormatContext *s) if (par->codec_id == AV_CODEC_ID_AAC_LATM) return 0; - if (par->codec_id != AV_CODEC_ID_AAC && par->codec_id != AV_CODEC_ID_MP4ALS) { - av_log(s, AV_LOG_ERROR, "Only AAC, LATM and ALS are supported\n"); - return AVERROR(EINVAL); - } if (par->extradata_size > 0 && latm_decode_extradata(s, par->extradata, par->extradata_size) < 0) @@ -269,7 +265,9 @@ const FFOutputFormat ff_latm_muxer = { .p.audio_codec = AV_CODEC_ID_AAC, .p.video_codec = AV_CODEC_ID_NONE, .p.subtitle_codec = AV_CODEC_ID_NONE, - .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH | + FF_OFMT_FLAG_CODEC_ID_LIST, + OFMT_CODEC_LIST(AV_CODEC_ID_AAC_LATM, AV_CODEC_ID_AAC, AV_CODEC_ID_MP4ALS), .write_header = latm_write_header, .write_packet = latm_write_packet, .p.priv_class = &latm_muxer_class, -- 2.49.1 >From 9e62af166607aa304c1a3ace70b692d5ed90d1c0 Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 15 Dec 2025 16:36:59 +0100 Subject: [PATCH 6/9] avformat/lrcenc: Check codec ids generically Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavformat/lrcenc.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libavformat/lrcenc.c b/libavformat/lrcenc.c index bf295dfade..6190dfee6c 100644 --- a/libavformat/lrcenc.c +++ b/libavformat/lrcenc.c @@ -43,12 +43,6 @@ static int lrc_write_header(AVFormatContext *s) { const AVDictionaryEntry *metadata_item; - if(s->streams[0]->codecpar->codec_id != AV_CODEC_ID_SUBRIP && - s->streams[0]->codecpar->codec_id != AV_CODEC_ID_TEXT) { - av_log(s, AV_LOG_ERROR, "Unsupported subtitle codec: %s\n", - avcodec_get_name(s->streams[0]->codecpar->codec_id)); - return AVERROR(EINVAL); - } avpriv_set_pts_info(s->streams[0], 64, 1, AV_TIME_BASE); ff_standardize_creation_time(s); @@ -157,9 +151,11 @@ const FFOutputFormat ff_lrc_muxer = { .p.video_codec = AV_CODEC_ID_NONE, .p.audio_codec = AV_CODEC_ID_NONE, .p.subtitle_codec = AV_CODEC_ID_SUBRIP, - .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH | + FF_OFMT_FLAG_CODEC_ID_LIST, .priv_data_size = sizeof(LRCSubtitleContext), .write_header = lrc_write_header, .write_packet = lrc_write_packet, .p.priv_class = &lrcenc_class, + OFMT_CODEC_LIST(AV_CODEC_ID_SUBRIP, AV_CODEC_ID_TEXT), }; -- 2.49.1 >From 20b5c4e5031b31a9695185d9086448ffdf70846e Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 15 Dec 2025 16:40:27 +0100 Subject: [PATCH 7/9] avformat/yuv4mpegenc: Check codec ids generically Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavformat/yuv4mpegenc.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libavformat/yuv4mpegenc.c b/libavformat/yuv4mpegenc.c index 371d3745c1..3c3a24aa34 100644 --- a/libavformat/yuv4mpegenc.c +++ b/libavformat/yuv4mpegenc.c @@ -221,12 +221,6 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) static int yuv4_init(AVFormatContext *s) { - if (s->streams[0]->codecpar->codec_id != AV_CODEC_ID_WRAPPED_AVFRAME && - s->streams[0]->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO) { - av_log(s, AV_LOG_ERROR, "ERROR: Codec not supported.\n"); - return AVERROR_INVALIDDATA; - } - switch (s->streams[0]->codecpar->format) { case AV_PIX_FMT_YUV411P: av_log(s, AV_LOG_WARNING, "Warning: generating rarely used 4:1:1 YUV " @@ -298,5 +292,7 @@ const FFOutputFormat ff_yuv4mpegpipe_muxer = { .init = yuv4_init, .write_header = yuv4_write_header, .write_packet = yuv4_write_packet, - .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH | + FF_OFMT_FLAG_CODEC_ID_LIST, + OFMT_CODEC_LIST(AV_CODEC_ID_WRAPPED_AVFRAME, AV_CODEC_ID_RAWVIDEO), }; -- 2.49.1 >From 051ed8a6ecc3f9f28c2f44d13dbd3f0b59594a9b Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 15 Dec 2025 17:02:37 +0100 Subject: [PATCH 8/9] avformat/segafilmenc: Check codec ids generically Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavformat/segafilmenc.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/libavformat/segafilmenc.c b/libavformat/segafilmenc.c index 88a5b9f972..983a3b1a21 100644 --- a/libavformat/segafilmenc.c +++ b/libavformat/segafilmenc.c @@ -106,10 +106,9 @@ static int get_audio_codec_id(enum AVCodecID codec_id) case AV_CODEC_ID_PCM_S8_PLANAR: case AV_CODEC_ID_PCM_S16BE_PLANAR: return 0; + default: case AV_CODEC_ID_ADPCM_ADX: return 2; - default: - return -1; } } @@ -123,22 +122,10 @@ static int film_init(AVFormatContext *format_context) for (int i = 0; i < format_context->nb_streams; i++) { AVStream *st = format_context->streams[i]; - if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { - if (get_audio_codec_id(st->codecpar->codec_id) < 0) { - av_log(format_context, AV_LOG_ERROR, - "Incompatible audio stream format.\n"); - return AVERROR(EINVAL); - } + if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) film->audio_index = i; - } if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { - if (st->codecpar->codec_id != AV_CODEC_ID_CINEPAK && - st->codecpar->codec_id != AV_CODEC_ID_RAWVIDEO) { - av_log(format_context, AV_LOG_ERROR, - "Incompatible video stream format.\n"); - return AVERROR(EINVAL); - } if (st->codecpar->format != AV_PIX_FMT_RGB24) { av_log(format_context, AV_LOG_ERROR, "Pixel format must be rgb24.\n"); @@ -280,7 +267,11 @@ const FFOutputFormat ff_segafilm_muxer = { .p.audio_codec = AV_CODEC_ID_PCM_S16BE_PLANAR, .p.video_codec = AV_CODEC_ID_CINEPAK, .p.subtitle_codec = AV_CODEC_ID_NONE, - .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH | + FF_OFMT_FLAG_CODEC_ID_LIST, + OFMT_CODEC_LIST(AV_CODEC_ID_CINEPAK, AV_CODEC_ID_RAWVIDEO, + AV_CODEC_ID_PCM_S8_PLANAR, AV_CODEC_ID_PCM_S16BE_PLANAR, + AV_CODEC_ID_ADPCM_ADX), .init = film_init, .write_trailer = film_write_header, .write_packet = film_write_packet, -- 2.49.1 >From 6c72e1ffca07dc697118013e9ab19d947e2373bf Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt <[email protected]> Date: Mon, 15 Dec 2025 17:04:42 +0100 Subject: [PATCH 9/9] avformat/supenc: Only allow AV_CODEC_ID_HDMV_PGS_SUBTITLE Do this by setting the FF_OFMT_FLAG_ONLY_DEFAULT_CODECS flag. Signed-off-by: Andreas Rheinhardt <[email protected]> --- libavformat/supenc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/supenc.c b/libavformat/supenc.c index c664723bc4..04a21a9e65 100644 --- a/libavformat/supenc.c +++ b/libavformat/supenc.c @@ -88,7 +88,8 @@ const FFOutputFormat ff_sup_muxer = { .p.audio_codec = AV_CODEC_ID_NONE, .p.subtitle_codec = AV_CODEC_ID_HDMV_PGS_SUBTITLE, .p.flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, - .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, + .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH | + FF_OFMT_FLAG_ONLY_DEFAULT_CODECS, .init = sup_init, .write_packet = sup_write_packet, }; -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
