FFmpeg
Loading...
Searching...
No Matches
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"
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
35static 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
43static int string_is_ascii(const uint8_t *str)
44{
45 while (*str && *str < 128) str++;
46 return !*str;
47}
48
49static 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
63static 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 */
157static 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 '"
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
201static 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
207static 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
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;
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
349void 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
411static 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
435static 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
468fail:
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
576int 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}
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
Main libavformat public API header.
Buffered I/O operations.
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition aviobuf.c:236
void avio_wl16(AVIOContext *s, unsigned int val)
Definition aviobuf.c:440
int avio_put_str(AVIOContext *s, const char *str)
Write a NULL-terminated string.
Definition aviobuf.c:376
void avio_w8(AVIOContext *s, int b)
Definition aviobuf.c:184
void avio_wb32(AVIOContext *s, unsigned int val)
Definition aviobuf.c:368
void avio_wb16(AVIOContext *s, unsigned int val)
Definition aviobuf.c:446
int avio_put_str16le(AVIOContext *s, const char *str)
Convert an UTF-8 string to UTF-16LE and write it.
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition avio.h:494
void avio_write(AVIOContext *s, const unsigned char *buf, int size)
Definition aviobuf.c:206
int avio_open_dyn_buf(AVIOContext **s)
Open a write only memory stream.
Definition aviobuf.c:1365
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition aviobuf.c:1377
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition aviobuf.c:1438
void ffio_fill(AVIOContext *s, int b, int64_t count)
Definition aviobuf.c:192
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
@ AV_LANG_ISO639_2_BIBL
Definition avlanguage.h:28
static int FUNC metadata(CodedBitstreamContext *ctx, RWContext *rw, APVRawMetadata *current)
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
static int FUNC comment(CodedBitstreamContext *ctx, RWContext *rw, JPEGRawComment *current)
#define s(width, name)
Definition cbs_vp9.c:198
#define av_clip
Definition common.h:100
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static AVPacket * pkt
Public dictionary API.
enum AVCodecID id
Definition dts2pts.c:607
double value
Definition eval.c:102
const char * key
#define fail
Definition test.h:479
@ AV_CODEC_ID_NONE
Definition codec_id.h:48
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:233
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
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Definition dict.c:42
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
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition mem.c:284
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition avstring.c:208
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
static av_const int av_isxdigit(int c)
Locale-independent conversion of ASCII isxdigit.
Definition avstring.h:247
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
cl_device_type type
attribute_nonstring const char ff_id3v2_4_tags[][4]
ID3v2.4-only text information frames.
Definition id3v2.c:103
attribute_nonstring 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:95
const AVMetadataConv ff_id3v2_34_metadata_conv[]
Definition id3v2.c:49
attribute_nonstring const char ff_id3v2_3_tags[][4]
ID3v2.3-only text information frames.
Definition id3v2.c:109
const AVMetadataConv ff_id3v2_4_metadata_conv[]
Definition id3v2.c:69
const char *const ff_id3v2_picture_types[21]
Definition id3v2.c:114
const CodecMime ff_id3v2_mime_tags[]
Definition id3v2.c:138
#define ID3v2_PRIV_METADATA_PREFIX
Definition id3v2.h:42
ID3v2Encoding
Definition id3v2.h:44
@ ID3v2_ENCODING_UTF8
Definition id3v2.h:48
@ ID3v2_ENCODING_UTF16BOM
Definition id3v2.h:46
@ ID3v2_ENCODING_ISO8859
Definition id3v2.h:45
#define ID3v2_HEADER_SIZE
Definition id3v2.h:30
void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version, const char *magic)
Initialize an ID3v2 tag.
Definition id3v2enc.c:349
static int id3v2_check_write_lang_descr_tag(ID3v2EncContext *id3, AVIOContext *pb, const AVDictionaryEntry *t, enum ID3v2Encoding enc)
Definition id3v2enc.c:212
void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb, int padding_bytes)
Finalize an opened ID3v2 tag.
Definition id3v2enc.c:552
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
static int is_valid_lang(const char *s)
Definition id3v2enc.c:207
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
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
static int write_metadata(AVIOContext *pb, AVDictionary **metadata, ID3v2EncContext *id3, int enc)
Definition id3v2enc.c:363
static int id3v2_check_write_tag(ID3v2EncContext *id3, AVIOContext *pb, const AVDictionaryEntry *t, const char table[][4], enum ID3v2Encoding enc)
Definition id3v2enc.c:292
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
static int string_is_ascii(const uint8_t *str)
Definition id3v2enc.c:43
static void id3v2_encode_string(AVIOContext *pb, const uint8_t *str, enum ID3v2Encoding enc)
Definition id3v2enc.c:49
static int id3v2_put_frame(ID3v2EncContext *id3, AVIOContext *avioc, AVIOContext *dyn_buf, const uint32_t tag, const uint8_t flags)
Definition id3v2enc.c:63
static void id3v2_3_metadata_split_date(AVDictionary **pm)
Definition id3v2enc.c:311
static int write_chapter(AVFormatContext *s, ID3v2EncContext *id3, int id, int enc)
Definition id3v2enc.c:435
static int write_ctoc(AVFormatContext *s, ID3v2EncContext *id3, int enc)
Definition id3v2enc.c:411
static const struct LangDescrTagMap id3v2_lang_descr_tags[]
Definition id3v2enc.c:201
static void id3v2_put_size(AVIOContext *pb, int size)
Definition id3v2enc.c:35
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
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
#define AV_RB32(p)
const char * desc
Definition libsvtav1.c:83
#define MKBETAG(a, b, c, d)
Definition macros.h:56
Memory handling functions.
void ff_metadata_conv(AVDictionary **pm, const AVMetadataConv *d_conv, const AVMetadataConv *s_conv)
Definition metadata.c:26
uint32_t tag
Definition movenc.c:2073
int ff_standardize_creation_time(AVFormatContext *s)
Standardize creation_time metadata in AVFormatContext to an ISO-8601 timestamp string.
Definition mux_utils.c:154
const char data[16]
Definition mxf.c:149
static const uint16_t table[]
Definition prosumer.c:203
const char * name
Definition qsvenc.c:142
#define FF_ARRAY_ELEMS(a)
#define snprintf
Definition snprintf.h:34
int64_t start
Definition avformat.h:1295
AVDictionary * metadata
Definition avformat.h:1296
int64_t end
chapter start/end time in time_base units
Definition avformat.h:1295
AVRational time_base
time base in which the start/end timestamps are specified
Definition avformat.h:1294
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition codec_par.h:57
char * key
Definition dict.h:91
char * value
Definition dict.h:92
Format I/O context.
Definition avformat.h:1333
Bytestream IO Context.
Definition avio.h:160
This structure stores compressed data.
Definition packet.h:580
Rational number (pair of numerator and denominator).
Definition rational.h:58
Stream structure.
Definition avformat.h:766
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:789
AVDictionary * metadata
Definition avformat.h:846
int index
stream index in AVFormatContext
Definition avformat.h:772
char str[32]
Definition internal.h:48
enum AVCodecID id
Definition internal.h:49
int64_t size_pos
offset of the tag total size
Definition id3v2.h:53
int len
size of the tag written so far
Definition id3v2.h:54
int version
ID3v2 minor version, either 3 or 4.
Definition id3v2.h:52
uint32_t tag
Definition id3v2enc.c:198
const char *const key
Definition id3v2enc.c:197
#define av_freep(p)
#define av_log(a,...)
int size
int len