summaryrefslogtreecommitdiff
path: root/libavformat/id3v2.c
diff options
context:
space:
mode:
authorPaul B Mahol <onemda@gmail.com>2013-05-09 13:09:28 +0000
committerPaul B Mahol <onemda@gmail.com>2013-06-07 09:28:07 +0000
commit379fcc4955d31c4057a973c926ec279bb0d53dde (patch)
tree439b88c5575da428ad24b64a824437e889b7a93c /libavformat/id3v2.c
parentf3c51215cef3add584a9e939476baf1f07ab56a9 (diff)
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.c54
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);