2 * Copyright (c) 2003 Fabrice Bellard
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * Specifications available at:
26 * http://id3.org/Developer_Information
35 #include "libavutil/avstring.h"
36 #include "libavutil/dict.h"
37 #include "libavutil/intreadwrite.h"
38 #include "avio_internal.h"
43 const AVMetadataConv ff_id3v2_34_metadata_conv
[] = {
45 { "TCOM", "composer" },
47 { "TCOP", "copyright" },
48 { "TENC", "encoded_by" },
50 { "TLAN", "language" },
52 { "TPE2", "album_artist" },
53 { "TPE3", "performer" },
55 { "TPUB", "publisher" },
57 { "TSSE", "encoder" },
61 const AVMetadataConv ff_id3v2_4_metadata_conv
[] = {
62 { "TCMP", "compilation" },
65 { "TDEN", "creation_time" },
66 { "TSOA", "album-sort" },
67 { "TSOP", "artist-sort" },
68 { "TSOT", "title-sort" },
72 static const AVMetadataConv id3v2_2_metadata_conv
[] = {
75 { "TCP", "compilation" },
77 { "TEN", "encoded_by" },
79 { "TP2", "album_artist" },
80 { "TP3", "performer" },
85 const char ff_id3v2_tags
[][4] = {
86 "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT",
87 "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED",
88 "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3",
89 "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE",
93 const char ff_id3v2_4_tags
[][4] = {
94 "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO",
95 "TPRO", "TSOA", "TSOP", "TSOT", "TSST",
99 const char ff_id3v2_3_tags
[][4] = {
100 "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER",
104 const char *ff_id3v2_picture_types
[21] = {
106 "32x32 pixels 'file icon'",
111 "Media (e.g. label side of CD)",
112 "Lead artist/lead performer/soloist",
117 "Lyricist/text writer",
118 "Recording Location",
120 "During performance",
121 "Movie/video screen capture",
122 "A bright coloured fish",
124 "Band/artist logotype",
125 "Publisher/Studio logotype",
128 const CodecMime ff_id3v2_mime_tags
[] = {
129 { "image/gif", AV_CODEC_ID_GIF
},
130 { "image/jpeg", AV_CODEC_ID_MJPEG
},
131 { "image/jpg", AV_CODEC_ID_MJPEG
},
132 { "image/png", AV_CODEC_ID_PNG
},
133 { "image/tiff", AV_CODEC_ID_TIFF
},
134 { "image/bmp", AV_CODEC_ID_BMP
},
135 { "JPG", AV_CODEC_ID_MJPEG
}, /* ID3v2.2 */
136 { "PNG", AV_CODEC_ID_PNG
}, /* ID3v2.2 */
137 { "", AV_CODEC_ID_NONE
},
140 int ff_id3v2_match(const uint8_t *buf
, const char *magic
)
142 return buf
[0] == magic
[0] &&
143 buf
[1] == magic
[1] &&
144 buf
[2] == magic
[2] &&
147 (buf
[6] & 0x80) == 0 &&
148 (buf
[7] & 0x80) == 0 &&
149 (buf
[8] & 0x80) == 0 &&
150 (buf
[9] & 0x80) == 0;
153 int ff_id3v2_tag_len(const uint8_t *buf
)
155 int len
= ((buf
[6] & 0x7f) << 21) +
156 ((buf
[7] & 0x7f) << 14) +
157 ((buf
[8] & 0x7f) << 7) +
161 len
+= ID3v2_HEADER_SIZE
;
165 static unsigned int get_size(AVIOContext
*s
, int len
)
169 v
= (v
<< 7) + (avio_r8(s
) & 0x7F);
174 * Free GEOB type extra metadata.
176 static void free_geobtag(void *obj
)
178 ID3v2ExtraMetaGEOB
*geob
= obj
;
179 av_free(geob
->mime_type
);
180 av_free(geob
->file_name
);
181 av_free(geob
->description
);
187 * Decode characters to UTF-8 according to encoding type. The decoded buffer is
188 * always null terminated. Stop reading when either *maxread bytes are read from
189 * pb or U+0000 character is found.
191 * @param dst Pointer where the address of the buffer with the decoded bytes is
192 * stored. Buffer must be freed by caller.
193 * @param maxread Pointer to maximum number of characters to read from the
194 * AVIOContext. After execution the value is decremented by the number of bytes
196 * @returns 0 if no error occurred, dst is uninitialized on error
198 static int decode_str(AVFormatContext
*s
, AVIOContext
*pb
, int encoding
,
199 uint8_t **dst
, int *maxread
)
205 unsigned int (*get
)(AVIOContext
*) = avio_rb16
;
208 if ((ret
= avio_open_dyn_buf(&dynbuf
)) < 0) {
209 av_log(s
, AV_LOG_ERROR
, "Error opening memory stream\n");
214 case ID3v2_ENCODING_ISO8859
:
217 PUT_UTF8(ch
, tmp
, avio_w8(dynbuf
, tmp
);)
222 case ID3v2_ENCODING_UTF16BOM
:
223 if ((left
-= 2) < 0) {
224 av_log(s
, AV_LOG_ERROR
, "Cannot read BOM value, input too short\n");
225 avio_close_dyn_buf(dynbuf
, dst
);
227 return AVERROR_INVALIDDATA
;
229 switch (avio_rb16(pb
)) {
235 av_log(s
, AV_LOG_ERROR
, "Incorrect BOM value\n");
236 avio_close_dyn_buf(dynbuf
, dst
);
239 return AVERROR_INVALIDDATA
;
243 case ID3v2_ENCODING_UTF16BE
:
244 while ((left
> 1) && ch
) {
245 GET_UTF16(ch
, ((left
-= 2) >= 0 ? get(pb
) : 0), break;)
246 PUT_UTF8(ch
, tmp
, avio_w8(dynbuf
, tmp
);)
249 left
+= 2; /* did not read last char from pb */
252 case ID3v2_ENCODING_UTF8
:
260 av_log(s
, AV_LOG_WARNING
, "Unknown encoding\n");
266 avio_close_dyn_buf(dynbuf
, dst
);
275 static void read_ttag(AVFormatContext
*s
, AVIOContext
*pb
, int taglen
,
276 AVDictionary
**metadata
, const char *key
)
279 int encoding
, dict_flags
= AV_DICT_DONT_OVERWRITE
| AV_DICT_DONT_STRDUP_VAL
;
285 encoding
= avio_r8(pb
);
286 taglen
--; /* account for encoding type byte */
288 if (decode_str(s
, pb
, encoding
, &dst
, &taglen
) < 0) {
289 av_log(s
, AV_LOG_ERROR
, "Error reading frame %s, skipped\n", key
);
293 if (!(strcmp(key
, "TCON") && strcmp(key
, "TCO")) &&
294 (sscanf(dst
, "(%d)", &genre
) == 1 || sscanf(dst
, "%d", &genre
) == 1) &&
295 genre
<= ID3v1_GENRE_MAX
) {
297 dst
= av_strdup(ff_id3v1_genre_str
[genre
]);
298 } else if (!(strcmp(key
, "TXXX") && strcmp(key
, "TXX"))) {
299 /* dst now contains the key, need to get value */
301 if (decode_str(s
, pb
, encoding
, &dst
, &taglen
) < 0) {
302 av_log(s
, AV_LOG_ERROR
, "Error reading frame %s, skipped\n", key
);
306 dict_flags
|= AV_DICT_DONT_STRDUP_KEY
;
311 av_dict_set(metadata
, key
, dst
, dict_flags
);
315 * Parse GEOB tag into a ID3v2ExtraMetaGEOB struct.
317 static void read_geobtag(AVFormatContext
*s
, AVIOContext
*pb
, int taglen
,
318 char *tag
, ID3v2ExtraMeta
**extra_meta
, int isv34
)
320 ID3v2ExtraMetaGEOB
*geob_data
= NULL
;
321 ID3v2ExtraMeta
*new_extra
= NULL
;
328 geob_data
= av_mallocz(sizeof(ID3v2ExtraMetaGEOB
));
330 av_log(s
, AV_LOG_ERROR
, "Failed to alloc %"SIZE_SPECIFIER
" bytes\n",
331 sizeof(ID3v2ExtraMetaGEOB
));
335 new_extra
= av_mallocz(sizeof(ID3v2ExtraMeta
));
337 av_log(s
, AV_LOG_ERROR
, "Failed to alloc %"SIZE_SPECIFIER
" bytes\n",
338 sizeof(ID3v2ExtraMeta
));
342 /* read encoding type byte */
343 encoding
= avio_r8(pb
);
346 /* read MIME type (always ISO-8859) */
347 if (decode_str(s
, pb
, ID3v2_ENCODING_ISO8859
, &geob_data
->mime_type
,
353 if (decode_str(s
, pb
, encoding
, &geob_data
->file_name
, &taglen
) < 0 ||
357 /* read content description */
358 if (decode_str(s
, pb
, encoding
, &geob_data
->description
, &taglen
) < 0 ||
363 /* save encapsulated binary data */
364 geob_data
->data
= av_malloc(taglen
);
365 if (!geob_data
->data
) {
366 av_log(s
, AV_LOG_ERROR
, "Failed to alloc %d bytes\n", taglen
);
369 if ((len
= avio_read(pb
, geob_data
->data
, taglen
)) < taglen
)
370 av_log(s
, AV_LOG_WARNING
,
371 "Error reading GEOB frame, data truncated.\n");
372 geob_data
->datasize
= len
;
374 geob_data
->data
= NULL
;
375 geob_data
->datasize
= 0;
378 /* add data to the list */
379 new_extra
->tag
= "GEOB";
380 new_extra
->data
= geob_data
;
381 new_extra
->next
= *extra_meta
;
382 *extra_meta
= new_extra
;
387 av_log(s
, AV_LOG_ERROR
, "Error reading frame %s, skipped\n", tag
);
388 free_geobtag(geob_data
);
393 static int is_number(const char *str
)
395 while (*str
>= '0' && *str
<= '9')
400 static AVDictionaryEntry
*get_date_tag(AVDictionary
*m
, const char *tag
)
402 AVDictionaryEntry
*t
;
403 if ((t
= av_dict_get(m
, tag
, NULL
, AV_DICT_MATCH_CASE
)) &&
404 strlen(t
->value
) == 4 && is_number(t
->value
))
409 static void merge_date(AVDictionary
**m
)
411 AVDictionaryEntry
*t
;
412 char date
[17] = { 0 }; // YYYY-MM-DD hh:mm
414 if (!(t
= get_date_tag(*m
, "TYER")) &&
415 !(t
= get_date_tag(*m
, "TYE")))
417 av_strlcpy(date
, t
->value
, 5);
418 av_dict_set(m
, "TYER", NULL
, 0);
419 av_dict_set(m
, "TYE", NULL
, 0);
421 if (!(t
= get_date_tag(*m
, "TDAT")) &&
422 !(t
= get_date_tag(*m
, "TDA")))
424 snprintf(date
+ 4, sizeof(date
) - 4, "-%.2s-%.2s", t
->value
+ 2, t
->value
);
425 av_dict_set(m
, "TDAT", NULL
, 0);
426 av_dict_set(m
, "TDA", NULL
, 0);
428 if (!(t
= get_date_tag(*m
, "TIME")) &&
429 !(t
= get_date_tag(*m
, "TIM")))
431 snprintf(date
+ 10, sizeof(date
) - 10,
432 " %.2s:%.2s", t
->value
, t
->value
+ 2);
433 av_dict_set(m
, "TIME", NULL
, 0);
434 av_dict_set(m
, "TIM", NULL
, 0);
438 av_dict_set(m
, "date", date
, 0);
441 static void free_apic(void *obj
)
443 ID3v2ExtraMetaAPIC
*apic
= obj
;
444 av_buffer_unref(&apic
->buf
);
445 av_freep(&apic
->description
);
449 static void read_apic(AVFormatContext
*s
, AVIOContext
*pb
, int taglen
,
450 char *tag
, ID3v2ExtraMeta
**extra_meta
, int isv34
)
454 const CodecMime
*mime
= ff_id3v2_mime_tags
;
455 enum AVCodecID id
= AV_CODEC_ID_NONE
;
456 ID3v2ExtraMetaAPIC
*apic
= NULL
;
457 ID3v2ExtraMeta
*new_extra
= NULL
;
458 int64_t end
= avio_tell(pb
) + taglen
;
463 new_extra
= av_mallocz(sizeof(*new_extra
));
464 apic
= av_mallocz(sizeof(*apic
));
465 if (!new_extra
|| !apic
)
473 taglen
-= avio_get_str(pb
, taglen
, mimetype
, sizeof(mimetype
));
475 avio_read(pb
, mimetype
, 3);
478 while (mime
->id
!= AV_CODEC_ID_NONE
) {
479 if (!av_strncasecmp(mime
->str
, mimetype
, sizeof(mimetype
))) {
485 if (id
== AV_CODEC_ID_NONE
) {
486 av_log(s
, AV_LOG_WARNING
,
487 "Unknown attached picture mimetype: %s, skipping.\n", mimetype
);
493 pic_type
= avio_r8(pb
);
495 if (pic_type
< 0 || pic_type
>= FF_ARRAY_ELEMS(ff_id3v2_picture_types
)) {
496 av_log(s
, AV_LOG_WARNING
, "Unknown attached picture type %d.\n",
500 apic
->type
= ff_id3v2_picture_types
[pic_type
];
502 /* description and picture data */
503 if (decode_str(s
, pb
, enc
, &apic
->description
, &taglen
) < 0) {
504 av_log(s
, AV_LOG_ERROR
,
505 "Error decoding attached picture description.\n");
509 apic
->buf
= av_buffer_alloc(taglen
+ FF_INPUT_BUFFER_PADDING_SIZE
);
510 if (!apic
->buf
|| !taglen
|| avio_read(pb
, apic
->buf
->data
, taglen
) != taglen
)
512 memset(apic
->buf
->data
+ taglen
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
514 new_extra
->tag
= "APIC";
515 new_extra
->data
= apic
;
516 new_extra
->next
= *extra_meta
;
517 *extra_meta
= new_extra
;
524 av_freep(&new_extra
);
525 avio_seek(pb
, end
, SEEK_SET
);
528 static void read_chapter(AVFormatContext
*s
, AVIOContext
*pb
, int len
, char *ttag
, ID3v2ExtraMeta
**extra_meta
, int isv34
)
530 AVRational time_base
= {1, 1000};
538 /* We should probably just put the chapter data to extra_meta here
539 * and do the AVFormatContext-needing part in a separate
540 * ff_id3v2_parse_apic()-like function. */
541 av_log(NULL
, AV_LOG_DEBUG
, "No AVFormatContext, skipped ID3 chapter data\n");
545 if (decode_str(s
, pb
, 0, &dst
, &len
) < 0)
550 start
= avio_rb32(pb
);
554 chapter
= avpriv_new_chapter(s
, s
->nb_chapters
+ 1, time_base
, start
, end
, dst
);
562 if (avio_read(pb
, tag
, 4) < 4)
565 taglen
= avio_rb32(pb
);
568 if (taglen
< 0 || taglen
> len
)
571 read_ttag(s
, pb
, taglen
, &chapter
->metadata
, tag
);
573 avio_skip(pb
, taglen
);
577 ff_metadata_conv(&chapter
->metadata
, NULL
, ff_id3v2_34_metadata_conv
);
578 ff_metadata_conv(&chapter
->metadata
, NULL
, ff_id3v2_4_metadata_conv
);
583 static void free_priv(void *obj
)
585 ID3v2ExtraMetaPRIV
*priv
= obj
;
586 av_freep(&priv
->owner
);
587 av_freep(&priv
->data
);
591 static void read_priv(AVFormatContext
*s
, AVIOContext
*pb
, int taglen
,
592 char *tag
, ID3v2ExtraMeta
**extra_meta
, int isv34
)
594 ID3v2ExtraMeta
*meta
;
595 ID3v2ExtraMetaPRIV
*priv
;
597 meta
= av_mallocz(sizeof(*meta
));
598 priv
= av_mallocz(sizeof(*priv
));
603 if (decode_str(s
, pb
, ID3v2_ENCODING_ISO8859
, &priv
->owner
, &taglen
) < 0)
606 priv
->data
= av_malloc(taglen
);
610 priv
->datasize
= taglen
;
612 if (avio_read(pb
, priv
->data
, priv
->datasize
) != priv
->datasize
)
617 meta
->next
= *extra_meta
;
628 typedef struct ID3v2EMFunc
{
631 void (*read
)(AVFormatContext
*, AVIOContext
*, int, char *,
632 ID3v2ExtraMeta
**, int isv34
);
633 void (*free
)(void *obj
);
636 static const ID3v2EMFunc id3v2_extra_meta_funcs
[] = {
637 { "GEO", "GEOB", read_geobtag
, free_geobtag
},
638 { "PIC", "APIC", read_apic
, free_apic
},
639 { "CHAP","CHAP", read_chapter
, NULL
},
640 { "PRIV","PRIV", read_priv
, free_priv
},
645 * Get the corresponding ID3v2EMFunc struct for a tag.
646 * @param isv34 Determines if v2.2 or v2.3/4 strings are used
647 * @return A pointer to the ID3v2EMFunc struct if found, NULL otherwise.
649 static const ID3v2EMFunc
*get_extra_meta_func(const char *tag
, int isv34
)
652 while (id3v2_extra_meta_funcs
[i
].tag3
) {
653 if (tag
&& !memcmp(tag
,
654 (isv34
? id3v2_extra_meta_funcs
[i
].tag4
:
655 id3v2_extra_meta_funcs
[i
].tag3
),
657 return &id3v2_extra_meta_funcs
[i
];
663 static void id3v2_parse(AVIOContext
*pb
, AVDictionary
**metadata
,
664 AVFormatContext
*s
, int len
, uint8_t version
,
665 uint8_t flags
, ID3v2ExtraMeta
**extra_meta
)
670 int64_t next
, end
= avio_tell(pb
) + len
;
672 const char *reason
= NULL
;
673 AVIOContext pb_local
;
675 unsigned char *buffer
= NULL
;
677 const ID3v2EMFunc
*extra_func
= NULL
;
678 unsigned char *uncompressed_buffer
= NULL
;
679 av_unused
int uncompressed_buffer_size
= 0;
681 av_log(s
, AV_LOG_DEBUG
, "id3v2 ver:%d flags:%02X len:%d\n", version
, flags
, len
);
686 reason
= "compression";
704 unsync
= flags
& 0x80;
706 if (isv34
&& flags
& 0x40) { /* Extended header present, just skip over it */
707 int extlen
= get_size(pb
, 4);
709 /* In v2.4 the length includes the length field we just read. */
713 reason
= "invalid extended header length";
716 avio_skip(pb
, extlen
);
719 reason
= "extended header too long.";
724 while (len
>= taghdrlen
) {
725 unsigned int tflags
= 0;
732 if (avio_read(pb
, tag
, 4) < 4)
736 tlen
= avio_rb32(pb
);
738 tlen
= get_size(pb
, 4);
739 tflags
= avio_rb16(pb
);
740 tunsync
= tflags
& ID3v2_FLAG_UNSYNCH
;
742 if (avio_read(pb
, tag
, 3) < 3)
745 tlen
= avio_rb24(pb
);
749 len
-= taghdrlen
+ tlen
;
754 next
= avio_tell(pb
) + tlen
;
758 av_log(s
, AV_LOG_DEBUG
, "Invalid empty frame %s, skipping.\n",
763 if (tflags
& ID3v2_FLAG_DATALEN
) {
766 dlen
= avio_rb32(pb
);
771 tcomp
= tflags
& ID3v2_FLAG_COMPRESSION
;
772 tencr
= tflags
& ID3v2_FLAG_ENCRYPTION
;
774 /* skip encrypted tags and, if no zlib, compressed tags */
775 if (tencr
|| (!CONFIG_ZLIB
&& tcomp
)) {
782 type
= "encrypted and compressed";
784 av_log(s
, AV_LOG_WARNING
, "Skipping %s ID3v2 frame %s.\n", type
, tag
);
786 /* check for text tag or supported special meta tag */
787 } else if (tag
[0] == 'T' ||
789 (extra_func
= get_extra_meta_func(tag
, isv34
)))) {
792 if (unsync
|| tunsync
|| tcomp
) {
793 av_fast_malloc(&buffer
, &buffer_size
, tlen
);
795 av_log(s
, AV_LOG_ERROR
, "Failed to alloc %d bytes\n", tlen
);
799 if (unsync
|| tunsync
) {
800 int64_t end
= avio_tell(pb
) + tlen
;
804 while (avio_tell(pb
) < end
&& b
- buffer
< tlen
&& !pb
->eof_reached
) {
806 if (*(b
- 1) == 0xff && avio_tell(pb
) < end
- 1 &&
809 uint8_t val
= avio_r8(pb
);
810 *b
++ = val
? val
: avio_r8(pb
);
813 ffio_init_context(&pb_local
, buffer
, b
- buffer
, 0, NULL
, NULL
, NULL
,
816 pbx
= &pb_local
; // read from sync buffer
823 av_log(s
, AV_LOG_DEBUG
, "Compresssed frame %s tlen=%d dlen=%ld\n", tag
, tlen
, dlen
);
825 av_fast_malloc(&uncompressed_buffer
, &uncompressed_buffer_size
, dlen
);
826 if (!uncompressed_buffer
) {
827 av_log(s
, AV_LOG_ERROR
, "Failed to alloc %ld bytes\n", dlen
);
831 if (!(unsync
|| tunsync
)) {
832 err
= avio_read(pb
, buffer
, tlen
);
834 av_log(s
, AV_LOG_ERROR
, "Failed to read compressed tag\n");
840 err
= uncompress(uncompressed_buffer
, &dlen
, buffer
, tlen
);
842 av_log(s
, AV_LOG_ERROR
, "Failed to uncompress tag: %d\n", err
);
845 ffio_init_context(&pb_local
, uncompressed_buffer
, dlen
, 0, NULL
, NULL
, NULL
, NULL
);
847 pbx
= &pb_local
; // read from sync buffer
852 read_ttag(s
, pbx
, tlen
, metadata
, tag
);
854 /* parse special meta tag */
855 extra_func
->read(s
, pbx
, tlen
, tag
, extra_meta
, isv34
);
856 } else if (!tag
[0]) {
858 av_log(s
, AV_LOG_WARNING
, "invalid frame id, assuming padding\n");
862 /* Skip to end of tag */
864 avio_seek(pb
, next
, SEEK_SET
);
867 /* Footer preset, always 10 bytes, skip over it */
868 if (version
== 4 && flags
& 0x10)
873 av_log(s
, AV_LOG_INFO
, "ID3v2.%d tag skipped, cannot handle %s\n",
875 avio_seek(pb
, end
, SEEK_SET
);
877 av_free(uncompressed_buffer
);
881 static void id3v2_read_internal(AVIOContext
*pb
, AVDictionary
**metadata
,
882 AVFormatContext
*s
, const char *magic
,
883 ID3v2ExtraMeta
**extra_meta
, int64_t max_search_size
)
886 uint8_t buf
[ID3v2_HEADER_SIZE
];
890 if (max_search_size
&& max_search_size
< ID3v2_HEADER_SIZE
)
893 start
= avio_tell(pb
);
895 /* save the current offset in case there's nothing to read/skip */
897 if (max_search_size
&& off
- start
>= max_search_size
- ID3v2_HEADER_SIZE
) {
898 avio_seek(pb
, off
, SEEK_SET
);
902 ret
= avio_read(pb
, buf
, ID3v2_HEADER_SIZE
);
903 if (ret
!= ID3v2_HEADER_SIZE
) {
904 avio_seek(pb
, off
, SEEK_SET
);
907 found_header
= ff_id3v2_match(buf
, magic
);
909 /* parse ID3v2 header */
910 len
= ((buf
[6] & 0x7f) << 21) |
911 ((buf
[7] & 0x7f) << 14) |
912 ((buf
[8] & 0x7f) << 7) |
914 id3v2_parse(pb
, metadata
, s
, len
, buf
[3], buf
[5], extra_meta
);
916 avio_seek(pb
, off
, SEEK_SET
);
918 } while (found_header
);
919 ff_metadata_conv(metadata
, NULL
, ff_id3v2_34_metadata_conv
);
920 ff_metadata_conv(metadata
, NULL
, id3v2_2_metadata_conv
);
921 ff_metadata_conv(metadata
, NULL
, ff_id3v2_4_metadata_conv
);
922 merge_date(metadata
);
925 void ff_id3v2_read_dict(AVIOContext
*pb
, AVDictionary
**metadata
,
926 const char *magic
, ID3v2ExtraMeta
**extra_meta
)
928 id3v2_read_internal(pb
, metadata
, NULL
, magic
, extra_meta
, 0);
931 void ff_id3v2_read(AVFormatContext
*s
, const char *magic
,
932 ID3v2ExtraMeta
**extra_meta
, unsigned int max_search_size
)
934 id3v2_read_internal(s
->pb
, &s
->metadata
, s
, magic
, extra_meta
, max_search_size
);
937 void ff_id3v2_free_extra_meta(ID3v2ExtraMeta
**extra_meta
)
939 ID3v2ExtraMeta
*current
= *extra_meta
, *next
;
940 const ID3v2EMFunc
*extra_func
;
943 if ((extra_func
= get_extra_meta_func(current
->tag
, 1)))
944 extra_func
->free(current
->data
);
945 next
= current
->next
;
953 int ff_id3v2_parse_apic(AVFormatContext
*s
, ID3v2ExtraMeta
**extra_meta
)
957 for (cur
= *extra_meta
; cur
; cur
= cur
->next
) {
958 ID3v2ExtraMetaAPIC
*apic
;
961 if (strcmp(cur
->tag
, "APIC"))
965 if (!(st
= avformat_new_stream(s
, NULL
)))
966 return AVERROR(ENOMEM
);
968 st
->disposition
|= AV_DISPOSITION_ATTACHED_PIC
;
969 st
->codec
->codec_type
= AVMEDIA_TYPE_VIDEO
;
970 st
->codec
->codec_id
= apic
->id
;
971 av_dict_set(&st
->metadata
, "title", apic
->description
, 0);
972 av_dict_set(&st
->metadata
, "comment", apic
->type
, 0);
974 av_init_packet(&st
->attached_pic
);
975 st
->attached_pic
.buf
= apic
->buf
;
976 st
->attached_pic
.data
= apic
->buf
->data
;
977 st
->attached_pic
.size
= apic
->buf
->size
- FF_INPUT_BUFFER_PADDING_SIZE
;
978 st
->attached_pic
.stream_index
= st
->index
;
979 st
->attached_pic
.flags
|= AV_PKT_FLAG_KEY
;