]> git.sesse.net Git - ffmpeg/blob - libavformat/oggdec.c
lavf: fix the comparison in an overflow check
[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     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     struct ogg *ogg = s->priv_data;
159     int idx         = ogg->nstreams++;
160     AVStream *st;
161     struct ogg_stream *os;
162
163     os = av_realloc(ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
164
165     if (!os)
166         return AVERROR(ENOMEM);
167
168     ogg->streams = os;
169
170     memset(ogg->streams + idx, 0, sizeof(*ogg->streams));
171
172     os                = ogg->streams + idx;
173     os->serial        = serial;
174     os->bufsize       = DECODER_BUFFER_SIZE;
175     os->buf           = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
176     os->header        = -1;
177     os->start_granule = OGG_NOGRANULE_VALUE;
178
179     if (new_avstream) {
180         st = avformat_new_stream(s, NULL);
181         if (!st)
182             return AVERROR(ENOMEM);
183
184         st->id = idx;
185         avpriv_set_pts_info(st, 64, 1, 1000000);
186     }
187
188     return idx;
189 }
190
191 static int ogg_new_buf(struct ogg *ogg, int idx)
192 {
193     struct ogg_stream *os = ogg->streams + idx;
194     uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
195     int size = os->bufpos - os->pstart;
196
197     if (os->buf) {
198         memcpy(nb, os->buf + os->pstart, size);
199         av_free(os->buf);
200     }
201
202     os->buf    = nb;
203     os->bufpos = size;
204     os->pstart = 0;
205
206     return 0;
207 }
208
209 static int ogg_read_page(AVFormatContext *s, int *str)
210 {
211     AVIOContext *bc = s->pb;
212     struct ogg *ogg = s->priv_data;
213     struct ogg_stream *os;
214     int ret, i = 0;
215     int flags, nsegs;
216     uint64_t gp;
217     uint32_t serial;
218     int size, idx;
219     uint8_t sync[4];
220     int sp = 0;
221
222     ret = avio_read(bc, sync, 4);
223     if (ret < 4)
224         return ret < 0 ? ret : AVERROR_EOF;
225
226     do {
227         int c;
228
229         if (sync[sp & 3] == 'O' &&
230             sync[(sp + 1) & 3] == 'g' &&
231             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
232             break;
233
234         c = avio_r8(bc);
235
236         if (bc->eof_reached)
237             return AVERROR_EOF;
238
239         sync[sp++ & 3] = c;
240     } while (i++ < MAX_PAGE_SIZE);
241
242     if (i >= MAX_PAGE_SIZE) {
243         av_log(s, AV_LOG_INFO, "cannot find sync word\n");
244         return AVERROR_INVALIDDATA;
245     }
246
247     if (avio_r8(bc) != 0)      /* version */
248         return AVERROR_INVALIDDATA;
249
250     flags  = avio_r8(bc);
251     gp     = avio_rl64(bc);
252     serial = avio_rl32(bc);
253     avio_skip(bc, 8); /* seq, crc */
254     nsegs  = avio_r8(bc);
255
256     idx = ogg_find_stream(ogg, serial);
257     if (idx < 0) {
258         if (ogg->headers) {
259             int n;
260
261             for (n = 0; n < ogg->nstreams; n++) {
262                 av_freep(&ogg->streams[n].buf);
263                 if (!ogg->state ||
264                     ogg->state->streams[n].private != ogg->streams[n].private)
265                     av_freep(&ogg->streams[n].private);
266             }
267
268             ogg->curidx   = -1;
269             ogg->nstreams = 0;
270
271             idx = ogg_new_stream(s, serial, 0);
272         } else {
273             idx = ogg_new_stream(s, serial, 1);
274         }
275         if (idx < 0)
276             return idx;
277     }
278
279     os = ogg->streams + idx;
280     os->page_pos = avio_tell(bc) - 27;
281
282     if (os->psize > 0)
283         ogg_new_buf(ogg, idx);
284
285     ret = avio_read(bc, os->segments, nsegs);
286     if (ret < nsegs)
287         return ret < 0 ? ret : AVERROR_EOF;
288
289     os->nsegs = nsegs;
290     os->segp  = 0;
291
292     size = 0;
293     for (i = 0; i < nsegs; i++)
294         size += os->segments[i];
295
296     if (flags & OGG_FLAG_CONT || os->incomplete) {
297         if (!os->psize) {
298             while (os->segp < os->nsegs) {
299                 int seg = os->segments[os->segp++];
300                 os->pstart += seg;
301                 if (seg < 255)
302                     break;
303             }
304             os->sync_pos = os->page_pos;
305         }
306     } else {
307         os->psize    = 0;
308         os->sync_pos = os->page_pos;
309     }
310
311     if (os->bufsize - os->bufpos < size) {
312         uint8_t *nb = av_malloc((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
313         if (!nb)
314             return AVERROR(ENOMEM);
315         memcpy(nb, os->buf, os->bufpos);
316         av_free(os->buf);
317         os->buf = nb;
318     }
319
320     ret = avio_read(bc, os->buf + os->bufpos, size);
321     if (ret < size)
322         return ret < 0 ? ret : AVERROR_EOF;
323
324     os->bufpos += size;
325     os->granule = gp;
326     os->flags   = flags;
327
328     memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
329     if (str)
330         *str = idx;
331
332     return 0;
333 }
334
335 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
336                       int64_t *fpos)
337 {
338     struct ogg *ogg = s->priv_data;
339     int idx, i, ret;
340     struct ogg_stream *os;
341     int complete = 0;
342     int segp     = 0, psize = 0;
343
344     av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
345
346     do {
347         idx = ogg->curidx;
348
349         while (idx < 0) {
350             ret = ogg_read_page(s, &idx);
351             if (ret < 0)
352                 return ret;
353         }
354
355         os = ogg->streams + idx;
356
357         av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
358                 idx, os->pstart, os->psize, os->segp, os->nsegs);
359
360         if (!os->codec) {
361             if (os->header < 0) {
362                 os->codec = ogg_find_codec(os->buf, os->bufpos);
363                 if (!os->codec) {
364                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
365                     os->header = 0;
366                     return 0;
367                 }
368             } else {
369                 return 0;
370             }
371         }
372
373         segp  = os->segp;
374         psize = os->psize;
375
376         while (os->segp < os->nsegs) {
377             int ss = os->segments[os->segp++];
378             os->psize += ss;
379             if (ss < 255) {
380                 complete = 1;
381                 break;
382             }
383         }
384
385         if (!complete && os->segp == os->nsegs) {
386             ogg->curidx    = -1;
387             // Do not set incomplete for empty packets.
388             // Together with the code in ogg_read_page
389             // that discards all continuation of empty packets
390             // we would get an infinite loop.
391             os->incomplete = !!os->psize;
392         }
393     } while (!complete);
394
395     av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n",
396             idx, os->psize, os->pstart);
397
398     if (os->granule == -1)
399         av_log(s, AV_LOG_WARNING,
400                "Page at %"PRId64" is missing granule\n",
401                os->page_pos);
402
403     ogg->curidx    = idx;
404     os->incomplete = 0;
405
406     if (os->header) {
407         os->header = os->codec->header(s, idx);
408         if (!os->header) {
409             os->segp  = segp;
410             os->psize = psize;
411
412             // We have reached the first non-header packet in this stream.
413             // Unfortunately more header packets may still follow for others,
414             // but if we continue with header parsing we may lose data packets.
415             ogg->headers = 1;
416
417             // Update the header state for all streams and
418             // compute the data_offset.
419             if (!s->data_offset)
420                 s->data_offset = os->sync_pos;
421
422             for (i = 0; i < ogg->nstreams; i++) {
423                 struct ogg_stream *cur_os = ogg->streams + i;
424
425                 // if we have a partial non-header packet, its start is
426                 // obviously at or after the data start
427                 if (cur_os->incomplete)
428                     s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
429             }
430         } else {
431             os->nb_header++;
432             os->pstart += os->psize;
433             os->psize   = 0;
434         }
435     } else {
436         os->pflags    = 0;
437         os->pduration = 0;
438         if (os->codec && os->codec->packet)
439             os->codec->packet(s, idx);
440         if (str)
441             *str = idx;
442         if (dstart)
443             *dstart = os->pstart;
444         if (dsize)
445             *dsize = os->psize;
446         if (fpos)
447             *fpos = os->sync_pos;
448         os->pstart  += os->psize;
449         os->psize    = 0;
450         os->sync_pos = os->page_pos;
451     }
452
453     // determine whether there are more complete packets in this page
454     // if not, the page's granule will apply to this packet
455     os->page_end = 1;
456     for (i = os->segp; i < os->nsegs; i++)
457         if (os->segments[i] < 255) {
458             os->page_end = 0;
459             break;
460         }
461
462     if (os->segp == os->nsegs)
463         ogg->curidx = -1;
464
465     return 0;
466 }
467
468 static int ogg_get_headers(AVFormatContext *s)
469 {
470     struct ogg *ogg = s->priv_data;
471     int ret, i;
472
473     do {
474         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
475         if (ret < 0)
476             return ret;
477     } while (!ogg->headers);
478
479     for (i = 0; i < ogg->nstreams; i++) {
480         struct ogg_stream *os = ogg->streams + i;
481
482         if (os->codec && os->codec->nb_header &&
483             os->nb_header < os->codec->nb_header) {
484             av_log(s, AV_LOG_ERROR,
485                    "Headers mismatch for stream %d: "
486                    "expected %d received %d.\n",
487                    i, os->codec->nb_header, os->nb_header);
488             if (s->error_recognition & AV_EF_EXPLODE)
489                 return AVERROR_INVALIDDATA;
490         }
491         if (os->start_granule != OGG_NOGRANULE_VALUE)
492             os->lastpts = s->streams[i]->start_time =
493                 ogg_gptopts(s, i, os->start_granule, NULL);
494     }
495     av_dlog(s, "found headers\n");
496
497     return 0;
498 }
499
500 static int ogg_get_length(AVFormatContext *s)
501 {
502     struct ogg *ogg = s->priv_data;
503     int i;
504     int64_t size, end;
505
506     if (!s->pb->seekable)
507         return 0;
508
509 // already set
510     if (s->duration != AV_NOPTS_VALUE)
511         return 0;
512
513     size = avio_size(s->pb);
514     if (size < 0)
515         return 0;
516     end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
517
518     ogg_save(s);
519     avio_seek(s->pb, end, SEEK_SET);
520
521     while (!ogg_read_page(s, &i)) {
522         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
523             ogg->streams[i].codec) {
524             s->streams[i]->duration =
525                 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
526             if (s->streams[i]->start_time != AV_NOPTS_VALUE)
527                 s->streams[i]->duration -= s->streams[i]->start_time;
528         }
529     }
530
531     ogg_restore(s, 0);
532
533     return 0;
534 }
535
536 static int ogg_read_close(AVFormatContext *s)
537 {
538     struct ogg *ogg = s->priv_data;
539     int i;
540
541     for (i = 0; i < ogg->nstreams; i++) {
542         av_free(ogg->streams[i].buf);
543         if (ogg->streams[i].codec &&
544             ogg->streams[i].codec->cleanup) {
545             ogg->streams[i].codec->cleanup(s, i);
546         }
547         av_free(ogg->streams[i].private);
548     }
549     av_free(ogg->streams);
550     return 0;
551 }
552
553 static int ogg_read_header(AVFormatContext *s)
554 {
555     struct ogg *ogg = s->priv_data;
556     int ret, i;
557     ogg->curidx = -1;
558     //linear headers seek from start
559     ret = ogg_get_headers(s);
560     if (ret < 0) {
561         ogg_read_close(s);
562         return ret;
563     }
564
565     for (i = 0; i < ogg->nstreams; i++)
566         if (ogg->streams[i].header < 0)
567             ogg->streams[i].codec = NULL;
568
569     //linear granulepos seek from end
570     ogg_get_length(s);
571
572     //fill the extradata in the per codec callbacks
573     return 0;
574 }
575
576 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
577 {
578     struct ogg *ogg       = s->priv_data;
579     struct ogg_stream *os = ogg->streams + idx;
580     int64_t pts           = AV_NOPTS_VALUE;
581
582     if (dts)
583         *dts = AV_NOPTS_VALUE;
584
585     if (os->lastpts != AV_NOPTS_VALUE) {
586         pts         = os->lastpts;
587         os->lastpts = AV_NOPTS_VALUE;
588     }
589     if (os->lastdts != AV_NOPTS_VALUE) {
590         if (dts)
591             *dts = os->lastdts;
592         os->lastdts = AV_NOPTS_VALUE;
593     }
594     if (os->page_end) {
595         if (os->granule != -1LL) {
596             if (os->codec && os->codec->granule_is_start)
597                 pts = ogg_gptopts(s, idx, os->granule, dts);
598             else
599                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
600             os->granule = -1LL;
601         }
602     }
603     return pts;
604 }
605
606 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
607 {
608     struct ogg *ogg;
609     struct ogg_stream *os;
610     int idx = -1, ret;
611     int pstart, psize;
612     int64_t fpos, pts, dts;
613
614     //Get an ogg packet
615 retry:
616     do {
617         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
618         if (ret < 0)
619             return ret;
620     } while (idx < 0 || !s->streams[idx]);
621
622     ogg = s->priv_data;
623     os  = ogg->streams + idx;
624
625     // pflags might not be set until after this
626     pts = ogg_calc_pts(s, idx, &dts);
627
628     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
629         goto retry;
630     os->keyframe_seek = 0;
631
632     //Alloc a pkt
633     ret = av_new_packet(pkt, psize);
634     if (ret < 0)
635         return ret;
636     pkt->stream_index = idx;
637     memcpy(pkt->data, os->buf + pstart, psize);
638
639     pkt->pts      = pts;
640     pkt->dts      = dts;
641     pkt->flags    = os->pflags;
642     pkt->duration = os->pduration;
643     pkt->pos      = fpos;
644
645     return psize;
646 }
647
648 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
649                                   int64_t *pos_arg, int64_t pos_limit)
650 {
651     struct ogg *ogg = s->priv_data;
652     AVIOContext *bc = s->pb;
653     int64_t pts     = AV_NOPTS_VALUE;
654     int i           = -1;
655     avio_seek(bc, *pos_arg, SEEK_SET);
656     ogg_reset(ogg);
657
658     while (avio_tell(bc) < pos_limit &&
659            !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
660         if (i == stream_index) {
661             struct ogg_stream *os = ogg->streams + stream_index;
662             pts = ogg_calc_pts(s, i, NULL);
663             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
664                 pts = AV_NOPTS_VALUE;
665         }
666         if (pts != AV_NOPTS_VALUE)
667             break;
668     }
669     ogg_reset(ogg);
670     return pts;
671 }
672
673 static int ogg_read_seek(AVFormatContext *s, int stream_index,
674                          int64_t timestamp, int flags)
675 {
676     struct ogg *ogg       = s->priv_data;
677     struct ogg_stream *os = ogg->streams + stream_index;
678     int ret;
679
680     // Try seeking to a keyframe first. If this fails (very possible),
681     // av_seek_frame will fall back to ignoring keyframes
682     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
683         && !(flags & AVSEEK_FLAG_ANY))
684         os->keyframe_seek = 1;
685
686     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
687     os  = ogg->streams + stream_index;
688     if (ret < 0)
689         os->keyframe_seek = 0;
690     return ret;
691 }
692
693 static int ogg_probe(AVProbeData *p)
694 {
695     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
696         return AVPROBE_SCORE_MAX;
697     return 0;
698 }
699
700 AVInputFormat ff_ogg_demuxer = {
701     .name           = "ogg",
702     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
703     .priv_data_size = sizeof(struct ogg),
704     .read_probe     = ogg_probe,
705     .read_header    = ogg_read_header,
706     .read_packet    = ogg_read_packet,
707     .read_close     = ogg_read_close,
708     .read_seek      = ogg_read_seek,
709     .read_timestamp = ogg_read_timestamp,
710     .extensions     = "ogg",
711     .flags          = AVFMT_GENERIC_INDEX | AVFMT_NOBINSEARCH,
712 };