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