]> git.sesse.net Git - ffmpeg/blob - libavformat/oggdec.c
avformat/oggdec: Factor buffer reallocation out
[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->start_trimming = 0;
182         os->end_trimming = 0;
183         av_freep(&os->new_metadata);
184         os->new_metadata_size = 0;
185     }
186
187     ogg->page_pos = -1;
188     ogg->curidx = -1;
189
190     return 0;
191 }
192
193 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
194 {
195     int i;
196
197     for (i = 0; ogg_codecs[i]; i++)
198         if (size >= ogg_codecs[i]->magicsize &&
199             !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
200             return ogg_codecs[i];
201
202     return NULL;
203 }
204
205 /**
206  * Replace the current stream with a new one. This is a typical webradio
207  * situation where a new audio stream spawn (identified with a new serial) and
208  * must replace the previous one (track switch).
209  */
210 static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic,
211                               int probing)
212 {
213     struct ogg *ogg = s->priv_data;
214     struct ogg_stream *os;
215     const struct ogg_codec *codec;
216     int i = 0;
217
218     if (ogg->nstreams != 1) {
219         avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
220         return AVERROR_PATCHWELCOME;
221     }
222
223     /* Check for codecs */
224     codec = ogg_find_codec(magic, 8);
225     if (!codec && !probing) {
226         av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
227         return AVERROR_INVALIDDATA;
228     }
229
230     /* We only have a single stream anyway, so if there's a new stream with
231      * a different codec just replace it */
232     os = &ogg->streams[0];
233     os->serial  = serial;
234     os->codec   = codec;
235     os->serial  = serial;
236     os->lastpts = 0;
237     os->lastdts = 0;
238     os->start_trimming = 0;
239     os->end_trimming = 0;
240
241     /* Chained files have extradata as a new packet */
242     if (codec == &ff_opus_codec)
243         os->header = -1;
244
245     return i;
246 }
247
248 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
249 {
250     struct ogg *ogg = s->priv_data;
251     int idx         = ogg->nstreams;
252     AVStream *st;
253     struct ogg_stream *os;
254     size_t size;
255
256     if (ogg->state) {
257         av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
258                "in between Ogg context save/restore operations.\n");
259         return AVERROR_BUG;
260     }
261
262     /* Allocate and init a new Ogg Stream */
263     if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
264         !(os = av_realloc(ogg->streams, size)))
265         return AVERROR(ENOMEM);
266     ogg->streams = os;
267     os           = ogg->streams + idx;
268     memset(os, 0, sizeof(*os));
269     os->serial        = serial;
270     os->bufsize       = DECODER_BUFFER_SIZE;
271     os->buf           = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
272     os->header        = -1;
273     os->start_granule = OGG_NOGRANULE_VALUE;
274     if (!os->buf)
275         return AVERROR(ENOMEM);
276
277     /* Create the associated AVStream */
278     st = avformat_new_stream(s, NULL);
279     if (!st) {
280         av_freep(&os->buf);
281         return AVERROR(ENOMEM);
282     }
283     st->id = idx;
284     avpriv_set_pts_info(st, 64, 1, 1000000);
285
286     ogg->nstreams++;
287     return idx;
288 }
289
290 static int data_packets_seen(const struct ogg *ogg)
291 {
292     int i;
293
294     for (i = 0; i < ogg->nstreams; i++)
295         if (ogg->streams[i].got_data)
296             return 1;
297     return 0;
298 }
299
300 static int buf_realloc(struct ogg_stream *os, int size)
301 {
302     /* Even if invalid guarantee there's enough memory to read the page */
303     if (os->bufsize - os->bufpos < size) {
304         uint8_t *nb = av_realloc(os->buf, 2*os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
305         if (!nb)
306             return AVERROR(ENOMEM);
307         os->buf = nb;
308         os->bufsize *= 2;
309     }
310
311     return 0;
312 }
313
314 static int ogg_read_page(AVFormatContext *s, int *sid, int probing)
315 {
316     AVIOContext *bc = s->pb;
317     struct ogg *ogg = s->priv_data;
318     struct ogg_stream *os;
319     int ret, i = 0;
320     int flags, nsegs;
321     uint64_t gp;
322     uint32_t serial;
323     uint32_t crc, crc_tmp;
324     int size = 0, idx;
325     int64_t version, page_pos;
326     int64_t start_pos;
327     uint8_t sync[4];
328     uint8_t segments[255];
329     uint8_t *readout_buf;
330     int sp = 0;
331
332     ret = avio_read(bc, sync, 4);
333     if (ret < 4)
334         return ret < 0 ? ret : AVERROR_EOF;
335
336     do {
337         int c;
338
339         if (sync[sp & 3] == 'O' &&
340             sync[(sp + 1) & 3] == 'g' &&
341             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
342             break;
343
344         if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
345             memset(sync, 0, 4);
346             avio_seek(bc, ogg->page_pos+4, SEEK_SET);
347             ogg->page_pos = -1;
348         }
349
350         c = avio_r8(bc);
351
352         if (avio_feof(bc))
353             return AVERROR_EOF;
354
355         sync[sp++ & 3] = c;
356     } while (i++ < MAX_PAGE_SIZE);
357
358     if (i >= MAX_PAGE_SIZE) {
359         av_log(s, AV_LOG_INFO, "cannot find sync word\n");
360         return AVERROR_INVALIDDATA;
361     }
362
363     /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */
364     ffio_init_checksum(bc, ff_crc04C11DB7_update, 0x4fa9b05f);
365
366     /* To rewind if checksum is bad/check magic on switches - this is the max packet size */
367     ffio_ensure_seekback(bc, MAX_PAGE_SIZE);
368     start_pos = avio_tell(bc);
369
370     version = avio_r8(bc);
371     flags   = avio_r8(bc);
372     gp      = avio_rl64(bc);
373     serial  = avio_rl32(bc);
374     avio_skip(bc, 4); /* seq */
375
376     crc_tmp = ffio_get_checksum(bc);
377     crc     = avio_rb32(bc);
378     crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4);
379     ffio_init_checksum(bc, ff_crc04C11DB7_update, crc_tmp);
380
381     nsegs    = avio_r8(bc);
382     page_pos = avio_tell(bc) - 27;
383
384     ret = avio_read(bc, segments, nsegs);
385     if (ret < nsegs)
386         return ret < 0 ? ret : AVERROR_EOF;
387
388     for (i = 0; i < nsegs; i++)
389         size += segments[i];
390
391     idx = ogg_find_stream(ogg, serial);
392     if (idx >= 0) {
393         os = ogg->streams + idx;
394
395         ret = buf_realloc(os, size);
396         if (ret < 0)
397             return ret;
398
399         readout_buf = os->buf + os->bufpos;
400     } else {
401         readout_buf = av_malloc(size);
402     }
403
404     ret = avio_read(bc, readout_buf, size);
405     if (ret < size) {
406         if (idx < 0)
407             av_free(readout_buf);
408         return ret < 0 ? ret : AVERROR_EOF;
409     }
410
411     if (crc ^ ffio_get_checksum(bc)) {
412         av_log(s, AV_LOG_ERROR, "CRC mismatch!\n");
413         if (idx < 0)
414             av_free(readout_buf);
415         avio_seek(bc, start_pos, SEEK_SET);
416         return 0;
417     }
418
419     /* Since we're almost sure its a valid packet, checking the version after
420      * the checksum lets the demuxer be more tolerant */
421     if (version) {
422         av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n");
423         if (idx < 0)
424             av_free(readout_buf);
425         avio_seek(bc, start_pos, SEEK_SET);
426         return 0;
427     }
428
429     /* CRC is correct so we can be 99% sure there's an actual change here */
430     if (idx < 0) {
431         if (data_packets_seen(ogg))
432             idx = ogg_replace_stream(s, serial, readout_buf, probing);
433         else
434             idx = ogg_new_stream(s, serial);
435
436         if (idx < 0) {
437             av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
438             av_free(readout_buf);
439             return idx;
440         }
441
442         os = ogg->streams + idx;
443
444         memcpy(os->buf + os->bufpos, readout_buf, size);
445         av_free(readout_buf);
446     }
447
448     ogg->page_pos = page_pos;
449     os->page_pos  = page_pos;
450     os->nsegs     = nsegs;
451     os->segp      = 0;
452     os->got_data  = !(flags & OGG_FLAG_BOS);
453     os->bufpos   += size;
454     os->granule   = gp;
455     os->flags     = flags;
456     memcpy(os->segments, segments, nsegs);
457     memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
458
459     if (flags & OGG_FLAG_CONT || os->incomplete) {
460         if (!os->psize) {
461             // If this is the very first segment we started
462             // playback in the middle of a continuation packet.
463             // Discard it since we missed the start of it.
464             while (os->segp < os->nsegs) {
465                 int seg = os->segments[os->segp++];
466                 os->pstart += seg;
467                 if (seg < 255)
468                     break;
469             }
470             os->sync_pos = os->page_pos;
471         }
472     } else {
473         os->psize    = 0;
474         os->sync_pos = os->page_pos;
475     }
476
477     /* This function is always called with sid != NULL */
478     *sid = idx;
479
480     return 0;
481 }
482
483 /**
484  * @brief find the next Ogg packet
485  * @param *sid is set to the stream for the packet or -1 if there is
486  *             no matching stream, in that case assume all other return
487  *             values to be uninitialized.
488  * @return negative value on error or EOF.
489  */
490 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
491                       int64_t *fpos)
492 {
493     struct ogg *ogg = s->priv_data;
494     int idx, i, ret;
495     struct ogg_stream *os;
496     int complete = 0;
497     int segp     = 0, psize = 0;
498
499     av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
500     if (sid)
501         *sid = -1;
502
503     do {
504         idx = ogg->curidx;
505
506         while (idx < 0) {
507             ret = ogg_read_page(s, &idx, 0);
508             if (ret < 0)
509                 return ret;
510         }
511
512         os = ogg->streams + idx;
513
514         av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
515                 idx, os->pstart, os->psize, os->segp, os->nsegs);
516
517         if (!os->codec) {
518             if (os->header < 0) {
519                 os->codec = ogg_find_codec(os->buf, os->bufpos);
520                 if (!os->codec) {
521                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
522                     os->header = 0;
523                     return 0;
524                 }
525             } else {
526                 return 0;
527             }
528         }
529
530         segp  = os->segp;
531         psize = os->psize;
532
533         while (os->segp < os->nsegs) {
534             int ss = os->segments[os->segp++];
535             os->psize += ss;
536             if (ss < 255) {
537                 complete = 1;
538                 break;
539             }
540         }
541
542         if (!complete && os->segp == os->nsegs) {
543             ogg->curidx    = -1;
544             // Do not set incomplete for empty packets.
545             // Together with the code in ogg_read_page
546             // that discards all continuation of empty packets
547             // we would get an infinite loop.
548             os->incomplete = !!os->psize;
549         }
550     } while (!complete);
551
552
553     if (os->granule == -1)
554         av_log(s, AV_LOG_WARNING,
555                "Page at %"PRId64" is missing granule\n",
556                os->page_pos);
557
558     ogg->curidx    = idx;
559     os->incomplete = 0;
560
561     if (os->header) {
562         if ((ret = os->codec->header(s, idx)) < 0) {
563             av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret));
564             return ret;
565         }
566         os->header = ret;
567         if (!os->header) {
568             os->segp  = segp;
569             os->psize = psize;
570
571             // We have reached the first non-header packet in this stream.
572             // Unfortunately more header packets may still follow for others,
573             // but if we continue with header parsing we may lose data packets.
574             ogg->headers = 1;
575
576             // Update the header state for all streams and
577             // compute the data_offset.
578             if (!s->internal->data_offset)
579                 s->internal->data_offset = os->sync_pos;
580
581             for (i = 0; i < ogg->nstreams; i++) {
582                 struct ogg_stream *cur_os = ogg->streams + i;
583
584                 // if we have a partial non-header packet, its start is
585                 // obviously at or after the data start
586                 if (cur_os->incomplete)
587                     s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
588             }
589         } else {
590             os->nb_header++;
591             os->pstart += os->psize;
592             os->psize   = 0;
593         }
594     } else {
595         os->pflags    = 0;
596         os->pduration = 0;
597         if (os->codec && os->codec->packet) {
598             if ((ret = os->codec->packet(s, idx)) < 0) {
599                 av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret));
600                 return ret;
601             }
602         }
603         if (sid)
604             *sid = idx;
605         if (dstart)
606             *dstart = os->pstart;
607         if (dsize)
608             *dsize = os->psize;
609         if (fpos)
610             *fpos = os->sync_pos;
611         os->pstart  += os->psize;
612         os->psize    = 0;
613         if(os->pstart == os->bufpos)
614             os->bufpos = os->pstart = 0;
615         os->sync_pos = os->page_pos;
616     }
617
618     // determine whether there are more complete packets in this page
619     // if not, the page's granule will apply to this packet
620     os->page_end = 1;
621     for (i = os->segp; i < os->nsegs; i++)
622         if (os->segments[i] < 255) {
623             os->page_end = 0;
624             break;
625         }
626
627     if (os->segp == os->nsegs)
628         ogg->curidx = -1;
629
630     return 0;
631 }
632
633 static int ogg_get_length(AVFormatContext *s)
634 {
635     struct ogg *ogg = s->priv_data;
636     int i, ret;
637     int64_t size, end;
638     int streams_left=0;
639
640     if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
641         return 0;
642
643 // already set
644     if (s->duration != AV_NOPTS_VALUE)
645         return 0;
646
647     size = avio_size(s->pb);
648     if (size < 0)
649         return 0;
650     end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
651
652     ret = ogg_save(s);
653     if (ret < 0)
654         return ret;
655     avio_seek(s->pb, end, SEEK_SET);
656     ogg->page_pos = -1;
657
658     while (!ogg_read_page(s, &i, 1)) {
659         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
660             ogg->streams[i].codec) {
661             s->streams[i]->duration =
662                 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
663             if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
664                 s->streams[i]->duration -= s->streams[i]->start_time;
665                 streams_left-= (ogg->streams[i].got_start==-1);
666                 ogg->streams[i].got_start= 1;
667             } else if(!ogg->streams[i].got_start) {
668                 ogg->streams[i].got_start= -1;
669                 streams_left++;
670             }
671         }
672     }
673
674     ogg_restore(s);
675
676     ret = ogg_save(s);
677     if (ret < 0)
678         return ret;
679
680     avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
681     ogg_reset(s);
682     while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
683         int64_t pts;
684         if (i < 0) continue;
685         pts = ogg_calc_pts(s, i, NULL);
686         if (s->streams[i]->duration == AV_NOPTS_VALUE)
687             continue;
688         if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
689             s->streams[i]->duration -= pts;
690             ogg->streams[i].got_start= 1;
691             streams_left--;
692         }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
693             ogg->streams[i].got_start= 1;
694             streams_left--;
695         }
696     }
697     ogg_restore (s);
698
699     return 0;
700 }
701
702 static int ogg_read_close(AVFormatContext *s)
703 {
704     struct ogg *ogg = s->priv_data;
705     int i;
706
707     for (i = 0; i < ogg->nstreams; i++) {
708         free_stream(s, i);
709     }
710
711     ogg->nstreams = 0;
712
713     av_freep(&ogg->streams);
714     return 0;
715 }
716
717 static int ogg_read_header(AVFormatContext *s)
718 {
719     struct ogg *ogg = s->priv_data;
720     int ret, i;
721
722     ogg->curidx = -1;
723
724     //linear headers seek from start
725     do {
726         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
727         if (ret < 0) {
728             ogg_read_close(s);
729             return ret;
730         }
731     } while (!ogg->headers);
732     av_log(s, AV_LOG_TRACE, "found headers\n");
733
734     for (i = 0; i < ogg->nstreams; i++) {
735         struct ogg_stream *os = ogg->streams + i;
736
737         if (ogg->streams[i].header < 0) {
738             av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
739             ogg->streams[i].codec = NULL;
740             av_freep(&ogg->streams[i].private);
741         } else if (os->codec && os->nb_header < os->codec->nb_header) {
742             av_log(s, AV_LOG_WARNING,
743                    "Headers mismatch for stream %d: "
744                    "expected %d received %d.\n",
745                    i, os->codec->nb_header, os->nb_header);
746             if (s->error_recognition & AV_EF_EXPLODE) {
747                 ogg_read_close(s);
748                 return AVERROR_INVALIDDATA;
749             }
750         }
751         if (os->start_granule != OGG_NOGRANULE_VALUE)
752             os->lastpts = s->streams[i]->start_time =
753                 ogg_gptopts(s, i, os->start_granule, NULL);
754     }
755
756     //linear granulepos seek from end
757     ret = ogg_get_length(s);
758     if (ret < 0) {
759         ogg_read_close(s);
760         return ret;
761     }
762
763     return 0;
764 }
765
766 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
767 {
768     struct ogg *ogg       = s->priv_data;
769     struct ogg_stream *os = ogg->streams + idx;
770     int64_t pts           = AV_NOPTS_VALUE;
771
772     if (dts)
773         *dts = AV_NOPTS_VALUE;
774
775     if (os->lastpts != AV_NOPTS_VALUE) {
776         pts         = os->lastpts;
777         os->lastpts = AV_NOPTS_VALUE;
778     }
779     if (os->lastdts != AV_NOPTS_VALUE) {
780         if (dts)
781             *dts = os->lastdts;
782         os->lastdts = AV_NOPTS_VALUE;
783     }
784     if (os->page_end) {
785         if (os->granule != -1LL) {
786             if (os->codec && os->codec->granule_is_start)
787                 pts = ogg_gptopts(s, idx, os->granule, dts);
788             else
789                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
790             os->granule = -1LL;
791         }
792     }
793     return pts;
794 }
795
796 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
797 {
798     struct ogg *ogg = s->priv_data;
799     struct ogg_stream *os = ogg->streams + idx;
800     int invalid = 0;
801     if (psize) {
802         switch (s->streams[idx]->codecpar->codec_id) {
803         case AV_CODEC_ID_THEORA:
804             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
805         break;
806         case AV_CODEC_ID_VP8:
807             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
808         }
809         if (invalid) {
810             os->pflags ^= AV_PKT_FLAG_KEY;
811             av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
812                    (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
813         }
814     }
815 }
816
817 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
818 {
819     struct ogg *ogg;
820     struct ogg_stream *os;
821     int idx, ret;
822     int pstart, psize;
823     int64_t fpos, pts, dts;
824
825     if (s->io_repositioned) {
826         ogg_reset(s);
827         s->io_repositioned = 0;
828     }
829
830     //Get an ogg packet
831 retry:
832     do {
833         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
834         if (ret < 0)
835             return ret;
836     } while (idx < 0 || !s->streams[idx]);
837
838     ogg = s->priv_data;
839     os  = ogg->streams + idx;
840
841     // pflags might not be set until after this
842     pts = ogg_calc_pts(s, idx, &dts);
843     ogg_validate_keyframe(s, idx, pstart, psize);
844
845     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
846         goto retry;
847     os->keyframe_seek = 0;
848
849     //Alloc a pkt
850     ret = av_new_packet(pkt, psize);
851     if (ret < 0)
852         return ret;
853     pkt->stream_index = idx;
854     memcpy(pkt->data, os->buf + pstart, psize);
855
856     pkt->pts      = pts;
857     pkt->dts      = dts;
858     pkt->flags    = os->pflags;
859     pkt->duration = os->pduration;
860     pkt->pos      = fpos;
861
862     if (os->start_trimming || os->end_trimming) {
863         uint8_t *side_data = av_packet_new_side_data(pkt,
864                                                      AV_PKT_DATA_SKIP_SAMPLES,
865                                                      10);
866         if(!side_data)
867             return AVERROR(ENOMEM);
868          AV_WL32(side_data + 0, os->start_trimming);
869         AV_WL32(side_data + 4, os->end_trimming);
870         os->start_trimming = 0;
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 };