use bytestream_get_* in vorbis_header()
[libav.git] / libavformat / oggparsevorbis.c
CommitLineData
9146ca37
MR
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 "avformat.h"
27#include "bitstream.h"
739587bf 28#include "bytestream.h"
9146ca37
MR
29#include "bswap.h"
30#include "ogg2.h"
d3677839 31#include "avstring.h"
9146ca37
MR
32
33extern int
4bd684bc 34vorbis_comment(AVFormatContext * as, uint8_t *buf, int size)
9146ca37 35{
f5475e1b
MR
36 uint8_t *p = buf;
37 unsigned s, n, j;
9146ca37 38
f5475e1b 39 if (size < 8) /* must have vendor_length and user_comment_list_length */
9146ca37
MR
40 return -1;
41
1eb1f6fd 42 s = AV_RL32(p);
9146ca37
MR
43 p += 4;
44 size -= 4;
45
f5475e1b 46 if (size - 4 < s)
9146ca37
MR
47 return -1;
48
49 p += s;
50 size -= s;
51
1eb1f6fd 52 n = AV_RL32(p);
9146ca37
MR
53 p += 4;
54 size -= 4;
55
4bd684bc 56 while (size >= 4) {
9146ca37
MR
57 char *t, *v;
58 int tl, vl;
59
1eb1f6fd 60 s = AV_RL32(p);
9146ca37
MR
61 p += 4;
62 size -= 4;
63
64 if (size < s)
65 break;
66
67 t = p;
68 p += s;
69 size -= s;
70 n--;
71
4bd684bc 72 v = memchr(t, '=', s);
9146ca37
MR
73 if (!v)
74 continue;
75
76 tl = v - t;
77 vl = s - tl - 1;
78 v++;
79
4bd684bc 80 if (tl && vl) {
9146ca37
MR
81 char tt[tl + 1];
82 char ct[vl + 1];
83
84 for (j = 0; j < tl; j++)
4bd684bc 85 tt[j] = toupper(t[j]);
9146ca37
MR
86 tt[tl] = 0;
87
4bd684bc 88 memcpy(ct, v, vl);
9146ca37
MR
89 ct[vl] = 0;
90
115329f1 91 // took from Vorbis_I_spec
4bd684bc
MR
92 if (!strcmp(tt, "AUTHOR") || !strcmp(tt, "ARTIST"))
93 av_strlcpy(as->author, ct, sizeof(as->author));
94 else if (!strcmp(tt, "TITLE"))
95 av_strlcpy(as->title, ct, sizeof(as->title));
96 else if (!strcmp(tt, "COPYRIGHT"))
97 av_strlcpy(as->copyright, ct, sizeof(as->copyright));
98 else if (!strcmp(tt, "DESCRIPTION"))
99 av_strlcpy(as->comment, ct, sizeof(as->comment));
100 else if (!strcmp(tt, "GENRE"))
101 av_strlcpy(as->genre, ct, sizeof(as->genre));
102 else if (!strcmp(tt, "TRACKNUMBER"))
103 as->track = atoi(ct);
d66c30ad
MR
104 else if (!strcmp(tt, "ALBUM"))
105 av_strlcpy(as->album, ct, sizeof(as->album));
9146ca37
MR
106 }
107 }
108
109 if (size > 0)
4bd684bc 110 av_log(as, AV_LOG_INFO, "%i bytes of comment header remain\n", size);
9146ca37 111 if (n > 0)
4bd684bc
MR
112 av_log(as, AV_LOG_INFO,
113 "truncated comment header, %i comments not found\n", n);
9146ca37
MR
114
115 return 0;
116}
117
118
119/** Parse the vorbis header
120 * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec
121 * [vorbis_version] = read 32 bits as unsigned integer | Not used
122 * [audio_channels] = read 8 bit integer as unsigned | Used
115329f1 123 * [audio_sample_rate] = read 32 bits as unsigned integer | Used
9146ca37
MR
124 * [bitrate_maximum] = read 32 bits as signed integer | Not used yet
125 * [bitrate_nominal] = read 32 bits as signed integer | Not used yet
126 * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate
127 * [blocksize_0] = read 4 bits as unsigned integer | Not Used
128 * [blocksize_1] = read 4 bits as unsigned integer | Not Used
129 * [framing_flag] = read one bit | Not Used
130 * */
131
ad2b531d
MR
132typedef struct {
133 unsigned int len[3];
134 unsigned char *packet[3];
135} oggvorbis_private_t;
136
137
138static unsigned int
139fixup_vorbis_headers(AVFormatContext * as, oggvorbis_private_t *priv,
19f4ceca 140 uint8_t **buf)
ad2b531d
MR
141{
142 int i,offset, len;
143 unsigned char *ptr;
144
145 len = priv->len[0] + priv->len[1] + priv->len[2];
146 ptr = *buf = av_mallocz(len + len/255 + 64);
147
148 ptr[0] = 2;
149 offset = 1;
150 offset += av_xiphlacing(&ptr[offset], priv->len[0]);
151 offset += av_xiphlacing(&ptr[offset], priv->len[1]);
4bd684bc 152 for (i = 0; i < 3; i++) {
ad2b531d
MR
153 memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
154 offset += priv->len[i];
155 }
156 *buf = av_realloc(*buf, offset);
157 return offset;
158}
159
160
9146ca37
MR
161static int
162vorbis_header (AVFormatContext * s, int idx)
163{
164 ogg_t *ogg = s->priv_data;
165 ogg_stream_t *os = ogg->streams + idx;
166 AVStream *st = s->streams[idx];
ad2b531d 167 oggvorbis_private_t *priv;
9146ca37
MR
168
169 if (os->seq > 2)
170 return 0;
171
4bd684bc 172 if (os->seq == 0) {
ad2b531d 173 os->private = av_mallocz(sizeof(oggvorbis_private_t));
4bd684bc 174 if (!os->private)
ad2b531d
MR
175 return 0;
176 }
9146ca37 177
f5475e1b
MR
178 if (os->psize < 1)
179 return -1;
180
ad2b531d
MR
181 priv = os->private;
182 priv->len[os->seq] = os->psize;
183 priv->packet[os->seq] = av_mallocz(os->psize);
184 memcpy(priv->packet[os->seq], os->buf + os->pstart, os->psize);
9146ca37 185 if (os->buf[os->pstart] == 1) {
056f6179 186 uint8_t *p = os->buf + os->pstart + 11; //skip up to the audio channels
f5475e1b
MR
187
188 if (os->psize != 30)
189 return -1;
190
739587bf
MR
191 st->codec->channels = bytestream_get_byte(&p);
192 st->codec->sample_rate = bytestream_get_le32(&p);
193 p += 4; // skip maximum bitrate
194 st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
9146ca37 195
01f4895c
MN
196 st->codec->codec_type = CODEC_TYPE_AUDIO;
197 st->codec->codec_id = CODEC_ID_VORBIS;
9146ca37 198
3644cb8f
MR
199 st->time_base.num = 1;
200 st->time_base.den = st->codec->sample_rate;
9146ca37 201 } else if (os->buf[os->pstart] == 3) {
f5475e1b
MR
202 if (os->psize > 8)
203 vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8);
ad2b531d 204 } else {
01f4895c
MN
205 st->codec->extradata_size =
206 fixup_vorbis_headers(s, priv, &st->codec->extradata);
9146ca37
MR
207 }
208
209 return os->seq < 3;
210}
211
212ogg_codec_t vorbis_codec = {
213 .magic = "\001vorbis",
214 .magicsize = 7,
215 .header = vorbis_header
216};