vorbiscomment: Add support for embedded cover art
[ffmpeg.git] / 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/base64.h"
28 #include "libavutil/bswap.h"
29 #include "libavutil/dict.h"
30 #include "libavcodec/get_bits.h"
31 #include "libavcodec/bytestream.h"
32 #include "libavcodec/vorbis_parser.h"
33 #include "avformat.h"
34 #include "flacdec.h"
35 #include "internal.h"
36 #include "oggdec.h"
37 #include "vorbiscomment.h"
38
39 static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val)
40 {
41     int i, cnum, h, m, s, ms, keylen = strlen(key);
42     AVChapter *chapter = NULL;
43
44     if (keylen < 9 || sscanf(key, "CHAPTER%02d", &cnum) != 1)
45         return 0;
46
47     if (keylen == 9) {
48         if (sscanf(val, "%02d:%02d:%02d.%03d", &h, &m, &s, &ms) < 4)
49             return 0;
50
51         avpriv_new_chapter(as, cnum, (AVRational){1,1000},
52                        ms + 1000*(s + 60*(m + 60*h)),
53                        AV_NOPTS_VALUE, NULL);
54         av_free(val);
55     } else if (!strcmp(key+9, "NAME")) {
56         for(i = 0; i < as->nb_chapters; i++)
57             if (as->chapters[i]->id == cnum) {
58                 chapter = as->chapters[i];
59                 break;
60             }
61         if (!chapter)
62             return 0;
63
64         av_dict_set(&chapter->metadata, "title", val,
65                          AV_DICT_DONT_STRDUP_VAL);
66     } else
67         return 0;
68
69     av_free(key);
70     return 1;
71 }
72
73 int
74 ff_vorbis_comment(AVFormatContext * as, AVDictionary **m, const uint8_t *buf, int size)
75 {
76     const uint8_t *p = buf;
77     const uint8_t *end = buf + size;
78     unsigned n, j;
79     int s;
80
81     if (size < 8) /* must have vendor_length and user_comment_list_length */
82         return -1;
83
84     s = bytestream_get_le32(&p);
85
86     if (end - p - 4 < s || s < 0)
87         return -1;
88
89     p += s;
90
91     n = bytestream_get_le32(&p);
92
93     while (end - p >= 4 && n > 0) {
94         const char *t, *v;
95         int tl, vl;
96
97         s = bytestream_get_le32(&p);
98
99         if (end - p < s || s < 0)
100             break;
101
102         t = p;
103         p += s;
104         n--;
105
106         v = memchr(t, '=', s);
107         if (!v)
108             continue;
109
110         tl = v - t;
111         vl = s - tl - 1;
112         v++;
113
114         if (tl && vl) {
115             char *tt, *ct;
116
117             tt = av_malloc(tl + 1);
118             ct = av_malloc(vl + 1);
119             if (!tt || !ct) {
120                 av_freep(&tt);
121                 av_freep(&ct);
122                 av_log(as, AV_LOG_WARNING, "out-of-memory error. skipping VorbisComment tag.\n");
123                 continue;
124             }
125
126             for (j = 0; j < tl; j++)
127                 tt[j] = av_toupper(t[j]);
128             tt[tl] = 0;
129
130             memcpy(ct, v, vl);
131             ct[vl] = 0;
132
133             if (!strcmp(tt, "METADATA_BLOCK_PICTURE")) {
134                 int ret;
135                 char *pict = av_malloc(vl);
136
137                 if (!pict) {
138                     av_log(as, AV_LOG_WARNING, "out-of-memory error. Skipping cover art block.\n");
139                     continue;
140                 }
141                 if ((ret = av_base64_decode(pict, ct, vl)) > 0)
142                     ret = ff_flac_parse_picture(as, pict, ret);
143                 av_freep(&pict);
144                 if (ret < 0) {
145                     av_log(as, AV_LOG_WARNING, "Failed to parse cover art block.\n");
146                     continue;
147                 }
148             } else if (!ogm_chapter(as, tt, ct))
149                 av_dict_set(m, tt, ct,
150                                    AV_DICT_DONT_STRDUP_KEY |
151                                    AV_DICT_DONT_STRDUP_VAL);
152         }
153     }
154
155     if (p != end)
156         av_log(as, AV_LOG_INFO, "%ti bytes of comment header remain\n", end-p);
157     if (n > 0)
158         av_log(as, AV_LOG_INFO,
159                "truncated comment header, %i comments not found\n", n);
160
161     ff_metadata_conv(m, NULL, ff_vorbiscomment_metadata_conv);
162
163     return 0;
164 }
165
166
167 /** Parse the vorbis header
168  * Vorbis Identification header from Vorbis_I_spec.html#vorbis-spec-codec
169  * [vorbis_version] = read 32 bits as unsigned integer | Not used
170  * [audio_channels] = read 8 bit integer as unsigned | Used
171  * [audio_sample_rate] = read 32 bits as unsigned integer | Used
172  * [bitrate_maximum] = read 32 bits as signed integer | Not used yet
173  * [bitrate_nominal] = read 32 bits as signed integer | Not used yet
174  * [bitrate_minimum] = read 32 bits as signed integer | Used as bitrate
175  * [blocksize_0] = read 4 bits as unsigned integer | Not Used
176  * [blocksize_1] = read 4 bits as unsigned integer | Not Used
177  * [framing_flag] = read one bit | Not Used
178  *    */
179
180 struct oggvorbis_private {
181     unsigned int len[3];
182     unsigned char *packet[3];
183     VorbisParseContext vp;
184     int64_t final_pts;
185     int final_duration;
186 };
187
188
189 static unsigned int
190 fixup_vorbis_headers(AVFormatContext * as, struct oggvorbis_private *priv,
191                      uint8_t **buf)
192 {
193     int i,offset, len, buf_len;
194     unsigned char *ptr;
195
196     len = priv->len[0] + priv->len[1] + priv->len[2];
197     buf_len = len + len/255 + 64;
198     ptr = *buf = av_realloc(NULL, buf_len);
199     if (!*buf)
200         return 0;
201     memset(*buf, '\0', buf_len);
202
203     ptr[0] = 2;
204     offset = 1;
205     offset += av_xiphlacing(&ptr[offset], priv->len[0]);
206     offset += av_xiphlacing(&ptr[offset], priv->len[1]);
207     for (i = 0; i < 3; i++) {
208         memcpy(&ptr[offset], priv->packet[i], priv->len[i]);
209         offset += priv->len[i];
210         av_freep(&priv->packet[i]);
211     }
212     *buf = av_realloc(*buf, offset + FF_INPUT_BUFFER_PADDING_SIZE);
213     return offset;
214 }
215
216 static void vorbis_cleanup(AVFormatContext *s, int idx)
217 {
218     struct ogg *ogg = s->priv_data;
219     struct ogg_stream *os = ogg->streams + idx;
220     struct oggvorbis_private *priv = os->private;
221     int i;
222     if (os->private)
223         for (i = 0; i < 3; i++)
224             av_freep(&priv->packet[i]);
225 }
226
227 static int
228 vorbis_header (AVFormatContext * s, int idx)
229 {
230     struct ogg *ogg = s->priv_data;
231     struct ogg_stream *os = ogg->streams + idx;
232     AVStream *st = s->streams[idx];
233     struct oggvorbis_private *priv;
234     int pkt_type = os->buf[os->pstart];
235
236     if (!(pkt_type & 1))
237         return os->private ? 0 : -1;
238
239     if (!os->private) {
240         os->private = av_mallocz(sizeof(struct oggvorbis_private));
241         if (!os->private)
242             return -1;
243     }
244
245     if (os->psize < 1 || pkt_type > 5)
246         return -1;
247
248     priv = os->private;
249
250     if (priv->packet[pkt_type>>1])
251         return -1;
252     if (pkt_type > 1 && !priv->packet[0] || pkt_type > 3 && !priv->packet[1])
253         return -1;
254
255     priv->len[pkt_type >> 1] = os->psize;
256     priv->packet[pkt_type >> 1] = av_mallocz(os->psize);
257     if (!priv->packet[pkt_type >> 1])
258         return AVERROR(ENOMEM);
259     memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize);
260     if (os->buf[os->pstart] == 1) {
261         const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
262         unsigned blocksize, bs0, bs1;
263         int srate;
264         int channels;
265
266         if (os->psize != 30)
267             return -1;
268
269         if (bytestream_get_le32(&p) != 0) /* vorbis_version */
270             return -1;
271
272         channels= bytestream_get_byte(&p);
273         if (st->codec->channels && channels != st->codec->channels) {
274             av_log(s, AV_LOG_ERROR, "Channel change is not supported\n");
275             return AVERROR_PATCHWELCOME;
276         }
277         st->codec->channels = channels;
278         srate = bytestream_get_le32(&p);
279         p += 4; // skip maximum bitrate
280         st->codec->bit_rate = bytestream_get_le32(&p); // nominal bitrate
281         p += 4; // skip minimum bitrate
282
283         blocksize = bytestream_get_byte(&p);
284         bs0 = blocksize & 15;
285         bs1 = blocksize >> 4;
286
287         if (bs0 > bs1)
288             return -1;
289         if (bs0 < 6 || bs1 > 13)
290             return -1;
291
292         if (bytestream_get_byte(&p) != 1) /* framing_flag */
293             return -1;
294
295         st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
296         st->codec->codec_id = AV_CODEC_ID_VORBIS;
297
298         if (srate > 0) {
299             st->codec->sample_rate = srate;
300             avpriv_set_pts_info(st, 64, 1, srate);
301         }
302     } else if (os->buf[os->pstart] == 3) {
303         if (os->psize > 8 &&
304             ff_vorbis_comment(s, &st->metadata, os->buf + os->pstart + 7, os->psize - 8) >= 0) {
305             // drop all metadata we parsed and which is not required by libvorbis
306             unsigned new_len = 7 + 4 + AV_RL32(priv->packet[1] + 7) + 4 + 1;
307             if (new_len >= 16 && new_len < os->psize) {
308                 AV_WL32(priv->packet[1] + new_len - 5, 0);
309                 priv->packet[1][new_len - 1] = 1;
310                 priv->len[1] = new_len;
311             }
312         }
313     } else {
314         int ret;
315         st->codec->extradata_size =
316             fixup_vorbis_headers(s, priv, &st->codec->extradata);
317         if ((ret = avpriv_vorbis_parse_extradata(st->codec, &priv->vp))) {
318             av_freep(&st->codec->extradata);
319             st->codec->extradata_size = 0;
320             return ret;
321         }
322     }
323
324     return 1;
325 }
326
327 static int vorbis_packet(AVFormatContext *s, int idx)
328 {
329     struct ogg *ogg = s->priv_data;
330     struct ogg_stream *os = ogg->streams + idx;
331     struct oggvorbis_private *priv = os->private;
332     int duration;
333
334     /* first packet handling
335        here we parse the duration of each packet in the first page and compare
336        the total duration to the page granule to find the encoder delay and
337        set the first timestamp */
338     if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
339         int seg, d;
340         uint8_t *last_pkt = os->buf + os->pstart;
341         uint8_t *next_pkt = last_pkt;
342
343         avpriv_vorbis_parse_reset(&priv->vp);
344         duration = 0;
345         seg = os->segp;
346         d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
347         if (d < 0) {
348             os->pflags |= AV_PKT_FLAG_CORRUPT;
349             return 0;
350         }
351         duration += d;
352         last_pkt = next_pkt =  next_pkt + os->psize;
353         for (; seg < os->nsegs; seg++) {
354             if (os->segments[seg] < 255) {
355                 int d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
356                 if (d < 0) {
357                     duration = os->granule;
358                     break;
359                 }
360                 duration += d;
361                 last_pkt = next_pkt + os->segments[seg];
362             }
363             next_pkt += os->segments[seg];
364         }
365         os->lastpts = os->lastdts   = os->granule - duration;
366         if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
367             s->streams[idx]->start_time = FFMAX(os->lastpts, 0);
368             if (s->streams[idx]->duration)
369                 s->streams[idx]->duration -= s->streams[idx]->start_time;
370         }
371         priv->final_pts             = AV_NOPTS_VALUE;
372         avpriv_vorbis_parse_reset(&priv->vp);
373     }
374
375     /* parse packet duration */
376     if (os->psize > 0) {
377         duration = avpriv_vorbis_parse_frame(&priv->vp, os->buf + os->pstart, 1);
378         if (duration < 0) {
379             os->pflags |= AV_PKT_FLAG_CORRUPT;
380             return 0;
381         }
382         os->pduration = duration;
383     }
384
385     /* final packet handling
386        here we save the pts of the first packet in the final page, sum up all
387        packet durations in the final page except for the last one, and compare
388        to the page granule to find the duration of the final packet */
389     if (os->flags & OGG_FLAG_EOS) {
390         if (os->lastpts != AV_NOPTS_VALUE) {
391             priv->final_pts = os->lastpts;
392             priv->final_duration = 0;
393         }
394         if (os->segp == os->nsegs)
395             os->pduration = os->granule - priv->final_pts - priv->final_duration;
396         priv->final_duration += os->pduration;
397     }
398
399     return 0;
400 }
401
402 const struct ogg_codec ff_vorbis_codec = {
403     .magic = "\001vorbis",
404     .magicsize = 7,
405     .header = vorbis_header,
406     .packet = vorbis_packet,
407     .cleanup= vorbis_cleanup,
408     .nb_header = 3,
409 };