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 #include "libavutil/attributes.h"
31 
32 #if CONFIG_ZLIB
33 #include <zlib.h>
34 #endif
35 
37 #include "libavutil/avstring.h"
38 #include "libavutil/bprint.h"
39 #include "libavutil/dict.h"
40 #include "libavutil/intreadwrite.h"
41 #include "libavutil/mem.h"
42 #include "libavcodec/png.h"
43 #include "avio_internal.h"
44 #include "demux.h"
45 #include "id3v1.h"
46 #include "id3v2.h"
47 
49  { "TALB", "album" },
50  { "TCOM", "composer" },
51  { "TCON", "genre" },
52  { "TCOP", "copyright" },
53  { "TENC", "encoded_by" },
54  { "TIT2", "title" },
55  { "TLAN", "language" },
56  { "TPE1", "artist" },
57  { "TPE2", "album_artist" },
58  { "TPE3", "performer" },
59  { "TPOS", "disc" },
60  { "TPUB", "publisher" },
61  { "TRCK", "track" },
62  { "TSSE", "encoder" },
63  { "USLT", "lyrics" },
64  { 0 }
65 };
66 
68  { "TCMP", "compilation" },
69  { "TDRC", "date" },
70  { "TDRL", "date" },
71  { "TDEN", "creation_time" },
72  { "TSOA", "album-sort" },
73  { "TSOP", "artist-sort" },
74  { "TSOT", "title-sort" },
75  { "TSST", "disc_subtitle" },
76  { "TIT1", "grouping" },
77  { 0 }
78 };
79 
81  { "TAL", "album" },
82  { "TCO", "genre" },
83  { "TCP", "compilation" },
84  { "TT2", "title" },
85  { "TEN", "encoded_by" },
86  { "TP1", "artist" },
87  { "TP2", "album_artist" },
88  { "TP3", "performer" },
89  { "TRK", "track" },
90  { 0 }
91 };
92 
94  "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT",
95  "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED",
96  "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3",
97  "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE",
98  { 0 },
99 };
100 
102  "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO",
103  "TPRO", "TSOA", "TSOP", "TSOT", "TSST",
104  { 0 },
105 };
106 
108  "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER",
109  { 0 },
110 };
111 
112 const char * const ff_id3v2_picture_types[21] = {
113  "Other",
114  "32x32 pixels 'file icon'",
115  "Other file icon",
116  "Cover (front)",
117  "Cover (back)",
118  "Leaflet page",
119  "Media (e.g. label side of CD)",
120  "Lead artist/lead performer/soloist",
121  "Artist/performer",
122  "Conductor",
123  "Band/Orchestra",
124  "Composer",
125  "Lyricist/text writer",
126  "Recording Location",
127  "During recording",
128  "During performance",
129  "Movie/video screen capture",
130  "A bright coloured fish",
131  "Illustration",
132  "Band/artist logotype",
133  "Publisher/Studio logotype",
134 };
135 
137  { "image/gif", AV_CODEC_ID_GIF },
138  { "image/jpeg", AV_CODEC_ID_MJPEG },
139  { "image/jpg", AV_CODEC_ID_MJPEG },
140  { "image/jxl", AV_CODEC_ID_JPEGXL },
141  { "image/png", AV_CODEC_ID_PNG },
142  { "image/tiff", AV_CODEC_ID_TIFF },
143  { "image/bmp", AV_CODEC_ID_BMP },
144  { "image/webp", AV_CODEC_ID_WEBP },
145  { "JPG", AV_CODEC_ID_MJPEG }, /* ID3v2.2 */
146  { "PNG", AV_CODEC_ID_PNG }, /* ID3v2.2 */
147  { "", AV_CODEC_ID_NONE },
148 };
149 
150 int ff_id3v2_match(const uint8_t *buf, const char *magic)
151 {
152  return buf[0] == magic[0] &&
153  buf[1] == magic[1] &&
154  buf[2] == magic[2] &&
155  buf[3] != 0xff &&
156  buf[4] != 0xff &&
157  (buf[6] & 0x80) == 0 &&
158  (buf[7] & 0x80) == 0 &&
159  (buf[8] & 0x80) == 0 &&
160  (buf[9] & 0x80) == 0;
161 }
162 
163 int ff_id3v2_tag_len(const uint8_t *buf)
164 {
165  int len = ((buf[6] & 0x7f) << 21) +
166  ((buf[7] & 0x7f) << 14) +
167  ((buf[8] & 0x7f) << 7) +
168  (buf[9] & 0x7f) +
170  if (buf[5] & 0x10)
172  return len;
173 }
174 
175 static unsigned int get_size(AVIOContext *s, int len)
176 {
177  int v = 0;
178  while (len--)
179  v = (v << 7) + (avio_r8(s) & 0x7F);
180  return v;
181 }
182 
183 static unsigned int size_to_syncsafe(unsigned int size)
184 {
185  return (((size) & (0x7f << 0)) >> 0) +
186  (((size) & (0x7f << 8)) >> 1) +
187  (((size) & (0x7f << 16)) >> 2) +
188  (((size) & (0x7f << 24)) >> 3);
189 }
190 
191 /* No real verification, only check that the tag consists of
192  * a combination of capital alpha-numerical characters */
193 static int is_tag(const char *buf, unsigned int len)
194 {
195  if (!len)
196  return 0;
197 
198  while (len--)
199  if ((buf[len] < 'A' ||
200  buf[len] > 'Z') &&
201  (buf[len] < '0' ||
202  buf[len] > '9'))
203  return 0;
204 
205  return 1;
206 }
207 
208 /**
209  * Return 1 if the tag of length len at the given offset is valid, 0 if not, -1 on error
210  */
211 static int check_tag(AVIOContext *s, int offset, unsigned int len)
212 {
213  char tag[4];
214 
215  if (len > 4 ||
216  avio_seek(s, offset, SEEK_SET) < 0 ||
217  avio_read(s, tag, len) < (int)len)
218  return -1;
219  else if (!AV_RB32(tag) || is_tag(tag, len))
220  return 1;
221 
222  return 0;
223 }
224 
225 /**
226  * Free GEOB type extra metadata.
227  */
228 static void free_geobtag(void *obj)
229 {
230  ID3v2ExtraMetaGEOB *geob = obj;
231  av_freep(&geob->mime_type);
232  av_freep(&geob->file_name);
233  av_freep(&geob->description);
234  av_freep(&geob->data);
235 }
236 
237 /**
238  * Decode characters to UTF-8 according to encoding type. The decoded buffer is
239  * always null terminated. Stop reading when either *maxread bytes are read from
240  * pb or U+0000 character is found.
241  *
242  * @param dst Pointer where the address of the buffer with the decoded bytes is
243  * stored. Buffer must be freed by caller.
244  * @param maxread Pointer to maximum number of characters to read from the
245  * AVIOContext. After execution the value is decremented by the number of bytes
246  * actually read.
247  * @returns 0 if no error occurred, dst is uninitialized on error
248  */
249 static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding,
250  uint8_t **dst, int *maxread)
251 {
252  int ret;
253  uint8_t tmp;
254  uint32_t ch = 1;
255  int left = *maxread, dynsize;
256  unsigned int (*get)(AVIOContext*) = avio_rb16;
257  AVIOContext *dynbuf;
258 
259  if ((ret = avio_open_dyn_buf(&dynbuf)) < 0) {
260  av_log(s, AV_LOG_ERROR, "Error opening memory stream\n");
261  return ret;
262  }
263 
264  if (left == 0)
265  goto end;
266 
267  switch (encoding) {
269  while (left && ch) {
270  ch = avio_r8(pb);
271  PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);)
272  left--;
273  }
274  break;
275 
277  if ((left -= 2) < 0) {
278  av_log(s, AV_LOG_ERROR, "Cannot read BOM value, input too short %d\n", left);
279  ffio_free_dyn_buf(&dynbuf);
280  *dst = NULL;
281  return AVERROR_INVALIDDATA;
282  }
283  uint16_t bom = avio_rb16(pb);
284  switch (bom) {
285  case 0xfffe:
286  get = avio_rl16;
287  break;
288  case 0xfeff:
289  break;
290  case 0: // empty string without bom
291  goto end;
292  default:
293  av_log(s, AV_LOG_ERROR, "Incorrect BOM value: 0x%x\n", bom);
294  ffio_free_dyn_buf(&dynbuf);
295  *dst = NULL;
296  *maxread = left;
297  return AVERROR_INVALIDDATA;
298  }
300 
302  while ((left > 1) && ch) {
303  GET_UTF16(ch, ((left -= 2) >= 0 ? get(pb) : 0), break;)
304  PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);)
305  }
306  if (left < 0)
307  left += 2; /* did not read last char from pb */
308  break;
309 
310  case ID3v2_ENCODING_UTF8:
311  while (left && ch) {
312  ch = avio_r8(pb);
313  avio_w8(dynbuf, ch);
314  left--;
315  }
316  break;
317  default:
318  av_log(s, AV_LOG_WARNING, "Unknown encoding %d\n", encoding);
319  }
320 
321 end:
322  if (ch)
323  avio_w8(dynbuf, 0);
324 
325  dynsize = avio_close_dyn_buf(dynbuf, dst);
326  if (dynsize <= 0) {
327  av_freep(dst);
328  return AVERROR(ENOMEM);
329  }
330  *maxread = left;
331 
332  return 0;
333 }
334 
335 /**
336  * Parse a text tag.
337  */
338 static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen,
339  AVDictionary **metadata, const char *key)
340 {
341  uint8_t *dst;
342  int encoding, dict_flags = AV_DICT_DONT_OVERWRITE | AV_DICT_DONT_STRDUP_VAL;
343  unsigned genre;
344 
345  if (taglen < 1)
346  return;
347 
348  encoding = avio_r8(pb);
349  taglen--; /* account for encoding type byte */
350 
351  if (decode_str(s, pb, encoding, &dst, &taglen) < 0) {
352  av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", key);
353  return;
354  }
355 
356  if (!(strcmp(key, "TCON") && strcmp(key, "TCO")) &&
357  (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1) &&
358  genre <= ID3v1_GENRE_MAX) {
359  av_freep(&dst);
360  dst = av_strdup(ff_id3v1_genre_str[genre]);
361  } else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) {
362  /* dst now contains the key, need to get value */
363  key = dst;
364  if (decode_str(s, pb, encoding, &dst, &taglen) < 0) {
365  av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", key);
366  av_freep(&key);
367  return;
368  }
369  dict_flags |= AV_DICT_DONT_STRDUP_KEY;
370  } else if (!*dst)
371  av_freep(&dst);
372 
373  if (dst)
374  av_dict_set(metadata, key, dst, dict_flags);
375 }
376 
377 static void read_uslt(AVFormatContext *s, AVIOContext *pb, int taglen,
379 {
380  uint8_t lang[4];
381  uint8_t *descriptor = NULL; // 'Content descriptor'
382  uint8_t *text;
383  char *key;
384  int encoding;
385  int ok = 0;
386 
387  if (taglen < 4)
388  goto error;
389 
390  encoding = avio_r8(pb);
391  taglen--;
392 
393  if (avio_read(pb, lang, 3) < 3)
394  goto error;
395  lang[3] = '\0';
396  taglen -= 3;
397 
398  if (decode_str(s, pb, encoding, &descriptor, &taglen) < 0 || taglen < 0)
399  goto error;
400 
401  if (decode_str(s, pb, encoding, &text, &taglen) < 0 || taglen < 0)
402  goto error;
403 
404  // FFmpeg does not support hierarchical metadata, so concatenate the keys.
405  key = av_asprintf("lyrics-%s%s%s", descriptor[0] ? (char *)descriptor : "",
406  descriptor[0] ? "-" : "",
407  lang);
408  if (!key) {
409  av_free(text);
410  goto error;
411  }
412 
413  av_dict_set(metadata, key, text,
415 
416  ok = 1;
417 error:
418  if (!ok)
419  av_log(s, AV_LOG_ERROR, "Error reading lyrics, skipped\n");
420  av_free(descriptor);
421 }
422 
423 /**
424  * Parse a comment tag.
425  */
426 static void read_comment(AVFormatContext *s, AVIOContext *pb, int taglen,
428 {
429  const char *key = "comment";
430  uint8_t *dst;
431  int encoding, dict_flags = AV_DICT_DONT_OVERWRITE | AV_DICT_DONT_STRDUP_VAL;
432  av_unused int language;
433 
434  if (taglen < 4)
435  return;
436 
437  encoding = avio_r8(pb);
438  language = avio_rl24(pb);
439  taglen -= 4;
440 
441  if (decode_str(s, pb, encoding, &dst, &taglen) < 0) {
442  av_log(s, AV_LOG_ERROR, "Error reading comment frame, skipped\n");
443  return;
444  }
445 
446  if (dst && !*dst)
447  av_freep(&dst);
448 
449  if (dst) {
450  key = (const char *) dst;
451  dict_flags |= AV_DICT_DONT_STRDUP_KEY;
452  }
453 
454  if (decode_str(s, pb, encoding, &dst, &taglen) < 0) {
455  av_log(s, AV_LOG_ERROR, "Error reading comment frame, skipped\n");
456  if (dict_flags & AV_DICT_DONT_STRDUP_KEY)
457  av_freep((void*)&key);
458  return;
459  }
460 
461  if (dst)
462  av_dict_set(metadata, key, (const char *) dst, dict_flags);
463 }
464 
465 typedef struct ExtraMetaList {
467 } ExtraMetaList;
468 
470 {
471  if (list->tail)
472  list->tail->next = new_elem;
473  else
474  list->head = new_elem;
475  list->tail = new_elem;
476 }
477 
478 /**
479  * Parse GEOB tag into a ID3v2ExtraMetaGEOB struct.
480  */
481 static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen,
482  const char *tag, ExtraMetaList *extra_meta, int isv34)
483 {
484  ID3v2ExtraMetaGEOB *geob_data = NULL;
485  ID3v2ExtraMeta *new_extra = NULL;
486  char encoding;
487  unsigned int len;
488 
489  if (taglen < 1)
490  return;
491 
492  new_extra = av_mallocz(sizeof(ID3v2ExtraMeta));
493  if (!new_extra) {
494  av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n",
495  sizeof(ID3v2ExtraMeta));
496  return;
497  }
498 
499  geob_data = &new_extra->data.geob;
500 
501  /* read encoding type byte */
502  encoding = avio_r8(pb);
503  taglen--;
504 
505  /* read MIME type (always ISO-8859) */
506  if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &geob_data->mime_type,
507  &taglen) < 0 ||
508  taglen <= 0)
509  goto fail;
510 
511  /* read file name */
512  if (decode_str(s, pb, encoding, &geob_data->file_name, &taglen) < 0 ||
513  taglen <= 0)
514  goto fail;
515 
516  /* read content description */
517  if (decode_str(s, pb, encoding, &geob_data->description, &taglen) < 0 ||
518  taglen < 0)
519  goto fail;
520 
521  if (taglen) {
522  /* save encapsulated binary data */
523  geob_data->data = av_malloc(taglen);
524  if (!geob_data->data) {
525  av_log(s, AV_LOG_ERROR, "Failed to alloc %d bytes\n", taglen);
526  goto fail;
527  }
528  if ((len = avio_read(pb, geob_data->data, taglen)) < taglen)
530  "Error reading GEOB frame, data truncated.\n");
531  geob_data->datasize = len;
532  } else {
533  geob_data->data = NULL;
534  geob_data->datasize = 0;
535  }
536 
537  /* add data to the list */
538  new_extra->tag = "GEOB";
539  list_append(new_extra, extra_meta);
540 
541  return;
542 
543 fail:
544  av_log(s, AV_LOG_ERROR, "Error reading frame %s, skipped\n", tag);
545  free_geobtag(geob_data);
546  av_free(new_extra);
547  return;
548 }
549 
550 static int is_number(const char *str)
551 {
552  while (*str >= '0' && *str <= '9')
553  str++;
554  return !*str;
555 }
556 
558 {
560  if ((t = av_dict_get(m, tag, NULL, AV_DICT_MATCH_CASE)) &&
561  strlen(t->value) == 4 && is_number(t->value))
562  return t;
563  return NULL;
564 }
565 
566 static void merge_date(AVDictionary **m)
567 {
569  char date[17] = { 0 }; // YYYY-MM-DD hh:mm
570 
571  if (!(t = get_date_tag(*m, "TYER")) &&
572  !(t = get_date_tag(*m, "TYE")))
573  return;
574  av_strlcpy(date, t->value, 5);
575  av_dict_set(m, "TYER", NULL, 0);
576  av_dict_set(m, "TYE", NULL, 0);
577 
578  if (!(t = get_date_tag(*m, "TDAT")) &&
579  !(t = get_date_tag(*m, "TDA")))
580  goto finish;
581  snprintf(date + 4, sizeof(date) - 4, "-%.2s-%.2s", t->value + 2, t->value);
582  av_dict_set(m, "TDAT", NULL, 0);
583  av_dict_set(m, "TDA", NULL, 0);
584 
585  if (!(t = get_date_tag(*m, "TIME")) &&
586  !(t = get_date_tag(*m, "TIM")))
587  goto finish;
588  snprintf(date + 10, sizeof(date) - 10,
589  " %.2s:%.2s", t->value, t->value + 2);
590  av_dict_set(m, "TIME", NULL, 0);
591  av_dict_set(m, "TIM", NULL, 0);
592 
593 finish:
594  if (date[0])
595  av_dict_set(m, "date", date, 0);
596 }
597 
598 static void free_apic(void *obj)
599 {
600  ID3v2ExtraMetaAPIC *apic = obj;
601  av_buffer_unref(&apic->buf);
602  av_freep(&apic->description);
603 }
604 
605 static void rstrip_spaces(char *buf)
606 {
607  size_t len = strlen(buf);
608  while (len > 0 && buf[len - 1] == ' ')
609  buf[--len] = 0;
610 }
611 
612 static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen,
613  const char *tag, ExtraMetaList *extra_meta, int isv34)
614 {
615  int enc, pic_type;
616  char mimetype[64] = {0};
617  const CodecMime *mime = ff_id3v2_mime_tags;
618  enum AVCodecID id = AV_CODEC_ID_NONE;
619  ID3v2ExtraMetaAPIC *apic = NULL;
620  ID3v2ExtraMeta *new_extra = NULL;
621  int64_t end = avio_tell(pb) + taglen;
622 
623  if (taglen <= 4 || (!isv34 && taglen <= 6))
624  goto fail;
625 
626  new_extra = av_mallocz(sizeof(*new_extra));
627  if (!new_extra)
628  goto fail;
629 
630  apic = &new_extra->data.apic;
631 
632  enc = avio_r8(pb);
633  taglen--;
634 
635  /* mimetype */
636  if (isv34) {
637  int ret = avio_get_str(pb, taglen, mimetype, sizeof(mimetype));
638  if (ret < 0 || ret >= taglen)
639  goto fail;
640  taglen -= ret;
641  } else {
642  if (avio_read(pb, mimetype, 3) < 0)
643  goto fail;
644 
645  mimetype[3] = 0;
646  taglen -= 3;
647  }
648 
649  while (mime->id != AV_CODEC_ID_NONE) {
650  if (!av_strncasecmp(mime->str, mimetype, sizeof(mimetype))) {
651  id = mime->id;
652  break;
653  }
654  mime++;
655  }
656  if (id == AV_CODEC_ID_NONE) {
658  "Unknown attached picture mimetype: %s, skipping.\n", mimetype);
659  goto fail;
660  }
661  apic->id = id;
662 
663  /* picture type */
664  pic_type = avio_r8(pb);
665  taglen--;
666  if (pic_type < 0 || pic_type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types)) {
667  av_log(s, AV_LOG_WARNING, "Unknown attached picture type %d.\n",
668  pic_type);
669  pic_type = 0;
670  }
671  apic->type = ff_id3v2_picture_types[pic_type];
672 
673  /* description and picture data */
674  if (decode_str(s, pb, enc, &apic->description, &taglen) < 0) {
676  "Error decoding attached picture description.\n");
677  goto fail;
678  }
679 
681  if (!apic->buf || !taglen || avio_read(pb, apic->buf->data, taglen) != taglen)
682  goto fail;
683  memset(apic->buf->data + taglen, 0, AV_INPUT_BUFFER_PADDING_SIZE);
684 
685  new_extra->tag = "APIC";
686 
687  // The description must be unique, and some ID3v2 tag writers add spaces
688  // to write several APIC entries with the same description.
689  rstrip_spaces(apic->description);
690  list_append(new_extra, extra_meta);
691 
692  return;
693 
694 fail:
695  if (apic)
696  free_apic(apic);
697  av_freep(&new_extra);
698  avio_seek(pb, end, SEEK_SET);
699 }
700 
701 static void free_chapter(void *obj)
702 {
703  ID3v2ExtraMetaCHAP *chap = obj;
704  av_freep(&chap->element_id);
705  av_dict_free(&chap->meta);
706 }
707 
709  const char *ttag, ExtraMetaList *extra_meta, int isv34)
710 {
711  int taglen;
712  char tag[5];
713  ID3v2ExtraMeta *new_extra = NULL;
714  ID3v2ExtraMetaCHAP *chap = NULL;
715 
716  new_extra = av_mallocz(sizeof(*new_extra));
717  if (!new_extra)
718  return;
719 
720  chap = &new_extra->data.chap;
721 
722  if (decode_str(s, pb, 0, &chap->element_id, &len) < 0)
723  goto fail;
724 
725  if (len < 16)
726  goto fail;
727 
728  chap->start = avio_rb32(pb);
729  chap->end = avio_rb32(pb);
730  avio_skip(pb, 8);
731 
732  len -= 16;
733  while (len > 10) {
734  if (avio_read(pb, tag, 4) < 4)
735  goto fail;
736  tag[4] = 0;
737  taglen = avio_rb32(pb);
738  avio_skip(pb, 2);
739  len -= 10;
740  if (taglen < 0 || taglen > len)
741  goto fail;
742  if (tag[0] == 'T')
743  read_ttag(s, pb, taglen, &chap->meta, tag);
744  else
745  avio_skip(pb, taglen);
746  len -= taglen;
747  }
748 
751 
752  new_extra->tag = "CHAP";
753  list_append(new_extra, extra_meta);
754 
755  return;
756 
757 fail:
758  free_chapter(chap);
759  av_freep(&new_extra);
760 }
761 
762 static void free_priv(void *obj)
763 {
764  ID3v2ExtraMetaPRIV *priv = obj;
765  av_freep(&priv->owner);
766  av_freep(&priv->data);
767 }
768 
769 static void read_priv(AVFormatContext *s, AVIOContext *pb, int taglen,
770  const char *tag, ExtraMetaList *extra_meta, int isv34)
771 {
772  ID3v2ExtraMeta *meta;
773  ID3v2ExtraMetaPRIV *priv;
774 
775  meta = av_mallocz(sizeof(*meta));
776  if (!meta)
777  return;
778 
779  priv = &meta->data.priv;
780 
781  if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &priv->owner, &taglen) < 0)
782  goto fail;
783 
784  priv->data = av_malloc(taglen);
785  if (!priv->data)
786  goto fail;
787 
788  priv->datasize = taglen;
789 
790  if (avio_read(pb, priv->data, priv->datasize) != priv->datasize)
791  goto fail;
792 
793  meta->tag = "PRIV";
794  list_append(meta, extra_meta);
795 
796  return;
797 
798 fail:
799  free_priv(priv);
800  av_freep(&meta);
801 }
802 
803 typedef struct ID3v2EMFunc {
804  const char *tag3;
805  const char *tag4;
806  void (*read)(AVFormatContext *s, AVIOContext *pb, int taglen,
807  const char *tag, ExtraMetaList *extra_meta,
808  int isv34);
809  void (*free)(void *obj);
810 } ID3v2EMFunc;
811 
813  { "GEO", "GEOB", read_geobtag, free_geobtag },
814  { "PIC", "APIC", read_apic, free_apic },
815  { "CHAP","CHAP", read_chapter, free_chapter },
816  { "PRIV","PRIV", read_priv, free_priv },
817  { NULL }
818 };
819 
820 /**
821  * Get the corresponding ID3v2EMFunc struct for a tag.
822  * @param isv34 Determines if v2.2 or v2.3/4 strings are used
823  * @return A pointer to the ID3v2EMFunc struct if found, NULL otherwise.
824  */
825 static const ID3v2EMFunc *get_extra_meta_func(const char *tag, int isv34)
826 {
827  int i = 0;
828  while (id3v2_extra_meta_funcs[i].tag3) {
829  if (tag && !memcmp(tag,
830  (isv34 ? id3v2_extra_meta_funcs[i].tag4 :
831  id3v2_extra_meta_funcs[i].tag3),
832  (isv34 ? 4 : 3)))
833  return &id3v2_extra_meta_funcs[i];
834  i++;
835  }
836  return NULL;
837 }
838 
840  AVFormatContext *s, int len, uint8_t version,
841  uint8_t flags, ExtraMetaList *extra_meta)
842 {
843  int isv34, unsync;
844  unsigned tlen;
845  char tag[5];
846  int64_t next, end = avio_tell(pb);
847  int taghdrlen;
848  const char *reason = NULL;
849  FFIOContext pb_local;
850  AVIOContext *pbx;
851  unsigned char *buffer = NULL;
852  int buffer_size = 0;
853  const ID3v2EMFunc *extra_func = NULL;
854  unsigned char *uncompressed_buffer = NULL;
855  av_unused int uncompressed_buffer_size = 0;
856  const char *comm_frame;
857 
858  if (end > INT64_MAX - len - 10)
859  return;
860  end += len;
861 
862  av_log(s, AV_LOG_DEBUG, "id3v2 ver:%d flags:%02X len:%d\n", version, flags, len);
863 
864  switch (version) {
865  case 2:
866  if (flags & 0x40) {
867  reason = "compression";
868  goto error;
869  }
870  isv34 = 0;
871  taghdrlen = 6;
872  comm_frame = "COM";
873  break;
874 
875  case 3:
876  case 4:
877  isv34 = 1;
878  taghdrlen = 10;
879  comm_frame = "COMM";
880  break;
881 
882  default:
883  reason = "version";
884  goto error;
885  }
886 
887  unsync = flags & 0x80;
888 
889  if (isv34 && flags & 0x40) { /* Extended header present, just skip over it */
890  int extlen = get_size(pb, 4);
891  if (version == 4)
892  /* In v2.4 the length includes the length field we just read. */
893  extlen -= 4;
894 
895  if (extlen < 0) {
896  reason = "invalid extended header length";
897  goto error;
898  }
899  avio_skip(pb, extlen);
900  len -= extlen + 4;
901  if (len < 0) {
902  reason = "extended header too long.";
903  goto error;
904  }
905  }
906 
907  while (len >= taghdrlen) {
908  unsigned int tflags = 0;
909  int tunsync = 0;
910  int tcomp = 0;
911  int tencr = 0;
912  av_unused unsigned long dlen;
913 
914  if (isv34) {
915  if (avio_read(pb, tag, 4) < 4)
916  break;
917  tag[4] = 0;
918  if (version == 3) {
919  tlen = avio_rb32(pb);
920  } else {
921  /* some encoders incorrectly uses v3 sizes instead of syncsafe ones
922  * so check the next tag to see which one to use */
923  tlen = avio_rb32(pb);
924  if (tlen > 0x7f) {
925  if (tlen < len) {
926  int64_t cur = avio_tell(pb);
927 
928  if (ffio_ensure_seekback(pb, 2 /* tflags */ + tlen + 4 /* next tag */))
929  break;
930 
931  if (check_tag(pb, cur + 2 + size_to_syncsafe(tlen), 4) == 1)
932  tlen = size_to_syncsafe(tlen);
933  else if (check_tag(pb, cur + 2 + tlen, 4) != 1)
934  break;
935  avio_seek(pb, cur, SEEK_SET);
936  } else
937  tlen = size_to_syncsafe(tlen);
938  }
939  }
940  tflags = avio_rb16(pb);
941  tunsync = tflags & ID3v2_FLAG_UNSYNCH;
942  } else {
943  if (avio_read(pb, tag, 3) < 3)
944  break;
945  tag[3] = 0;
946  tlen = avio_rb24(pb);
947  }
948  if (tlen > (1<<28))
949  break;
950  len -= taghdrlen + tlen;
951 
952  if (len < 0)
953  break;
954 
955  next = avio_tell(pb) + tlen;
956 
957  if (!tlen) {
958  if (tag[0])
959  av_log(s, AV_LOG_DEBUG, "Invalid empty frame %s, skipping.\n",
960  tag);
961  continue;
962  }
963 
964  if (tflags & ID3v2_FLAG_DATALEN) {
965  if (tlen < 4)
966  break;
967  dlen = avio_rb32(pb);
968  tlen -= 4;
969  } else
970  dlen = tlen;
971 
972  tcomp = tflags & ID3v2_FLAG_COMPRESSION;
973  tencr = tflags & ID3v2_FLAG_ENCRYPTION;
974 
975  /* skip encrypted tags and, if no zlib, compressed tags */
976  if (tencr || (!CONFIG_ZLIB && tcomp)) {
977  const char *type;
978  if (!tcomp)
979  type = "encrypted";
980  else if (!tencr)
981  type = "compressed";
982  else
983  type = "encrypted and compressed";
984 
985  av_log(s, AV_LOG_WARNING, "Skipping %s ID3v2 frame %s.\n", type, tag);
986  avio_skip(pb, tlen);
987  /* check for text tag or supported special meta tag */
988  } else if (tag[0] == 'T' ||
989  !memcmp(tag, "USLT", 4) ||
990  !strcmp(tag, comm_frame) ||
991  (extra_meta &&
992  (extra_func = get_extra_meta_func(tag, isv34)))) {
993  pbx = pb;
994 
995  if (unsync || tunsync || tcomp) {
996  av_fast_malloc(&buffer, &buffer_size, tlen);
997  if (!buffer) {
998  av_log(s, AV_LOG_ERROR, "Failed to alloc %d bytes\n", tlen);
999  goto seek;
1000  }
1001  }
1002  if (unsync || tunsync) {
1003  uint8_t *b = buffer;
1004  uint8_t *t = buffer;
1005 
1006  if (avio_read(pb, buffer, tlen) != tlen) {
1007  av_log(s, AV_LOG_ERROR, "Failed to read tag data\n");
1008  goto seek;
1009  }
1010 
1011  const uint8_t *const buf_end = t + tlen;
1012  while (t != buf_end) {
1013  *b++ = *t++;
1014  if (t != buf_end && t[-1] == 0xff && !t[0])
1015  t++;
1016  }
1017 
1018  ffio_init_read_context(&pb_local, buffer, b - buffer);
1019  tlen = b - buffer;
1020  pbx = &pb_local.pub; // read from sync buffer
1021  }
1022 
1023 #if CONFIG_ZLIB
1024  if (tcomp) {
1025  int err;
1026 
1027  av_log(s, AV_LOG_DEBUG, "Compressed frame %s tlen=%d dlen=%ld\n", tag, tlen, dlen);
1028 
1029  if (tlen <= 0)
1030  goto seek;
1031  if (dlen / 32768 > tlen)
1032  goto seek;
1033 
1034  av_fast_malloc(&uncompressed_buffer, &uncompressed_buffer_size, dlen);
1035  if (!uncompressed_buffer) {
1036  av_log(s, AV_LOG_ERROR, "Failed to alloc %ld bytes\n", dlen);
1037  goto seek;
1038  }
1039 
1040  if (!(unsync || tunsync)) {
1041  err = avio_read(pb, buffer, tlen);
1042  if (err < 0) {
1043  av_log(s, AV_LOG_ERROR, "Failed to read compressed tag\n");
1044  goto seek;
1045  }
1046  tlen = err;
1047  }
1048 
1049  err = uncompress(uncompressed_buffer, &dlen, buffer, tlen);
1050  if (err != Z_OK) {
1051  av_log(s, AV_LOG_ERROR, "Failed to uncompress tag: %d\n", err);
1052  goto seek;
1053  }
1054  ffio_init_read_context(&pb_local, uncompressed_buffer, dlen);
1055  tlen = dlen;
1056  pbx = &pb_local.pub; // read from sync buffer
1057  }
1058 #endif
1059  if (s && (s->debug & AV_FDEBUG_ID3V2)) {
1060  int64_t pos = avio_tell(pbx);
1061  uint8_t *buf = av_malloc(tlen + 3U);
1062  if (buf) {
1063  int n = avio_read(pbx, buf + 1, tlen);
1064  if (n >= 0) {
1065  buf[0] = '|';
1066  for (unsigned i = 1; i <= n; i++)
1067  if (!(buf[i] >= 0x20 && buf[i] < 0x7f))
1068  buf[i] = '.';
1069  buf[n + 1] = '|';
1070  buf[n + 2] = '\0';
1071  av_log(s, AV_LOG_INFO, "ID3v2 frame %.4s (%d bytes):%s\n",
1072  tag, tlen, buf);
1073  }
1074  av_free(buf);
1075  avio_seek(pbx, pos, SEEK_SET);
1076  }
1077  }
1078  if (tag[0] == 'T')
1079  /* parse text tag */
1080  read_ttag(s, pbx, tlen, metadata, tag);
1081  else if (!memcmp(tag, "USLT", 4))
1082  read_uslt(s, pbx, tlen, metadata);
1083  else if (!strcmp(tag, comm_frame))
1084  read_comment(s, pbx, tlen, metadata);
1085  else
1086  /* parse special meta tag */
1087  extra_func->read(s, pbx, tlen, tag, extra_meta, isv34);
1088  } else if (!tag[0]) {
1089  if (tag[1])
1090  av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding\n");
1091  avio_skip(pb, tlen);
1092  break;
1093  }
1094  /* Skip to end of tag */
1095 seek:
1096  avio_seek(pb, next, SEEK_SET);
1097  }
1098 
1099  /* Footer preset, always 10 bytes, skip over it */
1100  if (version == 4 && flags & 0x10)
1101  end += 10;
1102 
1103 error:
1104  if (reason)
1105  av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n",
1106  version, reason);
1107  avio_seek(pb, end, SEEK_SET);
1108  av_free(buffer);
1109  av_free(uncompressed_buffer);
1110  return;
1111 }
1112 
1114  AVFormatContext *s, const char *magic,
1115  ID3v2ExtraMeta **extra_metap, int64_t max_search_size)
1116 {
1117  int len, ret;
1118  uint8_t buf[ID3v2_HEADER_SIZE];
1119  ExtraMetaList extra_meta = { NULL };
1120  int found_header;
1121  int64_t start, off;
1122 
1123  if (extra_metap)
1124  *extra_metap = NULL;
1125 
1126  if (max_search_size && max_search_size < ID3v2_HEADER_SIZE)
1127  return;
1128 
1129  start = avio_tell(pb);
1130  do {
1131  /* save the current offset in case there's nothing to read/skip */
1132  off = avio_tell(pb);
1133  if (max_search_size && off - start >= max_search_size - ID3v2_HEADER_SIZE) {
1134  avio_seek(pb, off, SEEK_SET);
1135  break;
1136  }
1137 
1139  if (ret >= 0)
1140  ret = avio_read(pb, buf, ID3v2_HEADER_SIZE);
1141  if (ret != ID3v2_HEADER_SIZE) {
1142  avio_seek(pb, off, SEEK_SET);
1143  break;
1144  }
1145  found_header = ff_id3v2_match(buf, magic);
1146  if (found_header) {
1147  /* parse ID3v2 header */
1148  len = ((buf[6] & 0x7f) << 21) |
1149  ((buf[7] & 0x7f) << 14) |
1150  ((buf[8] & 0x7f) << 7) |
1151  (buf[9] & 0x7f);
1152  id3v2_parse(pb, metadata, s, len, buf[3], buf[5],
1153  extra_metap ? &extra_meta : NULL);
1154  } else {
1155  avio_seek(pb, off, SEEK_SET);
1156  }
1157  } while (found_header);
1162  if (extra_metap)
1163  *extra_metap = extra_meta.head;
1164 }
1165 
1167  const char *magic, ID3v2ExtraMeta **extra_meta)
1168 {
1169  id3v2_read_internal(pb, metadata, NULL, magic, extra_meta, 0);
1170 }
1171 
1172 void ff_id3v2_read(AVFormatContext *s, const char *magic,
1173  ID3v2ExtraMeta **extra_meta, unsigned int max_search_size)
1174 {
1175  id3v2_read_internal(s->pb, &s->metadata, s, magic, extra_meta, max_search_size);
1176 }
1177 
1179 {
1180  ID3v2ExtraMeta *current = *extra_meta, *next;
1181  const ID3v2EMFunc *extra_func;
1182 
1183  while (current) {
1184  if ((extra_func = get_extra_meta_func(current->tag, 1)))
1185  extra_func->free(&current->data);
1186  next = current->next;
1187  av_freep(&current);
1188  current = next;
1189  }
1190 
1191  *extra_meta = NULL;
1192 }
1193 
1195 {
1196  ID3v2ExtraMeta *cur;
1197 
1198  for (cur = extra_meta; cur; cur = cur->next) {
1199  ID3v2ExtraMetaAPIC *apic;
1200  AVStream *st;
1201  int ret;
1202 
1203  if (strcmp(cur->tag, "APIC"))
1204  continue;
1205  apic = &cur->data.apic;
1206 
1207  ret = ff_add_attached_pic(s, NULL, NULL, &apic->buf, 0);
1208  if (ret < 0)
1209  return ret;
1210  st = s->streams[s->nb_streams - 1];
1211  st->codecpar->codec_id = apic->id;
1212 
1213  if (AV_RB64(st->attached_pic.data) == PNGSIG)
1215 
1216  if (apic->description[0])
1217  av_dict_set(&st->metadata, "title", apic->description, 0);
1218 
1219  av_dict_set(&st->metadata, "comment", apic->type, 0);
1220  }
1221 
1222  return 0;
1223 }
1224 
1226 {
1227  AVRational time_base = {1, 1000};
1228  int ret;
1229 
1230  for (unsigned i = 0; cur; cur = cur->next) {
1231  ID3v2ExtraMetaCHAP *chap;
1232  AVChapter *chapter;
1233 
1234  if (strcmp(cur->tag, "CHAP"))
1235  continue;
1236 
1237  chap = &cur->data.chap;
1238  chapter = avpriv_new_chapter(s, i++, time_base, chap->start,
1239  chap->end, chap->element_id);
1240  if (!chapter)
1241  continue;
1242 
1243  if ((ret = av_dict_copy(&chapter->metadata, chap->meta, 0)) < 0)
1244  return ret;
1245  }
1246 
1247  return 0;
1248 }
1249 
1251 {
1252  ID3v2ExtraMeta *cur;
1254 
1255  for (cur = extra_meta; cur; cur = cur->next) {
1256  if (!strcmp(cur->tag, "PRIV")) {
1257  ID3v2ExtraMetaPRIV *priv = &cur->data.priv;
1258  AVBPrint bprint;
1259  char *escaped, *key;
1260  int i, ret;
1261 
1262  if ((key = av_asprintf(ID3v2_PRIV_METADATA_PREFIX "%s", priv->owner)) == NULL) {
1263  return AVERROR(ENOMEM);
1264  }
1265 
1266  av_bprint_init(&bprint, priv->datasize + 1, AV_BPRINT_SIZE_UNLIMITED);
1267 
1268  for (i = 0; i < priv->datasize; i++) {
1269  if (priv->data[i] < 32 || priv->data[i] > 126 || priv->data[i] == '\\') {
1270  av_bprintf(&bprint, "\\x%02x", priv->data[i]);
1271  } else {
1272  av_bprint_chars(&bprint, priv->data[i], 1);
1273  }
1274  }
1275 
1276  if ((ret = av_bprint_finalize(&bprint, &escaped)) < 0) {
1277  av_free(key);
1278  return ret;
1279  }
1280 
1281  if ((ret = av_dict_set(metadata, key, escaped, dict_flags)) < 0) {
1282  return ret;
1283  }
1284  }
1285  }
1286 
1287  return 0;
1288 }
1289 
1291 {
1292  return ff_id3v2_parse_priv_dict(&s->metadata, extra_meta);
1293 }
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:72
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:1247
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:701
rstrip_spaces
static void rstrip_spaces(char *buf)
Definition: id3v2.c:605
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:228
size_to_syncsafe
static unsigned int size_to_syncsafe(unsigned int size)
Definition: id3v2.c:183
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
av_unused
#define av_unused
Definition: attributes.h:164
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:469
ID3v1_GENRE_MAX
#define ID3v1_GENRE_MAX
Definition: id3v1.h:29
AVPacket::data
uint8_t * data
Definition: packet.h:595
b
#define b
Definition: input.c:43
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:1172
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:612
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:338
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
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:249
ID3v2ExtraMetaGEOB
Definition: id3v2.h:57
free_apic
static void free_apic(void *obj)
Definition: id3v2.c:598
ExtraMetaList
Definition: id3v2.c:465
CodecMime
Definition: internal.h:47
ID3v2EMFunc::tag3
const char * tag3
Definition: id3v2.c:804
attribute_nonstring
#define attribute_nonstring
Definition: attributes_internal.h:42
finish
static void finish(void)
Definition: movenc.c:374
ExtraMetaList::tail
ID3v2ExtraMeta * tail
Definition: id3v2.c:466
fail
#define fail()
Definition: checkasm.h:225
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:211
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:494
AVChapter
Definition: avformat.h:1243
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:845
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:1225
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:557
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:708
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:426
attributes_internal.h
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
ID3v2ExtraMeta::data
union ID3v2ExtraMeta::@476 data
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
ff_id3v2_4_tags
const attribute_nonstring char ff_id3v2_4_tags[][4]
ID3v2.4-only text information frames.
Definition: id3v2.c:101
ID3v2ExtraMetaAPIC::buf
AVBufferRef * buf
Definition: id3v2.h:66
free_priv
static void free_priv(void *obj)
Definition: id3v2.c:762
key
const char * key
Definition: hwcontext_opencl.c:189
av_mallocz
#define av_mallocz(s)
Definition: tableprint_vlc.h:31
av_fallthrough
#define av_fallthrough
Definition: attributes.h:67
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:1284
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:770
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:1113
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:809
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:1194
ExtraMetaList::head
ID3v2ExtraMeta * head
Definition: id3v2.c:466
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:827
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:112
ID3v2_HEADER_SIZE
#define ID3v2_HEADER_SIZE
Definition: id3v2.h:30
ff_id3v2_3_tags
const attribute_nonstring char ff_id3v2_3_tags[][4]
ID3v2.3-only text information frames.
Definition: id3v2.c:107
ff_id3v2_mime_tags
const CodecMime ff_id3v2_mime_tags[]
Definition: id3v2.c:136
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:49
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:175
is_number
static int is_number(const char *str)
Definition: id3v2.c:550
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
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
FFIOContext::pub
AVIOContext pub
Definition: avio_internal.h:29
is_tag
static int is_tag(const char *buf, unsigned int len)
Definition: id3v2.c:193
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:566
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:48
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
attributes.h
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:313
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_malloc
#define av_malloc(s)
Definition: ops_asmgen.c:44
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:50
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:1166
ff_id3v1_genre_str
const char *const ff_id3v1_genre_str[ID3v1_GENRE_MAX+1]
ID3v1 genres.
Definition: id3v1.c:26
AV_CODEC_ID_JPEGXL
@ AV_CODEC_ID_JPEGXL
Definition: codec_id.h:317
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:839
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
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
AV_FDEBUG_ID3V2
#define AV_FDEBUG_ID3V2
Definition: avformat.h:1561
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:825
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:163
tag
uint32_t tag
Definition: movenc.c:2049
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:747
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
pos
unsigned int pos
Definition: spdifenc.c:414
av_bprintf
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition: bprint.c:122
dict.h
ff_id3v2_tags
const attribute_nonstring 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:93
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
id
enum AVCodecID id
Definition: dts2pts.c:550
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
U
#define U(x)
Definition: vpx_arith.h:37
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:67
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:481
CodecMime::str
char str[32]
Definition: internal.h:48
CodecMime::id
enum AVCodecID id
Definition: internal.h:49
ID3v2_FLAG_COMPRESSION
#define ID3v2_FLAG_COMPRESSION
Definition: id3v2.h:40
mem.h
av_strdup
#define av_strdup(s)
Definition: ops_asmgen.c:47
read_priv
static void read_priv(AVFormatContext *s, AVIOContext *pb, int taglen, const char *tag, ExtraMetaList *extra_meta, int isv34)
Definition: id3v2.c:769
ID3v2EMFunc
Definition: id3v2.c:803
id3v2_extra_meta_funcs
static const ID3v2EMFunc id3v2_extra_meta_funcs[]
Definition: id3v2.c:812
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:57
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:1178
ID3v2EMFunc::read
void(* read)(AVFormatContext *s, AVIOContext *pb, int taglen, const char *tag, ExtraMetaList *extra_meta, int isv34)
Definition: id3v2.c:806
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:1290
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:80
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:805
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:1250
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:150
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:377
ID3v2ExtraMetaAPIC::description
uint8_t * description
Definition: id3v2.h:68
ID3v2ExtraMeta::priv
ID3v2ExtraMetaPRIV priv
Definition: id3v2.h:91