diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 1aa18d8213..65ed376c89 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -530,6 +530,13 @@ typedef struct AVIndexEntry { #define AV_DISPOSITION_HEARING_IMPAIRED 0x0080 /**< stream for hearing impaired audiences */ #define AV_DISPOSITION_VISUAL_IMPAIRED 0x0100 /**< stream for visual impaired audiences */ #define AV_DISPOSITION_CLEAN_EFFECTS 0x0200 /**< stream without voice */ +/** + * The stream is stored in the file as an attached picture/"cover art" (e.g. + * APIC frame in ID3v2). The single packet associated with it will be returned + * among the first few packets read from the file unless seeking takes place. + * It can also be accessed at any time in AVStream.attached_pic. + */ +#define AV_DISPOSITION_ATTACHED_PIC 0x0400 /** * Stream structure. @@ -602,6 +609,15 @@ typedef struct AVStream { */ AVRational avg_frame_rate; + /** + * For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet + * will contain the attached picture. + * + * decoding: set by libavformat, must not be modified by the caller. + * encoding: unused + */ + AVPacket attached_pic; + /***************************************************************** * All fields below this line are not part of the public API. They * may not be used outside of libavformat and can be changed and diff --git a/libavformat/utils.c b/libavformat/utils.c index 0f9c8b6293..c8dd7f5868 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -498,10 +498,27 @@ 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; +} + int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options) { AVFormatContext *s = *ps; - int ret = 0; + int i, ret = 0; AVDictionary *tmp = NULL; if (!s && !(s = avformat_alloc_context())) @@ -551,6 +568,14 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma if ((ret = s->iformat->read_header(s)) < 0) goto fail; + /* queue attached pictures */ + for (i = 0; i < s->nb_streams; i++) + if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) { + AVPacket copy = s->streams[i]->attached_pic; + copy.destruct = NULL; + add_to_pktbuf(&s->raw_packet_buffer, ©, &s->raw_packet_buffer_end); + } + if (s->pb && !s->data_offset) s->data_offset = avio_tell(s->pb); @@ -574,23 +599,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; @@ -2547,6 +2555,8 @@ void avformat_free_context(AVFormatContext *s) av_parser_close(st->parser); av_free_packet(&st->cur_pkt); } + if (st->attached_pic.data) + av_free_packet(&st->attached_pic); av_dict_free(&st->metadata); av_free(st->index_entries); av_free(st->codec->extradata);