[FFmpeg-cvslog] id3v2: read attached pictures and export them in ID3v2ExtraMeta.
Anton Khirnov
git at videolan.org
Thu Mar 1 03:20:18 CET 2012
ffmpeg | branch: master | Anton Khirnov <anton at khirnov.net> | Sat Feb 25 09:45:38 2012 +0100| [a93b09cb45b86427d6e81fa51c660877d8d5fd17] | committer: Anton Khirnov
id3v2: read attached pictures and export them in ID3v2ExtraMeta.
> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=a93b09cb45b86427d6e81fa51c660877d8d5fd17
---
libavformat/id3v2.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++
libavformat/id3v2.h | 13 ++++++
2 files changed, 125 insertions(+), 0 deletions(-)
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index deb652d..853a04c 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -25,6 +25,7 @@
#include "libavutil/intreadwrite.h"
#include "libavutil/dict.h"
#include "avio_internal.h"
+#include "internal.h"
const AVMetadataConv ff_id3v2_34_metadata_conv[] = {
{ "TALB", "album"},
@@ -86,6 +87,38 @@ const char ff_id3v2_3_tags[][4] = {
{ 0 },
};
+const char *ff_id3v2_picture_types[21] = {
+ "Other",
+ "32x32 pixels 'file icon'",
+ "Other file icon",
+ "Cover (front)",
+ "Cover (back)",
+ "Leaflet page",
+ "Media (e.g. label side of CD)",
+ "Lead artist/lead performer/soloist",
+ "Artist/performer",
+ "Conductor",
+ "Band/Orchestra",
+ "Composer",
+ "Lyricist/text writer",
+ "Recording Location",
+ "During recording",
+ "During performance",
+ "Movie/video screen capture",
+ "A bright coloured fish",
+ "Illustration",
+ "Band/artist logotype",
+ "Publisher/Studio logotype",
+};
+
+const CodecMime ff_id3v2_mime_tags[] = {
+ {"image/gif" , CODEC_ID_GIF},
+ {"image/jpeg", CODEC_ID_MJPEG},
+ {"image/png" , CODEC_ID_PNG},
+ {"image/tiff", CODEC_ID_TIFF},
+ {"", CODEC_ID_NONE},
+};
+
int ff_id3v2_match(const uint8_t *buf, const char * magic)
{
return buf[0] == magic[0] &&
@@ -381,6 +414,84 @@ finish:
av_dict_set(m, "date", date, 0);
}
+static void free_apic(void *obj)
+{
+ ID3v2ExtraMetaAPIC *apic = obj;
+ av_freep(&apic->data);
+ av_freep(&apic->description);
+ av_freep(&apic);
+}
+
+static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag, ID3v2ExtraMeta **extra_meta)
+{
+ int enc, pic_type;
+ char mimetype[64];
+ const CodecMime *mime = ff_id3v2_mime_tags;
+ enum CodecID id = CODEC_ID_NONE;
+ ID3v2ExtraMetaAPIC *apic = NULL;
+ ID3v2ExtraMeta *new_extra = NULL;
+ int64_t end = avio_tell(pb) + taglen;
+
+ if (taglen <= 4)
+ goto fail;
+
+ new_extra = av_mallocz(sizeof(*new_extra));
+ apic = av_mallocz(sizeof(*apic));
+ if (!new_extra || !apic)
+ goto fail;
+
+ enc = avio_r8(pb);
+ taglen--;
+
+ /* mimetype */
+ taglen -= avio_get_str(pb, taglen, mimetype, sizeof(mimetype));
+ while (mime->id != CODEC_ID_NONE) {
+ if (!strncmp(mime->str, mimetype, sizeof(mimetype))) {
+ id = mime->id;
+ break;
+ }
+ mime++;
+ }
+ if (id == CODEC_ID_NONE) {
+ av_log(s, AV_LOG_WARNING, "Unknown attached picture mimetype: %s, skipping.\n", mimetype);
+ goto fail;
+ }
+ apic->id = id;
+
+ /* picture type */
+ pic_type = avio_r8(pb);
+ taglen--;
+ if (pic_type < 0 || pic_type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types)) {
+ av_log(s, AV_LOG_WARNING, "Unknown attached picture type %d.\n", pic_type);
+ pic_type = 0;
+ }
+ apic->type = ff_id3v2_picture_types[pic_type];
+
+ /* description and picture data */
+ if (decode_str(s, pb, enc, &apic->description, &taglen) < 0) {
+ av_log(s, AV_LOG_ERROR, "Error decoding attached picture description.\n");
+ goto fail;
+ }
+
+ apic->len = taglen;
+ apic->data = av_malloc(taglen);
+ if (!apic->data || avio_read(pb, apic->data, taglen) != taglen)
+ goto fail;
+
+ new_extra->tag = "APIC";
+ new_extra->data = apic;
+ new_extra->next = *extra_meta;
+ *extra_meta = new_extra;
+
+ return;
+
+fail:
+ if (apic)
+ free_apic(apic);
+ av_freep(&new_extra);
+ avio_seek(pb, end, SEEK_SET);
+}
+
typedef struct ID3v2EMFunc {
const char *tag3;
const char *tag4;
@@ -390,6 +501,7 @@ typedef struct ID3v2EMFunc {
static const ID3v2EMFunc id3v2_extra_meta_funcs[] = {
{ "GEO", "GEOB", read_geobtag, free_geobtag },
+ { "PIC", "APIC", read_apic, free_apic },
{ NULL }
};
diff --git a/libavformat/id3v2.h b/libavformat/id3v2.h
index a296e03..f358d02 100644
--- a/libavformat/id3v2.h
+++ b/libavformat/id3v2.h
@@ -24,6 +24,7 @@
#include <stdint.h>
#include "avformat.h"
+#include "internal.h"
#include "metadata.h"
#define ID3v2_HEADER_SIZE 10
@@ -59,6 +60,14 @@ typedef struct ID3v2ExtraMetaGEOB {
uint8_t *data;
} ID3v2ExtraMetaGEOB;
+typedef struct ID3v2ExtraMetaAPIC {
+ uint8_t *data;
+ int len;
+ const char *type;
+ uint8_t *description;
+ enum CodecID id;
+} ID3v2ExtraMetaAPIC;
+
/**
* Detect ID3v2 Header.
* @param buf must be ID3v2_HEADER_SIZE byte long
@@ -120,4 +129,8 @@ extern const char ff_id3v2_4_tags[][4];
*/
extern const char ff_id3v2_3_tags[][4];
+extern const CodecMime ff_id3v2_mime_tags[];
+
+extern const char *ff_id3v2_picture_types[21];
+
#endif /* AVFORMAT_ID3V2_H */
More information about the ffmpeg-cvslog
mailing list