ogg: check that the expected number of headers had been parsed
[ffmpeg.git] / libavformat / oggdec.c
1 /*
2  * Ogg bitstream support
3  * Luca Barbato <lu_zero@gentoo.org>
4  * Based on tcvp implementation
5  */
6
7 /*
8     Copyright (C) 2005  Michael Ahlberg, Måns Rullgård
9
10     Permission is hereby granted, free of charge, to any person
11     obtaining a copy of this software and associated documentation
12     files (the "Software"), to deal in the Software without
13     restriction, including without limitation the rights to use, copy,
14     modify, merge, publish, distribute, sublicense, and/or sell copies
15     of the Software, and to permit persons to whom the Software is
16     furnished to do so, subject to the following conditions:
17
18     The above copyright notice and this permission notice shall be
19     included in all copies or substantial portions of the Software.
20
21     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28     DEALINGS IN THE SOFTWARE.
29  */
30
31
32 #include <stdio.h>
33 #include "oggdec.h"
34 #include "avformat.h"
35 #include "internal.h"
36 #include "vorbiscomment.h"
37
38 #define MAX_PAGE_SIZE 65307
39 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
40
41 static const struct ogg_codec * const ogg_codecs[] = {
42     &ff_skeleton_codec,
43     &ff_dirac_codec,
44     &ff_speex_codec,
45     &ff_vorbis_codec,
46     &ff_theora_codec,
47     &ff_flac_codec,
48     &ff_celt_codec,
49     &ff_old_dirac_codec,
50     &ff_old_flac_codec,
51     &ff_ogm_video_codec,
52     &ff_ogm_audio_codec,
53     &ff_ogm_text_codec,
54     &ff_ogm_old_codec,
55     NULL
56 };
57
58 //FIXME We could avoid some structure duplication
59 static int ogg_save(AVFormatContext *s)
60 {
61     struct ogg *ogg = s->priv_data;
62     struct ogg_state *ost =
63         av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
64     int i;
65     ost->pos = avio_tell (s->pb);
66     ost->curidx = ogg->curidx;
67     ost->next = ogg->state;
68     ost->nstreams = ogg->nstreams;
69     memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
70
71     for (i = 0; i < ogg->nstreams; i++){
72         struct ogg_stream *os = ogg->streams + i;
73         os->buf = av_mallocz (os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
74         memcpy (os->buf, ost->streams[i].buf, os->bufpos);
75     }
76
77     ogg->state = ost;
78
79     return 0;
80 }
81
82 static int ogg_restore(AVFormatContext *s, int discard)
83 {
84     struct ogg *ogg = s->priv_data;
85     AVIOContext *bc = s->pb;
86     struct ogg_state *ost = ogg->state;
87     int i;
88
89     if (!ost)
90         return 0;
91
92     ogg->state = ost->next;
93
94     if (!discard){
95         struct ogg_stream *old_streams = ogg->streams;
96
97         for (i = 0; i < ogg->nstreams; i++)
98             av_free (ogg->streams[i].buf);
99
100         avio_seek (bc, ost->pos, SEEK_SET);
101         ogg->curidx = ost->curidx;
102         ogg->nstreams = ost->nstreams;
103         ogg->streams = av_realloc (ogg->streams,
104                                    ogg->nstreams * sizeof (*ogg->streams));
105
106         if (ogg->streams) {
107             memcpy(ogg->streams, ost->streams,
108                    ost->nstreams * sizeof(*ogg->streams));
109         } else {
110             av_free(old_streams);
111             ogg->nstreams = 0;
112         }
113     }
114
115     av_free (ost);
116
117     return 0;
118 }
119
120 static int ogg_reset(struct ogg *ogg)
121 {
122     int i;
123
124     for (i = 0; i < ogg->nstreams; i++){
125         struct ogg_stream *os = ogg->streams + i;
126         os->bufpos = 0;
127         os->pstart = 0;
128         os->psize = 0;
129         os->granule = -1;
130         os->lastpts = AV_NOPTS_VALUE;
131         os->lastdts = AV_NOPTS_VALUE;
132         os->sync_pos = -1;
133         os->page_pos = 0;
134         os->nsegs = 0;
135         os->segp = 0;
136         os->incomplete = 0;
137     }
138
139     ogg->curidx = -1;
140
141     return 0;
142 }
143
144 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
145 {
146     int i;
147
148     for (i = 0; ogg_codecs[i]; i++)
149         if (size >= ogg_codecs[i]->magicsize &&
150             !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
151             return ogg_codecs[i];
152
153     return NULL;
154 }
155
156 static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
157 {
158
159     struct ogg *ogg = s->priv_data;
160     int idx = ogg->nstreams++;
161     AVStream *st;
162     struct ogg_stream *os;
163
164     ogg->streams = av_realloc (ogg->streams,
165                                ogg->nstreams * sizeof (*ogg->streams));
166     memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
167     os = ogg->streams + idx;
168     os->serial = serial;
169     os->bufsize = DECODER_BUFFER_SIZE;
170     os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
171     os->header = -1;
172
173     if (new_avstream) {
174         st = avformat_new_stream(s, NULL);
175         if (!st)
176             return AVERROR(ENOMEM);
177
178         st->id = idx;
179         avpriv_set_pts_info(st, 64, 1, 1000000);
180     }
181
182     return idx;
183 }
184
185 static int ogg_new_buf(struct ogg *ogg, int idx)
186 {
187     struct ogg_stream *os = ogg->streams + idx;
188     uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
189     int size = os->bufpos - os->pstart;
190     if(os->buf){
191         memcpy(nb, os->buf + os->pstart, size);
192         av_free(os->buf);
193     }
194     os->buf = nb;
195     os->bufpos = size;
196     os->pstart = 0;
197
198     return 0;
199 }
200
201 static int ogg_read_page(AVFormatContext *s, int *str)
202 {
203     AVIOContext *bc = s->pb;
204     struct ogg *ogg = s->priv_data;
205     struct ogg_stream *os;
206     int ret, i = 0;
207     int flags, nsegs;
208     uint64_t gp;
209     uint32_t serial;
210     int size, idx;
211     uint8_t sync[4];
212     int sp = 0;
213
214     ret = avio_read(bc, sync, 4);
215     if (ret < 4)
216         return ret < 0 ? ret : AVERROR_EOF;
217
218     do{
219         int c;
220
221         if (sync[sp & 3] == 'O' &&
222             sync[(sp + 1) & 3] == 'g' &&
223             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
224             break;
225
226         c = avio_r8(bc);
227         if (bc->eof_reached)
228             return AVERROR_EOF;
229         sync[sp++ & 3] = c;
230     }while (i++ < MAX_PAGE_SIZE);
231
232     if (i >= MAX_PAGE_SIZE){
233         av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
234         return AVERROR_INVALIDDATA;
235     }
236
237     if (avio_r8(bc) != 0)      /* version */
238         return AVERROR_INVALIDDATA;
239
240     flags = avio_r8(bc);
241     gp = avio_rl64 (bc);
242     serial = avio_rl32 (bc);
243     avio_skip(bc, 8); /* seq, crc */
244     nsegs = avio_r8(bc);
245
246     idx = ogg_find_stream (ogg, serial);
247     if (idx < 0){
248         if (ogg->headers) {
249             int n;
250
251             for (n = 0; n < ogg->nstreams; n++) {
252                 av_freep(&ogg->streams[n].buf);
253                 if (!ogg->state || ogg->state->streams[n].private != ogg->streams[n].private)
254                     av_freep(&ogg->streams[n].private);
255             }
256             ogg->curidx   = -1;
257             ogg->nstreams = 0;
258             idx = ogg_new_stream(s, serial, 0);
259         } else {
260             idx = ogg_new_stream(s, serial, 1);
261         }
262         if (idx < 0)
263             return idx;
264     }
265
266     os = ogg->streams + idx;
267     os->page_pos = avio_tell(bc) - 27;
268
269     if(os->psize > 0)
270         ogg_new_buf(ogg, idx);
271
272     ret = avio_read(bc, os->segments, nsegs);
273     if (ret < nsegs)
274         return ret < 0 ? ret : AVERROR_EOF;
275
276     os->nsegs = nsegs;
277     os->segp = 0;
278
279     size = 0;
280     for (i = 0; i < nsegs; i++)
281         size += os->segments[i];
282
283     if (flags & OGG_FLAG_CONT || os->incomplete){
284         if (!os->psize){
285             while (os->segp < os->nsegs){
286                 int seg = os->segments[os->segp++];
287                 os->pstart += seg;
288                 if (seg < 255)
289                     break;
290             }
291             os->sync_pos = os->page_pos;
292         }
293     }else{
294         os->psize = 0;
295         os->sync_pos = os->page_pos;
296     }
297
298     if (os->bufsize - os->bufpos < size){
299         uint8_t *nb = av_malloc ((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
300         memcpy (nb, os->buf, os->bufpos);
301         av_free (os->buf);
302         os->buf = nb;
303     }
304
305     ret = avio_read(bc, os->buf + os->bufpos, size);
306     if (ret < size)
307         return ret < 0 ? ret : AVERROR_EOF;
308
309     os->bufpos += size;
310     os->granule = gp;
311     os->flags = flags;
312
313     memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
314     if (str)
315         *str = idx;
316
317     return 0;
318 }
319
320 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
321                       int64_t *fpos)
322 {
323     struct ogg *ogg = s->priv_data;
324     int idx, i, ret;
325     struct ogg_stream *os;
326     int complete = 0;
327     int segp = 0, psize = 0;
328
329     av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
330
331     do{
332         idx = ogg->curidx;
333
334         while (idx < 0){
335             ret = ogg_read_page(s, &idx);
336             if (ret < 0)
337                 return ret;
338         }
339
340         os = ogg->streams + idx;
341
342         av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
343                 idx, os->pstart, os->psize, os->segp, os->nsegs);
344
345         if (!os->codec){
346             if (os->header < 0){
347                 os->codec = ogg_find_codec (os->buf, os->bufpos);
348                 if (!os->codec){
349                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
350                     os->header = 0;
351                     return 0;
352                 }
353             }else{
354                 return 0;
355             }
356         }
357
358         segp = os->segp;
359         psize = os->psize;
360
361         while (os->segp < os->nsegs){
362             int ss = os->segments[os->segp++];
363             os->psize += ss;
364             if (ss < 255){
365                 complete = 1;
366                 break;
367             }
368         }
369
370         if (!complete && os->segp == os->nsegs){
371             ogg->curidx = -1;
372             os->incomplete = 1;
373         }
374     }while (!complete);
375
376     av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n",
377             idx, os->psize, os->pstart);
378
379     if (os->granule == -1)
380         av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
381
382     ogg->curidx = idx;
383     os->incomplete = 0;
384
385     if (os->header) {
386         os->header = os->codec->header (s, idx);
387         if (!os->header){
388             os->segp = segp;
389             os->psize = psize;
390
391             // We have reached the first non-header packet in this stream.
392             // Unfortunately more header packets may still follow for others,
393             // but if we continue with header parsing we may lose data packets.
394             ogg->headers = 1;
395
396             // Update the header state for all streams and
397             // compute the data_offset.
398             if (!s->data_offset)
399                 s->data_offset = os->sync_pos;
400             for (i = 0; i < ogg->nstreams; i++) {
401                 struct ogg_stream *cur_os = ogg->streams + i;
402
403                 // if we have a partial non-header packet, its start is
404                 // obviously at or after the data start
405                 if (cur_os->incomplete)
406                     s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
407             }
408         }else{
409             os->nb_header++;
410             os->pstart += os->psize;
411             os->psize = 0;
412         }
413     } else {
414         os->pflags = 0;
415         os->pduration = 0;
416         if (os->codec && os->codec->packet)
417             os->codec->packet (s, idx);
418         if (str)
419             *str = idx;
420         if (dstart)
421             *dstart = os->pstart;
422         if (dsize)
423             *dsize = os->psize;
424         if (fpos)
425             *fpos = os->sync_pos;
426         os->pstart += os->psize;
427         os->psize = 0;
428         os->sync_pos = os->page_pos;
429     }
430
431     // determine whether there are more complete packets in this page
432     // if not, the page's granule will apply to this packet
433     os->page_end = 1;
434     for (i = os->segp; i < os->nsegs; i++)
435         if (os->segments[i] < 255) {
436             os->page_end = 0;
437             break;
438         }
439
440     if (os->segp == os->nsegs)
441         ogg->curidx = -1;
442
443     return 0;
444 }
445
446 static int ogg_get_headers(AVFormatContext *s)
447 {
448     struct ogg *ogg = s->priv_data;
449     int ret, i;
450
451     do{
452         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
453         if (ret < 0)
454             return ret;
455     }while (!ogg->headers);
456
457     for (i = 0; i < ogg->nstreams; i++) {
458         struct ogg_stream *os = ogg->streams + i;
459
460         if (os->codec && os->codec->nb_header &&
461             os->nb_header < os->codec->nb_header) {
462             av_log(s, AV_LOG_ERROR,
463                    "Headers mismatch for stream %d\n", i);
464             return AVERROR_INVALIDDATA;
465         }
466     }
467     av_dlog(s, "found headers\n");
468
469     return 0;
470 }
471
472 static int ogg_get_length(AVFormatContext *s)
473 {
474     struct ogg *ogg = s->priv_data;
475     int i;
476     int64_t size, end;
477
478     if(!s->pb->seekable)
479         return 0;
480
481 // already set
482     if (s->duration != AV_NOPTS_VALUE)
483         return 0;
484
485     size = avio_size(s->pb);
486     if(size < 0)
487         return 0;
488     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
489
490     ogg_save (s);
491     avio_seek (s->pb, end, SEEK_SET);
492
493     while (!ogg_read_page (s, &i)){
494         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
495             ogg->streams[i].codec) {
496             s->streams[i]->duration =
497                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
498             if (s->streams[i]->start_time != AV_NOPTS_VALUE)
499                 s->streams[i]->duration -= s->streams[i]->start_time;
500         }
501     }
502
503     ogg_restore (s, 0);
504
505     return 0;
506 }
507
508 static int ogg_read_header(AVFormatContext *s)
509 {
510     struct ogg *ogg = s->priv_data;
511     int ret, i;
512     ogg->curidx = -1;
513     //linear headers seek from start
514     ret = ogg_get_headers(s);
515     if (ret < 0)
516         return ret;
517
518     for (i = 0; i < ogg->nstreams; i++)
519         if (ogg->streams[i].header < 0)
520             ogg->streams[i].codec = NULL;
521
522     //linear granulepos seek from end
523     ogg_get_length (s);
524
525     //fill the extradata in the per codec callbacks
526     return 0;
527 }
528
529 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
530 {
531     struct ogg *ogg = s->priv_data;
532     struct ogg_stream *os = ogg->streams + idx;
533     int64_t pts = AV_NOPTS_VALUE;
534
535     if (dts)
536         *dts = AV_NOPTS_VALUE;
537
538     if (os->lastpts != AV_NOPTS_VALUE) {
539         pts = os->lastpts;
540         os->lastpts = AV_NOPTS_VALUE;
541     }
542     if (os->lastdts != AV_NOPTS_VALUE) {
543         if (dts)
544             *dts = os->lastdts;
545         os->lastdts = AV_NOPTS_VALUE;
546     }
547     if (os->page_end) {
548         if (os->granule != -1LL) {
549             if (os->codec && os->codec->granule_is_start)
550                 pts = ogg_gptopts(s, idx, os->granule, dts);
551             else
552                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
553             os->granule = -1LL;
554         }
555     }
556     return pts;
557 }
558
559 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
560 {
561     struct ogg *ogg;
562     struct ogg_stream *os;
563     int idx = -1, ret;
564     int pstart, psize;
565     int64_t fpos, pts, dts;
566
567     //Get an ogg packet
568 retry:
569     do{
570         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
571         if (ret < 0)
572             return ret;
573     }while (idx < 0 || !s->streams[idx]);
574
575     ogg = s->priv_data;
576     os = ogg->streams + idx;
577
578     // pflags might not be set until after this
579     pts = ogg_calc_pts(s, idx, &dts);
580
581     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
582         goto retry;
583     os->keyframe_seek = 0;
584
585     //Alloc a pkt
586     ret = av_new_packet(pkt, psize);
587     if (ret < 0)
588         return ret;
589     pkt->stream_index = idx;
590     memcpy (pkt->data, os->buf + pstart, psize);
591
592     pkt->pts = pts;
593     pkt->dts = dts;
594     pkt->flags = os->pflags;
595     pkt->duration = os->pduration;
596     pkt->pos = fpos;
597
598     return psize;
599 }
600
601 static int ogg_read_close(AVFormatContext *s)
602 {
603     struct ogg *ogg = s->priv_data;
604     int i;
605
606     for (i = 0; i < ogg->nstreams; i++){
607         av_free (ogg->streams[i].buf);
608         av_free (ogg->streams[i].private);
609     }
610     av_free (ogg->streams);
611     return 0;
612 }
613
614 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
615                                   int64_t *pos_arg, int64_t pos_limit)
616 {
617     struct ogg *ogg = s->priv_data;
618     AVIOContext *bc = s->pb;
619     int64_t pts = AV_NOPTS_VALUE;
620     int i = -1;
621     avio_seek(bc, *pos_arg, SEEK_SET);
622     ogg_reset(ogg);
623
624     while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
625         if (i == stream_index) {
626             struct ogg_stream *os = ogg->streams + stream_index;
627             pts = ogg_calc_pts(s, i, NULL);
628             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
629                 pts = AV_NOPTS_VALUE;
630         }
631         if (pts != AV_NOPTS_VALUE)
632             break;
633     }
634     ogg_reset(ogg);
635     return pts;
636 }
637
638 static int ogg_read_seek(AVFormatContext *s, int stream_index,
639                          int64_t timestamp, int flags)
640 {
641     struct ogg *ogg = s->priv_data;
642     struct ogg_stream *os = ogg->streams + stream_index;
643     int ret;
644
645     // Try seeking to a keyframe first. If this fails (very possible),
646     // av_seek_frame will fall back to ignoring keyframes
647     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
648         && !(flags & AVSEEK_FLAG_ANY))
649         os->keyframe_seek = 1;
650
651     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
652     os = ogg->streams + stream_index;
653     if (ret < 0)
654         os->keyframe_seek = 0;
655     return ret;
656 }
657
658 static int ogg_probe(AVProbeData *p)
659 {
660     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
661         return AVPROBE_SCORE_MAX;
662     return 0;
663 }
664
665 AVInputFormat ff_ogg_demuxer = {
666     .name           = "ogg",
667     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
668     .priv_data_size = sizeof(struct ogg),
669     .read_probe     = ogg_probe,
670     .read_header    = ogg_read_header,
671     .read_packet    = ogg_read_packet,
672     .read_close     = ogg_read_close,
673     .read_seek      = ogg_read_seek,
674     .read_timestamp = ogg_read_timestamp,
675     .extensions     = "ogg",
676     .flags          = AVFMT_GENERIC_INDEX,
677 };