ffmpeg / libavformat / oggparsevorbis.c @ e4d2d8c5
History | View | Annotate | Download (6.84 KB)
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/get_bits.h" |
29 |
#include "libavcodec/bytestream.h" |
30 |
#include "avformat.h" |
31 |
#include "oggdec.h" |
32 |
|
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 |
*/
|
38 |
const AVMetadataConv ff_vorbiscomment_metadata_conv[] = {
|
39 |
{ "ALBUMARTIST", "album_artist"}, |
40 |
{ "TRACKNUMBER", "track" }, |
41 |
{ 0 }
|
42 |
}; |
43 |
|
44 |
int
|
45 |
ff_vorbis_comment(AVFormatContext * as, uint8_t *buf, int size)
|
46 |
{ |
47 |
const uint8_t *p = buf;
|
48 |
const uint8_t *end = buf + size;
|
49 |
unsigned n, j;
|
50 |
int s;
|
51 |
|
52 |
if (size < 8) /* must have vendor_length and user_comment_list_length */ |
53 |
return -1; |
54 |
|
55 |
s = bytestream_get_le32(&p); |
56 |
|
57 |
if (end - p - 4 < s || s < 0) |
58 |
return -1; |
59 |
|
60 |
p += s; |
61 |
|
62 |
n = bytestream_get_le32(&p); |
63 |
|
64 |
while (end - p >= 4 && n > 0) { |
65 |
const char *t, *v; |
66 |
int tl, vl;
|
67 |
|
68 |
s = bytestream_get_le32(&p); |
69 |
|
70 |
if (end - p < s || s < 0) |
71 |
break;
|
72 |
|
73 |
t = p; |
74 |
p += s; |
75 |
n--; |
76 |
|
77 |
v = memchr(t, '=', s);
|
78 |
if (!v)
|
79 |
continue;
|
80 |
|
81 |
tl = v - t; |
82 |
vl = s - tl - 1;
|
83 |
v++; |
84 |
|
85 |
if (tl && vl) {
|
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 |
} |
96 |
|
97 |
for (j = 0; j < tl; j++) |
98 |
tt[j] = toupper(t[j]); |
99 |
tt[tl] = 0;
|
100 |
|
101 |
memcpy(ct, v, vl); |
102 |
ct[vl] = 0;
|
103 |
|
104 |
av_metadata_set2(&as->metadata, tt, ct, |
105 |
AV_METADATA_DONT_STRDUP_KEY | |
106 |
AV_METADATA_DONT_STRDUP_VAL); |
107 |
} |
108 |
} |
109 |
|
110 |
if (p != end)
|
111 |
av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", end-p);
|
112 |
if (n > 0) |
113 |
av_log(as, AV_LOG_INFO, |
114 |
"truncated comment header, %i comments not found\n", n);
|
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
|
124 |
* [audio_sample_rate] = read 32 bits as unsigned integer | Used
|
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 |
|
133 |
struct oggvorbis_private {
|
134 |
unsigned int len[3]; |
135 |
unsigned char *packet[3]; |
136 |
}; |
137 |
|
138 |
|
139 |
static unsigned int |
140 |
fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
|
141 |
uint8_t **buf) |
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]);
|
153 |
for (i = 0; i < 3; i++) { |
154 |
memcpy(&ptr[offset], priv->packet[i], priv->len[i]); |
155 |
offset += priv->len[i]; |
156 |
av_freep(&priv->packet[i]); |
157 |
} |
158 |
*buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE); |
159 |
return offset;
|
160 |
} |
161 |
|
162 |
|
163 |
static int |
164 |
vorbis_header (AVFormatContext * s, int idx)
|
165 |
{ |
166 |
struct ogg *ogg = s->priv_data;
|
167 |
struct ogg_stream *os = ogg->streams + idx;
|
168 |
AVStream *st = s->streams[idx]; |
169 |
struct oggvorbis_private *priv;
|
170 |
int pkt_type = os->buf[os->pstart];
|
171 |
|
172 |
if (!(pkt_type & 1)) |
173 |
return 0; |
174 |
|
175 |
if (!os->private) {
|
176 |
os->private = av_mallocz(sizeof(struct oggvorbis_private)); |
177 |
if (!os->private)
|
178 |
return 0; |
179 |
} |
180 |
|
181 |
if (os->psize < 1 || pkt_type > 5) |
182 |
return -1; |
183 |
|
184 |
priv = os->private; |
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);
|
188 |
if (os->buf[os->pstart] == 1) { |
189 |
const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */ |
190 |
unsigned blocksize, bs0, bs1;
|
191 |
|
192 |
if (os->psize != 30) |
193 |
return -1; |
194 |
|
195 |
if (bytestream_get_le32(&p) != 0) /* vorbis_version */ |
196 |
return -1; |
197 |
|
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
|
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; |
215 |
|
216 |
st->codec->codec_type = CODEC_TYPE_AUDIO; |
217 |
st->codec->codec_id = CODEC_ID_VORBIS; |
218 |
|
219 |
st->time_base.num = 1;
|
220 |
st->time_base.den = st->codec->sample_rate; |
221 |
} else if (os->buf[os->pstart] == 3) { |
222 |
if (os->psize > 8) |
223 |
ff_vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8); |
224 |
} else {
|
225 |
st->codec->extradata_size = |
226 |
fixup_vorbis_headers(s, priv, &st->codec->extradata); |
227 |
} |
228 |
|
229 |
return 1; |
230 |
} |
231 |
|
232 |
const struct ogg_codec ff_vorbis_codec = { |
233 |
.magic = "\001vorbis",
|
234 |
.magicsize = 7,
|
235 |
.header = vorbis_header |
236 |
}; |