| ... | ... |
@@ -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); |