]> git.sesse.net Git - ffmpeg/blob - libavformat/oggparsevorbis.c
Use AV_METADATA_DONT_STRDUP* / use av_malloced metadata instead of strduped
[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
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     { "ARTIST"     , "author" },
40     { "DATE"       , "year"   },
41     { "TRACKNUMBER", "track"  },
42     { 0 }
43 };
44
45 int
46 vorbis_comment(AVFormatContext * as, uint8_t *buf, int size)
47 {
48     const uint8_t *p = buf;
49     const uint8_t *end = buf + size;
50     unsigned n, j;
51     int s;
52
53     if (size < 8) /* must have vendor_length and user_comment_list_length */
54         return -1;
55
56     s = bytestream_get_le32(&p);
57
58     if (end - p - 4 < s || s < 0)
59         return -1;
60
61     p += s;
62
63     n = bytestream_get_le32(&p);
64
65     while (end - p >= 4 && n > 0) {
66         const char *t, *v;
67         int tl, vl;
68
69         s = bytestream_get_le32(&p);
70
71         if (end - p < s || s < 0)
72             break;
73
74         t = p;
75         p += s;
76         n--;
77
78         v = memchr(t, '=', s);
79         if (!v)
80             continue;
81
82         tl = v - t;
83         vl = s - tl - 1;
84         v++;
85
86         if (tl && vl) {
87             char *tt, *ct;
88
89             tt = av_malloc(tl + 1);
90             ct = av_malloc(vl + 1);
91             if (!tt || !ct) {
92                 av_freep(&tt);
93                 av_freep(&ct);
94                 av_log(as, AV_LOG_WARNING, "out-of-memory error. skipping VorbisComment tag.\n");
95                 continue;
96             }
97
98             for (j = 0; j < tl; j++)
99                 tt[j] = toupper(t[j]);
100             tt[tl] = 0;
101
102             memcpy(ct, v, vl);
103             ct[vl] = 0;
104
105             av_metadata_set2(&as->metadata, tt, ct,
106                                    AV_METADATA_DONT_STRDUP_KEY |
107                                    AV_METADATA_DONT_STRDUP_VAL);
108         }
109     }
110
111     if (p != end)
112         av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", end-p);
113     if (n > 0)
114         av_log(as, AV_LOG_INFO,
115                "truncated comment header, %i comments not found\n", n);
116
117     return 0;
118 }
119
120
121 /** Parse the vorbis header
122  * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec
123  * [vorbis_version] = read 32 bits as unsigned integer | Not used
124  * [audio_channels] = read 8 bit integer as unsigned | Used
125  * [audio_sample_rate] = read 32 bits as unsigned integer | Used
126  * [bitrate_maximum] = read 32 bits as signed integer | Not used yet
127  * [bitrate_nominal] = read 32 bits as signed integer | Not used yet
128  * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate
129  * [blocksize_0] = read 4 bits as unsigned integer | Not Used
130  * [blocksize_1] = read 4 bits as unsigned integer | Not Used
131  * [framing_flag] = read one bit | Not Used
132  *    */
133
134 struct oggvorbis_private {
135     unsigned int len[3];
136     unsigned char *packet[3];
137 };
138
139
140 static unsigned int
141 fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
142                      uint8_t **buf)
143 {
144     int i,offset, len;
145     unsigned char *ptr;
146
147     len = priv->len[0] + priv->len[1] + priv->len[2];
148     ptr = *buf = av_mallocz(len + len/255 + 64);
149
150     ptr[0] = 2;
151     offset = 1;
152     offset += av_xiphlacing(&ptr[offset], priv->len[0]);
153     offset += av_xiphlacing(&ptr[offset], priv->len[1]);
154     for (i = 0; i < 3; i++) {
155         memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
156         offset += priv->len[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
171     if (os->seq > 2)
172         return 0;
173
174     if (os->seq == 0) {
175         os->private = av_mallocz(sizeof(struct oggvorbis_private));
176         if (!os->private)
177             return 0;
178     }
179
180     if (os->psize < 1)
181         return -1;
182
183     priv = os->private;
184     priv->len[os->seq] = os->psize;
185     priv->packet[os->seq] = av_mallocz(os->psize);
186     memcpy(priv->packet[os->seq], os->buf + os->pstart, os->psize);
187     if (os->buf[os->pstart] == 1) {
188         const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
189         unsigned blocksize, bs0, bs1;
190
191         if (os->psize != 30)
192             return -1;
193
194         if (bytestream_get_le32(&p) != 0) /* vorbis_version */
195             return -1;
196
197         st->codec->channels = bytestream_get_byte(&p);
198         st->codec->sample_rate = bytestream_get_le32(&p);
199         p += 4; // skip maximum bitrate
200         st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
201         p += 4; // skip minimum bitrate
202
203         blocksize = bytestream_get_byte(&p);
204         bs0 = blocksize & 15;
205         bs1 = blocksize >> 4;
206
207         if (bs0 > bs1)
208             return -1;
209         if (bs0 < 6 || bs1 > 13)
210             return -1;
211
212         if (bytestream_get_byte(&p) != 1) /* framing_flag */
213             return -1;
214
215         st->codec->codec_type = CODEC_TYPE_AUDIO;
216         st->codec->codec_id = CODEC_ID_VORBIS;
217
218         st->time_base.num = 1;
219         st->time_base.den = st->codec->sample_rate;
220     } else if (os->buf[os->pstart] == 3) {
221         if (os->psize > 8)
222             vorbis_comment (s, os->buf + os->pstart + 7, os->psize - 8);
223     } else {
224         st->codec->extradata_size =
225             fixup_vorbis_headers(s, priv, &st->codec->extradata);
226     }
227
228     return os->seq < 3;
229 }
230
231 const struct ogg_codec ff_vorbis_codec = {
232     .magic = "\001vorbis",
233     .magicsize = 7,
234     .header = vorbis_header
235 };