4 * This file is part of FFmpeg.
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.
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.
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
24 #include "libavutil/avstring.h"
25 #include "libavutil/dict.h"
26 #include "libavutil/intreadwrite.h"
29 #include "avio_internal.h"
32 static void id3v2_put_size(AVIOContext
*pb
, int size
)
34 avio_w8(pb
, size
>> 21 & 0x7f);
35 avio_w8(pb
, size
>> 14 & 0x7f);
36 avio_w8(pb
, size
>> 7 & 0x7f);
37 avio_w8(pb
, size
& 0x7f);
40 static int string_is_ascii(const uint8_t *str
)
42 while (*str
&& *str
< 128) str
++;
46 static void id3v2_encode_string(AVIOContext
*pb
, const uint8_t *str
,
47 enum ID3v2Encoding enc
)
49 int (*put
)(AVIOContext
*, const char*);
51 if (enc
== ID3v2_ENCODING_UTF16BOM
) {
52 avio_wl16(pb
, 0xFEFF); /* BOM */
53 put
= avio_put_str16le
;
61 * Write a text frame with one (normal frames) or two (TXXX frames) strings
62 * according to encoding (only UTF-8 or UTF-16+BOM supported).
63 * @return number of bytes written or a negative error code.
65 static int id3v2_put_ttag(ID3v2EncContext
*id3
, AVIOContext
*avioc
, const char *str1
, const char *str2
,
66 uint32_t tag
, enum ID3v2Encoding enc
)
71 if (avio_open_dyn_buf(&dyn_buf
) < 0)
72 return AVERROR(ENOMEM
);
74 /* check if the strings are ASCII-only and use UTF16 only if
76 if (enc
== ID3v2_ENCODING_UTF16BOM
&& string_is_ascii(str1
) &&
77 (!str2
|| string_is_ascii(str2
)))
78 enc
= ID3v2_ENCODING_ISO8859
;
80 avio_w8(dyn_buf
, enc
);
81 id3v2_encode_string(dyn_buf
, str1
, enc
);
83 id3v2_encode_string(dyn_buf
, str2
, enc
);
84 len
= avio_close_dyn_buf(dyn_buf
, &pb
);
86 avio_wb32(avioc
, tag
);
87 /* ID3v2.3 frame size is not synchsafe */
88 if (id3
->version
== 3)
89 avio_wb32(avioc
, len
);
91 id3v2_put_size(avioc
, len
);
93 avio_write(avioc
, pb
, len
);
96 return len
+ ID3v2_HEADER_SIZE
;
99 static int id3v2_check_write_tag(ID3v2EncContext
*id3
, AVIOContext
*pb
, AVDictionaryEntry
*t
,
100 const char table
[][4], enum ID3v2Encoding enc
)
105 if (t
->key
[0] != 'T' || strlen(t
->key
) != 4)
107 tag
= AV_RB32(t
->key
);
108 for (i
= 0; *table
[i
]; i
++)
109 if (tag
== AV_RB32(table
[i
]))
110 return id3v2_put_ttag(id3
, pb
, t
->value
, NULL
, tag
, enc
);
114 static void id3v2_3_metadata_split_date(AVDictionary
**pm
)
116 AVDictionaryEntry
*mtag
= NULL
;
117 AVDictionary
*dst
= NULL
;
118 const char *key
, *value
;
119 char year
[5] = {0}, day_month
[5] = {0};
122 while ((mtag
= av_dict_get(*pm
, "", mtag
, AV_DICT_IGNORE_SUFFIX
))) {
124 if (!av_strcasecmp(key
, "date")) {
125 /* split date tag using "YYYY-MM-DD" format into year and month/day segments */
128 while (value
[i
] >= '0' && value
[i
] <= '9') i
++;
129 if (value
[i
] == '\0' || value
[i
] == '-') {
130 av_strlcpy(year
, value
, sizeof(year
));
131 av_dict_set(&dst
, "TYER", year
, 0);
133 if (value
[i
] == '-' &&
134 value
[i
+1] >= '0' && value
[i
+1] <= '1' &&
135 value
[i
+2] >= '0' && value
[i
+2] <= '9' &&
137 value
[i
+4] >= '0' && value
[i
+4] <= '3' &&
138 value
[i
+5] >= '0' && value
[i
+5] <= '9' &&
139 (value
[i
+6] == '\0' || value
[i
+6] == ' ')) {
140 snprintf(day_month
, sizeof(day_month
), "%.2s%.2s", value
+ i
+ 4, value
+ i
+ 1);
141 av_dict_set(&dst
, "TDAT", day_month
, 0);
144 av_dict_set(&dst
, key
, value
, 0);
146 av_dict_set(&dst
, key
, mtag
->value
, 0);
152 void ff_id3v2_start(ID3v2EncContext
*id3
, AVIOContext
*pb
, int id3v2_version
,
155 id3
->version
= id3v2_version
;
157 avio_wb32(pb
, MKBETAG(magic
[0], magic
[1], magic
[2], id3v2_version
));
159 avio_w8(pb
, 0); /* flags */
161 /* reserve space for size */
162 id3
->size_pos
= avio_tell(pb
);
166 static int write_metadata(AVIOContext
*pb
, AVDictionary
**metadata
,
167 ID3v2EncContext
*id3
, int enc
)
169 AVDictionaryEntry
*t
= NULL
;
172 ff_metadata_conv(metadata
, ff_id3v2_34_metadata_conv
, NULL
);
173 if (id3
->version
== 3)
174 id3v2_3_metadata_split_date(metadata
);
175 else if (id3
->version
== 4)
176 ff_metadata_conv(metadata
, ff_id3v2_4_metadata_conv
, NULL
);
178 while ((t
= av_dict_get(*metadata
, "", t
, AV_DICT_IGNORE_SUFFIX
))) {
179 if ((ret
= id3v2_check_write_tag(id3
, pb
, t
, ff_id3v2_tags
, enc
)) > 0) {
183 if ((ret
= id3v2_check_write_tag(id3
, pb
, t
, id3
->version
== 3 ?
184 ff_id3v2_3_tags
: ff_id3v2_4_tags
, enc
)) > 0) {
189 /* unknown tag, write as TXXX frame */
190 if ((ret
= id3v2_put_ttag(id3
, pb
, t
->key
, t
->value
, MKBETAG('T', 'X', 'X', 'X'), enc
)) < 0)
198 static int write_chapter(AVFormatContext
*s
, ID3v2EncContext
*id3
, int id
, int enc
)
200 const AVRational time_base
= {1, 1000};
201 AVChapter
*ch
= s
->chapters
[id
];
202 uint8_t *dyn_buf
= NULL
;
203 AVIOContext
*dyn_bc
= NULL
;
205 int len
, start
, end
, ret
;
207 if ((ret
= avio_open_dyn_buf(&dyn_bc
)) < 0)
210 start
= av_rescale_q(ch
->start
, ch
->time_base
, time_base
);
211 end
= av_rescale_q(ch
->end
, ch
->time_base
, time_base
);
213 snprintf(name
, 122, "ch%d", id
);
214 id3
->len
+= avio_put_str(dyn_bc
, name
);
215 avio_wb32(dyn_bc
, start
);
216 avio_wb32(dyn_bc
, end
);
217 avio_wb32(dyn_bc
, 0xFFFFFFFFu
);
218 avio_wb32(dyn_bc
, 0xFFFFFFFFu
);
220 if ((ret
= write_metadata(dyn_bc
, &ch
->metadata
, id3
, enc
)) < 0)
223 len
= avio_close_dyn_buf(dyn_bc
, &dyn_buf
);
224 id3
->len
+= 16 + ID3v2_HEADER_SIZE
;
226 avio_wb32(s
->pb
, MKBETAG('C', 'H', 'A', 'P'));
227 avio_wb32(s
->pb
, len
);
229 avio_write(s
->pb
, dyn_buf
, len
);
232 if (dyn_bc
&& !dyn_buf
)
233 avio_close_dyn_buf(dyn_bc
, &dyn_buf
);
239 int ff_id3v2_write_metadata(AVFormatContext
*s
, ID3v2EncContext
*id3
)
241 int enc
= id3
->version
== 3 ? ID3v2_ENCODING_UTF16BOM
:
245 if ((ret
= write_metadata(s
->pb
, &s
->metadata
, id3
, enc
)) < 0)
248 for (i
= 0; i
< s
->nb_chapters
; i
++) {
249 if ((ret
= write_chapter(s
, id3
, i
, enc
)) < 0)
256 int ff_id3v2_write_apic(AVFormatContext
*s
, ID3v2EncContext
*id3
, AVPacket
*pkt
)
258 AVStream
*st
= s
->streams
[pkt
->stream_index
];
259 AVDictionaryEntry
*e
;
261 AVIOContext
*dyn_buf
;
263 const CodecMime
*mime
= ff_id3v2_mime_tags
;
264 const char *mimetype
= NULL
, *desc
= "";
265 int enc
= id3
->version
== 3 ? ID3v2_ENCODING_UTF16BOM
:
267 int i
, len
, type
= 0;
269 /* get the mimetype*/
270 while (mime
->id
!= AV_CODEC_ID_NONE
) {
271 if (mime
->id
== st
->codec
->codec_id
) {
272 mimetype
= mime
->str
;
278 av_log(s
, AV_LOG_ERROR
, "No mimetype is known for stream %d, cannot "
279 "write an attached picture.\n", st
->index
);
280 return AVERROR(EINVAL
);
283 /* get the picture type */
284 e
= av_dict_get(st
->metadata
, "comment", NULL
, 0);
285 for (i
= 0; e
&& i
< FF_ARRAY_ELEMS(ff_id3v2_picture_types
); i
++) {
286 if (!av_strcasecmp(e
->value
, ff_id3v2_picture_types
[i
])) {
292 /* get the description */
293 if ((e
= av_dict_get(st
->metadata
, "title", NULL
, 0)))
296 /* use UTF16 only for non-ASCII strings */
297 if (enc
== ID3v2_ENCODING_UTF16BOM
&& string_is_ascii(desc
))
298 enc
= ID3v2_ENCODING_ISO8859
;
301 if (avio_open_dyn_buf(&dyn_buf
) < 0)
302 return AVERROR(ENOMEM
);
304 avio_w8(dyn_buf
, enc
);
305 avio_put_str(dyn_buf
, mimetype
);
306 avio_w8(dyn_buf
, type
);
307 id3v2_encode_string(dyn_buf
, desc
, enc
);
308 avio_write(dyn_buf
, pkt
->data
, pkt
->size
);
309 len
= avio_close_dyn_buf(dyn_buf
, &buf
);
311 avio_wb32(s
->pb
, MKBETAG('A', 'P', 'I', 'C'));
312 if (id3
->version
== 3)
313 avio_wb32(s
->pb
, len
);
315 id3v2_put_size(s
->pb
, len
);
317 avio_write(s
->pb
, buf
, len
);
320 id3
->len
+= len
+ ID3v2_HEADER_SIZE
;
325 void ff_id3v2_finish(ID3v2EncContext
*id3
, AVIOContext
*pb
,
330 if (padding_bytes
< 0)
333 /* The ID3v2.3 specification states that 28 bits are used to represent the
334 * size of the whole tag. Therefore the current size of the tag needs to be
335 * subtracted from the upper limit of 2^28-1 to clip the value correctly. */
336 /* The minimum of 10 is an arbitrary amount of padding at the end of the tag
337 * to fix cover art display with some software such as iTunes, Traktor,
339 padding_bytes
= av_clip(padding_bytes
, 10, 268435455 - id3
->len
);
340 ffio_fill(pb
, 0, padding_bytes
);
341 id3
->len
+= padding_bytes
;
343 cur_pos
= avio_tell(pb
);
344 avio_seek(pb
, id3
->size_pos
, SEEK_SET
);
345 id3v2_put_size(pb
, id3
->len
);
346 avio_seek(pb
, cur_pos
, SEEK_SET
);
349 int ff_id3v2_write_simple(struct AVFormatContext
*s
, int id3v2_version
,
352 ID3v2EncContext id3
= { 0 };
355 ff_id3v2_start(&id3
, s
->pb
, id3v2_version
, magic
);
356 if ((ret
= ff_id3v2_write_metadata(s
, &id3
)) < 0)
358 ff_id3v2_finish(&id3
, s
->pb
, s
->metadata_header_padding
);