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