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