a74fb9a9ff58de25e626cff4d19494ca5922e4b1
[libav.git] / libavformat / oggparsevorbis.c
1 /**
2 Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
3
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:
11
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
14
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.
23 **/
24
25 #include <stdlib.h>
26 #include "libavutil/avstring.h"
27 #include "libavutil/bswap.h"
28 #include "libavcodec/bitstream.h"
29 #include "libavcodec/bytestream.h"
30 #include "avformat.h"
31 #include "oggdec.h"
32
33 int
34 vorbis_comment(AVFormatContext * as, uint8_t *buf, int size)
35 {
36 const uint8_t *p = buf;
37 const uint8_t *end = buf + size;
38 unsigned s, n, j;
39
40 if (size < 8) /* must have vendor_length and user_comment_list_length */
41 return -1;
42
43 s = bytestream_get_le32(&p);
44
45 if (end - p < s)
46 return -1;
47
48 p += s;
49
50 n = bytestream_get_le32(&p);
51
52 while (p < end && n > 0) {
53 const char *t, *v;
54 int tl, vl;
55
56 s = bytestream_get_le32(&p);
57
58 if (end - p < s)
59 break;
60
61 t = p;
62 p += s;
63 n--;
64
65 v = memchr(t, '=', s);
66 if (!v)
67 continue;
68
69 tl = v - t;
70 vl = s - tl - 1;
71 v++;
72
73 if (tl && vl) {
74 char tt[tl + 1];
75 char ct[vl + 1];
76
77 for (j = 0; j < tl; j++)
78 tt[j] = toupper(t[j]);
79 tt[tl] = 0;
80
81 memcpy(ct, v, vl);
82 ct[vl] = 0;
83
84 av_metadata_set(&as->metadata, tt, ct);
85 }
86 }
87
88 if (p != end)
89 av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", p-end);
90 if (n > 0)
91 av_log(as, AV_LOG_INFO,
92 "truncated comment header, %i comments not found\n", n);
93
94 return 0;
95 }
96
97
98 /** Parse the vorbis header
99 * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec
100 * [vorbis_version] = read 32 bits as unsigned integer | Not used
101 * [audio_channels] = read 8 bit integer as unsigned | Used
102 * [audio_sample_rate] = read 32 bits as unsigned integer | Used
103 * [bitrate_maximum] = read 32 bits as signed integer | Not used yet
104 * [bitrate_nominal] = read 32 bits as signed integer | Not used yet
105 * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate
106 * [blocksize_0] = read 4 bits as unsigned integer | Not Used
107 * [blocksize_1] = read 4 bits as unsigned integer | Not Used
108 * [framing_flag] = read one bit | Not Used
109 * */
110
111 struct oggvorbis_private {
112 unsigned int len[3];
113 unsigned char *packet[3];
114 };
115
116
117 static unsigned int
118 fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
119 uint8_t **buf)
120 {
121 int i,offset, len;
122 unsigned char *ptr;
123
124 len = priv->len[0] + priv->len[1] + priv->len[2];
125 ptr = *buf = av_mallocz(len + len/255 + 64);
126
127 ptr[0] = 2;
128 offset = 1;
129 offset += av_xiphlacing(&ptr[offset], priv->len[0]);
130 offset += av_xiphlacing(&ptr[offset], priv->len[1]);
131 for (i = 0; i < 3; i++) {
132 memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
133 offset += priv->len[i];
134 }
135 *buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
136 return offset;
137 }
138
139
140 static int
141 vorbis_header (AVFormatContext * s, int idx)
142 {
143 struct ogg *ogg = s->priv_data;
144 struct ogg_stream *os = ogg->streams + idx;
145 AVStream *st = s->streams[idx];
146 struct oggvorbis_private *priv;
147
148 if (os->seq > 2)
149 return 0;
150
151 if (os->seq == 0) {
152 os->private = av_mallocz(sizeof(struct oggvorbis_private));
153 if (!os->private)
154 return 0;
155 }
156
157 if (os->psize < 1)
158 return -1;
159
160 priv = os->private;
161 priv->len[os->seq] = os->psize;
162 priv->packet[os->seq] = av_mallocz(os->psize);
163 memcpy(priv->packet[os->seq], os->buf + os->pstart, os->psize);
164 if (os->buf[os->pstart] == 1) {
165 const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
166 unsigned blocksize, bs0, bs1;
167
168 if (os->psize != 30)
169 return -1;
170
171 if (bytestream_get_le32(&p) != 0) /* vorbis_version */
172 return -1;
173
174 st->codec->channels = bytestream_get_byte(&p);
175 st->codec->sample_rate = bytestream_get_le32(&p);
176 p += 4; // skip maximum bitrate
177 st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
178 p += 4; // skip minimum bitrate
179
180 blocksize = bytestream_get_byte(&p);
181 bs0 = blocksize & 15;
182 bs1 = blocksize >> 4;
183
184 if (bs0 > bs1)
185 return -1;
186 if (bs0 < 6 || bs1 > 13)
187 return -1;
188
189 if (bytestream_get_byte(&p) != 1) /* framing_flag */
190 return -1;
191
192 st->codec->codec_type = CODEC_TYPE_AUDIO;
193 st->codec->codec_id = CODEC_ID_VORBIS;
194
195 st->time_base.num = 1;
196 st->time_base.den = st->codec->sample_rate;
197 } else if (os->buf[os->pstart] == 3) {
198 if (os->psize > 8)
199 vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8);
200 } else {
201 st->codec->extradata_size =
202 fixup_vorbis_headers(s, priv, &st->codec->extradata);
203 }
204
205 return os->seq < 3;
206 }
207
208 const struct ogg_codec ff_vorbis_codec = {
209 .magic = "\001vorbis",
210 .magicsize = 7,
211 .header = vorbis_header
212 };