FFmpeg
id3v2.c
Go to the documentation of this file.
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 
29 #include "config.h"
30 
31 #if CONFIG_ZLIB
32 #include <zlib.h>
33 #endif
34 
35 #include "libavutil/avstring.h"
36 #include "libavutil/bprint.h"
37 #include "libavutil/dict.h"
38 #include "libavutil/intreadwrite.h"
39 #include "libavutil/mem.h"
40 #include "libavcodec/png.h"
41 #include "avio_internal.h"
42 #include "demux.h"
43 #include "id3v1.h"
44 #include "id3v2.h"
45 
47  { "TALB", "album" },
48  { "TCOM", "composer" },
49  { "TCON", "genre" },
50  { "TCOP", "copyright" },
51  { "TENC", "encoded_by" },
52  { "TIT2", "title" },
53  { "TLAN", "language" },
54  { "TPE1", "artist" },
55  { "TPE2", "album_artist" },
56  { "TPE3", "performer" },
57  { "TPOS", "disc" },
58  { "TPUB", "publisher" },
59  { "TRCK", "track" },
60  { "TSSE", "encoder" },
61  { "USLT", "lyrics" },
62  { 0 }
63 };
64 
66  { "TCMP", "compilation" },
67  { "TDRC", "date" },
68  { "TDRL", "date" },
69  { "TDEN", "creation_time" },
70  { "TSOA", "album-sort" },
71  { "TSOP", "artist-sort" },
72  { "TSOT", "title-sort" },
73  { "TIT1", "grouping" },
74  { 0 }
75 };
76 
78  { "TAL", "album" },
79  { "TCO", "genre" },
80  { "TCP", "compilation" },
81  { "TT2", "title" },
82  { "TEN", "encoded_by" },
83  { "TP1", "artist" },
84  { "TP2", "album_artist" },
85  { "TP3", "performer" },
86  { "TRK", "track" },
87  { 0 }
88 };
89 
90 const char ff_id3v2_tags[][4] = {
91  "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT",
92  "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED",
93  "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3",
94  "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE",
95  { 0 },
96 };
97 
98 const char ff_id3v2_4_tags[][4] = {
99  "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO",
100  "TPRO", "TSOA", "TSOP", "TSOT", "TSST",
101  { 0 },
102 };
103 
104 const char ff_id3v2_3_tags[][4] = {
105  "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER",
106  { 0 },
107 };
108 
109 const char * const ff_id3v2_picture_types[21] = {
110  "Other",
111  "32x32 pixels 'file icon'",
112  "Other file icon",
113  "Cover (front)",
114  "Cover (back)",
115  "Leaflet page",
116  "Media (e.g. label side of CD)",
117  "Lead artist/lead performer/soloist",
118  "Artist/performer",
119  "Conductor",
120  "Band/Orchestra",
121  "Composer",
122  "Lyricist/text writer",
123  "Recording Location",
124  "During recording",
125  "During performance",
126  "Movie/video screen capture",
127  "A bright coloured fish",
128  "Illustration",
129  "Band/artist logotype",
130  "Publisher/Studio logotype",
131 };
132 
134  { "image/gif", AV_CODEC_ID_GIF },
135  { "image/jpeg", AV_CODEC_ID_MJPEG },
136  { "image/jpg", AV_CODEC_ID_MJPEG },
137  { "image/png", AV_CODEC_ID_PNG },
138  { "image/tiff", AV_CODEC_ID_TIFF },
139  { "image/bmp", AV_CODEC_ID_BMP },
140  { "image/webp", AV_CODEC_ID_WEBP },
141  { "JPG", AV_CODEC_ID_MJPEG }, /* ID3v2.2 */
142  { "PNG", AV_CODEC_ID_PNG }, /* ID3v2.2 */
143  { "", AV_CODEC_ID_NONE },
144 };
145 
146 int ff_id3v2_match(const uint8_t *buf, const char *magic)
147 {
148  return buf[0] == magic[0] &&
149  buf[1] == magic[1] &&
150  buf[2] == magic[2] &&
151  buf[3] != 0xff &&
152  buf[4] != 0xff &&
153  (buf[6] & 0x80) == 0 &&
154  (buf[7] & 0x80) == 0 &&
155  (buf[8] & 0x80) == 0 &&
156  (buf[9] & 0x80) == 0;
157 }
158 
159 int ff_id3v2_tag_len(const uint8_t *buf)
160 {
161  int len = ((buf[6] & 0x7f) << 21) +
162  ((buf[7] & 0x7f) << 14) +
163  ((buf[8] & 0x7f) << 7) +
164  (buf[9] & 0x7f) +
166  if (buf[5] & 0x10)
168  return len;
169 }
170 
171 static unsigned int get_size(AVIOContext *s, int len)
172 {
173  int v = 0;
174  while (len--)
175  v = (v << 7) + (avio_r8(s) & 0x7F);
176  return v;
177 }
178 
179 static unsigned int size_to_syncsafe(unsigned int size)
180 {
181  return (((size) & (0x7f << 0)) >> 0) +
182  (((size) & (0x7f << 8)) >> 1) +
183  (((size) & (0x7f << 16)) >> 2) +
184  (((size) & (0x7f << 24)) >> 3);
185 }
186 
187 /* No real verification, only check that the tag consists of
188  * a combination of capital alpha-numerical characters */
189 static int is_tag(const char *buf, unsigned int len)
190 {
191  if (!len)
192  return 0;
193 
194  while (len--)
195  if ((buf[len] < 'A' ||
196  buf[len] > 'Z') &&
197  (buf[len] < '0' ||
198  buf[len] > '9'))
199  return 0;
200 
201  return 1;
202 }
203 
204 /**
205  * Return 1 if the tag of length len at the given offset is valid, 0 if not, -1 on error
206  */
207 static int check_tag(AVIOContext *s, int offset, unsigned int len)
208 {
209  char tag[4];
210 
211  if (len > 4 ||
212  avio_seek(s, offset, SEEK_SET) < 0 ||
213  avio_read(s, tag, len) < (int)len)
214  return -1;
215  else if (!AV_RB32(tag) || is_tag(tag, len))
216  return 1;
217 
218  return 0;
219 }
220 
221 /**
222  * Free GEOB type extra metadata.
223  */
224 static void free_geobtag(void *obj)
225 {
226  ID3v2ExtraMetaGEOB *geob = obj;
227  av_freep(&geob->mime_type);
228  av_freep(&geob->file_name);
229  av_freep(&geob->description);
230  av_freep(&geob->data);
231 }
232 
233 /**
234  * Decode characters to UTF-8 according to encoding type. The decoded buffer is
235  * always null terminated. Stop reading when either *maxread bytes are read from
236  * pb or U+0000 character is found.
237  *
238  * @param dst Pointer where the address of the buffer with the decoded bytes is
239  * stored. Buffer must be freed by caller.
240  * @param maxread Pointer to maximum number of characters to read from the
241  * AVIOContext. After execution the value is decremented by the number of bytes
242  * actually read.
243  * @returns 0 if no error occurred, dst is uninitialized on error
244  */
245 static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding,
246  uint8_t **dst, int *maxread)
247 {
248  int ret;
249  uint8_t tmp;
250  uint32_t ch = 1;
251  int left = *maxread, dynsize;
252  unsigned int (*get)(AVIOContext*) = avio_rb16;
253  AVIOContext *dynbuf;
254 
255  if ((ret = avio_open_dyn_buf(&dynbuf)) < 0) {
256  av_log(s, AV_LOG_ERROR, "Error opening memory stream\n");
257  return ret;
258  }
259 
260  switch (encoding) {
262  while (left && ch) {
263  ch = avio_r8(pb);
264  PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);)
265  left--;
266  }
267  break;
268 
270  if ((left -= 2) < 0) {
271  av_log(s, AV_LOG_ERROR, "Cannot read BOM value, input too short %d\n", left);
272  ffio_free_dyn_buf(&dynbuf);
273  *dst = NULL;
274  return AVERROR_INVALIDDATA;
275  }
276  uint16_t bom = avio_rb16(pb);
277  switch (bom) {
278  case 0xfffe:
279  get = avio_rl16;
280  case 0xfeff:
281  break;
282  case 0: // empty string without bom
283  ffio_free_dyn_buf(&dynbuf);
284  *dst = NULL;
285  *maxread = left;
286  return 0;
287  default:
288  av_log(s, AV_LOG_ERROR, "Incorrect BOM value: 0x%x\n", bom);
289  ffio_free_dyn_buf(&dynbuf);
290  *dst = NULL;
291  *maxread = left;
292  return AVERROR_INVALIDDATA;
293  }
294  // fall-through
295 
297  while ((left > 1) && ch) {
298  GET_UTF16(ch, ((left -= 2) >= 0 ? get(pb) : 0), break;)
299  PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);)
300  }
301  if (left < 0)
302  left += 2; /* did not read last char from pb */
303  break;
304 
305  case ID3v2_ENCODING_UTF8:
306  while (left && ch) {
307  ch = avio_r8(pb);
308  avio_w8(dynbuf, ch);
309  left--;
310  }
311  break;
312  default:
313  av_log(s, AV_LOG_WARNING, "Unknown encoding %d\n", encoding);
314  }
315 
316  if (ch)
317  avio_w8(dynbuf, 0);
318 
319  dynsize = avio_close_dyn_buf(dynbuf, dst);
320  if (dynsize <= 0) {
321  av_freep(dst);
322  return AVERROR(ENOMEM);
323  }
324  *maxread = left;
325 
326  return 0;
327 }
328 
329 /**
330  * Parse a text tag.
331  */
332 static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen,
333  AVDictionary **metadata, const char *key)
334 {
335  uint8_t *dst;
336  int encoding, dict_flags = AV_DICT_DONT_OVERWRITE | AV_DICT_DONT_STRDUP_VAL;
337  unsigned genre;
338 
339  if (taglen < 1)
340  return;
341 
342  encoding = avio_r8(pb);
343  taglen--; /* account for encoding type byte */
344 
345  if (decode_str(s, pb, encoding, &dst, &taglen) < 0) {
346  av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", key);
347  return;
348  }
349 
350  if (!(strcmp(key, "TCON") && strcmp(key, "TCO")) &&
351  (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1) &&
352  genre <= ID3v1_GENRE_MAX) {
353  av_freep(&dst);
354  dst = av_strdup(ff_id3v1_genre_str[genre]);
355  } else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) {
356  /* dst now contains the key, need to get value */
357  key = dst;
358  if (decode_str(s, pb, encoding, &dst, &taglen) < 0) {
359  av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", key);
360  av_freep(&key);
361  return;
362  }
363  dict_flags |= AV_DICT_DONT_STRDUP_KEY;
364  } else if (!*dst)
365  av_freep(&dst);
366 
367  if (dst)
368  av_dict_set(metadata, key, dst, dict_flags);
369 }
370 
371 static void read_uslt(AVFormatContext *s, AVIOContext *pb, int taglen,
373 {
374  uint8_t lang[4];
375  uint8_t *descriptor = NULL; // 'Content descriptor'
376  uint8_t *text;
377  char *key;
378  int encoding;
379  int ok = 0;
380 
381  if (taglen < 4)
382  goto error;
383 
384  encoding = avio_r8(pb);
385  taglen--;
386 
387  if (avio_read(pb, lang, 3) < 3)
388  goto error;
389  lang[3] = '\0';
390  taglen -= 3;
391 
392  if (decode_str(s, pb, encoding, &descriptor, &taglen) < 0 || taglen < 0)
393  goto error;
394 
395  if (decode_str(s, pb, encoding, &text, &taglen) < 0 || taglen < 0)
396  goto error;
397 
398  // FFmpeg does not support hierarchical metadata, so concatenate the keys.
399  key = av_asprintf("lyrics-%s%s%s", descriptor[0] ? (char *)descriptor : "",
400  descriptor[0] ? "-" : "",
401  lang);
402  if (!key) {
403  av_free(text);
404  goto error;
405  }
406 
407  av_dict_set(metadata, key, text,
409 
410  ok = 1;
411 error:
412  if (!ok)
413  av_log(s, AV_LOG_ERROR, "Error reading lyrics, skipped\n");
414  av_free(descriptor);
415 }
416 
417 /**
418  * Parse a comment tag.
419  */
420 static void read_comment(AVFormatContext *s, AVIOContext *pb, int taglen,
422 {
423  const char *key = "comment";
424  uint8_t *dst;
425  int encoding, dict_flags = AV_DICT_DONT_OVERWRITE | AV_DICT_DONT_STRDUP_VAL;
426  av_unused int language;
427 
428  if (taglen < 4)
429  return;
430 
431  encoding = avio_r8(pb);
432  language = avio_rl24(pb);
433  taglen -= 4;
434 
435  if (decode_str(s, pb, encoding, &dst, &taglen) < 0) {
436  av_log(s, AV_LOG_ERROR, "Error reading comment frame, skipped\n");
437  return;
438  }
439 
440  if (dst && !*dst)
441  av_freep(&dst);
442 
443  if (dst) {
444  key = (const char *) dst;
445  dict_flags |= AV_DICT_DONT_STRDUP_KEY;
446  }
447 
448  if (decode_str(s, pb, encoding, &dst, &taglen) < 0) {
449  av_log(s, AV_LOG_ERROR, "Error reading comment frame, skipped\n");
450  if (dict_flags & AV_DICT_DONT_STRDUP_KEY)
451  av_freep((void*)&key);
452  return;
453  }
454 
455  if (dst)
456  av_dict_set(metadata, key, (const char *) dst, dict_flags);
457 }
458 
459 typedef struct ExtraMetaList {
461 } ExtraMetaList;
462 
464 {
465  if (list->tail)
466  list->tail->next = new_elem;
467  else
468  list->head = new_elem;
469  list->tail = new_elem;
470 }
471 
472 /**
473  * Parse GEOB tag into a ID3v2ExtraMetaGEOB struct.
474  */
475 static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen,
476  const char *tag, ExtraMetaList *extra_meta, int isv34)
477 {
478  ID3v2ExtraMetaGEOB *geob_data = NULL;
479  ID3v2ExtraMeta *new_extra = NULL;
480  char encoding;
481  unsigned int len;
482 
483  if (taglen < 1)
484  return;
485 
486  new_extra = av_mallocz(sizeof(ID3v2ExtraMeta));
487  if (!new_extra) {
488  av_log(s, AV_LOG_ERROR, "Failed to alloc %"SIZE_SPECIFIER" bytes\n",
489  sizeof(ID3v2ExtraMeta));
490  return;
491  }
492 
493  geob_data = &new_extra->data.geob;
494 
495  /* read encoding type byte */
496  encoding = avio_r8(pb);
497  taglen--;
498 
499  /* read MIME type (always ISO-8859) */
500  if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &geob_data->mime_type,
501  &taglen) < 0 ||
502  taglen <= 0)
503  goto fail;
504 
505  /* read file name */
506  if (decode_str(s, pb, encoding, &geob_data->file_name, &taglen) < 0 ||
507  taglen <= 0)
508  goto fail;
509 
510  /* read content description */
511  if (decode_str(s, pb, encoding, &geob_data->description, &taglen) < 0 ||
512  taglen < 0)
513  goto fail;
514 
515  if (taglen) {
516  /* save encapsulated binary data */
517  geob_data->data = av_malloc(taglen);
518  if (!geob_data->data) {
519  av_log(s, AV_LOG_ERROR, "Failed to alloc %d bytes\n", taglen);
520  goto fail;
521  }
522  if ((len = avio_read(pb, geob_data->data, taglen)) < taglen)
524  "Error reading GEOB frame, data truncated.\n");
525  geob_data->datasize = len;
526  } else {
527  geob_data->data = NULL;
528  geob_data->datasize = 0;
529  }
530 
531  /* add data to the list */
532  new_extra->tag = "GEOB";
533  list_append(new_extra, extra_meta);
534 
535  return;
536 
537 fail:
538  av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", tag);
539  free_geobtag(geob_data);
540  av_free(new_extra);
541  return;
542 }
543 
544 static int is_number(const char *str)
545 {
546  while (*str >= '0' && *str <= '9')
547  str++;
548  return !*str;
549 }
550 
552 {
554  if ((t = av_dict_get(m, tag, NULL, AV_DICT_MATCH_CASE)) &&
555  strlen(t->value) == 4 && is_number(t->value))
556  return t;
557  return NULL;
558 }
559 
560 static void merge_date(AVDictionary **m)
561 {
563  char date[17] = { 0 }; // YYYY-MM-DD hh:mm
564 
565  if (!(t = get_date_tag(*m, "TYER")) &&
566  !(t = get_date_tag(*m, "TYE")))
567  return;
568  av_strlcpy(date, t->value, 5);
569  av_dict_set(m, "TYER", NULL, 0);
570  av_dict_set(m, "TYE", NULL, 0);
571 
572  if (!(t = get_date_tag(*m, "TDAT")) &&
573  !(t = get_date_tag(*m, "TDA")))
574  goto finish;
575  snprintf(date + 4, sizeof(date) - 4, "-%.2s-%.2s", t->value + 2, t->value);
576  av_dict_set(m, "TDAT", NULL, 0);
577  av_dict_set(m, "TDA", NULL, 0);
578 
579  if (!(t = get_date_tag(*m, "TIME")) &&
580  !(t = get_date_tag(*m, "TIM")))
581  goto finish;
582  snprintf(date + 10, sizeof(date) - 10,
583  " %.2s:%.2s", t->value, t->value + 2);
584  av_dict_set(m, "TIME", NULL, 0);
585  av_dict_set(m, "TIM", NULL, 0);
586 
587 finish:
588  if (date[0])
589  av_dict_set(m, "date", date, 0);
590 }
591 
592 static void free_apic(void *obj)
593 {
594  ID3v2ExtraMetaAPIC *apic = obj;
595  av_buffer_unref(&apic->buf);
596  av_freep(&apic->description);
597 }
598 
599 static void rstrip_spaces(char *buf)
600 {
601  size_t len = strlen(buf);
602  while (len > 0 && buf[len - 1] == ' ')
603  buf[--len] = 0;
604 }
605 
606 static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen,
607  const char *tag, ExtraMetaList *extra_meta, int isv34)
608 {
609  int enc, pic_type;
610  char mimetype[64] = {0};
611  const CodecMime *mime = ff_id3v2_mime_tags;
612  enum AVCodecID id = AV_CODEC_ID_NONE;
613  ID3v2ExtraMetaAPIC *apic = NULL;
614  ID3v2ExtraMeta *new_extra = NULL;
615  int64_t end = avio_tell(pb) + taglen;
616 
617  if (taglen <= 4 || (!isv34 && taglen <= 6))
618  goto fail;
619 
620  new_extra = av_mallocz(sizeof(*new_extra));
621  if (!new_extra)
622  goto fail;
623 
624  apic = &new_extra->data.apic;
625 
626  enc = avio_r8(pb);
627  taglen--;
628 
629  /* mimetype */
630  if (isv34) {
631  int ret = avio_get_str(pb, taglen, mimetype, sizeof(mimetype));
632  if (ret < 0 || ret >= taglen)
633  goto fail;
634  taglen -= ret;
635  } else {
636  if (avio_read(pb, mimetype, 3) < 0)
637  goto fail;
638 
639  mimetype[3] = 0;
640  taglen -= 3;
641  }
642 
643  while (mime->id != AV_CODEC_ID_NONE) {
644  if (!av_strncasecmp(mime->str, mimetype, sizeof(mimetype))) {
645  id = mime->id;
646  break;
647  }
648  mime++;
649  }
650  if (id == AV_CODEC_ID_NONE) {
652  "Unknown attached picture mimetype: %s, skipping.\n", mimetype);
653  goto fail;
654  }
655  apic->id = id;
656 
657  /* picture type */
658  pic_type = avio_r8(pb);
659  taglen--;
660  if (pic_type < 0 || pic_type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types)) {
661  av_log(s, AV_LOG_WARNING, "Unknown attached picture type %d.\n",
662  pic_type);
663  pic_type = 0;
664  }
665  apic->type = ff_id3v2_picture_types[pic_type];
666 
667  /* description and picture data */
668  if (decode_str(s, pb, enc, &apic->description, &taglen) < 0) {
670  "Error decoding attached picture description.\n");
671  goto fail;
672  }
673 
675  if (!apic->buf || !taglen || avio_read(pb, apic->buf->data, taglen) != taglen)
676  goto fail;
677  memset(apic->buf->data + taglen, 0, AV_INPUT_BUFFER_PADDING_SIZE);
678 
679  new_extra->tag = "APIC";
680 
681  // The description must be unique, and some ID3v2 tag writers add spaces
682  // to write several APIC entries with the same description.
683  rstrip_spaces(apic->description);
684  list_append(new_extra, extra_meta);
685 
686  return;
687 
688 fail:
689  if (apic)
690  free_apic(apic);
691  av_freep(&new_extra);
692  avio_seek(pb, end, SEEK_SET);
693 }
694 
695 static void free_chapter(void *obj)
696 {
697  ID3v2ExtraMetaCHAP *chap = obj;
698  av_freep(&chap->element_id);
699  av_dict_free(&chap->meta);
700 }
701 
703  const char *ttag, ExtraMetaList *extra_meta, int isv34)
704 {
705  int taglen;
706  char tag[5];
707  ID3v2ExtraMeta *new_extra = NULL;
708  ID3v2ExtraMetaCHAP *chap = NULL;
709 
710  new_extra = av_mallocz(sizeof(*new_extra));
711  if (!new_extra)
712  return;
713 
714  chap = &new_extra->data.chap;
715 
716  if (decode_str(s, pb, 0, &chap->element_id, &len) < 0)
717  goto fail;
718 
719  if (len < 16)
720  goto fail;
721 
722  chap->start = avio_rb32(pb);
723  chap->end = avio_rb32(pb);
724  avio_skip(pb, 8);
725 
726  len -= 16;
727  while (len > 10) {
728  if (avio_read(pb, tag, 4) < 4)
729  goto fail;
730  tag[4] = 0;
731  taglen = avio_rb32(pb);
732  avio_skip(pb, 2);
733  len -= 10;
734  if (taglen < 0 || taglen > len)
735  goto fail;
736  if (tag[0] == 'T')
737  read_ttag(s, pb, taglen, &chap->meta, tag);
738  else
739  avio_skip(pb, taglen);
740  len -= taglen;
741  }
742 
745 
746  new_extra->tag = "CHAP";
747  list_append(new_extra, extra_meta);
748 
749  return;
750 
751 fail:
752  free_chapter(chap);
753  av_freep(&new_extra);
754 }
755 
756 static void free_priv(void *obj)
757 {
758  ID3v2ExtraMetaPRIV *priv = obj;
759  av_freep(&priv->owner);
760  av_freep(&priv->data);
761 }
762 
763 static void read_priv(AVFormatContext *s, AVIOContext *pb, int taglen,
764  const char *tag, ExtraMetaList *extra_meta, int isv34)
765 {
766  ID3v2ExtraMeta *meta;
767  ID3v2ExtraMetaPRIV *priv;
768 
769  meta = av_mallocz(sizeof(*meta));
770  if (!meta)
771  return;
772 
773  priv = &meta->data.priv;
774 
775  if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &priv->owner, &taglen) < 0)
776  goto fail;
777 
778  priv->data = av_malloc(taglen);
779  if (!priv->data)
780  goto fail;
781 
782  priv->datasize = taglen;
783 
784  if (avio_read(pb, priv->data, priv->datasize) != priv->datasize)
785  goto fail;
786 
787  meta->tag = "PRIV";
788  list_append(meta, extra_meta);
789 
790  return;
791 
792 fail:
793  free_priv(priv);
794  av_freep(&meta);
795 }
796 
797 typedef struct ID3v2EMFunc {
798  const char *tag3;
799  const char *tag4;
800  void (*read)(AVFormatContext *s, AVIOContext *pb, int taglen,
801  const char *tag, ExtraMetaList *extra_meta,
802  int isv34);
803  void (*free)(void *obj);
804 } ID3v2EMFunc;
805 
807  { "GEO", "GEOB", read_geobtag, free_geobtag },
808  { "PIC", "APIC", read_apic, free_apic },
809  { "CHAP","CHAP", read_chapter, free_chapter },
810  { "PRIV","PRIV", read_priv, free_priv },
811  { NULL }
812 };
813 
814 /**
815  * Get the corresponding ID3v2EMFunc struct for a tag.
816  * @param isv34 Determines if v2.2 or v2.3/4 strings are used
817  * @return A pointer to the ID3v2EMFunc struct if found, NULL otherwise.
818  */
819 static const ID3v2EMFunc *get_extra_meta_func(const char *tag, int isv34)
820 {
821  int i = 0;
822  while (id3v2_extra_meta_funcs[i].tag3) {
823  if (tag && !memcmp(tag,
824  (isv34 ? id3v2_extra_meta_funcs[i].tag4 :
825  id3v2_extra_meta_funcs[i].tag3),
826  (isv34 ? 4 : 3)))
827  return &id3v2_extra_meta_funcs[i];
828  i++;
829  }
830  return NULL;
831 }
832 
834  AVFormatContext *s, int len, uint8_t version,
835  uint8_t flags, ExtraMetaList *extra_meta)
836 {
837  int isv34, unsync;
838  unsigned tlen;
839  char tag[5];
840  int64_t next, end = avio_tell(pb);
841  int taghdrlen;
842  const char *reason = NULL;
843  FFIOContext pb_local;
844  AVIOContext *pbx;
845  unsigned char *buffer = NULL;
846  int buffer_size = 0;
847  const ID3v2EMFunc *extra_func = NULL;
848  unsigned char *uncompressed_buffer = NULL;
849  av_unused int uncompressed_buffer_size = 0;
850  const char *comm_frame;
851 
852  if (end > INT64_MAX - len - 10)
853  return;
854  end += len;
855 
856  av_log(s, AV_LOG_DEBUG, "id3v2 ver:%d flags:%02X len:%d\n", version, flags, len);
857 
858  switch (version) {
859  case 2:
860  if (flags & 0x40) {
861  reason = "compression";
862  goto error;
863  }
864  isv34 = 0;
865  taghdrlen = 6;
866  comm_frame = "COM";
867  break;
868 
869  case 3:
870  case 4:
871  isv34 = 1;
872  taghdrlen = 10;
873  comm_frame = "COMM";
874  break;
875 
876  default:
877  reason = "version";
878  goto error;
879  }
880 
881  unsync = flags & 0x80;
882 
883  if (isv34 && flags & 0x40) { /* Extended header present, just skip over it */
884  int extlen = get_size(pb, 4);
885  if (version == 4)
886  /* In v2.4 the length includes the length field we just read. */
887  extlen -= 4;
888 
889  if (extlen < 0) {
890  reason = "invalid extended header length";
891  goto error;
892  }
893  avio_skip(pb, extlen);
894  len -= extlen + 4;
895  if (len < 0) {
896  reason = "extended header too long.";
897  goto error;
898  }
899  }
900 
901  while (len >= taghdrlen) {
902  unsigned int tflags = 0;
903  int tunsync = 0;
904  int tcomp = 0;
905  int tencr = 0;
906  av_unused unsigned long dlen;
907 
908  if (isv34) {
909  if (avio_read(pb, tag, 4) < 4)
910  break;
911  tag[4] = 0;
912  if (version == 3) {
913  tlen = avio_rb32(pb);
914  } else {
915  /* some encoders incorrectly uses v3 sizes instead of syncsafe ones
916  * so check the next tag to see which one to use */
917  tlen = avio_rb32(pb);
918  if (tlen > 0x7f) {
919  if (tlen < len) {
920  int64_t cur = avio_tell(pb);
921 
922  if (ffio_ensure_seekback(pb, 2 /* tflags */ + tlen + 4 /* next tag */))
923  break;
924 
925  if (check_tag(pb, cur + 2 + size_to_syncsafe(tlen), 4) == 1)
926  tlen = size_to_syncsafe(tlen);
927  else if (check_tag(pb, cur + 2 + tlen, 4) != 1)
928  break;
929  avio_seek(pb, cur, SEEK_SET);
930  } else
931  tlen = size_to_syncsafe(tlen);
932  }
933  }
934  tflags = avio_rb16(pb);
935  tunsync = tflags & ID3v2_FLAG_UNSYNCH;
936  } else {
937  if (avio_read(pb, tag, 3) < 3)
938  break;
939  tag[3] = 0;
940  tlen = avio_rb24(pb);
941  }
942  if (tlen > (1<<28))
943  break;
944  len -= taghdrlen + tlen;
945 
946  if (len < 0)
947  break;
948 
949  next = avio_tell(pb) + tlen;
950 
951  if (!tlen) {
952  if (tag[0])
953  av_log(s, AV_LOG_DEBUG, "Invalid empty frame %s, skipping.\n",
954  tag);
955  continue;
956  }
957 
958  if (tflags & ID3v2_FLAG_DATALEN) {
959  if (tlen < 4)
960  break;
961  dlen = avio_rb32(pb);
962  tlen -= 4;
963  } else
964  dlen = tlen;
965 
966  tcomp = tflags & ID3v2_FLAG_COMPRESSION;
967  tencr = tflags & ID3v2_FLAG_ENCRYPTION;
968 
969  /* skip encrypted tags and, if no zlib, compressed tags */
970  if (tencr || (!CONFIG_ZLIB && tcomp)) {
971  const char *type;
972  if (!tcomp)
973  type = "encrypted";
974  else if (!tencr)
975  type = "compressed";
976  else
977  type = "encrypted and compressed";
978 
979  av_log(s, AV_LOG_WARNING, "Skipping %s ID3v2 frame %s.\n", type, tag);
980  avio_skip(pb, tlen);
981  /* check for text tag or supported special meta tag */
982  } else if (tag[0] == 'T' ||
983  !memcmp(tag, "USLT", 4) ||
984  !strcmp(tag, comm_frame) ||
985  (extra_meta &&
986  (extra_func = get_extra_meta_func(tag, isv34)))) {
987  pbx = pb;
988 
989  if (unsync || tunsync || tcomp) {
990  av_fast_malloc(&buffer, &buffer_size, tlen);
991  if (!buffer) {
992  av_log(s, AV_LOG_ERROR, "Failed to alloc %d bytes\n", tlen);
993  goto seek;
994  }
995  }
996  if (unsync || tunsync) {
997  uint8_t *b = buffer;
998  uint8_t *t = buffer;
999  uint8_t *end = t + tlen;
1000 
1001  if (avio_read(pb, buffer, tlen) != tlen) {
1002  av_log(s, AV_LOG_ERROR, "Failed to read tag data\n");
1003  goto seek;
1004  }
1005 
1006  while (t != end) {
1007  *b++ = *t++;
1008  if (t != end && t[-1] == 0xff && !t[0])
1009  t++;
1010  }
1011 
1012  ffio_init_read_context(&pb_local, buffer, b - buffer);
1013  tlen = b - buffer;
1014  pbx = &pb_local.pub; // read from sync buffer
1015  }
1016 
1017 #if CONFIG_ZLIB
1018  if (tcomp) {
1019  int err;
1020 
1021  av_log(s, AV_LOG_DEBUG, "Compressed frame %s tlen=%d dlen=%ld\n", tag, tlen, dlen);
1022 
1023  if (tlen <= 0)
1024  goto seek;
1025  if (dlen / 32768 > tlen)
1026  goto seek;
1027 
1028  av_fast_malloc(&uncompressed_buffer, &uncompressed_buffer_size, dlen);
1029  if (!uncompressed_buffer) {
1030  av_log(s, AV_LOG_ERROR, "Failed to alloc %ld bytes\n", dlen);
1031  goto seek;
1032  }
1033 
1034  if (!(unsync || tunsync)) {
1035  err = avio_read(pb, buffer, tlen);
1036  if (err < 0) {
1037  av_log(s, AV_LOG_ERROR, "Failed to read compressed tag\n");
1038  goto seek;
1039  }
1040  tlen = err;
1041  }
1042 
1043  err = uncompress(uncompressed_buffer, &dlen, buffer, tlen);
1044  if (err != Z_OK) {
1045  av_log(s, AV_LOG_ERROR, "Failed to uncompress tag: %d\n", err);
1046  goto seek;
1047  }
1048  ffio_init_read_context(&pb_local, uncompressed_buffer, dlen);
1049  tlen = dlen;
1050  pbx = &pb_local.pub; // read from sync buffer
1051  }
1052 #endif
1053  if (tag[0] == 'T')
1054  /* parse text tag */
1055  read_ttag(s, pbx, tlen, metadata, tag);
1056  else if (!memcmp(tag, "USLT", 4))
1057  read_uslt(s, pbx, tlen, metadata);
1058  else if (!strcmp(tag, comm_frame))
1059  read_comment(s, pbx, tlen, metadata);
1060  else
1061  /* parse special meta tag */
1062  extra_func->read(s, pbx, tlen, tag, extra_meta, isv34);
1063  } else if (!tag[0]) {
1064  if (tag[1])
1065  av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding\n");
1066  avio_skip(pb, tlen);
1067  break;
1068  }
1069  /* Skip to end of tag */
1070 seek:
1071  avio_seek(pb, next, SEEK_SET);
1072  }
1073 
1074  /* Footer preset, always 10 bytes, skip over it */
1075  if (version == 4 && flags & 0x10)
1076  end += 10;
1077 
1078 error:
1079  if (reason)
1080  av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n",
1081  version, reason);
1082  avio_seek(pb, end, SEEK_SET);
1083  av_free(buffer);
1084  av_free(uncompressed_buffer);
1085  return;
1086 }
1087 
1089  AVFormatContext *s, const char *magic,
1090  ID3v2ExtraMeta **extra_metap, int64_t max_search_size)
1091 {
1092  int len, ret;
1093  uint8_t buf[ID3v2_HEADER_SIZE];
1094  ExtraMetaList extra_meta = { NULL };
1095  int found_header;
1096  int64_t start, off;
1097 
1098  if (extra_metap)
1099  *extra_metap = NULL;
1100 
1101  if (max_search_size && max_search_size < ID3v2_HEADER_SIZE)
1102  return;
1103 
1104  start = avio_tell(pb);
1105  do {
1106  /* save the current offset in case there's nothing to read/skip */
1107  off = avio_tell(pb);
1108  if (max_search_size && off - start >= max_search_size - ID3v2_HEADER_SIZE) {
1109  avio_seek(pb, off, SEEK_SET);
1110  break;
1111  }
1112 
1114  if (ret >= 0)
1115  ret = avio_read(pb, buf, ID3v2_HEADER_SIZE);
1116  if (ret != ID3v2_HEADER_SIZE) {
1117  avio_seek(pb, off, SEEK_SET);
1118  break;
1119  }
1120  found_header = ff_id3v2_match(buf, magic);
1121  if (found_header) {
1122  /* parse ID3v2 header */
1123  len = ((buf[6] & 0x7f) << 21) |
1124  ((buf[7] & 0x7f) << 14) |
1125  ((buf[8] & 0x7f) << 7) |
1126  (buf[9] & 0x7f);
1127  id3v2_parse(pb, metadata, s, len, buf[3], buf[5],
1128  extra_metap ? &extra_meta : NULL);
1129  } else {
1130  avio_seek(pb, off, SEEK_SET);
1131  }
1132  } while (found_header);
1137  if (extra_metap)
1138  *extra_metap = extra_meta.head;
1139 }
1140 
1142  const char *magic, ID3v2ExtraMeta **extra_meta)
1143 {
1144  id3v2_read_internal(pb, metadata, NULL, magic, extra_meta, 0);
1145 }
1146 
1147 void ff_id3v2_read(AVFormatContext *s, const char *magic,
1148  ID3v2ExtraMeta **extra_meta, unsigned int max_search_size)
1149 {
1150  id3v2_read_internal(s->pb, &s->metadata, s, magic, extra_meta, max_search_size);
1151 }
1152 
1154 {
1155  ID3v2ExtraMeta *current = *extra_meta, *next;
1156  const ID3v2EMFunc *extra_func;
1157 
1158  while (current) {
1159  if ((extra_func = get_extra_meta_func(current->tag, 1)))
1160  extra_func->free(&current->data);
1161  next = current->next;
1162  av_freep(&current);
1163  current = next;
1164  }
1165 
1166  *extra_meta = NULL;
1167 }
1168 
1170 {
1171  ID3v2ExtraMeta *cur;
1172 
1173  for (cur = extra_meta; cur; cur = cur->next) {
1174  ID3v2ExtraMetaAPIC *apic;
1175  AVStream *st;
1176  int ret;
1177 
1178  if (strcmp(cur->tag, "APIC"))
1179  continue;
1180  apic = &cur->data.apic;
1181 
1182  ret = ff_add_attached_pic(s, NULL, NULL, &apic->buf, 0);
1183  if (ret < 0)
1184  return ret;
1185  st = s->streams[s->nb_streams - 1];
1186  st->codecpar->codec_id = apic->id;
1187 
1188  if (AV_RB64(st->attached_pic.data) == PNGSIG)
1190 
1191  if (apic->description[0])
1192  av_dict_set(&st->metadata, "title", apic->description, 0);
1193 
1194  av_dict_set(&st->metadata, "comment", apic->type, 0);
1195  }
1196 
1197  return 0;
1198 }
1199 
1201 {
1202  AVRational time_base = {1, 1000};
1203  int ret;
1204 
1205  for (unsigned i = 0; cur; cur = cur->next) {
1206  ID3v2ExtraMetaCHAP *chap;
1207  AVChapter *chapter;
1208 
1209  if (strcmp(cur->tag, "CHAP"))
1210  continue;
1211 
1212  chap = &cur->data.chap;
1213  chapter = avpriv_new_chapter(s, i++, time_base, chap->start,
1214  chap->end, chap->element_id);
1215  if (!chapter)
1216  continue;
1217 
1218  if ((ret = av_dict_copy(&chapter->metadata, chap->meta, 0)) < 0)
1219  return ret;
1220  }
1221 
1222  return 0;
1223 }
1224 
1226 {
1227  ID3v2ExtraMeta *cur;
1229 
1230  for (cur = extra_meta; cur; cur = cur->next) {
1231  if (!strcmp(cur->tag, "PRIV")) {
1232  ID3v2ExtraMetaPRIV *priv = &cur->data.priv;
1233  AVBPrint bprint;
1234  char *escaped, *key;
1235  int i, ret;
1236 
1237  if ((key = av_asprintf(ID3v2_PRIV_METADATA_PREFIX "%s", priv->owner)) == NULL) {
1238  return AVERROR(ENOMEM);
1239  }
1240 
1241  av_bprint_init(&bprint, priv->datasize + 1, AV_BPRINT_SIZE_UNLIMITED);
1242 
1243  for (i = 0; i < priv->datasize; i++) {
1244  if (priv->data[i] < 32 || priv->data[i] > 126 || priv->data[i] == '\\') {
1245  av_bprintf(&bprint, "\\x%02x", priv->data[i]);
1246  } else {
1247  av_bprint_chars(&bprint, priv->data[i], 1);
1248  }
1249  }
1250 
1251  if ((ret = av_bprint_finalize(&bprint, &escaped)) < 0) {
1252  av_free(key);
1253  return ret;
1254  }
1255 
1256  if ((ret = av_dict_set(metadata, key, escaped, dict_flags)) < 0) {
1257  return ret;
1258  }
1259  }
1260  }
1261 
1262  return 0;
1263 }
1264 
1266 {
1267  return ff_id3v2_parse_priv_dict(&s->metadata, extra_meta);
1268 }
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:32
avpriv_new_chapter
AVChapter * avpriv_new_chapter(AVFormatContext *s, int64_t id, AVRational time_base, int64_t start, int64_t end, const char *title)
Add a new chapter.
Definition: demux_utils.c:43
flags
const SwsFlags flags[]
Definition: swscale.c:61
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
PUT_UTF8
#define PUT_UTF8(val, tmp, PUT_BYTE)
Definition: common.h:541
ID3v2ExtraMeta::geob
ID3v2ExtraMetaGEOB geob
Definition: id3v2.h:90
AVChapter::metadata
AVDictionary * metadata
Definition: avformat.h:1227
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
ID3v2ExtraMeta::next
struct ID3v2ExtraMeta * next
Definition: id3v2.h:86
free_chapter
static void free_chapter(void *obj)
Definition: id3v2.c:695
rstrip_spaces
static void rstrip_spaces(char *buf)
Definition: id3v2.c:599
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
free_geobtag
static void free_geobtag(void *obj)
Free GEOB type extra metadata.
Definition: id3v2.c:224
size_to_syncsafe
static unsigned int size_to_syncsafe(unsigned int size)
Definition: id3v2.c:179
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
int64_t
long long int64_t
Definition: coverity.c:34
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:115
ff_id3v2_4_tags
const char ff_id3v2_4_tags[][4]
ID3v2.4-only text information frames.
Definition: id3v2.c:98
av_unused
#define av_unused
Definition: attributes.h:151
id3v2.h
ff_metadata_conv
void ff_metadata_conv(AVDictionary **pm, const AVMetadataConv *d_conv, const AVMetadataConv *s_conv)
Definition: metadata.c:26
list_append
static void list_append(ID3v2ExtraMeta *new_elem, ExtraMetaList *list)
Definition: id3v2.c:463
ID3v1_GENRE_MAX
#define ID3v1_GENRE_MAX
Definition: id3v1.h:29
AVPacket::data
uint8_t * data
Definition: packet.h:558
b
#define b
Definition: input.c:42
ff_id3v2_read
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.
Definition: id3v2.c:1147
AVMetadataConv
Definition: metadata.h:34
read_apic
static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, const char *tag, ExtraMetaList *extra_meta, int isv34)
Definition: id3v2.c:606
ID3v2ExtraMetaAPIC::id
enum AVCodecID id
Definition: id3v2.h:69
read_ttag
static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, AVDictionary **metadata, const char *key)
Parse a text tag.
Definition: id3v2.c:332
AVDictionary
Definition: dict.c:32
ffio_init_read_context
void ffio_init_read_context(FFIOContext *s, const uint8_t *buffer, int buffer_size)
Wrap a buffer in an AVIOContext for reading.
Definition: aviobuf.c:99
ID3v2_FLAG_ENCRYPTION
#define ID3v2_FLAG_ENCRYPTION
Definition: id3v2.h:39
id3v1.h
FFIOContext
Definition: avio_internal.h:28
ID3v2ExtraMeta::data
union ID3v2ExtraMeta::@446 data
decode_str
static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, uint8_t **dst, int *maxread)
Decode characters to UTF-8 according to encoding type.
Definition: id3v2.c:245
ID3v2ExtraMetaGEOB
Definition: id3v2.h:57
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
free_apic
static void free_apic(void *obj)
Definition: id3v2.c:592
ExtraMetaList
Definition: id3v2.c:459
CodecMime
Definition: internal.h:47
ID3v2EMFunc::tag3
const char * tag3
Definition: id3v2.c:798
finish
static void finish(void)
Definition: movenc.c:374
ExtraMetaList::tail
ID3v2ExtraMeta * tail
Definition: id3v2.c:460
fail
#define fail()
Definition: checkasm.h:206
check_tag
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.
Definition: id3v2.c:207
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:494
AVChapter
Definition: avformat.h:1223
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
ID3v2ExtraMetaCHAP
Definition: id3v2.h:78
ID3v2ExtraMeta::apic
ID3v2ExtraMetaAPIC apic
Definition: id3v2.h:88
avio_rl16
unsigned int avio_rl16(AVIOContext *s)
Definition: aviobuf.c:717
AVStream::attached_pic
AVPacket attached_pic
For streams with AV_DISPOSITION_ATTACHED_PIC disposition, this packet will contain the attached pictu...
Definition: avformat.h:842
ff_id3v2_parse_chapters
int ff_id3v2_parse_chapters(AVFormatContext *s, ID3v2ExtraMeta *cur)
Create chapters for all CHAP tags found in the ID3v2 header.
Definition: id3v2.c:1200
AV_DICT_DONT_STRDUP_VAL
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that's been allocated with av_malloc() or another memory allocation functio...
Definition: dict.h:79
ID3v2_PRIV_METADATA_PREFIX
#define ID3v2_PRIV_METADATA_PREFIX
Definition: id3v2.h:42
avio_close_dyn_buf
int avio_close_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1410
get_date_tag
static AVDictionaryEntry * get_date_tag(AVDictionary *m, const char *tag)
Definition: id3v2.c:551
avio_rb32
unsigned int avio_rb32(AVIOContext *s)
Definition: aviobuf.c:764
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
read_chapter
static void read_chapter(AVFormatContext *s, AVIOContext *pb, int len, const char *ttag, ExtraMetaList *extra_meta, int isv34)
Definition: id3v2.c:702
ID3v2ExtraMeta
Definition: id3v2.h:84
ID3v2_ENCODING_UTF8
@ ID3v2_ENCODING_UTF8
Definition: id3v2.h:48
ID3v2ExtraMetaCHAP::element_id
uint8_t * element_id
Definition: id3v2.h:79
av_dict_get
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:60
avio_open_dyn_buf
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition: aviobuf.c:1365
ff_add_attached_pic
int ff_add_attached_pic(AVFormatContext *s, AVStream *st, AVIOContext *pb, AVBufferRef **buf, int size)
Add an attached pic to an AVStream.
Definition: demux_utils.c:107
read_comment
static void read_comment(AVFormatContext *s, AVIOContext *pb, int taglen, AVDictionary **metadata)
Parse a comment tag.
Definition: id3v2.c:420
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_CODEC_ID_BMP
@ AV_CODEC_ID_BMP
Definition: codec_id.h:130
ID3v2_FLAG_UNSYNCH
#define ID3v2_FLAG_UNSYNCH
Definition: id3v2.h:38
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
ID3v2ExtraMetaAPIC::buf
AVBufferRef * buf
Definition: id3v2.h:66
free_priv
static void free_priv(void *obj)
Definition: id3v2.c:756
key
const char * key
Definition: hwcontext_opencl.c:189
tmp
static uint8_t tmp[40]
Definition: aes_ctr.c:52
ID3v2_FLAG_DATALEN
#define ID3v2_FLAG_DATALEN
Definition: id3v2.h:37
ID3v2ExtraMetaGEOB::datasize
uint32_t datasize
Definition: id3v2.h:58
AV_CODEC_ID_PNG
@ AV_CODEC_ID_PNG
Definition: codec_id.h:113
ID3v2ExtraMeta::tag
const char * tag
Definition: id3v2.h:85
AVFormatContext
Format I/O context.
Definition: avformat.h:1264
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:767
id3v2_read_internal
static void id3v2_read_internal(AVIOContext *pb, AVDictionary **metadata, AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_metap, int64_t max_search_size)
Definition: id3v2.c:1088
metadata
Stream codec metadata
Definition: ogg-flac-chained-meta.txt:2
NULL
#define NULL
Definition: coverity.c:32
ID3v2EMFunc::free
void(* free)(void *obj)
Definition: id3v2.c:803
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
ID3v2ExtraMetaPRIV::data
uint8_t * data
Definition: id3v2.h:74
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
ID3v2ExtraMetaGEOB::mime_type
uint8_t * mime_type
Definition: id3v2.h:59
ff_id3v2_parse_apic
int ff_id3v2_parse_apic(AVFormatContext *s, ID3v2ExtraMeta *extra_meta)
Create a stream for each APIC (attached picture) extracted from the ID3v2 header.
Definition: id3v2.c:1169
ExtraMetaList::head
ID3v2ExtraMeta * head
Definition: id3v2.c:460
list
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining list
Definition: filter_design.txt:25
AVStream::metadata
AVDictionary * metadata
Definition: avformat.h:824
seek
static void BS_FUNC() seek(BSCTX *bc, unsigned pos)
Seek to the given bit position.
Definition: bitstream_template.h:407
AV_DICT_DONT_OVERWRITE
#define AV_DICT_DONT_OVERWRITE
Don't overwrite existing entries.
Definition: dict.h:81
avio_w8
void avio_w8(AVIOContext *s, int b)
Definition: aviobuf.c:184
get
static void get(const uint8_t *pixels, int stride, int16_t *block)
Definition: proresenc_anatoliy.c:318
ff_id3v2_picture_types
const char *const ff_id3v2_picture_types[21]
Definition: id3v2.c:109
ID3v2_HEADER_SIZE
#define ID3v2_HEADER_SIZE
Definition: id3v2.h:30
ff_id3v2_3_tags
const char ff_id3v2_3_tags[][4]
ID3v2.3-only text information frames.
Definition: id3v2.c:104
ff_id3v2_mime_tags
const CodecMime ff_id3v2_mime_tags[]
Definition: id3v2.c:133
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:49
ff_id3v2_tags
const char ff_id3v2_tags[][4]
A list of text information frames allowed in both ID3 v2.3 and v2.4 http://www.id3....
Definition: id3v2.c:90
av_strncasecmp
int av_strncasecmp(const char *a, const char *b, size_t n)
Locale-independent case-insensitive compare.
Definition: avstring.c:218
ID3v2ExtraMetaGEOB::file_name
uint8_t * file_name
Definition: id3v2.h:60
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
avio_rb24
unsigned int avio_rb24(AVIOContext *s)
Definition: aviobuf.c:757
get_size
static unsigned int get_size(AVIOContext *s, int len)
Definition: id3v2.c:171
is_number
static int is_number(const char *str)
Definition: id3v2.c:544
ID3v2_ENCODING_UTF16BOM
@ ID3v2_ENCODING_UTF16BOM
Definition: id3v2.h:46
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
ID3v2ExtraMetaCHAP::start
uint32_t start
Definition: id3v2.h:80
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
FFIOContext::pub
AVIOContext pub
Definition: avio_internal.h:29
is_tag
static int is_tag(const char *buf, unsigned int len)
Definition: id3v2.c:189
avio_get_str
int avio_get_str(AVIOContext *pb, int maxlen, char *buf, int buflen)
Read a string from pb into buf.
Definition: aviobuf.c:869
merge_date
static void merge_date(AVDictionary **m)
Definition: id3v2.c:560
size
int size
Definition: twinvq_data.h:10344
AV_RB32
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
Definition: bytestream.h:96
ff_id3v2_34_metadata_conv
const AVMetadataConv ff_id3v2_34_metadata_conv[]
Definition: id3v2.c:46
avio_r8
int avio_r8(AVIOContext *s)
Definition: aviobuf.c:606
ffio_ensure_seekback
int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
Ensures that the requested seekback buffer size will be available.
Definition: aviobuf.c:1026
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:233
av_buffer_alloc
AVBufferRef * av_buffer_alloc(size_t size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:77
version
version
Definition: libkvazaar.c:315
ID3v2ExtraMetaAPIC
Definition: id3v2.h:65
ID3v2ExtraMeta::chap
ID3v2ExtraMetaCHAP chap
Definition: id3v2.h:89
PNGSIG
#define PNGSIG
Definition: png.h:49
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:221
AV_CODEC_ID_GIF
@ AV_CODEC_ID_GIF
Definition: codec_id.h:149
AV_CODEC_ID_MJPEG
@ AV_CODEC_ID_MJPEG
Definition: codec_id.h:59
bprint.h
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:50
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
avio_rl24
unsigned int avio_rl24(AVIOContext *s)
Definition: aviobuf.c:725
avio_internal.h
ff_id3v2_read_dict
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.
Definition: id3v2.c:1141
ff_id3v1_genre_str
const char *const ff_id3v1_genre_str[ID3v1_GENRE_MAX+1]
ID3v1 genres.
Definition: id3v1.c:26
id3v2_parse
static void id3v2_parse(AVIOContext *pb, AVDictionary **metadata, AVFormatContext *s, int len, uint8_t version, uint8_t flags, ExtraMetaList *extra_meta)
Definition: id3v2.c:833
GET_UTF16
#define GET_UTF16(val, GET_16BIT, ERROR)
Convert a UTF-16 character (2 or 4 bytes) to its 32-bit UCS-4 encoded form.
Definition: common.h:513
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
demux.h
AV_CODEC_ID_WEBP
@ AV_CODEC_ID_WEBP
Definition: codec_id.h:226
len
int len
Definition: vorbis_enc_data.h:426
ID3v2ExtraMetaPRIV::datasize
uint32_t datasize
Definition: id3v2.h:75
get_extra_meta_func
static const ID3v2EMFunc * get_extra_meta_func(const char *tag, int isv34)
Get the corresponding ID3v2EMFunc struct for a tag.
Definition: id3v2.c:819
ID3v2_ENCODING_UTF16BE
@ ID3v2_ENCODING_UTF16BE
Definition: id3v2.h:47
language
Undefined Behavior In the C language
Definition: undefined.txt:3
ff_id3v2_tag_len
int ff_id3v2_tag_len(const uint8_t *buf)
Get the length of an ID3v2 tag.
Definition: id3v2.c:159
tag
uint32_t tag
Definition: movenc.c:1995
ffio_free_dyn_buf
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition: aviobuf.c:1438
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:744
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:236
avio_rb16
unsigned int avio_rb16(AVIOContext *s)
Definition: aviobuf.c:749
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:122
dict.h
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
id
enum AVCodecID id
Definition: dts2pts.c:367
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
AV_DICT_MATCH_CASE
#define AV_DICT_MATCH_CASE
Only get an entry with exact-case key match.
Definition: dict.h:74
ID3v2ExtraMetaGEOB::description
uint8_t * description
Definition: id3v2.h:61
SIZE_SPECIFIER
#define SIZE_SPECIFIER
Definition: internal.h:129
ID3v2ExtraMetaAPIC::type
const char * type
Definition: id3v2.h:67
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
ff_id3v2_4_metadata_conv
const AVMetadataConv ff_id3v2_4_metadata_conv[]
Definition: id3v2.c:65
avio_read
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:615
ID3v2ExtraMetaGEOB::data
uint8_t * data
Definition: id3v2.h:62
avio_skip
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:321
read_geobtag
static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, const char *tag, ExtraMetaList *extra_meta, int isv34)
Parse GEOB tag into a ID3v2ExtraMetaGEOB struct.
Definition: id3v2.c:475
CodecMime::str
char str[32]
Definition: internal.h:48
CodecMime::id
enum AVCodecID id
Definition: internal.h:49
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:272
ID3v2_FLAG_COMPRESSION
#define ID3v2_FLAG_COMPRESSION
Definition: id3v2.h:40
mem.h
read_priv
static void read_priv(AVFormatContext *s, AVIOContext *pb, int taglen, const char *tag, ExtraMetaList *extra_meta, int isv34)
Definition: id3v2.c:763
ID3v2EMFunc
Definition: id3v2.c:797
id3v2_extra_meta_funcs
static const ID3v2EMFunc id3v2_extra_meta_funcs[]
Definition: id3v2.c:806
ID3v2ExtraMetaCHAP::end
uint32_t end
Definition: id3v2.h:80
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
AVDictionaryEntry
Definition: dict.h:90
AVCodecParameters::codec_id
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:55
png.h
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
av_dict_set
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:86
av_fast_malloc
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
Definition: mem.c:557
av_dict_copy
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:247
ff_id3v2_free_extra_meta
void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta)
Free memory allocated parsing special (non-text) metadata.
Definition: id3v2.c:1153
ID3v2EMFunc::read
void(* read)(AVFormatContext *s, AVIOContext *pb, int taglen, const char *tag, ExtraMetaList *extra_meta, int isv34)
Definition: id3v2.c:800
av_strlcpy
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.
Definition: avstring.c:85
ff_id3v2_parse_priv
int ff_id3v2_parse_priv(AVFormatContext *s, ID3v2ExtraMeta *extra_meta)
Add metadata for all PRIV tags in the ID3v2 header.
Definition: id3v2.c:1265
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
id3v2_2_metadata_conv
static const AVMetadataConv id3v2_2_metadata_conv[]
Definition: id3v2.c:77
av_bprint_chars
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition: bprint.c:130
AV_CODEC_ID_TIFF
@ AV_CODEC_ID_TIFF
Definition: codec_id.h:148
AVDictionaryEntry::value
char * value
Definition: dict.h:92
avstring.h
ID3v2EMFunc::tag4
const char * tag4
Definition: id3v2.c:799
ff_id3v2_parse_priv_dict
int ff_id3v2_parse_priv_dict(AVDictionary **metadata, ID3v2ExtraMeta *extra_meta)
Parse PRIV tags into a dictionary.
Definition: id3v2.c:1225
snprintf
#define snprintf
Definition: snprintf.h:34
ID3v2ExtraMetaCHAP::meta
AVDictionary * meta
Definition: id3v2.h:81
ID3v2ExtraMetaPRIV
Definition: id3v2.h:72
AV_RB64
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
Definition: bytestream.h:95
ID3v2ExtraMetaPRIV::owner
uint8_t * owner
Definition: id3v2.h:73
AV_DICT_DONT_STRDUP_KEY
#define AV_DICT_DONT_STRDUP_KEY
Take ownership of a key that's been allocated with av_malloc() or another memory allocation function.
Definition: dict.h:77
ID3v2_ENCODING_ISO8859
@ ID3v2_ENCODING_ISO8859
Definition: id3v2.h:45
ff_id3v2_match
int ff_id3v2_match(const uint8_t *buf, const char *magic)
Detect ID3v2 Header.
Definition: id3v2.c:146
bom
static const char * bom
Definition: microdvddec.c:78
read_uslt
static void read_uslt(AVFormatContext *s, AVIOContext *pb, int taglen, AVDictionary **metadata)
Definition: id3v2.c:371
ID3v2ExtraMetaAPIC::description
uint8_t * description
Definition: id3v2.h:68
ID3v2ExtraMeta::priv
ID3v2ExtraMetaPRIV priv
Definition: id3v2.h:91