summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2012-02-25 09:53:35 +0100
committerAnton Khirnov <anton@khirnov.net>2012-02-29 14:16:32 +0100
commit079ea6ca5f8f108ec328d3c2c1792e676fc30b9c (patch)
tree15d38cabd66e3c5219fd66badb9410447c049683 /libavformat
parentdd2a4bcfd72eee85710142943a1c68ac02520771 (diff)
lavf: export id3v2 attached pictures as streams.
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/id3v2.c34
-rw-r--r--libavformat/id3v2.h6
-rw-r--r--libavformat/utils.c9
3 files changed, 48 insertions, 1 deletions
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 853a04c78e..4170c853a6 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -702,3 +702,37 @@ void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta)
current = next;
}
}
+
+int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta)
+{
+ ID3v2ExtraMeta *cur;
+
+ for (cur = *extra_meta; cur; cur = cur->next) {
+ ID3v2ExtraMetaAPIC *apic;
+ AVStream *st;
+
+ if (strcmp(cur->tag, "APIC"))
+ continue;
+ apic = cur->data;
+
+ if (!(st = avformat_new_stream(s, NULL)))
+ return AVERROR(ENOMEM);
+
+ st->disposition |= AV_DISPOSITION_ATTACHED_PIC;
+ st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+ st->codec->codec_id = apic->id;
+ av_dict_set(&st->metadata, "title", apic->description, 0);
+ av_dict_set(&st->metadata, "comment", apic->type, 0);
+
+ av_init_packet(&st->attached_pic);
+ st->attached_pic.data = apic->data;
+ st->attached_pic.size = apic->len;
+ st->attached_pic.destruct = av_destruct_packet;
+ st->attached_pic.stream_index = st->index;
+
+ apic->data = NULL;
+ apic->len = 0;
+ }
+
+ return 0;
+}
diff --git a/libavformat/id3v2.h b/libavformat/id3v2.h
index f358d02892..c3f08f5875 100644
--- a/libavformat/id3v2.h
+++ b/libavformat/id3v2.h
@@ -109,6 +109,12 @@ int ff_id3v2_write(struct AVFormatContext *s, int id3v2_version, const char *mag
*/
void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta);
+/**
+ * Create a stream for each APIC (attached picture) extracted from the
+ * ID3v2 header.
+ */
+int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta);
+
extern const AVMetadataConv ff_id3v2_34_metadata_conv[];
extern const AVMetadataConv ff_id3v2_4_metadata_conv[];
diff --git a/libavformat/utils.c b/libavformat/utils.c
index c8dd7f5868..e657362a38 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -520,6 +520,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
AVFormatContext *s = *ps;
int i, ret = 0;
AVDictionary *tmp = NULL;
+ ID3v2ExtraMeta *id3v2_extra_meta = NULL;
if (!s && !(s = avformat_alloc_context()))
return AVERROR(ENOMEM);
@@ -562,12 +563,17 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
/* e.g. AVFMT_NOFILE formats will not have a AVIOContext */
if (s->pb)
- ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC);
+ ff_id3v2_read_all(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta);
if (s->iformat->read_header)
if ((ret = s->iformat->read_header(s)) < 0)
goto fail;
+ if (id3v2_extra_meta &&
+ (ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0)
+ goto fail;
+ ff_id3v2_free_extra_meta(&id3v2_extra_meta);
+
/* queue attached pictures */
for (i = 0; i < s->nb_streams; i++)
if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) {
@@ -589,6 +595,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma
return 0;
fail:
+ ff_id3v2_free_extra_meta(&id3v2_extra_meta);
av_dict_free(&tmp);
if (s->pb && !(s->flags & AVFMT_FLAG_CUSTOM_IO))
avio_close(s->pb);