]> git.sesse.net Git - ffmpeg/blob - libavformat/oggdec.c
oggdec: verify page checksum
[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 #include <stdio.h>
32 #include "libavutil/avassert.h"
33 #include "libavutil/intreadwrite.h"
34 #include "avio_internal.h"
35 #include "oggdec.h"
36 #include "avformat.h"
37 #include "internal.h"
38 #include "vorbiscomment.h"
39
40 #define MAX_PAGE_SIZE 65307
41 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
42
43 static const struct ogg_codec * const ogg_codecs[] = {
44     &ff_skeleton_codec,
45     &ff_daala_codec,
46     &ff_dirac_codec,
47     &ff_speex_codec,
48     &ff_vorbis_codec,
49     &ff_theora_codec,
50     &ff_flac_codec,
51     &ff_celt_codec,
52     &ff_opus_codec,
53     &ff_vp8_codec,
54     &ff_old_dirac_codec,
55     &ff_old_flac_codec,
56     &ff_ogm_video_codec,
57     &ff_ogm_audio_codec,
58     &ff_ogm_text_codec,
59     &ff_ogm_old_codec,
60     NULL
61 };
62
63 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts);
64 static int ogg_new_stream(AVFormatContext *s, uint32_t serial);
65 static int ogg_restore(AVFormatContext *s);
66
67 static void free_stream(AVFormatContext *s, int i)
68 {
69     struct ogg *ogg = s->priv_data;
70     struct ogg_stream *stream = &ogg->streams[i];
71
72     av_freep(&stream->buf);
73     if (stream->codec &&
74         stream->codec->cleanup) {
75         stream->codec->cleanup(s, i);
76     }
77
78     av_freep(&stream->private);
79     av_freep(&stream->new_metadata);
80 }
81
82 //FIXME We could avoid some structure duplication
83 static int ogg_save(AVFormatContext *s)
84 {
85     struct ogg *ogg = s->priv_data;
86     struct ogg_state *ost =
87         av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
88     int i;
89     int ret = 0;
90
91     if (!ost)
92         return AVERROR(ENOMEM);
93
94     ost->pos      = avio_tell(s->pb);
95     ost->curidx   = ogg->curidx;
96     ost->next     = ogg->state;
97     ost->nstreams = ogg->nstreams;
98     memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
99
100     for (i = 0; i < ogg->nstreams; i++) {
101         struct ogg_stream *os = ogg->streams + i;
102         os->buf = av_mallocz(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
103         if (os->buf)
104             memcpy(os->buf, ost->streams[i].buf, os->bufpos);
105         else
106             ret = AVERROR(ENOMEM);
107         os->new_metadata      = NULL;
108         os->new_metadata_size = 0;
109     }
110
111     ogg->state = ost;
112
113     if (ret < 0)
114         ogg_restore(s);
115
116     return ret;
117 }
118
119 static int ogg_restore(AVFormatContext *s)
120 {
121     struct ogg *ogg = s->priv_data;
122     AVIOContext *bc = s->pb;
123     struct ogg_state *ost = ogg->state;
124     int i, err;
125
126     if (!ost)
127         return 0;
128
129     ogg->state = ost->next;
130
131         for (i = 0; i < ogg->nstreams; i++) {
132             struct ogg_stream *stream = &ogg->streams[i];
133             av_freep(&stream->buf);
134             av_freep(&stream->new_metadata);
135
136             if (i >= ost->nstreams || !ost->streams[i].private) {
137                 free_stream(s, i);
138             }
139         }
140
141         avio_seek(bc, ost->pos, SEEK_SET);
142         ogg->page_pos = -1;
143         ogg->curidx   = ost->curidx;
144         ogg->nstreams = ost->nstreams;
145         if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams,
146                                      sizeof(*ogg->streams))) < 0) {
147             ogg->nstreams = 0;
148             return err;
149         } else
150             memcpy(ogg->streams, ost->streams,
151                    ost->nstreams * sizeof(*ogg->streams));
152
153     av_free(ost);
154
155     return 0;
156 }
157
158 static int ogg_reset(AVFormatContext *s)
159 {
160     struct ogg *ogg = s->priv_data;
161     int i;
162     int64_t start_pos = avio_tell(s->pb);
163
164     for (i = 0; i < ogg->nstreams; i++) {
165         struct ogg_stream *os = ogg->streams + i;
166         os->bufpos     = 0;
167         os->pstart     = 0;
168         os->psize      = 0;
169         os->granule    = -1;
170         os->lastpts    = AV_NOPTS_VALUE;
171         os->lastdts    = AV_NOPTS_VALUE;
172         os->sync_pos   = -1;
173         os->page_pos   = 0;
174         os->nsegs      = 0;
175         os->segp       = 0;
176         os->incomplete = 0;
177         os->got_data = 0;
178         if (start_pos <= s->internal->data_offset) {
179             os->lastpts = 0;
180         }
181         os->end_trimming = 0;
182         av_freep(&os->new_metadata);
183         os->new_metadata_size = 0;
184     }
185
186     ogg->page_pos = -1;
187     ogg->curidx = -1;
188
189     return 0;
190 }
191
192 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
193 {
194     int i;
195
196     for (i = 0; ogg_codecs[i]; i++)
197         if (size >= ogg_codecs[i]->magicsize &&
198             !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
199             return ogg_codecs[i];
200
201     return NULL;
202 }
203
204 /**
205  * Replace the current stream with a new one. This is a typical webradio
206  * situation where a new audio stream spawn (identified with a new serial) and
207  * must replace the previous one (track switch).
208  */
209 static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int size)
210 {
211     struct ogg *ogg = s->priv_data;
212     struct ogg_stream *os;
213     const struct ogg_codec *codec;
214     int i = 0;
215
216     if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) {
217         uint8_t magic[8];
218         avio_seek(s->pb, -size, SEEK_CUR);
219         if (avio_read(s->pb, magic, sizeof(magic)) != sizeof(magic))
220             return AVERROR_INVALIDDATA;
221         avio_seek(s->pb, size - sizeof(magic), SEEK_CUR);
222         codec = ogg_find_codec(magic, sizeof(magic));
223         if (!codec) {
224             av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
225             return AVERROR_INVALIDDATA;
226         }
227         for (i = 0; i < ogg->nstreams; i++) {
228             if (ogg->streams[i].codec == codec)
229                 break;
230         }
231         if (i >= ogg->nstreams)
232             return ogg_new_stream(s, serial);
233     } else if (ogg->nstreams != 1) {
234         avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
235         return AVERROR_PATCHWELCOME;
236     }
237
238     os = &ogg->streams[i];
239
240     os->serial  = serial;
241     return i;
242
243 #if 0
244     buf     = os->buf;
245     bufsize = os->bufsize;
246     codec   = os->codec;
247
248     if (!ogg->state || ogg->state->streams[i].private != os->private)
249         av_freep(&ogg->streams[i].private);
250
251     /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
252      * also re-use the ogg_stream allocated buffer */
253     memset(os, 0, sizeof(*os));
254     os->serial  = serial;
255     os->bufsize = bufsize;
256     os->buf     = buf;
257     os->header  = -1;
258     os->codec   = codec;
259
260     return i;
261 #endif
262 }
263
264 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
265 {
266     struct ogg *ogg = s->priv_data;
267     int idx         = ogg->nstreams;
268     AVStream *st;
269     struct ogg_stream *os;
270     size_t size;
271
272     if (ogg->state) {
273         av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
274                "in between Ogg context save/restore operations.\n");
275         return AVERROR_BUG;
276     }
277
278     /* Allocate and init a new Ogg Stream */
279     if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
280         !(os = av_realloc(ogg->streams, size)))
281         return AVERROR(ENOMEM);
282     ogg->streams = os;
283     os           = ogg->streams + idx;
284     memset(os, 0, sizeof(*os));
285     os->serial        = serial;
286     os->bufsize       = DECODER_BUFFER_SIZE;
287     os->buf           = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
288     os->header        = -1;
289     os->start_granule = OGG_NOGRANULE_VALUE;
290     if (!os->buf)
291         return AVERROR(ENOMEM);
292
293     /* Create the associated AVStream */
294     st = avformat_new_stream(s, NULL);
295     if (!st) {
296         av_freep(&os->buf);
297         return AVERROR(ENOMEM);
298     }
299     st->id = idx;
300     avpriv_set_pts_info(st, 64, 1, 1000000);
301
302     ogg->nstreams++;
303     return idx;
304 }
305
306 static int data_packets_seen(const struct ogg *ogg)
307 {
308     int i;
309
310     for (i = 0; i < ogg->nstreams; i++)
311         if (ogg->streams[i].got_data)
312             return 1;
313     return 0;
314 }
315
316 static int ogg_read_page(AVFormatContext *s, int *sid)
317 {
318     AVIOContext *bc = s->pb;
319     struct ogg *ogg = s->priv_data;
320     struct ogg_stream *os;
321     int ret, i = 0;
322     int flags, nsegs;
323     uint64_t gp;
324     uint32_t serial;
325     uint32_t crc, crc_tmp;
326     int size = 0, idx;
327     int64_t version, page_pos;
328     uint8_t sync[4];
329     uint8_t segments[255];
330     uint8_t *readout_buf;
331     int sp = 0;
332
333     ret = avio_read(bc, sync, 4);
334     if (ret < 4)
335         return ret < 0 ? ret : AVERROR_EOF;
336
337     do {
338         int c;
339
340         if (sync[sp & 3] == 'O' &&
341             sync[(sp + 1) & 3] == 'g' &&
342             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
343             break;
344
345         if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
346             memset(sync, 0, 4);
347             avio_seek(bc, ogg->page_pos+4, SEEK_SET);
348             ogg->page_pos = -1;
349         }
350
351         c = avio_r8(bc);
352
353         if (avio_feof(bc))
354             return AVERROR_EOF;
355
356         sync[sp++ & 3] = c;
357     } while (i++ < MAX_PAGE_SIZE);
358
359     if (i >= MAX_PAGE_SIZE) {
360         av_log(s, AV_LOG_INFO, "cannot find sync word\n");
361         return AVERROR_INVALIDDATA;
362     }
363
364     /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */
365     ffio_init_checksum(bc, ff_crc04C11DB7_update, 0x4fa9b05f);
366
367     version = avio_r8(bc);
368     flags   = avio_r8(bc);
369     gp      = avio_rl64(bc);
370     serial  = avio_rl32(bc);
371     avio_skip(bc, 4); /* seq */
372
373     crc_tmp = ffio_get_checksum(bc);
374     crc     = avio_rb32(bc);
375     crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4);
376     ffio_init_checksum(bc, ff_crc04C11DB7_update, crc_tmp);
377
378     nsegs    = avio_r8(bc);
379     page_pos = avio_tell(bc) - 27;
380
381     ret = avio_read(bc, segments, nsegs);
382     if (ret < nsegs)
383         return ret < 0 ? ret : AVERROR_EOF;
384
385     for (i = 0; i < nsegs; i++)
386         size += segments[i];
387
388     idx = ogg_find_stream(ogg, serial);
389     if (idx >= 0) {
390         os = ogg->streams + idx;
391
392         /* Even if invalid guarantee there's enough memory to read the page */
393         if (os->bufsize - os->bufpos < size) {
394             uint8_t *nb = av_realloc(os->buf, 2*os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
395             if (!nb)
396                 return AVERROR(ENOMEM);
397             os->buf = nb;
398             os->bufsize *= 2;
399         }
400
401         readout_buf = os->buf + os->bufpos;
402     } else {
403         readout_buf = av_malloc(size);
404     }
405
406     ret = avio_read(bc, readout_buf, size);
407     if (ret < size) {
408         if (idx < 0)
409             av_free(readout_buf);
410         return ret < 0 ? ret : AVERROR_EOF;
411     }
412
413     if (crc ^ ffio_get_checksum(bc)) {
414         av_log(s, AV_LOG_ERROR, "CRC mismatch!\n");
415         if (idx < 0)
416             av_free(readout_buf);
417         avio_seek(bc, -size, SEEK_CUR);
418         return 0;
419     }
420
421     /* Since we're almost sure its a valid packet, checking the version after
422      * the checksum lets the demuxer be more tolerant */
423     if (version) {
424         av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n");
425         if (idx < 0)
426             av_free(readout_buf);
427         avio_seek(bc, -size, SEEK_CUR);
428         return 0;
429     }
430
431     /* CRC is correct so we can be 99% sure there's an actual change here */
432     if (idx < 0) {
433         if (data_packets_seen(ogg))
434             idx = ogg_replace_stream(s, serial, size);
435         else
436             idx = ogg_new_stream(s, serial);
437
438         if (idx < 0) {
439             av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
440             av_free(readout_buf);
441             return idx;
442         }
443
444         os = ogg->streams + idx;
445
446         memcpy(os->buf + os->bufpos, readout_buf, size);
447         av_free(readout_buf);
448     }
449
450     ogg->page_pos = page_pos;
451     os->page_pos  = page_pos;
452     os->nsegs     = nsegs;
453     os->segp      = 0;
454     os->got_data  = !(flags & OGG_FLAG_BOS);
455     os->bufpos   += size;
456     os->granule   = gp;
457     os->flags     = flags;
458     memcpy(os->segments, segments, nsegs);
459     memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
460
461     if (flags & OGG_FLAG_CONT || os->incomplete) {
462         if (!os->psize) {
463             // If this is the very first segment we started
464             // playback in the middle of a continuation packet.
465             // Discard it since we missed the start of it.
466             while (os->segp < os->nsegs) {
467                 int seg = os->segments[os->segp++];
468                 os->pstart += seg;
469                 if (seg < 255)
470                     break;
471             }
472             os->sync_pos = os->page_pos;
473         }
474     } else {
475         os->psize    = 0;
476         os->sync_pos = os->page_pos;
477     }
478
479     /* This function is always called with sid != NULL */
480     *sid = idx;
481
482     return 0;
483 }
484
485 /**
486  * @brief find the next Ogg packet
487  * @param *sid is set to the stream for the packet or -1 if there is
488  *             no matching stream, in that case assume all other return
489  *             values to be uninitialized.
490  * @return negative value on error or EOF.
491  */
492 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
493                       int64_t *fpos)
494 {
495     struct ogg *ogg = s->priv_data;
496     int idx, i, ret;
497     struct ogg_stream *os;
498     int complete = 0;
499     int segp     = 0, psize = 0;
500
501     av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
502     if (sid)
503         *sid = -1;
504
505     do {
506         idx = ogg->curidx;
507
508         while (idx < 0) {
509             ret = ogg_read_page(s, &idx);
510             if (ret < 0)
511                 return ret;
512         }
513
514         os = ogg->streams + idx;
515
516         av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
517                 idx, os->pstart, os->psize, os->segp, os->nsegs);
518
519         if (!os->codec) {
520             if (os->header < 0) {
521                 os->codec = ogg_find_codec(os->buf, os->bufpos);
522                 if (!os->codec) {
523                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
524                     os->header = 0;
525                     return 0;
526                 }
527             } else {
528                 return 0;
529             }
530         }
531
532         segp  = os->segp;
533         psize = os->psize;
534
535         while (os->segp < os->nsegs) {
536             int ss = os->segments[os->segp++];
537             os->psize += ss;
538             if (ss < 255) {
539                 complete = 1;
540                 break;
541             }
542         }
543
544         if (!complete && os->segp == os->nsegs) {
545             ogg->curidx    = -1;
546             // Do not set incomplete for empty packets.
547             // Together with the code in ogg_read_page
548             // that discards all continuation of empty packets
549             // we would get an infinite loop.
550             os->incomplete = !!os->psize;
551         }
552     } while (!complete);
553
554
555     if (os->granule == -1)
556         av_log(s, AV_LOG_WARNING,
557                "Page at %"PRId64" is missing granule\n",
558                os->page_pos);
559
560     ogg->curidx    = idx;
561     os->incomplete = 0;
562
563     if (os->header) {
564         if ((ret = os->codec->header(s, idx)) < 0) {
565             av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret));
566             return ret;
567         }
568         os->header = ret;
569         if (!os->header) {
570             os->segp  = segp;
571             os->psize = psize;
572
573             // We have reached the first non-header packet in this stream.
574             // Unfortunately more header packets may still follow for others,
575             // but if we continue with header parsing we may lose data packets.
576             ogg->headers = 1;
577
578             // Update the header state for all streams and
579             // compute the data_offset.
580             if (!s->internal->data_offset)
581                 s->internal->data_offset = os->sync_pos;
582
583             for (i = 0; i < ogg->nstreams; i++) {
584                 struct ogg_stream *cur_os = ogg->streams + i;
585
586                 // if we have a partial non-header packet, its start is
587                 // obviously at or after the data start
588                 if (cur_os->incomplete)
589                     s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
590             }
591         } else {
592             os->nb_header++;
593             os->pstart += os->psize;
594             os->psize   = 0;
595         }
596     } else {
597         os->pflags    = 0;
598         os->pduration = 0;
599         if (os->codec && os->codec->packet) {
600             if ((ret = os->codec->packet(s, idx)) < 0) {
601                 av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret));
602                 return ret;
603             }
604         }
605         if (sid)
606             *sid = idx;
607         if (dstart)
608             *dstart = os->pstart;
609         if (dsize)
610             *dsize = os->psize;
611         if (fpos)
612             *fpos = os->sync_pos;
613         os->pstart  += os->psize;
614         os->psize    = 0;
615         if(os->pstart == os->bufpos)
616             os->bufpos = os->pstart = 0;
617         os->sync_pos = os->page_pos;
618     }
619
620     // determine whether there are more complete packets in this page
621     // if not, the page's granule will apply to this packet
622     os->page_end = 1;
623     for (i = os->segp; i < os->nsegs; i++)
624         if (os->segments[i] < 255) {
625             os->page_end = 0;
626             break;
627         }
628
629     if (os->segp == os->nsegs)
630         ogg->curidx = -1;
631
632     return 0;
633 }
634
635 static int ogg_get_length(AVFormatContext *s)
636 {
637     struct ogg *ogg = s->priv_data;
638     int i, ret;
639     int64_t size, end;
640     int streams_left=0;
641
642     if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
643         return 0;
644
645 // already set
646     if (s->duration != AV_NOPTS_VALUE)
647         return 0;
648
649     size = avio_size(s->pb);
650     if (size < 0)
651         return 0;
652     end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
653
654     ret = ogg_save(s);
655     if (ret < 0)
656         return ret;
657     avio_seek(s->pb, end, SEEK_SET);
658     ogg->page_pos = -1;
659
660     while (!ogg_read_page(s, &i)) {
661         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
662             ogg->streams[i].codec) {
663             s->streams[i]->duration =
664                 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
665             if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
666                 s->streams[i]->duration -= s->streams[i]->start_time;
667                 streams_left-= (ogg->streams[i].got_start==-1);
668                 ogg->streams[i].got_start= 1;
669             } else if(!ogg->streams[i].got_start) {
670                 ogg->streams[i].got_start= -1;
671                 streams_left++;
672             }
673         }
674     }
675
676     ogg_restore(s);
677
678     ret = ogg_save(s);
679     if (ret < 0)
680         return ret;
681
682     avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
683     ogg_reset(s);
684     while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
685         int64_t pts;
686         if (i < 0) continue;
687         pts = ogg_calc_pts(s, i, NULL);
688         if (s->streams[i]->duration == AV_NOPTS_VALUE)
689             continue;
690         if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
691             s->streams[i]->duration -= pts;
692             ogg->streams[i].got_start= 1;
693             streams_left--;
694         }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
695             ogg->streams[i].got_start= 1;
696             streams_left--;
697         }
698     }
699     ogg_restore (s);
700
701     return 0;
702 }
703
704 static int ogg_read_close(AVFormatContext *s)
705 {
706     struct ogg *ogg = s->priv_data;
707     int i;
708
709     for (i = 0; i < ogg->nstreams; i++) {
710         free_stream(s, i);
711     }
712
713     ogg->nstreams = 0;
714
715     av_freep(&ogg->streams);
716     return 0;
717 }
718
719 static int ogg_read_header(AVFormatContext *s)
720 {
721     struct ogg *ogg = s->priv_data;
722     int ret, i;
723
724     ogg->curidx = -1;
725
726     //linear headers seek from start
727     do {
728         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
729         if (ret < 0) {
730             ogg_read_close(s);
731             return ret;
732         }
733     } while (!ogg->headers);
734     av_log(s, AV_LOG_TRACE, "found headers\n");
735
736     for (i = 0; i < ogg->nstreams; i++) {
737         struct ogg_stream *os = ogg->streams + i;
738
739         if (ogg->streams[i].header < 0) {
740             av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
741             ogg->streams[i].codec = NULL;
742             av_freep(&ogg->streams[i].private);
743         } else if (os->codec && os->nb_header < os->codec->nb_header) {
744             av_log(s, AV_LOG_WARNING,
745                    "Headers mismatch for stream %d: "
746                    "expected %d received %d.\n",
747                    i, os->codec->nb_header, os->nb_header);
748             if (s->error_recognition & AV_EF_EXPLODE) {
749                 ogg_read_close(s);
750                 return AVERROR_INVALIDDATA;
751             }
752         }
753         if (os->start_granule != OGG_NOGRANULE_VALUE)
754             os->lastpts = s->streams[i]->start_time =
755                 ogg_gptopts(s, i, os->start_granule, NULL);
756     }
757
758     //linear granulepos seek from end
759     ret = ogg_get_length(s);
760     if (ret < 0) {
761         ogg_read_close(s);
762         return ret;
763     }
764
765     return 0;
766 }
767
768 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
769 {
770     struct ogg *ogg       = s->priv_data;
771     struct ogg_stream *os = ogg->streams + idx;
772     int64_t pts           = AV_NOPTS_VALUE;
773
774     if (dts)
775         *dts = AV_NOPTS_VALUE;
776
777     if (os->lastpts != AV_NOPTS_VALUE) {
778         pts         = os->lastpts;
779         os->lastpts = AV_NOPTS_VALUE;
780     }
781     if (os->lastdts != AV_NOPTS_VALUE) {
782         if (dts)
783             *dts = os->lastdts;
784         os->lastdts = AV_NOPTS_VALUE;
785     }
786     if (os->page_end) {
787         if (os->granule != -1LL) {
788             if (os->codec && os->codec->granule_is_start)
789                 pts = ogg_gptopts(s, idx, os->granule, dts);
790             else
791                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
792             os->granule = -1LL;
793         }
794     }
795     return pts;
796 }
797
798 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
799 {
800     struct ogg *ogg = s->priv_data;
801     struct ogg_stream *os = ogg->streams + idx;
802     int invalid = 0;
803     if (psize) {
804         switch (s->streams[idx]->codecpar->codec_id) {
805         case AV_CODEC_ID_THEORA:
806             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
807         break;
808         case AV_CODEC_ID_VP8:
809             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
810         }
811         if (invalid) {
812             os->pflags ^= AV_PKT_FLAG_KEY;
813             av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
814                    (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
815         }
816     }
817 }
818
819 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
820 {
821     struct ogg *ogg;
822     struct ogg_stream *os;
823     int idx, ret;
824     int pstart, psize;
825     int64_t fpos, pts, dts;
826
827     if (s->io_repositioned) {
828         ogg_reset(s);
829         s->io_repositioned = 0;
830     }
831
832     //Get an ogg packet
833 retry:
834     do {
835         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
836         if (ret < 0)
837             return ret;
838     } while (idx < 0 || !s->streams[idx]);
839
840     ogg = s->priv_data;
841     os  = ogg->streams + idx;
842
843     // pflags might not be set until after this
844     pts = ogg_calc_pts(s, idx, &dts);
845     ogg_validate_keyframe(s, idx, pstart, psize);
846
847     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
848         goto retry;
849     os->keyframe_seek = 0;
850
851     //Alloc a pkt
852     ret = av_new_packet(pkt, psize);
853     if (ret < 0)
854         return ret;
855     pkt->stream_index = idx;
856     memcpy(pkt->data, os->buf + pstart, psize);
857
858     pkt->pts      = pts;
859     pkt->dts      = dts;
860     pkt->flags    = os->pflags;
861     pkt->duration = os->pduration;
862     pkt->pos      = fpos;
863
864     if (os->end_trimming) {
865         uint8_t *side_data = av_packet_new_side_data(pkt,
866                                                      AV_PKT_DATA_SKIP_SAMPLES,
867                                                      10);
868         if(!side_data)
869             return AVERROR(ENOMEM);
870         AV_WL32(side_data + 4, os->end_trimming);
871         os->end_trimming = 0;
872     }
873
874     if (os->new_metadata) {
875         uint8_t *side_data = av_packet_new_side_data(pkt,
876                                                      AV_PKT_DATA_METADATA_UPDATE,
877                                                      os->new_metadata_size);
878         if(!side_data)
879             return AVERROR(ENOMEM);
880
881         memcpy(side_data, os->new_metadata, os->new_metadata_size);
882         av_freep(&os->new_metadata);
883         os->new_metadata_size = 0;
884     }
885
886     return psize;
887 }
888
889 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
890                                   int64_t *pos_arg, int64_t pos_limit)
891 {
892     struct ogg *ogg = s->priv_data;
893     AVIOContext *bc = s->pb;
894     int64_t pts     = AV_NOPTS_VALUE;
895     int64_t keypos  = -1;
896     int i;
897     int pstart, psize;
898     avio_seek(bc, *pos_arg, SEEK_SET);
899     ogg_reset(s);
900
901     while (   avio_tell(bc) <= pos_limit
902            && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
903         if (i == stream_index) {
904             struct ogg_stream *os = ogg->streams + stream_index;
905             // Do not trust the last timestamps of an ogm video
906             if (    (os->flags & OGG_FLAG_EOS)
907                 && !(os->flags & OGG_FLAG_BOS)
908                 && os->codec == &ff_ogm_video_codec)
909                 continue;
910             pts = ogg_calc_pts(s, i, NULL);
911             ogg_validate_keyframe(s, i, pstart, psize);
912             if (os->pflags & AV_PKT_FLAG_KEY) {
913                 keypos = *pos_arg;
914             } else if (os->keyframe_seek) {
915                 // if we had a previous keyframe but no pts for it,
916                 // return that keyframe with this pts value.
917                 if (keypos >= 0)
918                     *pos_arg = keypos;
919                 else
920                     pts = AV_NOPTS_VALUE;
921             }
922         }
923         if (pts != AV_NOPTS_VALUE)
924             break;
925     }
926     ogg_reset(s);
927     return pts;
928 }
929
930 static int ogg_read_seek(AVFormatContext *s, int stream_index,
931                          int64_t timestamp, int flags)
932 {
933     struct ogg *ogg       = s->priv_data;
934     struct ogg_stream *os = ogg->streams + stream_index;
935     int ret;
936
937     av_assert0(stream_index < ogg->nstreams);
938     // Ensure everything is reset even when seeking via
939     // the generated index.
940     ogg_reset(s);
941
942     // Try seeking to a keyframe first. If this fails (very possible),
943     // av_seek_frame will fall back to ignoring keyframes
944     if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
945         && !(flags & AVSEEK_FLAG_ANY))
946         os->keyframe_seek = 1;
947
948     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
949     ogg_reset(s);
950     os  = ogg->streams + stream_index;
951     if (ret < 0)
952         os->keyframe_seek = 0;
953     return ret;
954 }
955
956 static int ogg_probe(const AVProbeData *p)
957 {
958     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
959         return AVPROBE_SCORE_MAX;
960     return 0;
961 }
962
963 AVInputFormat ff_ogg_demuxer = {
964     .name           = "ogg",
965     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
966     .priv_data_size = sizeof(struct ogg),
967     .read_probe     = ogg_probe,
968     .read_header    = ogg_read_header,
969     .read_packet    = ogg_read_packet,
970     .read_close     = ogg_read_close,
971     .read_seek      = ogg_read_seek,
972     .read_timestamp = ogg_read_timestamp,
973     .extensions     = "ogg",
974     .flags          = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
975 };