---
The way I'm doing it here is quite hacky -- the packet with the picture
data is added to the AVFormatContext queue and is lost forever if the
user clears it (e.g. by seeking) before retrieving the packet.

Does anyone have a better suggestion on how to do this?
---
 libavformat/utils.c |   80 +++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 62 insertions(+), 18 deletions(-)

diff --git a/libavformat/utils.c b/libavformat/utils.c
index 0515c45..83afa12 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -498,11 +498,67 @@ static int init_input(AVFormatContext *s, const char 
*filename, AVDictionary **o
     return av_probe_input_buffer(s->pb, &s->iformat, filename, s, 0, 0);
 }
 
+static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt,
+                               AVPacketList **plast_pktl){
+    AVPacketList *pktl = av_mallocz(sizeof(AVPacketList));
+    if (!pktl)
+        return NULL;
+
+    if (*packet_buffer)
+        (*plast_pktl)->next = pktl;
+    else
+        *packet_buffer = pktl;
+
+    /* add the packet in the buffered packet list */
+    *plast_pktl = pktl;
+    pktl->pkt= *pkt;
+    return &pktl->pkt;
+}
+
+/* add streams for id3v2 attached pictures */
+static int add_streams_from_apic(AVFormatContext *s, ID3v2ExtraMeta 
**extra_meta)
+{
+    ID3v2ExtraMeta *cur;
+
+    for (cur = *extra_meta; cur; cur = cur->next) {
+        ID3v2ExtraMetaAPIC *apic;
+        AVStream *st;
+
+        AVPacket pkt;
+
+        if (strcmp(cur->tag, "APIC"))
+            continue;
+        apic = cur->data;
+
+        if (!(st = avformat_new_stream(s, NULL)))
+            return AVERROR(ENOMEM);
+
+        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(&pkt);
+        pkt.data         = apic->data;
+        pkt.size         = apic->len;
+        pkt.destruct     = av_destruct_packet;
+        pkt.stream_index = st->index;
+        add_to_pktbuf(&s->raw_packet_buffer, &pkt, &s->raw_packet_buffer_end);
+
+        apic->data = NULL;
+        apic->len  = 0;
+    }
+
+    ff_id3v2_free_extra_meta(extra_meta);
+    return 0;
+}
+
 int avformat_open_input(AVFormatContext **ps, const char *filename, 
AVInputFormat *fmt, AVDictionary **options)
 {
     AVFormatContext *s = *ps;
     int ret = 0;
     AVDictionary *tmp = NULL;
+    ID3v2ExtraMeta *id3v2_extra_meta = NULL;
 
     if (!s && !(s = avformat_alloc_context()))
         return AVERROR(ENOMEM);
@@ -545,12 +601,16 @@ 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 = add_streams_from_apic(s, &id3v2_extra_meta)) < 0)
+        goto fail;
+
     if (s->pb && !s->data_offset)
         s->data_offset = avio_tell(s->pb);
 
@@ -564,6 +624,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);
@@ -574,23 +635,6 @@ fail:
 
 /*******************************************************/
 
-static AVPacket *add_to_pktbuf(AVPacketList **packet_buffer, AVPacket *pkt,
-                               AVPacketList **plast_pktl){
-    AVPacketList *pktl = av_mallocz(sizeof(AVPacketList));
-    if (!pktl)
-        return NULL;
-
-    if (*packet_buffer)
-        (*plast_pktl)->next = pktl;
-    else
-        *packet_buffer = pktl;
-
-    /* add the packet in the buffered packet list */
-    *plast_pktl = pktl;
-    pktl->pkt= *pkt;
-    return &pktl->pkt;
-}
-
 int av_read_packet(AVFormatContext *s, AVPacket *pkt)
 {
     int ret, i;
-- 
1.7.9

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to