avformat/demux: avoid unconditional ID3v2 tag consumption

ID3v2 headers are now only parsed for formats that explicitly support them,
avoiding premature data consumption that broke demuxing in other formats.

Introduces AVFMT_FLAG_ID3V2_AUTO and applies it to mp3, aac, tta, and wav.

Signed-off-by: nilfm <nil.fons@gmail.com>
This commit is contained in:
nilfm
2025-07-02 14:37:24 -04:00
committed by Kyle Swanson
parent cd21fa41c7
commit 9d037c54f2
6 changed files with 11 additions and 6 deletions

View File

@@ -208,7 +208,7 @@ retry:
const FFInputFormat ff_aac_demuxer = {
.p.name = "aac",
.p.long_name = NULL_IF_CONFIG_SMALL("raw ADTS AAC (Advanced Audio Coding)"),
.p.flags = AVFMT_GENERIC_INDEX,
.p.flags = AVFMT_GENERIC_INDEX | AVFMT_FLAG_ID3V2_AUTO,
.p.extensions = "aac",
.p.mime_type = "audio/aac,audio/aacp,audio/x-aac",
.read_probe = adts_aac_probe,

View File

@@ -1435,6 +1435,7 @@ typedef struct AVFormatContext {
#define AVFMT_FLAG_SORT_DTS 0x10000 ///< try to interleave outputted packets by dts (using this flag can slow demuxing down)
#define AVFMT_FLAG_FAST_SEEK 0x80000 ///< Enable fast, but inaccurate seeks for some formats
#define AVFMT_FLAG_AUTO_BSF 0x200000 ///< Add bitstream filters as requested by the muxer
#define AVFMT_FLAG_ID3V2_AUTO 0x400000 ///< Automatically parse ID3v2 metadata
/**
* Maximum number of bytes read from input in order to determine stream

View File

@@ -214,6 +214,10 @@ static int update_stream_avctx(AVFormatContext *s)
return 0;
}
static av_always_inline int is_id3v2_format(const AVInputFormat *fmt) {
return fmt->flags & AVFMT_FLAG_ID3V2_AUTO;
}
int avformat_open_input(AVFormatContext **ps, const char *filename,
const AVInputFormat *fmt, AVDictionary **options)
{
@@ -302,7 +306,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
}
/* e.g. AVFMT_NOFILE formats will not have an AVIOContext */
if (s->pb)
if (s->pb && is_id3v2_format(s->iformat))
ff_id3v2_read_dict(s->pb, &si->id3v2_meta, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
if (ffifmt(s->iformat)->read_header)
@@ -321,8 +325,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
}
if (id3v2_extra_meta) {
if (!strcmp(s->iformat->name, "mp3") || !strcmp(s->iformat->name, "aac") ||
!strcmp(s->iformat->name, "tta") || !strcmp(s->iformat->name, "wav")) {
if (is_id3v2_format(s->iformat)) {
if ((ret = ff_id3v2_parse_apic(s, id3v2_extra_meta)) < 0)
goto close;
if ((ret = ff_id3v2_parse_chapters(s, id3v2_extra_meta)) < 0)

View File

@@ -618,7 +618,7 @@ static const AVClass demuxer_class = {
const FFInputFormat ff_mp3_demuxer = {
.p.name = "mp3",
.p.long_name = NULL_IF_CONFIG_SMALL("MP2/3 (MPEG audio layer 2/3)"),
.p.flags = AVFMT_GENERIC_INDEX,
.p.flags = AVFMT_GENERIC_INDEX | AVFMT_FLAG_ID3V2_AUTO,
.p.extensions = "mp2,mp3,m2a,mpa", /* XXX: use probe */
.p.priv_class = &demuxer_class,
.p.mime_type = "audio/mpeg",

View File

@@ -191,6 +191,7 @@ static int tta_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp
const FFInputFormat ff_tta_demuxer = {
.p.name = "tta",
.p.long_name = NULL_IF_CONFIG_SMALL("TTA (True Audio)"),
.p.flags = AVFMT_FLAG_ID3V2_AUTO,
.p.extensions = "tta",
.priv_data_size = sizeof(TTAContext),
.read_probe = tta_probe,

View File

@@ -1011,7 +1011,7 @@ static const AVClass w64_demuxer_class = {
const FFInputFormat ff_w64_demuxer = {
.p.name = "w64",
.p.long_name = NULL_IF_CONFIG_SMALL("Sony Wave64"),
.p.flags = AVFMT_GENERIC_INDEX,
.p.flags = AVFMT_GENERIC_INDEX | AVFMT_FLAG_ID3V2_AUTO,
.p.codec_tag = ff_wav_codec_tags_list,
.p.priv_class = &w64_demuxer_class,
.priv_data_size = sizeof(WAVDemuxContext),