]> git.sesse.net Git - ffmpeg/blob - libavformat/oggparsevorbis.c
reindent after last commit
[ffmpeg] / 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/get_bits.h"
29 #include "libavcodec/bytestream.h"
30 #include "avformat.h"
31 #include "oggdec.h"
32 #include "vorbiscomment.h"
33
34 static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
35 {
36     int i, cnum, h, m, s, ms, keylen = strlen(key);
37     AVChapter *chapter = NULL;
38
39     if (keylen < 9 || sscanf(key, "CHAPTER%02d", &cnum) != 1)
40         return 0;
41
42     if (keylen == 9) {
43         if (sscanf(val, "%02d:%02d:%02d.%03d", &h, &m, &s, &ms) < 4)
44             return 0;
45
46         ff_new_chapter(as, cnum, (AVRational){1,1000},
47                        ms + 1000*(s + 60*(m + 60*h)),
48                        AV_NOPTS_VALUE, NULL);
49         av_free(val);
50     } else if (!strcmp(key+9, "NAME")) {
51         for(i = 0; i < as->nb_chapters; i++)
52             if (as->chapters[i]->id == cnum) {
53                 chapter = as->chapters[i];
54                 break;
55             }
56         if (!chapter)
57             return 0;
58
59         av_metadata_set2(&chapter->metadata, "title", val,
60                          AV_METADATA_DONT_STRDUP_VAL);
61     } else
62         return 0;
63
64     av_free(key);
65     return 1;
66 }
67
68 int
69 ff_vorbis_comment(AVFormatContext * as, AVMetadata **m, const uint8_t *buf, int size)
70 {
71     const uint8_t *p = buf;
72     const uint8_t *end = buf + size;
73     unsigned n, j;
74     int s;
75
76     if (size < 8) /* must have vendor_length and user_comment_list_length */
77         return -1;
78
79     s = bytestream_get_le32(&p);
80
81     if (end - p - 4 < s || s < 0)
82         return -1;
83
84     p += s;
85
86     n = bytestream_get_le32(&p);
87
88     while (end - p >= 4 && n > 0) {
89         const char *t, *v;
90         int tl, vl;
91
92         s = bytestream_get_le32(&p);
93
94         if (end - p < s || s < 0)
95             break;
96
97         t = p;
98         p += s;
99         n--;
100
101         v = memchr(t, '=', s);
102         if (!v)
103             continue;
104
105         tl = v - t;
106         vl = s - tl - 1;
107         v++;
108
109         if (tl && vl) {
110             char *tt, *ct;
111
112             tt = av_malloc(tl + 1);
113             ct = av_malloc(vl + 1);
114             if (!tt || !ct) {
115                 av_freep(&tt);
116                 av_freep(&ct);
117                 av_log(as, AV_LOG_WARNING, "out-of-memory error. skipping VorbisComment tag.\n");
118                 continue;
119             }
120
121             for (j = 0; j < tl; j++)
122                 tt[j] = toupper(t[j]);
123             tt[tl] = 0;
124
125             memcpy(ct, v, vl);
126             ct[vl] = 0;
127
128             if (!ogm_chapter(as, tt, ct))
129                 av_metadata_set2(m, tt, ct,
130                                    AV_METADATA_DONT_STRDUP_KEY |
131                                    AV_METADATA_DONT_STRDUP_VAL);
132         }
133     }
134
135     if (p != end)
136         av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", end-p);
137     if (n > 0)
138         av_log(as, AV_LOG_INFO,
139                "truncated comment header, %i comments not found\n", n);
140
141     ff_metadata_conv(m, NULL, ff_vorbiscomment_metadata_conv);
142
143     return 0;
144 }
145
146
147 /** Parse the vorbis header
148  * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec
149  * [vorbis_version] = read 32 bits as unsigned integer | Not used
150  * [audio_channels] = read 8 bit integer as unsigned | Used
151  * [audio_sample_rate] = read 32 bits as unsigned integer | Used
152  * [bitrate_maximum] = read 32 bits as signed integer | Not used yet
153  * [bitrate_nominal] = read 32 bits as signed integer | Not used yet
154  * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate
155  * [blocksize_0] = read 4 bits as unsigned integer | Not Used
156  * [blocksize_1] = read 4 bits as unsigned integer | Not Used
157  * [framing_flag] = read one bit | Not Used
158  *    */
159
160 struct oggvorbis_private {
161     unsigned int len[3];
162     unsigned char *packet[3];
163 };
164
165
166 static unsigned int
167 fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
168                      uint8_t **buf)
169 {
170     int i,offset, len;
171     unsigned char *ptr;
172
173     len = priv->len[0] + priv->len[1] + priv->len[2];
174     ptr = *buf = av_mallocz(len + len/255 + 64);
175
176     ptr[0] = 2;
177     offset = 1;
178     offset += av_xiphlacing(&ptr[offset], priv->len[0]);
179     offset += av_xiphlacing(&ptr[offset], priv->len[1]);
180     for (i = 0; i < 3; i++) {
181         memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
182         offset += priv->len[i];
183         av_freep(&priv->packet[i]);
184     }
185     *buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
186     return offset;
187 }
188
189
190 static int
191 vorbis_header (AVFormatContext * s, int idx)
192 {
193     struct ogg *ogg = s->priv_data;
194     struct ogg_stream *os = ogg->streams + idx;
195     AVStream *st = s->streams[idx];
196     struct oggvorbis_private *priv;
197     int pkt_type = os->buf[os->pstart];
198
199     if (!(pkt_type & 1))
200         return 0;
201
202     if (!os->private) {
203         os->private = av_mallocz(sizeof(struct oggvorbis_private));
204         if (!os->private)
205             return 0;
206     }
207
208     if (os->psize < 1 || pkt_type > 5)
209         return -1;
210
211     priv = os->private;
212
213     if (priv->packet[pkt_type>>1])
214         return -1;
215     if (pkt_type > 1 && !priv->packet[0] || pkt_type > 3 && !priv->packet[1])
216         return -1;
217
218     priv->len[pkt_type >> 1] = os->psize;
219     priv->packet[pkt_type >> 1] = av_mallocz(os->psize);
220     memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize);
221     if (os->buf[os->pstart] == 1) {
222         const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
223         unsigned blocksize, bs0, bs1;
224
225         if (os->psize != 30)
226             return -1;
227
228         if (bytestream_get_le32(&p) != 0) /* vorbis_version */
229             return -1;
230
231         st->codec->channels = bytestream_get_byte(&p);
232         st->codec->sample_rate = bytestream_get_le32(&p);
233         p += 4; // skip maximum bitrate
234         st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
235         p += 4; // skip minimum bitrate
236
237         blocksize = bytestream_get_byte(&p);
238         bs0 = blocksize & 15;
239         bs1 = blocksize >> 4;
240
241         if (bs0 > bs1)
242             return -1;
243         if (bs0 < 6 || bs1 > 13)
244             return -1;
245
246         if (bytestream_get_byte(&p) != 1) /* framing_flag */
247             return -1;
248
249         st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
250         st->codec->codec_id = CODEC_ID_VORBIS;
251
252         st->time_base.num = 1;
253         st->time_base.den = st->codec->sample_rate;
254     } else if (os->buf[os->pstart] == 3) {
255         if (os->psize > 8)
256             ff_vorbis_comment (s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8);
257     } else {
258         st->codec->extradata_size =
259             fixup_vorbis_headers(s, priv, &st->codec->extradata);
260     }
261
262     return 1;
263 }
264
265 const struct ogg_codec ff_vorbis_codec = {
266     .magic = "\001vorbis",
267     .magicsize = 7,
268     .header = vorbis_header
269 };