oggdec: Cosmetics
[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>
245976da
DB
26#include "libavutil/avstring.h"
27#include "libavutil/bswap.h"
9106a698 28#include "libavcodec/get_bits.h"
245976da 29#include "libavcodec/bytestream.h"
9146ca37 30#include "avformat.h"
a0ddef24 31#include "oggdec.h"
9146ca37 32
d7bb185f
JR
33/**
34 * VorbisComment metadata conversion mapping.
35 * from Ogg Vorbis I format specification: comment field and header specification
36 * http://xiph.org/vorbis/doc/v-comment.html
37 */
38const AVMetadataConv ff_vorbiscomment_metadata_conv[] = {
ca76a119 39 { "ALBUMARTIST", "album_artist"},
d7bb185f 40 { "TRACKNUMBER", "track" },
d7bb185f
JR
41 { 0 }
42};
43
9686df2b 44int
533c30fc 45ff_vorbis_comment(AVFormatContext * as, AVMetadata **m, const uint8_t *buf, int size)
9146ca37 46{
47a0513b
BC
47 const uint8_t *p = buf;
48 const uint8_t *end = buf + size;
98422c44
RD
49 unsigned n, j;
50 int s;
9146ca37 51
f5475e1b 52 if (size < 8) /* must have vendor_length and user_comment_list_length */
9146ca37
MR
53 return -1;
54
0a770ae7 55 s = bytestream_get_le32(&p);
9146ca37 56
98422c44 57 if (end - p - 4 < s || s < 0)
9146ca37
MR
58 return -1;
59
60 p += s;
9146ca37 61
0a770ae7 62 n = bytestream_get_le32(&p);
9146ca37 63
98422c44 64 while (end - p >= 4 && n > 0) {
47a0513b 65 const char *t, *v;
9146ca37
MR
66 int tl, vl;
67
0a770ae7 68 s = bytestream_get_le32(&p);
9146ca37 69
98422c44 70 if (end - p < s || s < 0)
9146ca37
MR
71 break;
72
73 t = p;
74 p += s;
9146ca37
MR
75 n--;
76
4bd684bc 77 v = memchr(t, '=', s);
9146ca37
MR
78 if (!v)
79 continue;
80
81 tl = v - t;
82 vl = s - tl - 1;
83 v++;
84
4bd684bc 85 if (tl && vl) {
e3b44649
JR
86 char *tt, *ct;
87
88 tt = av_malloc(tl + 1);
89 ct = av_malloc(vl + 1);
90 if (!tt || !ct) {
91 av_freep(&tt);
92 av_freep(&ct);
93 av_log(as, AV_LOG_WARNING, "out-of-memory error. skipping VorbisComment tag.\n");
94 continue;
95 }
9146ca37
MR
96
97 for (j = 0; j < tl; j++)
4bd684bc 98 tt[j] = toupper(t[j]);
9146ca37
MR
99 tt[tl] = 0;
100
4bd684bc 101 memcpy(ct, v, vl);
9146ca37
MR
102 ct[vl] = 0;
103
b53cde48 104 av_metadata_set2(m, tt, ct,
12ad6671
MN
105 AV_METADATA_DONT_STRDUP_KEY |
106 AV_METADATA_DONT_STRDUP_VAL);
9146ca37
MR
107 }
108 }
109
972c5f9e 110 if (p != end)
7d507ceb 111 av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", end-p);
9146ca37 112 if (n > 0)
4bd684bc
MR
113 av_log(as, AV_LOG_INFO,
114 "truncated comment header, %i comments not found\n", n);
9146ca37
MR
115
116 return 0;
117}
118
119
120/** Parse the vorbis header
121 * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec
122 * [vorbis_version] = read 32 bits as unsigned integer | Not used
123 * [audio_channels] = read 8 bit integer as unsigned | Used
115329f1 124 * [audio_sample_rate] = read 32 bits as unsigned integer | Used
9146ca37
MR
125 * [bitrate_maximum] = read 32 bits as signed integer | Not used yet
126 * [bitrate_nominal] = read 32 bits as signed integer | Not used yet
127 * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate
128 * [blocksize_0] = read 4 bits as unsigned integer | Not Used
129 * [blocksize_1] = read 4 bits as unsigned integer | Not Used
130 * [framing_flag] = read one bit | Not Used
131 * */
132
77be08ee 133struct oggvorbis_private {
ad2b531d
MR
134 unsigned int len[3];
135 unsigned char *packet[3];
77be08ee 136};
ad2b531d
MR
137
138
139static unsigned int
77be08ee 140fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
19f4ceca 141 uint8_t **buf)
ad2b531d
MR
142{
143 int i,offset, len;
144 unsigned char *ptr;
145
146 len = priv->len[0] + priv->len[1] + priv->len[2];
147 ptr = *buf = av_mallocz(len + len/255 + 64);
148
149 ptr[0] = 2;
150 offset = 1;
151 offset += av_xiphlacing(&ptr[offset], priv->len[0]);
152 offset += av_xiphlacing(&ptr[offset], priv->len[1]);
4bd684bc 153 for (i = 0; i < 3; i++) {
ad2b531d
MR
154 memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
155 offset += priv->len[i];
2ac41150 156 av_freep(&priv->packet[i]);
ad2b531d 157 }
589790c2 158 *buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
ad2b531d
MR
159 return offset;
160}
161
162
9146ca37
MR
163static int
164vorbis_header (AVFormatContext * s, int idx)
165{
77be08ee
MR
166 struct ogg *ogg = s->priv_data;
167 struct ogg_stream *os = ogg->streams + idx;
9146ca37 168 AVStream *st = s->streams[idx];
77be08ee 169 struct oggvorbis_private *priv;
8f8320d7 170 int pkt_type = os->buf[os->pstart];
9146ca37 171
8f8320d7 172 if (!(pkt_type & 1))
9146ca37
MR
173 return 0;
174
8f8320d7 175 if (!os->private) {
77be08ee 176 os->private = av_mallocz(sizeof(struct oggvorbis_private));
4bd684bc 177 if (!os->private)
ad2b531d
MR
178 return 0;
179 }
9146ca37 180
8f8320d7 181 if (os->psize < 1 || pkt_type > 5)
f5475e1b
MR
182 return -1;
183
ad2b531d 184 priv = os->private;
8f8320d7
DC
185 priv->len[pkt_type >> 1] = os->psize;
186 priv->packet[pkt_type >> 1] = av_mallocz(os->psize);
187 memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize);
9146ca37 188 if (os->buf[os->pstart] == 1) {
47a0513b 189 const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
736e63ed 190 unsigned blocksize, bs0, bs1;
f5475e1b
MR
191
192 if (os->psize != 30)
193 return -1;
194
736e63ed
MR
195 if (bytestream_get_le32(&p) != 0) /* vorbis_version */
196 return -1;
197
739587bf
MR
198 st->codec->channels = bytestream_get_byte(&p);
199 st->codec->sample_rate = bytestream_get_le32(&p);
200 p += 4; // skip maximum bitrate
201 st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
736e63ed
MR
202 p += 4; // skip minimum bitrate
203
204 blocksize = bytestream_get_byte(&p);
205 bs0 = blocksize & 15;
206 bs1 = blocksize >> 4;
207
208 if (bs0 > bs1)
209 return -1;
210 if (bs0 < 6 || bs1 > 13)
211 return -1;
212
213 if (bytestream_get_byte(&p) != 1) /* framing_flag */
214 return -1;
9146ca37 215
01f4895c
MN
216 st->codec->codec_type = CODEC_TYPE_AUDIO;
217 st->codec->codec_id = CODEC_ID_VORBIS;
9146ca37 218
3644cb8f
MR
219 st->time_base.num = 1;
220 st->time_base.den = st->codec->sample_rate;
9146ca37 221 } else if (os->buf[os->pstart] == 3) {
f5475e1b 222 if (os->psize > 8)
b53cde48 223 ff_vorbis_comment (s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8);
ad2b531d 224 } else {
01f4895c
MN
225 st->codec->extradata_size =
226 fixup_vorbis_headers(s, priv, &st->codec->extradata);
9146ca37
MR
227 }
228
8f8320d7 229 return 1;
9146ca37
MR
230}
231
77be08ee 232const struct ogg_codec ff_vorbis_codec = {
9146ca37
MR
233 .magic = "\001vorbis",
234 .magicsize = 7,
235 .header = vorbis_header
236};