diff options
author | Paul B Mahol <onemda@gmail.com> | 2013-05-09 13:09:28 +0000 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2013-06-07 09:28:07 +0000 |
commit | 379fcc4955d31c4057a973c926ec279bb0d53dde (patch) | |
tree | 439b88c5575da428ad24b64a824437e889b7a93c /libavformat/id3v2.c | |
parent | f3c51215cef3add584a9e939476baf1f07ab56a9 (diff) | |
download | ffmpeg-379fcc4955d31c4057a973c926ec279bb0d53dde.tar.gz |
id3v2: read all textual chapter subframes
Signed-off-by: Paul B Mahol <onemda@gmail.com>
Diffstat (limited to 'libavformat/id3v2.c')
-rw-r--r-- | libavformat/id3v2.c | 54 |
1 files changed, 32 insertions, 22 deletions
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index e585f0eeb3..74d637554f 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -271,7 +271,7 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, * Parse a text tag. */ static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, - const char *key) + AVDictionary **metadata, const char *key) { uint8_t *dst; int encoding, dict_flags = AV_DICT_DONT_OVERWRITE | AV_DICT_DONT_STRDUP_VAL; @@ -306,7 +306,7 @@ static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, av_freep(&dst); if (dst) - av_dict_set(&s->metadata, key, dst, dict_flags); + av_dict_set(metadata, key, dst, dict_flags); } /** @@ -518,39 +518,49 @@ fail: avio_seek(pb, end, SEEK_SET); } -static void read_chapter(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag, ID3v2ExtraMeta **extra_meta) +static void read_chapter(AVFormatContext *s, AVIOContext *pb, int len, char *ttag, ID3v2ExtraMeta **extra_meta) { AVRational time_base = {1, 1000}; uint32_t start, end; + AVChapter *chapter; uint8_t *dst = NULL; - int encoding; + int taglen; + char tag[5]; - decode_str(s, pb, 0, &dst, &taglen); - if (taglen < 16) + decode_str(s, pb, 0, &dst, &len); + if (len < 16) return; start = avio_rb32(pb); end = avio_rb32(pb); - taglen -= 27; - if (taglen > 0) { - char tag[4]; + avio_skip(pb, 8); + + chapter = avpriv_new_chapter(s, s->nb_chapters + 1, time_base, start, end, dst); + if (!chapter) { + av_free(dst); + return; + } - avio_skip(pb, 8); + len -= 16; + while (len > 10) { avio_read(pb, tag, 4); - if (!memcmp(tag, "TIT2", 4)) { - taglen = FFMIN(taglen, avio_rb32(pb)); - if (taglen < 0) { - av_free(dst); - return; - } - avio_skip(pb, 2); - encoding = avio_r8(pb); - av_freep(&dst); - decode_str(s, pb, encoding, &dst, &taglen); + tag[4] = 0; + taglen = avio_rb32(pb); + avio_skip(pb, 2); + len -= 10; + if (taglen < 0 || taglen > len) { + av_free(dst); + return; } + if (tag[0] == 'T') + read_ttag(s, pb, taglen, &chapter->metadata, tag); + else + avio_skip(pb, taglen); + len -= taglen; } - avpriv_new_chapter(s, s->nb_chapters + 1, time_base, start, end, dst); + ff_metadata_conv(&chapter->metadata, NULL, ff_id3v2_34_metadata_conv); + ff_metadata_conv(&chapter->metadata, NULL, ff_id3v2_4_metadata_conv); av_free(dst); } @@ -774,7 +784,7 @@ static void id3v2_parse(AVFormatContext *s, int len, uint8_t version, #endif if (tag[0] == 'T') /* parse text tag */ - read_ttag(s, pbx, tlen, tag); + read_ttag(s, pbx, tlen, &s->metadata, tag); else /* parse special meta tag */ extra_func->read(s, pbx, tlen, tag, extra_meta); |