FFmpeg
Loading...
Searching...
No Matches
writer.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"
30#include "libavformat/avio.h"
32#include "libavformat/id3v2.h"
33#include "libavformat/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 */
57 } else
59
60 put(pb, str);
61}
62
63/* ID3v2.3 frame size is not synchsafe; 2.4 is. */
65 uint32_t tag, int len, int flags)
66{
67 avio_wb32(pb, tag);
68 if (id3->version == 3)
69 avio_wb32(pb, len);
70 else
72 avio_wb16(pb, flags);
73}
74
75static int id3v2_put_frame(ID3v2EncContext *id3, AVIOContext *avioc, AVIOContext *dyn_buf,
76 const uint32_t tag, const uint8_t flags)
77{
78 int len;
79 uint8_t *pb;
80 len = avio_get_dyn_buf(dyn_buf, &pb);
81
82 id3v2_put_frame_header(id3, avioc, tag, len, flags);
83 avio_write(avioc, pb, len);
84
85 id3->len += len + ID3v2_HEADER_SIZE;
86
87 ffio_free_dyn_buf(&dyn_buf);
88 return 1;
89}
90
91/**
92 * Write a frame containing lang, descr and text such as COMM and USLT
93 * according to encoding (only UTF-8 or UTF-16+BOM supported).
94 * @return number of bytes written or a negative error code.
95 */
97 ID3v2EncContext *id3, AVIOContext *avioc,
98 const uint32_t tag, const uint8_t flags,
99 const char *lang, const char *descr,
100 const char *comment, enum ID3v2Encoding enc)
101{
102 int ret;
103 AVIOContext *dyn_buf;
104 if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0)
105 return ret;
106
107 /* check if the strings are ASCII-only and use UTF16 only if
108 * they're not */
110 (!descr || string_is_ascii(descr)))
112
113 avio_w8(dyn_buf, enc);
114 avio_write(dyn_buf, lang, 3);
115 // avio_put_str can handle NULL pointer but avio_put_str16le cannot.
116 id3v2_encode_string(dyn_buf, descr ? descr : "", enc);
117 id3v2_encode_string(dyn_buf, comment, enc);
118
119 return id3v2_put_frame(id3, avioc, dyn_buf, tag, flags);
120}
121
122/**
123 * Write a text frame with multiple text string according to encoding (only
124 * UTF-8 or UTF-16+BOM supported).
125 * @return number of bytes written or a negative error code.
126 */
128 ID3v2EncContext *id3, AVIOContext *avioc,
129 const uint32_t tag, const uint8_t flags,
130 const char **strings, int len,
131 enum ID3v2Encoding enc)
132{
133 int i, ret;
134 AVIOContext *dyn_buf;
135 if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0)
136 return ret;
137
138 /* check if the strings are ASCII-only and use UTF16 only if
139 * they're not */
140 if (enc == ID3v2_ENCODING_UTF16BOM) {
142 for (i = 0; i < len; i++) {
143 if (!string_is_ascii((const uint8_t *)strings[i])) {
145 break;
146 }
147 }
148 }
149
150 avio_w8(dyn_buf, enc);
151
152 for (i = 0; i < len; i++)
153 id3v2_encode_string(dyn_buf, strings[i], enc);
154
155 return id3v2_put_frame(id3, avioc, dyn_buf, tag, flags);
156}
157
158/**
159 * Write a priv frame with owner and data. 'key' is the owner prepended with
160 * ID3v2_PRIV_METADATA_PREFIX. 'data' is provided as a string. Any \xXX
161 * (where 'X' is a valid hex digit) will be unescaped to the byte value.
162 */
163static int id3v2_put_priv(
164 ID3v2EncContext *id3, AVIOContext *avioc,
165 const uint8_t flags, const char *key,
166 const char *data)
167{
168 int ret;
169 AVIOContext *dyn_buf;
170
172 return 0;
173 }
174
175 if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0)
176 return ret;
177
178 // owner + null byte.
179 avio_write(dyn_buf, key, strlen(key) + 1);
180
181 while (*data) {
182 if (av_strstart(data, "\\x", &data)) {
183 if (data[0] && data[1] && av_isxdigit(data[0]) && av_isxdigit(data[1])) {
184 char digits[] = {data[0], data[1], 0};
185 avio_w8(dyn_buf, strtol(digits, NULL, 16));
186 data += 2;
187 } else {
188 ffio_free_dyn_buf(&dyn_buf);
189 av_log(avioc, AV_LOG_ERROR, "Invalid escape '\\x%.2s' in metadata tag '"
191 return AVERROR(EINVAL);
192 }
193 } else {
194 avio_write(dyn_buf, data++, 1);
195 }
196 }
197
198 return id3v2_put_frame(id3, avioc, dyn_buf, MKBETAG('P', 'R', 'I', 'V'),
199 flags);
200}
201
203 const char * const key;
204 uint32_t tag;
205};
206
207static const struct LangDescrTagMap id3v2_lang_descr_tags[] = {
208 {.key = "comment", .tag = MKBETAG('C', 'O', 'M', 'M')},
209 {.key = "lyrics", .tag = MKBETAG('U', 'S', 'L', 'T')},
210 {.key = NULL, .tag = 0}
211};
212
213static int is_valid_lang(const char *s)
214{
215 return strlen(s) == 3 && ff_convert_lang_to(s, AV_LANG_ISO639_2_BIBL);
216}
217
220 enum ID3v2Encoding enc)
221{
222 int i, key_len;
223 const char *key, *after_dash, *last_dash;
224 uint32_t tag, ff_tag = 0;
225 char lang[4] = "und";
226
227 /* Raw 4CC key (e.g. "COMM"): only exact match, no suffix modifiers. */
228 if (strlen(t->key) == 4)
229 ff_tag = AV_RB32(t->key);
230
231 for (i = 0; id3v2_lang_descr_tags[i].key; i++) {
234 key_len = strlen(key);
235
236 if (ff_tag == tag)
237 return id3v2_put_lang_descr_tag(id3, pb, tag, 0,
238 lang, NULL, t->value, enc);
239
240 /* Generic key (e.g. "comment"): require exact match or '-' separator. */
241 if (strncmp(t->key, key, key_len) ||
242 (t->key[key_len] != '\0' && t->key[key_len] != '-'))
243 continue;
244
245 if (t->key[key_len] == '\0')
246 return id3v2_put_lang_descr_tag(id3, pb, tag, 0,
247 lang, NULL, t->value, enc);
248
249 /* Has suffix(es) after '-'. */
250 after_dash = t->key + key_len + 1;
251 last_dash = strrchr(after_dash, '-');
252 const char *suffix = NULL;
253 const char *middle = NULL;
254
255 if (last_dash) {
256 middle = after_dash;
257 suffix = last_dash + 1;
258 } else {
259 suffix = after_dash;
260 }
261
262 if (!middle) {
263 /* <tag>-<suffix>: valid lang → lang only; otherwise →
264 * descriptor only. */
265 const char *descr = NULL;
266 if (is_valid_lang(suffix))
267 memcpy(lang, suffix, 3);
268 else
269 descr = suffix;
270 return id3v2_put_lang_descr_tag(id3, pb, tag, 0, lang,
271 descr, t->value, enc);
272 } else {
273 /* <tag>-<middle>-<suffix>: valid lang suffix → lang+descriptor;
274 * otherwise → full suffix after first '-' is the descriptor. */
275 if (is_valid_lang(suffix) || *suffix == '\0') {
276 /* Valid lang suffix or trailing dash (explicit empty lang):
277 * descriptor = everything before the last '-'. */
278 size_t descr_len = last_dash - after_dash;
279 char *descr = av_strndup(middle, descr_len);
280 int ret;
281 if (!descr)
282 return AVERROR(ENOMEM);
283 if (*suffix)
284 memcpy(lang, suffix, 3);
285 ret = id3v2_put_lang_descr_tag(id3, pb, tag, 0,
286 lang, descr, t->value, enc);
287 av_freep(&descr);
288 return ret;
289 }
290 return id3v2_put_lang_descr_tag(id3, pb, tag, 0,
291 lang, after_dash, t->value, enc);
292 }
293 }
294
295 return 0;
296}
297
299 const char table[][4], enum ID3v2Encoding enc)
300{
301 uint32_t tag;
302 int i;
303
304 if (t->key[0] != 'T' || strlen(t->key) != 4)
305 return 0;
306
307 tag = AV_RB32(t->key);
308 for (i = 0; *table[i]; i++)
309 if (tag == AV_RB32(table[i])) {
310 const char *strings[] = {t->value};
311 return id3v2_put_text_tag(id3, pb, tag, 0, strings, 1, enc);
312 }
313
314 return 0;
315}
316
318{
319 const AVDictionaryEntry *mtag = NULL;
321 const char *key, *value;
322 char year[5] = {0}, day_month[5] = {0};
323 int i;
324
325 while ((mtag = av_dict_iterate(*pm, mtag))) {
326 key = mtag->key;
327 if (!av_strcasecmp(key, "date")) {
328 /* split date tag using "YYYY-MM-DD" format into year and month/day segments */
329 value = mtag->value;
330 i = 0;
331 while (value[i] >= '0' && value[i] <= '9') i++;
332 if (value[i] == '\0' || value[i] == '-') {
333 av_strlcpy(year, value, sizeof(year));
334 av_dict_set(&dst, "TYER", year, 0);
335
336 if (value[i] == '-' &&
337 value[i+1] >= '0' && value[i+1] <= '1' &&
338 value[i+2] >= '0' && value[i+2] <= '9' &&
339 value[i+3] == '-' &&
340 value[i+4] >= '0' && value[i+4] <= '3' &&
341 value[i+5] >= '0' && value[i+5] <= '9' &&
342 (value[i+6] == '\0' || value[i+6] == ' ')) {
343 snprintf(day_month, sizeof(day_month), "%.2s%.2s", value + i + 4, value + i + 1);
344 av_dict_set(&dst, "TDAT", day_month, 0);
345 }
346 } else
347 av_dict_set(&dst, key, value, 0);
348 } else
349 av_dict_set(&dst, key, mtag->value, 0);
350 }
351 av_dict_free(pm);
352 *pm = dst;
353}
354
355void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version,
356 const char *magic)
357{
358 id3->version = id3v2_version;
359 id3->len = 0;
360
361 avio_wb32(pb, MKBETAG(magic[0], magic[1], magic[2], id3v2_version));
362 avio_w8(pb, 0);
363 avio_w8(pb, 0); /* flags */
364
365 /* reserve space for size */
366 id3->size_pos = avio_tell(pb);
367 avio_wb32(pb, 0);
368}
369
371 ID3v2EncContext *id3, int enc)
372{
373 const AVDictionaryEntry *t = NULL;
374 int ret;
375
377 if (id3->version == 3)
379 else if (id3->version == 4)
381
382 while ((t = av_dict_iterate(*metadata, t))) {
383 if ((ret = id3v2_check_write_lang_descr_tag(id3, pb, t, enc)) > 0)
384 continue;
385
386 if (ret < 0)
387 return ret;
388
389 if ((ret = id3v2_check_write_tag(id3, pb, t, ff_id3v2_tags, enc)) > 0)
390 continue;
391
392 if (ret < 0)
393 return ret;
394
395 if ((ret = id3v2_check_write_tag(id3, pb, t, id3->version == 3 ?
396 ff_id3v2_3_tags : ff_id3v2_4_tags, enc)) > 0)
397 continue;
398
399 if (ret < 0)
400 return ret;
401
402 if ((ret = id3v2_put_priv(id3, pb, 0, t->key, t->value)) > 0)
403 continue;
404
405 if (ret < 0)
406 return ret;
407
408 /* unknown tag, write as TXXX frame */
409 const char *strings[] = {t->key, t->value};
410 if ((ret = id3v2_put_text_tag(id3, pb, MKBETAG('T', 'X', 'X', 'X'),
411 0, strings, 2, enc)) < 0)
412 return ret;
413 }
414
415 return 0;
416}
417
419 ID3v2EncContext *id3, int enc)
420{
421 AVIOContext *dyn_bc;
422 char name[123];
423 int ret;
424
425 if (s->nb_chapters == 0)
426 return 0;
427
428 if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0)
429 return ret;
430
431 avio_put_str(dyn_bc, "toc");
432 avio_w8(dyn_bc, 0x03);
433 avio_w8(dyn_bc, s->nb_chapters);
434 for (int i = 0; i < s->nb_chapters; i++) {
435 snprintf(name, 122, "ch%d", i);
436 avio_put_str(dyn_bc, name);
437 }
438
439 return id3v2_put_frame(id3, pb, dyn_bc,
440 MKBETAG('C', 'T', 'O', 'C'), 0);
441}
442
444 ID3v2EncContext *id3, int id, int enc)
445{
446 const AVRational time_base = {1, 1000};
447 AVChapter *ch = s->chapters[id];
448 uint8_t *dyn_buf;
449 AVIOContext *dyn_bc;
450 char name[123];
451 int len, start, end, ret;
452
453 if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0)
454 return ret;
455
456 start = av_rescale_q(ch->start, ch->time_base, time_base);
457 end = av_rescale_q(ch->end, ch->time_base, time_base);
458
459 snprintf(name, 122, "ch%d", id);
460 id3->len += avio_put_str(dyn_bc, name);
461 avio_wb32(dyn_bc, start);
462 avio_wb32(dyn_bc, end);
463 avio_wb32(dyn_bc, 0xFFFFFFFFu);
464 avio_wb32(dyn_bc, 0xFFFFFFFFu);
465
466 if ((ret = write_metadata(dyn_bc, &ch->metadata, id3, enc)) < 0)
467 goto fail;
468
469 len = avio_get_dyn_buf(dyn_bc, &dyn_buf);
470 id3->len += 16 + ID3v2_HEADER_SIZE;
471
472 /* Nested frames already updated id3->len, so this header is written
473 * directly instead of through id3v2_put_frame(). */
474 id3v2_put_frame_header(id3, pb, MKBETAG('C', 'H', 'A', 'P'), len, 0);
475 avio_write(pb, dyn_buf, len);
476
477fail:
478 ffio_free_dyn_buf(&dyn_bc);
479
480 return ret;
481}
482
484 ID3v2EncContext *id3)
485{
486 int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM :
488 int i, ret;
489
491 if ((ret = write_metadata(pb, &s->metadata, id3, enc)) < 0)
492 return ret;
493
494 if ((ret = write_ctoc(s, pb, id3, enc)) < 0)
495 return ret;
496
497 for (i = 0; i < s->nb_chapters; i++) {
498 if ((ret = write_chapter(s, pb, id3, i, enc)) < 0)
499 return ret;
500 }
501
502 return 0;
503}
504
507{
508 AVStream *st = s->streams[pkt->stream_index];
510
511 AVIOContext *dyn_buf;
512 const CodecMime *mime = ff_id3v2_mime_tags;
513 const char *mimetype = NULL, *desc = "";
514 int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM :
516 int i, type = 0, ret;
517
518 /* get the mimetype*/
519 while (mime->id != AV_CODEC_ID_NONE) {
520 if (mime->id == st->codecpar->codec_id) {
521 mimetype = mime->str;
522 break;
523 }
524 mime++;
525 }
526 if (!mimetype) {
527 av_log(s, AV_LOG_ERROR, "No mimetype is known for stream %d, cannot "
528 "write an attached picture.\n", st->index);
529 return AVERROR(EINVAL);
530 }
531
532 /* get the picture type */
533 e = av_dict_get(st->metadata, "comment", NULL, 0);
534 for (i = 0; e && i < FF_ARRAY_ELEMS(ff_id3v2_picture_types); i++) {
536 type = i;
537 break;
538 }
539 }
540
541 /* get the description */
542 if ((e = av_dict_get(st->metadata, "title", NULL, 0)))
543 desc = e->value;
544
545 /* use UTF16 only for non-ASCII strings */
548
549 /* start writing */
550 if ((ret = avio_open_dyn_buf(&dyn_buf)) < 0)
551 return ret;
552
553 avio_w8(dyn_buf, enc);
554 avio_put_str(dyn_buf, mimetype);
555 avio_w8(dyn_buf, type);
556 id3v2_encode_string(dyn_buf, desc, enc);
557 avio_write(dyn_buf, pkt->data, pkt->size);
558
559 return id3v2_put_frame(id3, pb, dyn_buf,
560 MKBETAG('A', 'P', 'I', 'C'), 0);
561}
562
564 int padding_bytes)
565{
566 int64_t cur_pos;
567
568 if (padding_bytes < 0)
569 padding_bytes = 10;
570
571 /* The ID3v2.3 specification states that 28 bits are used to represent the
572 * size of the whole tag. Therefore the current size of the tag needs to be
573 * subtracted from the upper limit of 2^28-1 to clip the value correctly. */
574 /* The minimum of 10 is an arbitrary amount of padding at the end of the tag
575 * to fix cover art display with some software such as iTunes, Traktor,
576 * Serato, Torq. */
577 padding_bytes = av_clip(padding_bytes, 10, 268435455 - id3->len);
578 ffio_fill(pb, 0, padding_bytes);
579 id3->len += padding_bytes;
580
581 cur_pos = avio_tell(pb);
582 avio_seek(pb, id3->size_pos, SEEK_SET);
583 id3v2_put_size(pb, id3->len);
584 avio_seek(pb, cur_pos, SEEK_SET);
585}
586
587int ff_id3v2_write_simple(struct AVFormatContext *s, int id3v2_version,
588 const char *magic)
589{
590 ID3v2EncContext id3 = { 0 };
591 int ret;
592
593 ff_id3v2_start(&id3, s->pb, id3v2_version, magic);
594 if ((ret = ff_id3v2_write_metadata(s, s->pb, &id3)) < 0)
595 return ret;
596 ff_id3v2_finish(&id3, s->pb, s->metadata_header_padding);
597
598 return 0;
599}
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:97
static void put(Buf *b, const void *src, int n)
Definition apnggen.c:76
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:507
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:1333
int avio_get_dyn_buf(AVIOContext *s, uint8_t **pbuffer)
Return the written size and a pointer to the buffer.
Definition aviobuf.c:1345
void ffio_free_dyn_buf(AVIOContext **s)
Free a dynamic buffer.
Definition aviobuf.c:1406
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:612
double value
Definition eval.c:102
const char * key
int ret
Definition ffplay.c:391
#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:236
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:61
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
Definition dict.c:43
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:87
#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:390
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
void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version, const char *magic)
Initialize the encoding context and write the header for a new ID3v2 tag.
Definition writer.c:355
static int write_ctoc(AVFormatContext *s, AVIOContext *pb, ID3v2EncContext *id3, int enc)
Definition writer.c:418
static int id3v2_check_write_lang_descr_tag(ID3v2EncContext *id3, AVIOContext *pb, const AVDictionaryEntry *t, enum ID3v2Encoding enc)
Definition writer.c:218
void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb, int padding_bytes)
Finalize an opened ID3v2 tag.
Definition writer.c:563
static int write_chapter(AVFormatContext *s, AVIOContext *pb, ID3v2EncContext *id3, int id, int enc)
Definition writer.c:443
static int is_valid_lang(const char *s)
Definition writer.c:213
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 writer.c:163
static int write_metadata(AVIOContext *pb, AVDictionary **metadata, ID3v2EncContext *id3, int enc)
Definition writer.c:370
static int id3v2_check_write_tag(ID3v2EncContext *id3, AVIOContext *pb, const AVDictionaryEntry *t, const char table[][4], enum ID3v2Encoding enc)
Definition writer.c:298
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 writer.c:127
static int string_is_ascii(const uint8_t *str)
Definition writer.c:43
static void id3v2_encode_string(AVIOContext *pb, const uint8_t *str, enum ID3v2Encoding enc)
Definition writer.c:49
static int id3v2_put_frame(ID3v2EncContext *id3, AVIOContext *avioc, AVIOContext *dyn_buf, const uint32_t tag, const uint8_t flags)
Definition writer.c:75
static void id3v2_3_metadata_split_date(AVDictionary **pm)
Definition writer.c:317
static void id3v2_put_frame_header(ID3v2EncContext *id3, AVIOContext *pb, uint32_t tag, int len, int flags)
Definition writer.c:64
static const struct LangDescrTagMap id3v2_lang_descr_tags[]
Definition writer.c:207
static void id3v2_put_size(AVIOContext *pb, int size)
Definition writer.c:35
int ff_id3v2_write_apic(AVFormatContext *s, AVIOContext *pb, ID3v2EncContext *id3, AVPacket *pkt)
Write an attached picture from pkt into an ID3v2 tag.
Definition writer.c:505
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 writer.c:587
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 writer.c:96
int ff_id3v2_write_metadata(AVFormatContext *s, AVIOContext *pb, ID3v2EncContext *id3)
Convert and write all global metadata from s into an ID3v2 tag.
Definition writer.c:483
const char ff_id3v2_3_tags[][4]
ID3v2.3-only text information frames.
Definition reader.c:109
const AVMetadataConv ff_id3v2_34_metadata_conv[]
Definition reader.c:49
const char ff_id3v2_4_tags[][4]
ID3v2.4-only text information frames.
Definition reader.c:103
#define ID3v2_PRIV_METADATA_PREFIX
Definition id3v2.h:42
const AVMetadataConv ff_id3v2_4_metadata_conv[]
Definition reader.c:69
const char *const ff_id3v2_picture_types[21]
Definition reader.c:114
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
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 reader.c:95
const CodecMime ff_id3v2_mime_tags[]
Definition reader.c:138
#define AV_RB32(p)
enum MPFType type
Definition jpegmpfenc.c:55
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:2128
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)
int64_t start
Definition avformat.h:1363
AVDictionary * metadata
Definition avformat.h:1364
int64_t end
chapter start/end time in time_base units
Definition avformat.h:1363
AVRational time_base
time base in which the start/end timestamps are specified
Definition avformat.h:1362
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:1401
Bytestream IO Context.
Definition avio.h:160
This structure stores compressed data.
Definition packet.h:587
Rational number (pair of numerator and denominator).
Definition rational.h:58
Stream structure.
Definition avformat.h:768
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition avformat.h:791
AVDictionary * metadata
Definition avformat.h:848
int index
stream index in AVFormatContext
Definition avformat.h:774
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 writer.c:204
const char *const key
Definition writer.c:203
#define av_freep(p)
#define av_log(a,...)
int size
int len