Some encoders do not use syncsafe sizes in v2.4 id3 tags. Check the next tag to try to choose between the two.
Fixes ticket #4003 --- libavformat/id3v2.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 5469e0a..3bccd76 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -170,6 +170,23 @@ static unsigned int get_size(AVIOContext *s, int len) return v; } +/* No real verification, only check that the tag consists of + * a combination of capital alpha-numerical characters */ +static int is_tag(const char *buf, int len) +{ + if (!len) + return 0; + + while (len--) + if ((buf[len] < 'A' || + buf[len] > 'Z') && + (buf[len] < '0' || + buf[len] > '9')) + return 0; + + return 1; +} + /** * Free GEOB type extra metadata. */ @@ -734,8 +751,31 @@ static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata, tag[4] = 0; if (version == 3) { tlen = avio_rb32(pb); - } else + } else { tlen = get_size(pb, 4); + if (tlen > 0x7f) { + /* some encoders incorrectly uses v3 sizes instead of syncsafe ones + * so check the next tag to see which one to use */ + int64_t cur = avio_tell(pb); + char next_tag[5]; + + next = cur + 2 /* tflags */ + tlen; + avio_seek(pb, next, SEEK_SET); + if (avio_read(pb, next_tag, 4) < 4) + break; + if (AV_RB32(next_tag) && !is_tag(next_tag, 4)) { + avio_seek(pb, cur - 4, SEEK_SET); + tlen = avio_rb32(pb); + next = cur + 2 + tlen; + avio_seek(pb, next, SEEK_SET); + if (avio_read(pb, next_tag, 4) < 4) + break; + if (AV_RB32(next_tag) && !is_tag(next_tag, 4)) + break; + } + avio_seek(pb, cur, SEEK_SET); + } + } tflags = avio_rb16(pb); tunsync = tflags & ID3v2_FLAG_UNSYNCH; } else { -- 2.1.2.443.g670a3c1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel