[FFmpeg-devel] [RFC][PATCH] Rudimentary support for id3v2 APIC tags.
Adrian Drzewiecki
adrian.drzewiecki at gmail.com
Sat Dec 24 20:22:01 CET 2011
When parsing id3 tags, if an APIC tag is encountered, add it
to the tag dictionary encoded as "<mime type>\0<4 byte data len>\0<data>".
---
libavformat/id3v2.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 115 insertions(+), 0 deletions(-)
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 60a780c..93b1be4 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -274,6 +274,118 @@ static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const cha
av_dict_set(&s->metadata, key, dst, dict_flags);
}
+/*
+ * Parse an image tag.
+ * The image will be prefixed by the mime-type string (\0 terminated) and
+ * 32bit byte size of the image.
+ */
+static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, const char *tag)
+{
+ /* from http://id3.org/id3v2.4.0-frames #4.14 */
+ const char *key[] = {
+ "other_picture",
+ "32x32_icon",
+ "other_icon",
+ "front_cover",
+ "back_cover",
+ "leaflet_page",
+ "media_picture",
+ "lead_performer_picture",
+ "artist_picture",
+ "conductor_picture",
+ "band_picture",
+ "compose_picture",
+ "lyricist_picture",
+ "location_picture",
+ "recording_picture",
+ "performance_picture",
+ "screen_capture",
+ "a_bright_coloured_fish",
+ "illustration",
+ "band_logo",
+ "studio_logo"
+ };
+ static int max_key = sizeof(key)/sizeof(key[0]);
+ char *val, *mime_type = NULL;
+ unsigned char text_encoding;
+ unsigned char picture_type;
+ int i, len;
+
+ text_encoding = avio_r8(pb);
+ taglen --;
+
+ /* read mime type */
+ i = len = 0;
+ for (;;) {
+ unsigned char c = avio_r8(pb);
+ taglen --;
+ if (i == len) {
+ len = len ? (2 * len) : 8;
+ mime_type = av_realloc_f(mime_type, len, 1);
+ if (!mime_type) {
+ av_free(mime_type);
+ av_log(s, AV_LOG_ERROR, "Alloc of mime type failed\n");
+ return;
+ }
+ }
+ mime_type[i++] = c;
+ if (!c)
+ break;
+ if (!taglen) {
+ av_log(s, AV_LOG_ERROR, "Couldn't find end of mime type\n");
+ av_free(mime_type);
+ return;
+ }
+ }
+ len = i;
+
+ if (!taglen) {
+ av_log(s, AV_LOG_ERROR, "Truncated APIC tag.\n");
+ av_free(mime_type);
+ return;
+ }
+
+ /* which tag */
+ picture_type = avio_r8(pb);
+ taglen --;
+
+ av_log(s, AV_LOG_INFO, "Found %s APIC\n", mime_type);
+
+ if (picture_type >= max_key || !key[picture_type]) {
+ av_log(s, AV_LOG_INFO, "Unsupported picture type %x\n", picture_type);
+ av_free(mime_type);
+ return;
+ }
+
+ av_log(s, AV_LOG_INFO, "APIC is %s\n", key[picture_type]);
+
+ /* skip over description */
+ while (taglen && avio_r8(pb))
+ taglen --;
+
+ if (!taglen) {
+ av_log(s, AV_LOG_ERROR, "Truncated APIC tag.\n");
+ av_free(mime_type);
+ return;
+ }
+
+ /* len includes \0 */
+ val = av_malloc(len + taglen + sizeof(taglen));
+ if (!val) {
+ av_log(s, AV_LOG_ERROR, "Failed to allocate image buffer.\n");
+ av_free(mime_type);
+ return;
+ }
+
+ memcpy(val, mime_type, len);
+ memcpy(val + len, &taglen, sizeof (taglen));
+ avio_read(pb, val + len + sizeof(taglen), taglen);
+ av_free(mime_type);
+
+ av_log(s, AV_LOG_INFO, "Read image buffer of %d bytes\n", taglen);
+ av_dict_set(&s->metadata, key[picture_type], val, AV_DICT_DONT_STRDUP_VAL);
+}
+
/**
* Parse GEOB tag into a ID3v2ExtraMetaGEOB struct.
*/
@@ -597,6 +709,9 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t
/* parse special meta tag */
extra_func->read(s, pbx, tlen, tag, extra_meta);
}
+ else if (!strcmp(tag, "APIC"))
+ /* an image! */
+ read_apic(s, pbx, tlen, tag);
else if (!tag[0]) {
if (tag[1])
av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding");
--
1.7.8.1
More information about the ffmpeg-devel
mailing list