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