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