1 /*
2 * Copyright (c) 2003 Fabrice Bellard
3 *
4 * This file is part of FFmpeg.
5 *
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.
10 *
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.
15 *
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
19 */
20
21 /**
22 * @file
23 * ID3v2 header parser
24 *
25 * Specifications available at:
26 * http://id3.org/Developer_Information
27 */
28
30
31 #if CONFIG_ZLIB
32 #include <zlib.h>
33 #endif
34
43
45 { "TALB", "album" },
46 { "TCOM", "composer" },
47 { "TCON", "genre" },
48 { "TCOP", "copyright" },
49 { "TENC", "encoded_by" },
50 { "TIT2", "title" },
51 { "TLAN", "language" },
52 { "TPE1", "artist" },
53 { "TPE2", "album_artist" },
54 { "TPE3", "performer" },
55 { "TPOS", "disc" },
56 { "TPUB", "publisher" },
57 { "TRCK", "track" },
58 { "TSSE", "encoder" },
59 { "USLT", "lyrics" },
60 { 0 }
61 };
62
64 { "TCMP", "compilation" },
65 { "TDRC", "date" },
66 { "TDRL", "date" },
67 { "TDEN", "creation_time" },
68 { "TSOA", "album-sort" },
69 { "TSOP", "artist-sort" },
70 { "TSOT", "title-sort" },
71 { 0 }
72 };
73
75 { "TAL", "album" },
76 { "TCO", "genre" },
77 { "TCP", "compilation" },
78 { "TT2", "title" },
79 { "TEN", "encoded_by" },
80 { "TP1", "artist" },
81 { "TP2", "album_artist" },
82 { "TP3", "performer" },
83 { "TRK", "track" },
84 { 0 }
85 };
86
88 "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT",
89 "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED",
90 "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3",
91 "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE",
92 { 0 },
93 };
94
96 "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO",
97 "TPRO", "TSOA", "TSOP", "TSOT", "TSST",
98 { 0 },
99 };
100
102 "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER",
103 { 0 },
104 };
105
107 "Other",
108 "32x32 pixels 'file icon'",
109 "Other file icon",
110 "Cover (front)",
111 "Cover (back)",
112 "Leaflet page",
113 "Media (e.g. label side of CD)",
114 "Lead artist/lead performer/soloist",
115 "Artist/performer",
116 "Conductor",
117 "Band/Orchestra",
118 "Composer",
119 "Lyricist/text writer",
120 "Recording Location",
121 "During recording",
122 "During performance",
123 "Movie/video screen capture",
124 "A bright coloured fish",
125 "Illustration",
126 "Band/artist logotype",
127 "Publisher/Studio logotype",
128 };
129
140 };
141
143 {
144 return buf[0] == magic[0] &&
145 buf[1] == magic[1] &&
146 buf[2] == magic[2] &&
147 buf[3] != 0xff &&
148 buf[4] != 0xff &&
149 (buf[6] & 0x80) == 0 &&
150 (buf[7] & 0x80) == 0 &&
151 (buf[8] & 0x80) == 0 &&
152 (buf[9] & 0x80) == 0;
153 }
154
156 {
157 int len = ((buf[6] & 0x7f) << 21) +
158 ((buf[7] & 0x7f) << 14) +
159 ((buf[8] & 0x7f) << 7) +
160 (buf[9] & 0x7f) +
162 if (buf[5] & 0x10)
165 }
166
168 {
169 int v = 0;
170 while (len--)
171 v = (v << 7) + (
avio_r8(s) & 0x7F);
172 return v;
173 }
174
176 {
177 return (((size) & (0x7f << 0)) >> 0) +
178 (((
size) & (0x7f << 8)) >> 1) +
179 (((
size) & (0x7f << 16)) >> 2) +
180 (((
size) & (0x7f << 24)) >> 3);
181 }
182
183 /* No real verification, only check that the tag consists of
184 * a combination of capital alpha-numerical characters */
186 {
187 if (!len)
188 return 0;
189
190 while (len--)
191 if ((buf[len] < 'A' ||
192 buf[len] > 'Z') &&
193 (buf[len] < '0' ||
194 buf[len] > '9'))
195 return 0;
196
197 return 1;
198 }
199
200 /**
201 * Return 1 if the tag of length len at the given offset is valid, 0 if not, -1 on error
202 */
204 {
206
207 if (len > 4 ||
210 return -1;
212 return 1;
213
214 return 0;
215 }
216
217 /**
218 * Free GEOB type extra metadata.
219 */
221 {
228 }
229
230 /**
231 * Decode characters to UTF-8 according to encoding type. The decoded buffer is
232 * always null terminated. Stop reading when either *maxread bytes are read from
233 * pb or U+0000 character is found.
234 *
235 * @param dst Pointer where the address of the buffer with the decoded bytes is
236 * stored. Buffer must be freed by caller.
237 * @param maxread Pointer to maximum number of characters to read from the
238 * AVIOContext. After execution the value is decremented by the number of bytes
239 * actually read.
240 * @returns 0 if no error occurred, dst is uninitialized on error
241 */
244 {
245 int ret;
248 int left = *maxread;
251
254 return ret;
255 }
256
257 switch (encoding) {
259 while (left && ch) {
262 left--;
263 }
264 break;
265
267 if ((left -= 2) < 0) {
272 }
274 case 0xfffe:
276 case 0xfeff:
277 break;
278 default:
282 *maxread = left;
284 }
285 // fall-through
286
288 while ((left > 1) && ch) {
289 GET_UTF16(ch, ((left -= 2) >= 0 ?
get(pb) : 0),
break;)
291 }
292 if (left < 0)
293 left += 2; /* did not read last char from pb */
294 break;
295
297 while (left && ch) {
300 left--;
301 }
302 break;
303 default:
305 }
306
307 if (ch)
309
311 *maxread = left;
312
313 return 0;
314 }
315
316 /**
317 * Parse a text tag.
318 */
321 {
324 unsigned genre;
325
326 if (taglen < 1)
327 return;
328
330 taglen--; /* account for encoding type byte */
331
332 if (
decode_str(s, pb, encoding, &dst, &taglen) < 0) {
334 return;
335 }
336
337 if (!(strcmp(key, "TCON") && strcmp(key, "TCO")) &&
338 (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1) &&
342 } else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) {
343 /* dst now contains the key, need to get value */
344 key = dst;
345 if (
decode_str(s, pb, encoding, &dst, &taglen) < 0) {
348 return;
349 }
351 } else if (!*dst)
353
354 if (dst)
356 }
357
360 {
362 uint8_t *descriptor =
NULL;
// 'Content descriptor'
365 int encoding;
366 int ok = 0;
367
368 if (taglen < 1)
370
372 taglen--;
373
376 lang[3] = '0円';
377 taglen -= 3;
378
379 if (
decode_str(s, pb, encoding, &descriptor, &taglen) < 0)
381
382 if (
decode_str(s, pb, encoding, &text, &taglen) < 0)
384
385 // FFmpeg does not support hierarchical metadata, so concatenate the keys.
386 key =
av_asprintf(
"lyrics-%s%s%s", descriptor[0] ? (
char *)descriptor :
"",
387 descriptor[0] ? "-" : "",
388 lang);
389 if (!key)
391
393
394 ok = 1;
396 if (!ok)
401 }
402
403 /**
404 * Parse a comment tag.
405 */
408 {
409 const char *
key =
"comment";
413
414 if (taglen < 4)
415 return;
416
419 taglen -= 4;
420
421 if (
decode_str(s, pb, encoding, &dst, &taglen) < 0) {
423 return;
424 }
425
426 if (dst && !*dst)
428
429 if (dst) {
430 key = (const char *) dst;
432 }
433
434 if (
decode_str(s, pb, encoding, &dst, &taglen) < 0) {
438 return;
439 }
440
441 if (dst)
442 av_dict_set(metadata, key, (
const char *) dst, dict_flags);
443 }
444
445 /**
446 * Parse GEOB tag into a ID3v2ExtraMetaGEOB struct.
447 */
450 int isv34)
451 {
454 char encoding;
456
457 if (taglen < 1)
458 return;
459
461 if (!geob_data) {
464 return;
465 }
466
468 if (!new_extra) {
472 }
473
474 /* read encoding type byte */
476 taglen--;
477
478 /* read MIME type (always ISO-8859) */
480 &taglen) < 0 ||
481 taglen <= 0)
483
484 /* read file name */
486 taglen <= 0)
488
489 /* read content description */
491 taglen < 0)
493
494 if (taglen) {
495 /* save encapsulated binary data */
497 if (!geob_data->
data) {
500 }
503 "Error reading GEOB frame, data truncated.\n");
505 } else {
508 }
509
510 /* add data to the list */
511 new_extra->
tag =
"GEOB";
512 new_extra->
data = geob_data;
513 new_extra->
next = *extra_meta;
514 *extra_meta = new_extra;
515
516 return;
517
522 return;
523 }
524
526 {
527 while (*str >= '0' && *str <= '9')
528 str++;
529 return !*str;
530 }
531
533 {
537 return t;
539 }
540
542 {
544 char date[17] = { 0 }; // YYYY-MM-DD hh:mm
545
548 return;
552
559
563 snprintf(date + 10,
sizeof(date) - 10,
567
569 if (date[0])
571 }
572
574 {
579 }
580
582 {
583 size_t len = strlen(buf);
584 while (len > 0 && buf[len - 1] == ' ')
586 }
587
590 int isv34)
591 {
592 int enc, pic_type;
593 char mimetype[64];
599
600 if (taglen <= 4 || (!isv34 && taglen <= 6))
602
605 if (!new_extra || !apic)
607
609 taglen--;
610
611 /* mimetype */
612 if (isv34) {
613 taglen -=
avio_get_str(pb, taglen, mimetype,
sizeof(mimetype));
614 } else {
616 mimetype[3] = 0;
617 taglen -= 3;
618 }
619
623 break;
624 }
625 mime++;
626 }
629 "Unknown attached picture mimetype: %s, skipping.\n", mimetype);
631 }
633
634 /* picture type */
636 taglen--;
639 pic_type);
640 pic_type = 0;
641 }
643
644 /* description and picture data */
647 "Error decoding attached picture description.\n");
649 }
650
655
656 new_extra->
tag =
"APIC";
657 new_extra->
data = apic;
658 new_extra->
next = *extra_meta;
659 *extra_meta = new_extra;
660
661 // The description must be unique, and some ID3v2 tag writers add spaces
662 // to write several APIC entries with the same description.
664
665 return;
666
668 if (apic)
672 }
673
675 {
680 }
681
683 {
684 int taglen;
688
691
692 if (!new_extra || !chap)
694
697
698 if (len < 16)
700
704
705 len -= 16;
706 while (len > 10) {
709 tag[4] = 0;
712 len -= 10;
713 if (taglen < 0 || taglen > len)
715 if (tag[0] == 'T')
717 else
719 len -= taglen;
720 }
721
724
725 new_extra->
tag =
"CHAP";
726 new_extra->
data = chap;
727 new_extra->
next = *extra_meta;
728 *extra_meta = new_extra;
729
730 return;
731
733 if (chap)
736 }
737
739 {
744 }
745
748 {
751
754
755 if (!meta || !priv)
757
760
764
766
769
772 meta->
next = *extra_meta;
773 *extra_meta = meta;
774
775 return;
776
778 if (priv)
781 }
782
788 int isv34);
791
798 };
799
800 /**
801 * Get the corresponding ID3v2EMFunc struct for a tag.
802 * @param isv34 Determines if v2.2 or v2.3/4 strings are used
803 * @return A pointer to the ID3v2EMFunc struct if found, NULL otherwise.
804 */
806 {
807 int i = 0;
808 while (id3v2_extra_meta_funcs[i].tag3) {
809 if (tag && !memcmp(tag,
810 (isv34 ? id3v2_extra_meta_funcs[i].tag4 :
811 id3v2_extra_meta_funcs[i].tag3),
812 (isv34 ? 4 : 3)))
813 return &id3v2_extra_meta_funcs[i];
814 i++;
815 }
817 }
818
822 {
823 int isv34, unsync;
824 unsigned tlen;
827 int taghdrlen;
828 const char *reason =
NULL;
832 int buffer_size = 0;
834 unsigned char *uncompressed_buffer =
NULL;
835 av_unused int uncompressed_buffer_size = 0;
836 const char *comm_frame;
837
839
840 switch (version) {
841 case 2:
842 if (flags & 0x40) {
843 reason = "compression";
845 }
846 isv34 = 0;
847 taghdrlen = 6;
848 comm_frame = "COM";
849 break;
850
851 case 3:
852 case 4:
853 isv34 = 1;
854 taghdrlen = 10;
855 comm_frame = "COMM";
856 break;
857
858 default:
859 reason = "version";
861 }
862
863 unsync = flags & 0x80;
864
865 if (isv34 && flags & 0x40) { /* Extended header present, just skip over it */
867 if (version == 4)
868 /* In v2.4 the length includes the length field we just read. */
869 extlen -= 4;
870
871 if (extlen < 0) {
872 reason = "invalid extended header length";
874 }
876 len -= extlen + 4;
877 if (len < 0) {
878 reason = "extended header too long.";
880 }
881 }
882
883 while (len >= taghdrlen) {
884 unsigned int tflags = 0;
885 int tunsync = 0;
886 int tcomp = 0;
887 int tencr = 0;
889
890 if (isv34) {
892 break;
893 tag[4] = 0;
894 if (version == 3) {
896 } else {
897 /* some encoders incorrectly uses v3 sizes instead of syncsafe ones
898 * so check the next tag to see which one to use */
900 if (tlen > 0x7f) {
901 if (tlen < len) {
903
905 break;
906
909 else if (
check_tag(pb, cur + 2 + tlen, 4) != 1)
910 break;
912 } else
914 }
915 }
918 } else {
920 break;
921 tag[3] = 0;
923 }
924 if (tlen > (1<<28))
925 break;
926 len -= taghdrlen + tlen;
927
928 if (len < 0)
929 break;
930
932
933 if (!tlen) {
934 if (tag[0])
936 tag);
937 continue;
938 }
939
941 if (tlen < 4)
942 break;
944 tlen -= 4;
945 } else
946 dlen = tlen;
947
950
951 /* skip encrypted tags and, if no zlib, compressed tags */
952 if (tencr || (!CONFIG_ZLIB && tcomp)) {
954 if (!tcomp)
955 type = "encrypted";
956 else if (!tencr)
957 type = "compressed";
958 else
959 type = "encrypted and compressed";
960
963 /* check for text tag or supported special meta tag */
964 } else if (tag[0] == 'T' ||
965 !memcmp(tag, "USLT", 4) ||
966 !strcmp(tag, comm_frame) ||
967 (extra_meta &&
969 pbx = pb;
970
971 if (unsync || tunsync || tcomp) {
973 if (!buffer) {
975 goto seek;
976 }
977 }
978 if (unsync || tunsync) {
982
983 if (
avio_read(pb, buffer, tlen) != tlen) {
985 goto seek;
986 }
987
988 while (t != end) {
989 *b++ = *t++;
990 if (t != end && t[-1] == 0xff && !t[0])
991 t++;
992 }
993
997 pbx = &pb_local; // read from sync buffer
998 }
999
1000 #if CONFIG_ZLIB
1001 if (tcomp) {
1002 int err;
1003
1005
1006 av_fast_malloc(&uncompressed_buffer, &uncompressed_buffer_size, dlen);
1007 if (!uncompressed_buffer) {
1009 goto seek;
1010 }
1011
1012 if (!(unsync || tunsync)) {
1014 if (err < 0) {
1016 goto seek;
1017 }
1018 tlen = err;
1019 }
1020
1021 err = uncompress(uncompressed_buffer, &dlen, buffer, tlen);
1022 if (err != Z_OK) {
1024 goto seek;
1025 }
1027 tlen = dlen;
1028 pbx = &pb_local; // read from sync buffer
1029 }
1030 #endif
1031 if (tag[0] == 'T')
1032 /* parse text tag */
1034 else if (!memcmp(tag, "USLT", 4))
1036 else if (!strcmp(tag, comm_frame))
1038 else
1039 /* parse special meta tag */
1040 extra_func->
read(s, pbx, tlen, tag, extra_meta, isv34);
1041 } else if (!tag[0]) {
1042 if (tag[1])
1045 break;
1046 }
1047 /* Skip to end of tag */
1048 seek:
1050 }
1051
1052 /* Footer preset, always 10 bytes, skip over it */
1053 if (version == 4 && flags & 0x10)
1054 end += 10;
1055
1057 if (reason)
1059 version, reason);
1063 return;
1064 }
1065
1069 {
1072 int found_header;
1074
1076 return;
1077
1079 do {
1080 /* save the current offset in case there's nothing to read/skip */
1084 break;
1085 }
1086
1088 if (ret >= 0)
1092 break;
1093 }
1095 if (found_header) {
1096 /* parse ID3v2 header */
1097 len = ((buf[6] & 0x7f) << 21) |
1098 ((buf[7] & 0x7f) << 14) |
1099 ((buf[8] & 0x7f) << 7) |
1100 (buf[9] & 0x7f);
1101 id3v2_parse(pb, metadata, s, len, buf[3], buf[5], extra_meta);
1102 } else {
1104 }
1105 } while (found_header);
1110 }
1111
1114 {
1116 }
1117
1120 {
1122 }
1123
1125 {
1128
1129 while (current) {
1132 next = current->
next;
1134 current = next;
1135 }
1136
1138 }
1139
1141 {
1143
1144 for (cur = *extra_meta; cur; cur = cur->
next) {
1147
1148 if (strcmp(cur->
tag,
"APIC"))
1149 continue;
1151
1154
1158
1161
1164
1166
1173
1175 }
1176
1177 return 0;
1178 }
1179
1181 {
1182 int ret = 0;
1186 int num_chapters = 0;
1187 int i;
1188
1189 // since extra_meta is a linked list where elements are prepended,
1190 // we need to reverse the order of chapters
1191 for (cur = *extra_meta; cur; cur = cur->
next) {
1193
1194 if (strcmp(cur->
tag,
"CHAP"))
1195 continue;
1197
1200 }
1201
1202 for (i = 0; i < (num_chapters / 2); i++) {
1204 int right_index;
1205
1206 right_index = (num_chapters - 1) - i;
1207 right = chapters[right_index];
1208
1209 chapters[right_index] = chapters[i];
1210 chapters[i] = right;
1211 }
1212
1213 for (i = 0; i < num_chapters; i++) {
1216
1217 chap = chapters[i];
1219 if (!chapter)
1220 continue;
1221
1224 }
1225
1228 return ret;
1229 }
1230
1232 {
1235
1236 for (cur = *extra_meta; cur; cur = cur->
next) {
1237 if (!strcmp(cur->
tag,
"PRIV")) {
1239 AVBPrint bprint;
1240 char *escaped, *
key;
1241 int i, ret;
1242
1245 }
1246
1248
1249 for (i = 0; i < priv->
datasize; i++) {
1250 if (priv->
data[i] < 32 || priv->
data[i] > 126 || priv->
data[i] ==
'\\') {
1252 } else {
1254 }
1255 }
1256
1259 return ret;
1260 }
1261
1262 if ((ret =
av_dict_set(metadata, key, escaped, dict_flags)) < 0) {
1265 return ret;
1266 }
1267 }
1268 }
1269
1270 return 0;
1271 }
1272
1274 {
1276 }
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
void av_bprintf(AVBPrint *buf, const char *fmt,...)
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
static int is_number(const char *str)
static AVDictionaryEntry * get_date_tag(AVDictionary *m, const char *tag)
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_DICT_DONT_OVERWRITE
Don't overwrite existing entries.
static const ID3v2EMFunc id3v2_extra_meta_funcs[]
static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata, AVFormatContext *s, int len, uint8_t version, uint8_t flags, ID3v2ExtraMeta **extra_meta)
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
int index
stream index in AVFormatContext
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
#define ID3v2_PRIV_METADATA_PREFIX
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, const char *tag, ID3v2ExtraMeta **extra_meta, int isv34)
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
static void free_apic(void *obj)
const char ff_id3v2_4_tags[][4]
ID3v2.4-only text information frames.
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
#define PUT_UTF8(val, tmp, PUT_BYTE)
Convert a 32-bit Unicode character to its UTF-8 encoded form (up to 4 bytes long).
unsigned int avio_rb16(AVIOContext *s)
int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta **extra_meta)
Create a stream for each APIC (attached picture) extracted from the ID3v2 header. ...
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, uint8_t **dst, int *maxread)
Decode characters to UTF-8 according to encoding type.
#define AV_DICT_DONT_STRDUP_KEY
Take ownership of a key that's been allocated with av_malloc() or another memory allocation function...
void(* read)(AVFormatContext *s, AVIOContext *pb, int taglen, const char *tag, ID3v2ExtraMeta **extra_meta, int isv34)
static void id3v2_read_internal(AVIOContext *pb, AVDictionary **metadata, AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta, int64_t max_search_size)
#define ID3v2_HEADER_SIZE
const AVMetadataConv ff_id3v2_34_metadata_conv[]
int ff_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta **extra_meta)
Create chapters for all CHAP tags found in the ID3v2 header.
unsigned int avio_rb32(AVIOContext *s)
static av_cold int end(AVCodecContext *avctx)
int ff_id3v2_parse_priv_dict(AVDictionary **metadata, ID3v2ExtraMeta **extra_meta)
Parse PRIV tags into a dictionary.
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
static void read_priv(AVFormatContext *s, AVIOContext *pb, int taglen, const char *tag, ID3v2ExtraMeta **extra_meta, int isv34)
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_RB32
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
Add an element to a dynamic array.
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
static int is_tag(const char *buf, unsigned int len)
#define GET_UTF16(val, GET_16BIT, ERROR)
Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form.
AVCodecID
Identify the syntax and semantics of the bitstream.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
#define AV_DICT_MATCH_CASE
Only get an entry with exact-case key match.
AVDictionary * metadata
Metadata that applies to the whole file.
#define AV_BPRINT_SIZE_UNLIMITED
const AVMetadataConv ff_id3v2_4_metadata_conv[]
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
static void free_priv(void *obj)
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
int ff_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta **extra_meta)
Add metadata for all PRIV tags in the ID3v2 header.
enum AVMediaType codec_type
General type of the encoded data.
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta)
Free memory allocated parsing special (non-text) metadata.
static void read_comment(AVFormatContext *s, AVIOContext *pb, int taglen, AVDictionary **metadata)
Parse a comment tag.
static const uint8_t offset[127][2]
size_t av_strlcpy(char *dst, const char *src, size_t size)
Copy the string src to dst, but no more than size - 1 bytes, and null-terminate dst.
int flags
A combination of AV_PKT_FLAG values.
static unsigned int size_to_syncsafe(unsigned int size)
int avio_r8(AVIOContext *s)
char * av_asprintf(const char *fmt,...)
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
const CodecMime ff_id3v2_mime_tags[]
unsigned int avio_rb24(AVIOContext *s)
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that's been allocated with av_malloc() or another memory allocation functio...
static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, AVDictionary **metadata, const char *key)
Parse a text tag.
typedef void(APIENTRY *FF_PFNGLACTIVETEXTUREPROC)(GLenum texture)
static void free_geobtag(void *obj)
Free GEOB type extra metadata.
static unsigned int get_size(AVIOContext *s, int len)
static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, const char *tag, ID3v2ExtraMeta **extra_meta, int isv34)
Parse GEOB tag into a ID3v2ExtraMetaGEOB struct.
#define ID3v2_FLAG_UNSYNCH
static void error(const char *err)
#define FF_ARRAY_ELEMS(a)
static void merge_date(AVDictionary **m)
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
const char ff_id3v2_tags[][4]
A list of text information frames allowed in both ID3 v2.3 and v2.4 http://www.id3.org/id3v2.4.0-frames http://www.id3.org/id3v2.4.0-changes.
#define AV_LOG_INFO
Standard information.
char * av_strdup(const char *s)
Duplicate a string.
AVBufferRef * av_buffer_alloc(int size)
Allocate an AVBuffer of the given size using av_malloc().
AVIOContext * pb
I/O context.
void avio_w8(AVIOContext *s, int b)
uint8_t * data
The data buffer.
#define ID3v2_FLAG_COMPRESSION
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Rational number (pair of numerator and denominator).
int size
Size of data in bytes.
static void read_uslt(AVFormatContext *s, AVIOContext *pb, int taglen, AVDictionary **metadata)
static int check_tag(AVIOContext *s, int offset, unsigned int len)
Return 1 if the tag of length len at the given offset is valid, 0 if not, -1 on error.
static void rstrip_spaces(char *buf)
static const ID3v2EMFunc * get_extra_meta_func(const char *tag, int isv34)
Get the corresponding ID3v2EMFunc struct for a tag.
int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
Ensures that the requested seekback buffer size will be available.
static void free_chapter(void *obj)
unsigned int avio_rl16(AVIOContext *s)
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_RB64
int ff_id3v2_match(const uint8_t *buf, const char *magic)
Detect ID3v2 Header.
int ffio_init_context(AVIOContext *s, unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int(*read_packet)(void *opaque, uint8_t *buf, int buf_size), int(*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t(*seek)(void *opaque, int64_t offset, int whence))
int disposition
AV_DISPOSITION_* bit field.
#define ID3v2_FLAG_ENCRYPTION
void av_init_packet(AVPacket *pkt)
Initialize optional fields of a packet with default values.
void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta, unsigned int max_search_size)
Read an ID3v2 tag, including supported extra metadata.
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
const char ff_id3v2_3_tags[][4]
ID3v2.3-only text information frames.
void ff_id3v2_read_dict(AVIOContext *pb, AVDictionary **metadata, const char *magic, ID3v2ExtraMeta **extra_meta)
Read an ID3v2 tag into specified dictionary and retrieve supported extra metadata.
int ff_id3v2_tag_len(const uint8_t *buf)
Get the length of an ID3v2 tag.
AVCodecParameters * codecpar
Codec parameters associated with this stream.
const char *const ff_id3v2_picture_types[21]
int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen)
Read a string from pb into buf.
unsigned int avio_rl24(AVIOContext *s)
#define ID3v2_FLAG_DATALEN
const char *const ff_id3v1_genre_str[ID3v1_GENRE_MAX+1]
ID3v1 genres.
static void read_chapter(AVFormatContext *s, AVIOContext *pb, int len, const char *ttag, ID3v2ExtraMeta **extra_meta, int isv34)
AVPacket attached_pic
For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet will contain the attached pictu...
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(constuint8_t *) pi-0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(constint16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(constint32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(constint64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64,*(constint64_t *) pi *(1.0f/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64,*(constint64_t *) pi *(1.0/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(constfloat *) pi *(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(constdouble *) pi *(INT64_C(1)<< 63)))#defineFMT_PAIR_FUNC(out, in) staticconv_func_type *constfmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64),};staticvoidcpy1(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, len);}staticvoidcpy2(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 2 *len);}staticvoidcpy4(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 4 *len);}staticvoidcpy8(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 8 *len);}AudioConvert *swri_audio_convert_alloc(enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, constint *ch_map, intflags){AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) returnNULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) returnNULL;if(channels==1){in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);}ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map){switch(av_get_bytes_per_sample(in_fmt)){case1:ctx->simd_f=cpy1;break;case2:ctx->simd_f=cpy2;break;case4:ctx->simd_f=cpy4;break;case8:ctx->simd_f=cpy8;break;}}if(HAVE_X86ASM &&1) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);returnctx;}voidswri_audio_convert_free(AudioConvert **ctx){av_freep(ctx);}intswri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, intlen){intch;intoff=0;constintos=(out->planar?1:out->ch_count)*out->bps;unsignedmisaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask){intplanes=in->planar?in->ch_count:1;unsignedm=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;}if(ctx->out_simd_align_mask){intplanes=out->planar?out->ch_count:1;unsignedm=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;}if(ctx->simd_f &&!ctx->ch_map &&!misaligned){off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){if(out->planar==in->planar){intplanes=out->planar?out->ch_count:1;for(ch=0;ch< planes;ch++){ctx->simd_f(out-> ch ch
static const AVMetadataConv id3v2_2_metadata_conv[]
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.