... | ... |
@@ -702,3 +702,37 @@ void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta) |
702 | 702 |
current = next; |
703 | 703 |
} |
704 | 704 |
} |
705 |
+ |
|
706 |
+int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta) |
|
707 |
+{ |
|
708 |
+ ID3v2ExtraMeta *cur; |
|
709 |
+ |
|
710 |
+ for (cur = *extra_meta; cur; cur = cur->next) { |
|
711 |
+ ID3v2ExtraMetaAPIC *apic; |
|
712 |
+ AVStream *st; |
|
713 |
+ |
|
714 |
+ if (strcmp(cur->tag, "APIC")) |
|
715 |
+ continue; |
|
716 |
+ apic = cur->data; |
|
717 |
+ |
|
718 |
+ if (!(st = avformat_new_stream(s, NULL))) |
|
719 |
+ return AVERROR(ENOMEM); |
|
720 |
+ |
|
721 |
+ st->disposition |= AV_DISPOSITION_ATTACHED_PIC; |
|
722 |
+ st->codec->codec_type = AVMEDIA_TYPE_VIDEO; |
|
723 |
+ st->codec->codec_id = apic->id; |
|
724 |
+ av_dict_set(&st->metadata, "title", apic->description, 0); |
|
725 |
+ av_dict_set(&st->metadata, "comment", apic->type, 0); |
|
726 |
+ |
|
727 |
+ av_init_packet(&st->attached_pic); |
|
728 |
+ st->attached_pic.data = apic->data; |
|
729 |
+ st->attached_pic.size = apic->len; |
|
730 |
+ st->attached_pic.destruct = av_destruct_packet; |
|
731 |
+ st->attached_pic.stream_index = st->index; |
|
732 |
+ |
|
733 |
+ apic->data = NULL; |
|
734 |
+ apic->len = 0; |
|
735 |
+ } |
|
736 |
+ |
|
737 |
+ return 0; |
|
738 |
+} |
... | ... |
@@ -109,6 +109,12 @@ int ff_id3v2_write(struct AVFormatContext *s, int id3v2_version, const char *mag |
109 | 109 |
*/ |
110 | 110 |
void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta); |
111 | 111 |
|
112 |
+/** |
|
113 |
+ * Create a stream for each APIC (attached picture) extracted from the |
|
114 |
+ * ID3v2 header. |
|
115 |
+ */ |
|
116 |
+int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta); |
|
117 |
+ |
|
112 | 118 |
extern const AVMetadataConv ff_id3v2_34_metadata_conv[]; |
113 | 119 |
extern const AVMetadataConv ff_id3v2_4_metadata_conv[]; |
114 | 120 |
|
... | ... |
@@ -520,6 +520,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma |
520 | 520 |
AVFormatContext *s = *ps; |
521 | 521 |
int i, ret = 0; |
522 | 522 |
AVDictionary *tmp = NULL; |
523 |
+ ID3v2ExtraMeta *id3v2_extra_meta = NULL; |
|
523 | 524 |
|
524 | 525 |
if (!s && !(s = avformat_alloc_context())) |
525 | 526 |
return AVERROR(ENOMEM); |
... | ... |
@@ -562,12 +563,17 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma |
562 | 562 |
|
563 | 563 |
/* e.g. AVFMT_NOFILE formats will not have a AVIOContext */ |
564 | 564 |
if (s->pb) |
565 |
- ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC); |
|
565 |
+ ff_id3v2_read_all(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta); |
|
566 | 566 |
|
567 | 567 |
if (s->iformat->read_header) |
568 | 568 |
if ((ret = s->iformat->read_header(s)) < 0) |
569 | 569 |
goto fail; |
570 | 570 |
|
571 |
+ if (id3v2_extra_meta && |
|
572 |
+ (ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0) |
|
573 |
+ goto fail; |
|
574 |
+ ff_id3v2_free_extra_meta(&id3v2_extra_meta); |
|
575 |
+ |
|
571 | 576 |
/* queue attached pictures */ |
572 | 577 |
for (i = 0; i < s->nb_streams; i++) |
573 | 578 |
if (s->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) { |
... | ... |
@@ -589,6 +595,7 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma |
589 | 589 |
return 0; |
590 | 590 |
|
591 | 591 |
fail: |
592 |
+ ff_id3v2_free_extra_meta(&id3v2_extra_meta); |
|
592 | 593 |
av_dict_free(&tmp); |
593 | 594 |
if (s->pb && !(s->flags & AVFMT_FLAG_CUSTOM_IO)) |
594 | 595 |
avio_close(s->pb); |