2 Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
4 Permission is hereby granted, free of charge, to any person
5 obtaining a copy of this software and associated documentation
6 files (the "Software"), to deal in the Software without
7 restriction, including without limitation the rights to use, copy,
8 modify, merge, publish, distribute, sublicense, and/or sell copies
9 of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
26 #include "libavutil/avstring.h"
27 #include "libavutil/bswap.h"
28 #include "libavutil/dict.h"
29 #include "libavcodec/get_bits.h"
30 #include "libavcodec/bytestream.h"
34 #include "vorbiscomment.h"
36 static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
38 int i, cnum, h, m, s, ms, keylen = strlen(key);
39 AVChapter *chapter = NULL;
41 if (keylen < 9 || sscanf(key, "CHAPTER%02d", &cnum) != 1)
45 if (sscanf(val, "%02d:%02d:%02d.%03d", &h, &m, &s, &ms) < 4)
48 avpriv_new_chapter(as, cnum, (AVRational){1,1000},
49 ms + 1000*(s + 60*(m + 60*h)),
50 AV_NOPTS_VALUE, NULL);
52 } else if (!strcmp(key+9, "NAME")) {
53 for(i = 0; i < as->nb_chapters; i++)
54 if (as->chapters[i]->id == cnum) {
55 chapter = as->chapters[i];
61 av_dict_set(&chapter->metadata, "title", val,
62 AV_DICT_DONT_STRDUP_VAL);
71 ff_vorbis_comment(AVFormatContext * as, AVDictionary **m, const uint8_t *buf, int size)
73 const uint8_t *p = buf;
74 const uint8_t *end = buf + size;
78 if (size < 8) /* must have vendor_length and user_comment_list_length */
81 s = bytestream_get_le32(&p);
83 if (end - p - 4 < s || s < 0)
88 n = bytestream_get_le32(&p);
90 while (end - p >= 4 && n > 0) {
94 s = bytestream_get_le32(&p);
96 if (end - p < s || s < 0)
103 v = memchr(t, '=', s);
114 tt = av_malloc(tl + 1);
115 ct = av_malloc(vl + 1);
119 av_log(as, AV_LOG_WARNING, "out-of-memory error. skipping VorbisComment tag.\n");
123 for (j = 0; j < tl; j++)
124 tt[j] = toupper(t[j]);
130 if (!ogm_chapter(as, tt, ct))
131 av_dict_set(m, tt, ct,
132 AV_DICT_DONT_STRDUP_KEY |
133 AV_DICT_DONT_STRDUP_VAL);
138 av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", end-p);
140 av_log(as, AV_LOG_INFO,
141 "truncated comment header, %i comments not found\n", n);
143 ff_metadata_conv(m, NULL, ff_vorbiscomment_metadata_conv);
149 /** Parse the vorbis header
150 * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec
151 * [vorbis_version] = read 32 bits as unsigned integer | Not used
152 * [audio_channels] = read 8 bit integer as unsigned | Used
153 * [audio_sample_rate] = read 32 bits as unsigned integer | Used
154 * [bitrate_maximum] = read 32 bits as signed integer | Not used yet
155 * [bitrate_nominal] = read 32 bits as signed integer | Not used yet
156 * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate
157 * [blocksize_0] = read 4 bits as unsigned integer | Not Used
158 * [blocksize_1] = read 4 bits as unsigned integer | Not Used
159 * [framing_flag] = read one bit | Not Used
162 struct oggvorbis_private {
164 unsigned char *packet[3];
169 fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
175 len = priv->len[0] + priv->len[1] + priv->len[2];
176 ptr = *buf = av_mallocz(len + len/255 + 64);
180 offset += av_xiphlacing(&ptr[offset], priv->len[0]);
181 offset += av_xiphlacing(&ptr[offset], priv->len[1]);
182 for (i = 0; i < 3; i++) {
183 memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
184 offset += priv->len[i];
185 av_freep(&priv->packet[i]);
187 *buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
193 vorbis_header (AVFormatContext * s, int idx)
195 struct ogg *ogg = s->priv_data;
196 struct ogg_stream *os = ogg->streams + idx;
197 AVStream *st = s->streams[idx];
198 struct oggvorbis_private *priv;
199 int pkt_type = os->buf[os->pstart];
205 os->private = av_mallocz(sizeof(struct oggvorbis_private));
210 if (os->psize < 1 || pkt_type > 5)
215 if (priv->packet[pkt_type>>1])
217 if (pkt_type > 1 && !priv->packet[0] || pkt_type > 3 && !priv->packet[1])
220 priv->len[pkt_type >> 1] = os->psize;
221 priv->packet[pkt_type >> 1] = av_mallocz(os->psize);
222 memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize);
223 if (os->buf[os->pstart] == 1) {
224 const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
225 unsigned blocksize, bs0, bs1;
231 if (bytestream_get_le32(&p) != 0) /* vorbis_version */
234 st->codec->channels = bytestream_get_byte(&p);
235 srate = bytestream_get_le32(&p);
236 p += 4; // skip maximum bitrate
237 st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
238 p += 4; // skip minimum bitrate
240 blocksize = bytestream_get_byte(&p);
241 bs0 = blocksize & 15;
242 bs1 = blocksize >> 4;
246 if (bs0 < 6 || bs1 > 13)
249 if (bytestream_get_byte(&p) != 1) /* framing_flag */
252 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
253 st->codec->codec_id = CODEC_ID_VORBIS;
256 st->codec->sample_rate = srate;
257 avpriv_set_pts_info(st, 64, 1, srate);
259 } else if (os->buf[os->pstart] == 3) {
261 ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8) >= 0) {
262 // drop all metadata we parsed and which is not required by libvorbis
263 unsigned new_len = 7 + 4 + AV_RL32(priv->packet[1] + 7) + 4 + 1;
264 if (new_len >= 16 && new_len < os->psize) {
265 AV_WL32(priv->packet[1] + new_len - 5, 0);
266 priv->packet[1][new_len - 1] = 1;
267 priv->len[1] = new_len;
271 st->codec->extradata_size =
272 fixup_vorbis_headers(s, priv, &st->codec->extradata);
278 const struct ogg_codec ff_vorbis_codec = {
279 .magic = "\001vorbis",
281 .header = vorbis_header