FFmpeg
id3v2enc.c
Go to the documentation of this file.
1 /*
2  * ID3v2 header writer
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 #include <stdint.h>
22 #include <string.h>
23 
24 #include "libavutil/avstring.h"
25 #include "libavutil/dict.h"
26 #include "libavutil/intreadwrite.h"
27 #include "libavutil/mem.h"
28 #include "avformat.h"
29 #include "avlanguage.h"
30 #include "avio.h"
31 #include "avio_internal.h"
32 #include "id3v2.h"
33 #include "mux.h"
34 
35 static void id3v2_put_size(AVIOContext *pb, int size)
36 {
37  avio_w8(pb, size >> 21 & 0x7f);
38  avio_w8(pb, size >> 14 & 0x7f);
39  avio_w8(pb, size >> 7 & 0x7f);
40  avio_w8(pb, size & 0x7f);
41 }
42 
43 static int string_is_ascii(const uint8_t *str)
44 {
45  while (*str && *str < 128) str++;
46  return !*str;
47 }
48 
49 static void id3v2_encode_string(AVIOContext *pb, const uint8_t *str,
50  enum ID3v2Encoding enc)
51 {
52  int (*put)(AVIOContext*, const char*);
53 
54  if (enc == ID3v2_ENCODING_UTF16BOM) {
55  avio_wl16(pb, 0xFEFF); /* BOM */
56  put = avio_put_str16le;
57  } else
58  put = avio_put_str;
59 
60  put(pb, str);
61 }
62 
63 static int id3v2_put_frame(ID3v2EncContext *id3, AVIOContext *avioc, AVIOContext *dyn_buf,
64  const uint32_t tag, const uint8_t flags)
65 {
66  int len;
67  uint8_t *pb;
68  len = avio_get_dyn_buf(dyn_buf, &pb);
69 
70  avio_wb32(avioc, tag);
71  /* ID3v2.3 frame size is not sync-safe */
72  if (id3->version == 3)
73  avio_wb32(avioc, len);
74  else
75  id3v2_put_size(avioc, len);
76  avio_wb16(avioc, flags);
77  avio_write(avioc, pb, len);
78 
79  id3->len += len + ID3v2_HEADER_SIZE;
80 
81  ffio_free_dyn_buf(&dyn_buf);
82  return 1;
83 }
84 
85 /**
86  * Write a frame containing lang, descr and text such as COMM and USLT
87  * according to encoding (only UTF-8 or UTF-16+BOM supported).
88  * @return number of bytes written or a negative error code.
89  */
91  ID3v2EncContext *id3, AVIOContext *avioc,
92  const uint32_t tag, const uint8_t flags,
93  const char *lang, const char *descr,
94  const char *comment, enum ID3v2Encoding enc)
95 {
96  int ret;
97  AVIOContext *dyn_buf;
98  if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0)
99  return ret;
100 
101  /* check if the strings are ASCII-only and use UTF16 only if
102  * they're not */
104  (!descr || string_is_ascii(descr)))
106 
107  avio_w8(dyn_buf, enc);
108  avio_write(dyn_buf, lang, 3);
109  // avio_put_str can handle NULL pointer but avio_put_str16le cannot.
110  id3v2_encode_string(dyn_buf, descr ? descr : "", enc);
111  id3v2_encode_string(dyn_buf, comment, enc);
112 
113  return id3v2_put_frame(id3, avioc, dyn_buf, tag, flags);
114 }
115 
116 /**
117  * Write a text frame with multiple text string according to encoding (only
118  * UTF-8 or UTF-16+BOM supported).
119  * @return number of bytes written or a negative error code.
120  */
122  ID3v2EncContext *id3, AVIOContext *avioc,
123  const uint32_t tag, const uint8_t flags,
124  const char **strings, int len,
125  enum ID3v2Encoding enc)
126 {
127  int i, ret;
128  AVIOContext *dyn_buf;
129  if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0)
130  return ret;
131 
132  /* check if the strings are ASCII-only and use UTF16 only if
133  * they're not */
134  if (enc == ID3v2_ENCODING_UTF16BOM) {
136  for (i = 0; i < len; i++) {
137  if (!string_is_ascii((const uint8_t *)strings[i])) {
139  break;
140  }
141  }
142  }
143 
144  avio_w8(dyn_buf, enc);
145 
146  for (i = 0; i < len; i++)
147  id3v2_encode_string(dyn_buf, strings[i], enc);
148 
149  return id3v2_put_frame(id3, avioc, dyn_buf, tag, flags);
150 }
151 
152 /**
153  * Write a priv frame with owner and data. 'key' is the owner prepended with
154  * ID3v2_PRIV_METADATA_PREFIX. 'data' is provided as a string. Any \xXX
155  * (where 'X' is a valid hex digit) will be unescaped to the byte value.
156  */
157 static int id3v2_put_priv(
158  ID3v2EncContext *id3, AVIOContext *avioc,
159  const uint8_t flags, const char *key,
160  const char *data)
161 {
162  int ret;
163  AVIOContext *dyn_buf;
164 
166  return 0;
167  }
168 
169  if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0)
170  return ret;
171 
172  // owner + null byte.
173  avio_write(dyn_buf, key, strlen(key) + 1);
174 
175  while (*data) {
176  if (av_strstart(data, "\\x", &data)) {
177  if (data[0] && data[1] && av_isxdigit(data[0]) && av_isxdigit(data[1])) {
178  char digits[] = {data[0], data[1], 0};
179  avio_w8(dyn_buf, strtol(digits, NULL, 16));
180  data += 2;
181  } else {
182  ffio_free_dyn_buf(&dyn_buf);
183  av_log(avioc, AV_LOG_ERROR, "Invalid escape '\\x%.2s' in metadata tag '"
184  ID3v2_PRIV_METADATA_PREFIX "%s'.\n", data, key);
185  return AVERROR(EINVAL);
186  }
187  } else {
188  avio_write(dyn_buf, data++, 1);
189  }
190  }
191 
192  return id3v2_put_frame(id3, avioc, dyn_buf, MKBETAG('P', 'R', 'I', 'V'),
193  flags);
194 }
195 
197  const char * const key;
198  uint32_t tag;
199 };
200 
201 static const struct LangDescrTagMap id3v2_lang_descr_tags[] = {
202  {.key = "comment", .tag = MKBETAG('C', 'O', 'M', 'M')},
203  {.key = "lyrics", .tag = MKBETAG('U', 'S', 'L', 'T')},
204  {.key = NULL, .tag = 0}
205 };
206 
207 static int is_valid_lang(const char *s)
208 {
209  return strlen(s) == 3 && ff_convert_lang_to(s, AV_LANG_ISO639_2_BIBL);
210 }
211 
213  ID3v2EncContext *id3, AVIOContext *pb, const AVDictionaryEntry *t,
214  enum ID3v2Encoding enc)
215 {
216  int i, key_len;
217  const char *key, *after_dash, *last_dash;
218  uint32_t tag, ff_tag = 0;
219  char lang[4] = "und";
220 
221  /* Raw 4CC key (e.g. "COMM"): only exact match, no suffix modifiers. */
222  if (strlen(t->key) == 4)
223  ff_tag = AV_RB32(t->key);
224 
225  for (i = 0; id3v2_lang_descr_tags[i].key; i++) {
228  key_len = strlen(key);
229 
230  if (ff_tag == tag)
231  return id3v2_put_lang_descr_tag(id3, pb, tag, 0,
232  lang, NULL, t->value, enc);
233 
234  /* Generic key (e.g. "comment"): require exact match or '-' separator. */
235  if (strncmp(t->key, key, key_len) ||
236  (t->key[key_len] != '\0' && t->key[key_len] != '-'))
237  continue;
238 
239  if (t->key[key_len] == '\0')
240  return id3v2_put_lang_descr_tag(id3, pb, tag, 0,
241  lang, NULL, t->value, enc);
242 
243  /* Has suffix(es) after '-'. */
244  after_dash = t->key + key_len + 1;
245  last_dash = strrchr(after_dash, '-');
246  const char *suffix = NULL;
247  const char *middle = NULL;
248 
249  if (last_dash) {
250  middle = after_dash;
251  suffix = last_dash + 1;
252  } else {
253  suffix = after_dash;
254  }
255 
256  if (!middle) {
257  /* <tag>-<suffix>: valid lang → lang only; otherwise →
258  * descriptor only. */
259  const char *descr = NULL;
260  if (is_valid_lang(suffix))
261  memcpy(lang, suffix, 3);
262  else
263  descr = suffix;
264  return id3v2_put_lang_descr_tag(id3, pb, tag, 0, lang,
265  descr, t->value, enc);
266  } else {
267  /* <tag>-<middle>-<suffix>: valid lang suffix → lang+descriptor;
268  * otherwise → full suffix after first '-' is the descriptor. */
269  if (is_valid_lang(suffix) || *suffix == '\0') {
270  /* Valid lang suffix or trailing dash (explicit empty lang):
271  * descriptor = everything before the last '-'. */
272  size_t descr_len = last_dash - after_dash;
273  char *descr = av_strndup(middle, descr_len);
274  int ret;
275  if (!descr)
276  return AVERROR(ENOMEM);
277  if (*suffix)
278  memcpy(lang, suffix, 3);
279  ret = id3v2_put_lang_descr_tag(id3, pb, tag, 0,
280  lang, descr, t->value, enc);
281  av_freep(&descr);
282  return ret;
283  }
284  return id3v2_put_lang_descr_tag(id3, pb, tag, 0,
285  lang, after_dash, t->value, enc);
286  }
287  }
288 
289  return 0;
290 }
291 
293  const char table[][4], enum ID3v2Encoding enc)
294 {
295  uint32_t tag;
296  int i;
297 
298  if (t->key[0] != 'T' || strlen(t->key) != 4)
299  return 0;
300 
301  tag = AV_RB32(t->key);
302  for (i = 0; *table[i]; i++)
303  if (tag == AV_RB32(table[i])) {
304  const char *strings[] = {t->value};
305  return id3v2_put_text_tag(id3, pb, tag, 0, strings, 1, enc);
306  }
307 
308  return 0;
309 }
310 
312 {
313  const AVDictionaryEntry *mtag = NULL;
314  AVDictionary *dst = NULL;
315  const char *key, *value;
316  char year[5] = {0}, day_month[5] = {0};
317  int i;
318 
319  while ((mtag = av_dict_iterate(*pm, mtag))) {
320  key = mtag->key;
321  if (!av_strcasecmp(key, "date")) {
322  /* split date tag using "YYYY-MM-DD" format into year and month/day segments */
323  value = mtag->value;
324  i = 0;
325  while (value[i] >= '0' && value[i] <= '9') i++;
326  if (value[i] == '\0' || value[i] == '-') {
327  av_strlcpy(year, value, sizeof(year));
328  av_dict_set(&dst, "TYER", year, 0);
329 
330  if (value[i] == '-' &&
331  value[i+1] >= '0' && value[i+1] <= '1' &&
332  value[i+2] >= '0' && value[i+2] <= '9' &&
333  value[i+3] == '-' &&
334  value[i+4] >= '0' && value[i+4] <= '3' &&
335  value[i+5] >= '0' && value[i+5] <= '9' &&
336  (value[i+6] == '\0' || value[i+6] == ' ')) {
337  snprintf(day_month, sizeof(day_month), "%.2s%.2s", value + i + 4, value + i + 1);
338  av_dict_set(&dst, "TDAT", day_month, 0);
339  }
340  } else
341  av_dict_set(&dst, key, value, 0);
342  } else
343  av_dict_set(&dst, key, mtag->value, 0);
344  }
345  av_dict_free(pm);
346  *pm = dst;
347 }
348 
349 void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version,
350  const char *magic)
351 {
352  id3->version = id3v2_version;
353 
354  avio_wb32(pb, MKBETAG(magic[0], magic[1], magic[2], id3v2_version));
355  avio_w8(pb, 0);
356  avio_w8(pb, 0); /* flags */
357 
358  /* reserve space for size */
359  id3->size_pos = avio_tell(pb);
360  avio_wb32(pb, 0);
361 }
362 
364  ID3v2EncContext *id3, int enc)
365 {
366  const AVDictionaryEntry *t = NULL;
367  int ret;
368 
370  if (id3->version == 3)
372  else if (id3->version == 4)
374 
375  while ((t = av_dict_iterate(*metadata, t))) {
376  if ((ret = id3v2_check_write_lang_descr_tag(id3, pb, t, enc)) > 0)
377  continue;
378 
379  if (ret < 0)
380  return ret;
381 
382  if ((ret = id3v2_check_write_tag(id3, pb, t, ff_id3v2_tags, enc)) > 0)
383  continue;
384 
385  if (ret < 0)
386  return ret;
387 
388  if ((ret = id3v2_check_write_tag(id3, pb, t, id3->version == 3 ?
389  ff_id3v2_3_tags : ff_id3v2_4_tags, enc)) > 0)
390  continue;
391 
392  if (ret < 0)
393  return ret;
394 
395  if ((ret = id3v2_put_priv(id3, pb, 0, t->key, t->value)) > 0)
396  continue;
397 
398  if (ret < 0)
399  return ret;
400 
401  /* unknown tag, write as TXXX frame */
402  const char *strings[] = {t->key, t->value};
403  if ((ret = id3v2_put_text_tag(id3, pb, MKBETAG('T', 'X', 'X', 'X'),
404  0, strings, 2, enc)) < 0)
405  return ret;
406  }
407 
408  return 0;
409 }
410 
411 static int write_ctoc(AVFormatContext *s, ID3v2EncContext *id3, int enc)
412 {
413  AVIOContext *dyn_bc;
414  char name[123];
415  int ret;
416 
417  if (s->nb_chapters == 0)
418  return 0;
419 
420  if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0)
421  return ret;
422 
423  avio_put_str(dyn_bc, "toc");
424  avio_w8(dyn_bc, 0x03);
425  avio_w8(dyn_bc, s->nb_chapters);
426  for (int i = 0; i < s->nb_chapters; i++) {
427  snprintf(name, 122, "ch%d", i);
428  avio_put_str(dyn_bc, name);
429  }
430 
431  return id3v2_put_frame(id3, s->pb, dyn_bc,
432  MKBETAG('C', 'T', 'O', 'C'), 0);
433 }
434 
435 static int write_chapter(AVFormatContext *s, ID3v2EncContext *id3, int id, int enc)
436 {
437  const AVRational time_base = {1, 1000};
438  AVChapter *ch = s->chapters[id];
439  uint8_t *dyn_buf;
440  AVIOContext *dyn_bc;
441  char name[123];
442  int len, start, end, ret;
443 
444  if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0)
445  return ret;
446 
447  start = av_rescale_q(ch->start, ch->time_base, time_base);
448  end = av_rescale_q(ch->end, ch->time_base, time_base);
449 
450  snprintf(name, 122, "ch%d", id);
451  id3->len += avio_put_str(dyn_bc, name);
452  avio_wb32(dyn_bc, start);
453  avio_wb32(dyn_bc, end);
454  avio_wb32(dyn_bc, 0xFFFFFFFFu);
455  avio_wb32(dyn_bc, 0xFFFFFFFFu);
456 
457  if ((ret = write_metadata(dyn_bc, &ch->metadata, id3, enc)) < 0)
458  goto fail;
459 
460  len = avio_get_dyn_buf(dyn_bc, &dyn_buf);
461  id3->len += 16 + ID3v2_HEADER_SIZE;
462 
463  avio_wb32(s->pb, MKBETAG('C', 'H', 'A', 'P'));
464  avio_wb32(s->pb, len);
465  avio_wb16(s->pb, 0);
466  avio_write(s->pb, dyn_buf, len);
467 
468 fail:
469  ffio_free_dyn_buf(&dyn_bc);
470 
471  return ret;
472 }
473 
475 {
476  int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM :
478  int i, ret;
479 
481  if ((ret = write_metadata(s->pb, &s->metadata, id3, enc)) < 0)
482  return ret;
483 
484  if ((ret = write_ctoc(s, id3, enc)) < 0)
485  return ret;
486 
487  for (i = 0; i < s->nb_chapters; i++) {
488  if ((ret = write_chapter(s, id3, i, enc)) < 0)
489  return ret;
490  }
491 
492  return 0;
493 }
494 
496 {
497  AVStream *st = s->streams[pkt->stream_index];
499 
500  AVIOContext *dyn_buf;
501  const CodecMime *mime = ff_id3v2_mime_tags;
502  const char *mimetype = NULL, *desc = "";
503  int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM :
505  int i, type = 0, ret;
506 
507  /* get the mimetype*/
508  while (mime->id != AV_CODEC_ID_NONE) {
509  if (mime->id == st->codecpar->codec_id) {
510  mimetype = mime->str;
511  break;
512  }
513  mime++;
514  }
515  if (!mimetype) {
516  av_log(s, AV_LOG_ERROR, "No mimetype is known for stream %d, cannot "
517  "write an attached picture.\n", st->index);
518  return AVERROR(EINVAL);
519  }
520 
521  /* get the picture type */
522  e = av_dict_get(st->metadata, "comment", NULL, 0);
523  for (i = 0; e && i < FF_ARRAY_ELEMS(ff_id3v2_picture_types); i++) {
525  type = i;
526  break;
527  }
528  }
529 
530  /* get the description */
531  if ((e = av_dict_get(st->metadata, "title", NULL, 0)))
532  desc = e->value;
533 
534  /* use UTF16 only for non-ASCII strings */
537 
538  /* start writing */
539  if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0)
540  return ret;
541 
542  avio_w8(dyn_buf, enc);
543  avio_put_str(dyn_buf, mimetype);
544  avio_w8(dyn_buf, type);
545  id3v2_encode_string(dyn_buf, desc, enc);
546  avio_write(dyn_buf, pkt->data, pkt->size);
547 
548  return id3v2_put_frame(id3, s->pb, dyn_buf,
549  MKBETAG('A', 'P', 'I', 'C'), 0);
550 }
551 
553  int padding_bytes)
554 {
555  int64_t cur_pos;
556 
557  if (padding_bytes < 0)
558  padding_bytes = 10;
559 
560  /* The ID3v2.3 specification states that 28 bits are used to represent the
561  * size of the whole tag. Therefore the current size of the tag needs to be
562  * subtracted from the upper limit of 2^28-1 to clip the value correctly. */
563  /* The minimum of 10 is an arbitrary amount of padding at the end of the tag
564  * to fix cover art display with some software such as iTunes, Traktor,
565  * Serato, Torq. */
566  padding_bytes = av_clip(padding_bytes, 10, 268435455 - id3->len);
567  ffio_fill(pb, 0, padding_bytes);
568  id3->len += padding_bytes;
569 
570  cur_pos = avio_tell(pb);
571  avio_seek(pb, id3->size_pos, SEEK_SET);
572  id3v2_put_size(pb, id3->len);
573  avio_seek(pb, cur_pos, SEEK_SET);
574 }
575 
576 int ff_id3v2_write_simple(struct AVFormatContext *s, int id3v2_version,
577  const char *magic)
578 {
579  ID3v2EncContext id3 = { 0 };
580  int ret;
581 
582  ff_id3v2_start(&id3, s->pb, id3v2_version, magic);
583  if ((ret = ff_id3v2_write_metadata(s, &id3)) < 0)
584  return ret;
585  ff_id3v2_finish(&id3, s->pb, s->metadata_header_padding);
586 
587  return 0;
588 }
av_isxdigit
static av_const int av_isxdigit(int c)
Locale-independent conversion of ASCII isxdigit.
Definition: avstring.h:247
name
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 default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
av_clip
#define av_clip
Definition: common.h:100
ID3v2EncContext
Definition: id3v2.h:51
AVChapter::metadata
AVDictionary * metadata
Definition: avformat.h:1296
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
int64_t
long long int64_t
Definition: coverity.c:34
write_metadata
static int write_metadata(AVIOContext *pb, AVDictionary **metadata, ID3v2EncContext *id3, int enc)
Definition: id3v2enc.c:363
ID3v2EncContext::len
int len
size of the tag written so far
Definition: id3v2.h:54
avlanguage.h
av_strcasecmp
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:208
id3v2.h
ff_metadata_conv
void ff_metadata_conv(AVDictionary **pm, const AVMetadataConv *d_conv, const AVMetadataConv *s_conv)
Definition: metadata.c:26
AVPacket::data
uint8_t * data
Definition: packet.h:603
ID3v2EncContext::version
int version
ID3v2 minor version, either 3 or 4.
Definition: id3v2.h:52
table
static const uint16_t table[]
Definition: prosumer.c:203
AVChapter::start
int64_t start
Definition: avformat.h:1295
data
const char data[16]
Definition: mxf.c:149
ff_id3v2_finish
void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb, int padding_bytes)
Finalize an opened ID3v2 tag.
Definition: id3v2enc.c:552
AVDictionary
Definition: dict.c:32
key
const char * key
Definition: ffmpeg_mux_init.c:2971
avio_get_dyn_buf
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition: aviobuf.c:1377
ff_id3v2_write_metadata
int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3)
Convert and write all global metadata from s into an ID3v2 tag.
Definition: id3v2enc.c:474
avio_wl16
void avio_wl16(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:440
CodecMime
Definition: internal.h:47
id3v2_encode_string
static void id3v2_encode_string(AVIOContext *pb, const uint8_t *str, enum ID3v2Encoding enc)
Definition: id3v2enc.c:49
avio_tell
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:494
AVChapter
Definition: avformat.h:1292
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
ID3v2_PRIV_METADATA_PREFIX
#define ID3v2_PRIV_METADATA_PREFIX
Definition: id3v2.h:42
id3v2_put_frame
static int id3v2_put_frame(ID3v2EncContext *id3, AVIOContext *avioc, AVIOContext *dyn_buf, const uint32_t tag, const uint8_t flags)
Definition: id3v2enc.c:63
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
LangDescrTagMap
Definition: id3v2enc.c:196
ff_id3v2_write_simple
int ff_id3v2_write_simple(struct AVFormatContext *s, int id3v2_version, const char *magic)
Write an ID3v2 tag containing all global metadata from s.
Definition: id3v2enc.c:576
ID3v2_ENCODING_UTF8
@ ID3v2_ENCODING_UTF8
Definition: id3v2.h:48
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
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:504
AVChapter::end
int64_t end
chapter start/end time in time_base units
Definition: avformat.h:1295
intreadwrite.h
id3v2_put_size
static void id3v2_put_size(AVIOContext *pb, int size)
Definition: id3v2enc.c:35
AVDictionaryEntry::key
char * key
Definition: dict.h:91
id3v2_3_metadata_split_date
static void id3v2_3_metadata_split_date(AVDictionary **pm)
Definition: id3v2enc.c:311
ff_id3v2_4_tags
const attribute_nonstring char ff_id3v2_4_tags[][4]
ID3v2.4-only text information frames.
Definition: id3v2.c:103
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
if
if(ret)
Definition: filter_design.txt:179
AVFormatContext
Format I/O context.
Definition: avformat.h:1333
fail
#define fail
Definition: test.h:478
ff_id3v2_start
void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version, const char *magic)
Initialize an ID3v2 tag.
Definition: id3v2enc.c:349
AVStream::codecpar
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:789
AV_LANG_ISO639_2_BIBL
@ AV_LANG_ISO639_2_BIBL
Definition: avlanguage.h:28
metadata
Stream codec metadata
Definition: ogg-flac-chained-meta.txt:2
NULL
#define NULL
Definition: coverity.c:32
ID3v2Encoding
ID3v2Encoding
Definition: id3v2.h:44
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
ID3v2EncContext::size_pos
int64_t size_pos
offset of the tag total size
Definition: id3v2.h:53
AVStream::metadata
AVDictionary * metadata
Definition: avformat.h:846
avio_w8
void avio_w8(AVIOContext *s, int b)
Definition: aviobuf.c:184
ffio_fill
void ffio_fill(AVIOContext *s, int b, int64_t count)
Definition: aviobuf.c:192
ff_id3v2_picture_types
const char *const ff_id3v2_picture_types[21]
Definition: id3v2.c:114
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:109
ff_id3v2_mime_tags
const CodecMime ff_id3v2_mime_tags[]
Definition: id3v2.c:138
id3v2_put_lang_descr_tag
static int id3v2_put_lang_descr_tag(ID3v2EncContext *id3, AVIOContext *avioc, const uint32_t tag, const uint8_t flags, const char *lang, const char *descr, const char *comment, enum ID3v2Encoding enc)
Write a frame containing lang, descr and text such as COMM and USLT according to encoding (only UTF-8...
Definition: id3v2enc.c:90
id3v2_check_write_tag
static int id3v2_check_write_tag(ID3v2EncContext *id3, AVIOContext *pb, const AVDictionaryEntry *t, const char table[][4], enum ID3v2Encoding enc)
Definition: id3v2enc.c:292
AVIOContext
Bytestream IO Context.
Definition: avio.h:160
ID3v2_ENCODING_UTF16BOM
@ ID3v2_ENCODING_UTF16BOM
Definition: id3v2.h:46
AVPacket::size
int size
Definition: packet.h:604
ff_standardize_creation_time
int ff_standardize_creation_time(AVFormatContext *s)
Standardize creation_time metadata in AVFormatContext to an ISO-8601 timestamp string.
Definition: mux_utils.c:154
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
id3v2_lang_descr_tags
static const struct LangDescrTagMap id3v2_lang_descr_tags[]
Definition: id3v2enc.c:201
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
ff_convert_lang_to
const char * ff_convert_lang_to(const char *lang, enum AVLangCodespace target_codespace)
Convert a language code to a target codespace.
Definition: avlanguage.c:741
size
int size
Definition: twinvq_data.h:10344
avio.h
MKBETAG
#define MKBETAG(a, b, c, d)
Definition: macros.h:56
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:49
write_ctoc
static int write_ctoc(AVFormatContext *s, ID3v2EncContext *id3, int enc)
Definition: id3v2enc.c:411
avio_write
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition: aviobuf.c:206
avio_wb32
void avio_wb32(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:368
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_strstart
int av_strstart(const char *str, const char *pfx, const char **ptr)
Return non-zero if pfx is a prefix of str.
Definition: avstring.c:36
LangDescrTagMap::key
const char *const key
Definition: id3v2enc.c:197
id3v2_check_write_lang_descr_tag
static int id3v2_check_write_lang_descr_tag(ID3v2EncContext *id3, AVIOContext *pb, const AVDictionaryEntry *t, enum ID3v2Encoding enc)
Definition: id3v2enc.c:212
id3v2_put_text_tag
static int id3v2_put_text_tag(ID3v2EncContext *id3, AVIOContext *avioc, const uint32_t tag, const uint8_t flags, const char **strings, int len, enum ID3v2Encoding enc)
Write a text frame with multiple text string according to encoding (only UTF-8 or UTF-16+BOM supporte...
Definition: id3v2enc.c:121
ff_id3v2_write_apic
int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt)
Write an attached picture from pkt into an ID3v2 tag.
Definition: id3v2enc.c:495
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:48
avio_internal.h
id3v2_put_priv
static int id3v2_put_priv(ID3v2EncContext *id3, AVIOContext *avioc, const uint8_t flags, const char *key, const char *data)
Write a priv frame with owner and data.
Definition: id3v2enc.c:157
s
uint8_t s
Definition: llvidencdsp.c:39
value
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 default value
Definition: writing_filters.txt:86
len
int len
Definition: vorbis_enc_data.h:426
tag
uint32_t tag
Definition: movenc.c:2073
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:766
avio_seek
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:236
comment
static int FUNC() comment(CodedBitstreamContext *ctx, RWContext *rw, JPEGRawComment *current)
Definition: cbs_jpeg_syntax_template.c:174
avformat.h
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:95
id
enum AVCodecID id
Definition: dts2pts.c:607
AVStream::index
int index
stream index in AVFormatContext
Definition: avformat.h:772
ff_id3v2_4_metadata_conv
const AVMetadataConv ff_id3v2_4_metadata_conv[]
Definition: id3v2.c:69
AVPacket::stream_index
int stream_index
Definition: packet.h:605
is_valid_lang
static int is_valid_lang(const char *s)
Definition: id3v2enc.c:207
CodecMime::str
char str[32]
Definition: internal.h:48
CodecMime::id
enum AVCodecID id
Definition: internal.h:49
desc
const char * desc
Definition: libsvtav1.c:83
mem.h
string_is_ascii
static int string_is_ascii(const uint8_t *str)
Definition: id3v2enc.c:43
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
AVPacket
This structure stores compressed data.
Definition: packet.h:580
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
avio_put_str16le
int avio_put_str16le(AVIOContext *s, const char *str)
Convert an UTF-8 string to UTF-16LE and write it.
LangDescrTagMap::tag
uint32_t tag
Definition: id3v2enc.c:198
avio_wb16
void avio_wb16(AVIOContext *s, unsigned int val)
Definition: aviobuf.c:446
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
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVDictionaryEntry::value
char * value
Definition: dict.h:92
pkt
static AVPacket * pkt
Definition: demux_decode.c:55
avstring.h
av_strndup
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:284
AVChapter::time_base
AVRational time_base
time base in which the start/end timestamps are specified
Definition: avformat.h:1294
avio_put_str
int avio_put_str(AVIOContext *s, const char *str)
Write a NULL-terminated string.
Definition: aviobuf.c:376
snprintf
#define snprintf
Definition: snprintf.h:34
write_chapter
static int write_chapter(AVFormatContext *s, ID3v2EncContext *id3, int id, int enc)
Definition: id3v2enc.c:435
av_dict_iterate
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Definition: dict.c:42
ID3v2_ENCODING_ISO8859
@ ID3v2_ENCODING_ISO8859
Definition: id3v2.h:45
mux.h