summaryrefslogtreecommitdiff
path: root/libavformat/id3v2.c
diff options
context:
space:
mode:
authorwm4 <nfxjfg@googlemail.com>2015-01-05 18:56:20 +0100
committerMichael Niedermayer <michaelni@gmx.at>2015-01-06 16:39:52 +0100
commitea7af58fc6b3b867d1c98731ab0db81ec44a3576 (patch)
treea35d21b8e829fd6dc3c390d50fcde595e0164d4c /libavformat/id3v2.c
parent369b4cd4120bf67aa5187b6bc72574970a24ca22 (diff)
avformat/id3v2: support USLT tags
I think this turned out pretty terrible. There's no good way to add new custom tags that write to AVFormatContext->metadata. Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat/id3v2.c')
-rw-r--r--libavformat/id3v2.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 847d4af2c1..02955ffc87 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -55,6 +55,7 @@ const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
{ "TPUB", "publisher" },
{ "TRCK", "track" },
{ "TSSE", "encoder" },
+ { "USLT", "lyrics" },
{ 0 }
};
@@ -353,6 +354,52 @@ static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen,
av_dict_set(metadata, key, dst, dict_flags);
}
+static void read_uslt(AVFormatContext *s, AVIOContext *pb, int taglen,
+ AVDictionary **metadata)
+{
+ uint8_t lang[4];
+ uint8_t *descriptor = NULL; // 'Content descriptor'
+ uint8_t *text = NULL;
+ char *key = NULL;
+ int encoding;
+ unsigned genre;
+ int ok = 0;
+
+ if (taglen < 1)
+ goto error;
+
+ encoding = avio_r8(pb);
+ taglen--;
+
+ if (avio_read(pb, lang, 3) < 3)
+ goto error;
+ lang[3] = '\0';
+ taglen -= 3;
+
+ if (decode_str(s, pb, encoding, &descriptor, &taglen) < 0)
+ goto error;
+
+ if (decode_str(s, pb, encoding, &text, &taglen) < 0)
+ goto error;
+
+ // FFmpeg does not support hierarchical metadata, so concatenate the keys.
+ key = av_asprintf("lyrics-%s%s%s", descriptor[0] ? (char *)descriptor : "",
+ descriptor[0] ? "-" : "",
+ lang);
+ if (!key)
+ goto error;
+
+ av_dict_set(metadata, key, text, 0);
+
+ ok = 1;
+error:
+ if (!ok)
+ av_log(s, AV_LOG_ERROR, "Error reading lyrics, skipped\n");
+ av_free(descriptor);
+ av_free(text);
+ av_free(key);
+}
+
/**
* Parse GEOB tag into a ID3v2ExtraMetaGEOB struct.
*/
@@ -845,6 +892,7 @@ static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata,
avio_skip(pb, tlen);
/* check for text tag or supported special meta tag */
} else if (tag[0] == 'T' ||
+ !memcmp(tag, "USLT", 4) ||
(extra_meta &&
(extra_func = get_extra_meta_func(tag, isv34)))) {
pbx = pb;
@@ -910,6 +958,8 @@ static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata,
if (tag[0] == 'T')
/* parse text tag */
read_ttag(s, pbx, tlen, metadata, tag);
+ else if (!memcmp(tag, "USLT", 4))
+ read_uslt(s, pbx, tlen, metadata);
else
/* parse special meta tag */
extra_func->read(s, pbx, tlen, tag, extra_meta, isv34);