]> git.sesse.net Git - ffmpeg/blob - libavformat/oggdec.c
Merge commit '271ce76d317c5432e151216cf23f12b77ed6cb7e'
[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_log(s, AV_LOG_TRACE, "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_log(s, AV_LOG_TRACE, "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, ret;
588     int64_t size, end;
589     int streams_left=0;
590
591     if (!s->pb->seekable)
592         return 0;
593
594 // already set
595     if (s->duration != AV_NOPTS_VALUE)
596         return 0;
597
598     size = avio_size(s->pb);
599     if (size < 0)
600         return 0;
601     end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
602
603     ret = ogg_save(s);
604     if (ret < 0)
605         return ret;
606     avio_seek(s->pb, end, SEEK_SET);
607     ogg->page_pos = -1;
608
609     while (!ogg_read_page(s, &i)) {
610         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
611             ogg->streams[i].codec) {
612             s->streams[i]->duration =
613                 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
614             if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
615                 s->streams[i]->duration -= s->streams[i]->start_time;
616                 streams_left-= (ogg->streams[i].got_start==-1);
617                 ogg->streams[i].got_start= 1;
618             } else if(!ogg->streams[i].got_start) {
619                 ogg->streams[i].got_start= -1;
620                 streams_left++;
621             }
622         }
623     }
624
625     ogg_restore(s, 0);
626
627     ret = ogg_save(s);
628     if (ret < 0)
629         return ret;
630
631     avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
632     ogg_reset(s);
633     while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
634         int64_t pts;
635         if (i < 0) continue;
636         pts = ogg_calc_pts(s, i, NULL);
637         if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
638             s->streams[i]->duration -= pts;
639             ogg->streams[i].got_start= 1;
640             streams_left--;
641         }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
642             ogg->streams[i].got_start= 1;
643             streams_left--;
644         }
645     }
646     ogg_restore (s, 0);
647
648     return 0;
649 }
650
651 static int ogg_read_close(AVFormatContext *s)
652 {
653     struct ogg *ogg = s->priv_data;
654     int i;
655
656     for (i = 0; i < ogg->nstreams; i++) {
657         av_freep(&ogg->streams[i].buf);
658         if (ogg->streams[i].codec &&
659             ogg->streams[i].codec->cleanup) {
660             ogg->streams[i].codec->cleanup(s, i);
661         }
662         av_freep(&ogg->streams[i].private);
663         av_freep(&ogg->streams[i].new_metadata);
664     }
665
666     ogg->nstreams = 0;
667
668     av_freep(&ogg->streams);
669     return 0;
670 }
671
672 static int ogg_read_header(AVFormatContext *s)
673 {
674     struct ogg *ogg = s->priv_data;
675     int ret, i;
676
677     ogg->curidx = -1;
678
679     //linear headers seek from start
680     do {
681         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
682         if (ret < 0) {
683             ogg_read_close(s);
684             return ret;
685         }
686     } while (!ogg->headers);
687     av_log(s, AV_LOG_TRACE, "found headers\n");
688
689     for (i = 0; i < ogg->nstreams; i++) {
690         struct ogg_stream *os = ogg->streams + i;
691
692         if (ogg->streams[i].header < 0) {
693             av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
694             ogg->streams[i].codec = NULL;
695         } else if (os->codec && os->nb_header < os->codec->nb_header) {
696             av_log(s, AV_LOG_WARNING,
697                    "Headers mismatch for stream %d: "
698                    "expected %d received %d.\n",
699                    i, os->codec->nb_header, os->nb_header);
700             if (s->error_recognition & AV_EF_EXPLODE)
701                 return AVERROR_INVALIDDATA;
702         }
703         if (os->start_granule != OGG_NOGRANULE_VALUE)
704             os->lastpts = s->streams[i]->start_time =
705                 ogg_gptopts(s, i, os->start_granule, NULL);
706     }
707
708     //linear granulepos seek from end
709     ret = ogg_get_length(s);
710     if (ret < 0) {
711         ogg_read_close(s);
712         return ret;
713     }
714
715     return 0;
716 }
717
718 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
719 {
720     struct ogg *ogg       = s->priv_data;
721     struct ogg_stream *os = ogg->streams + idx;
722     int64_t pts           = AV_NOPTS_VALUE;
723
724     if (dts)
725         *dts = AV_NOPTS_VALUE;
726
727     if (os->lastpts != AV_NOPTS_VALUE) {
728         pts         = os->lastpts;
729         os->lastpts = AV_NOPTS_VALUE;
730     }
731     if (os->lastdts != AV_NOPTS_VALUE) {
732         if (dts)
733             *dts = os->lastdts;
734         os->lastdts = AV_NOPTS_VALUE;
735     }
736     if (os->page_end) {
737         if (os->granule != -1LL) {
738             if (os->codec && os->codec->granule_is_start)
739                 pts = ogg_gptopts(s, idx, os->granule, dts);
740             else
741                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
742             os->granule = -1LL;
743         }
744     }
745     return pts;
746 }
747
748 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
749 {
750     struct ogg *ogg = s->priv_data;
751     struct ogg_stream *os = ogg->streams + idx;
752     int invalid = 0;
753     if (psize) {
754         switch (s->streams[idx]->codec->codec_id) {
755         case AV_CODEC_ID_THEORA:
756             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
757         break;
758         case AV_CODEC_ID_VP8:
759             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
760         }
761         if (invalid) {
762             os->pflags ^= AV_PKT_FLAG_KEY;
763             av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
764                    (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
765         }
766     }
767 }
768
769 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
770 {
771     struct ogg *ogg;
772     struct ogg_stream *os;
773     int idx, ret;
774     int pstart, psize;
775     int64_t fpos, pts, dts;
776
777     if (s->io_repositioned) {
778         ogg_reset(s);
779         s->io_repositioned = 0;
780     }
781
782     //Get an ogg packet
783 retry:
784     do {
785         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
786         if (ret < 0)
787             return ret;
788     } while (idx < 0 || !s->streams[idx]);
789
790     ogg = s->priv_data;
791     os  = ogg->streams + idx;
792
793     // pflags might not be set until after this
794     pts = ogg_calc_pts(s, idx, &dts);
795     ogg_validate_keyframe(s, idx, pstart, psize);
796
797     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
798         goto retry;
799     os->keyframe_seek = 0;
800
801     //Alloc a pkt
802     ret = av_new_packet(pkt, psize);
803     if (ret < 0)
804         return ret;
805     pkt->stream_index = idx;
806     memcpy(pkt->data, os->buf + pstart, psize);
807
808     pkt->pts      = pts;
809     pkt->dts      = dts;
810     pkt->flags    = os->pflags;
811     pkt->duration = os->pduration;
812     pkt->pos      = fpos;
813
814     if (os->end_trimming) {
815         uint8_t *side_data = av_packet_new_side_data(pkt,
816                                                      AV_PKT_DATA_SKIP_SAMPLES,
817                                                      10);
818         if(!side_data)
819             goto fail;
820         AV_WL32(side_data + 4, os->end_trimming);
821         os->end_trimming = 0;
822     }
823
824     if (os->new_metadata) {
825         uint8_t *side_data = av_packet_new_side_data(pkt,
826                                                      AV_PKT_DATA_METADATA_UPDATE,
827                                                      os->new_metadata_size);
828         if(!side_data)
829             goto fail;
830
831         memcpy(side_data, os->new_metadata, os->new_metadata_size);
832         av_freep(&os->new_metadata);
833         os->new_metadata_size = 0;
834     }
835
836     return psize;
837 fail:
838     av_free_packet(pkt);
839     return AVERROR(ENOMEM);
840 }
841
842 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
843                                   int64_t *pos_arg, int64_t pos_limit)
844 {
845     struct ogg *ogg = s->priv_data;
846     AVIOContext *bc = s->pb;
847     int64_t pts     = AV_NOPTS_VALUE;
848     int64_t keypos  = -1;
849     int i;
850     int pstart, psize;
851     avio_seek(bc, *pos_arg, SEEK_SET);
852     ogg_reset(s);
853
854     while (   avio_tell(bc) <= pos_limit
855            && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
856         if (i == stream_index) {
857             struct ogg_stream *os = ogg->streams + stream_index;
858             // Do not trust the last timestamps of a ogm video
859             if (    (os->flags & OGG_FLAG_EOS)
860                 && !(os->flags & OGG_FLAG_BOS)
861                 && os->codec == &ff_ogm_video_codec)
862                 continue;
863             pts = ogg_calc_pts(s, i, NULL);
864             ogg_validate_keyframe(s, i, pstart, psize);
865             if (os->pflags & AV_PKT_FLAG_KEY) {
866                 keypos = *pos_arg;
867             } else if (os->keyframe_seek) {
868                 // if we had a previous keyframe but no pts for it,
869                 // return that keyframe with this pts value.
870                 if (keypos >= 0)
871                     *pos_arg = keypos;
872                 else
873                     pts = AV_NOPTS_VALUE;
874             }
875         }
876         if (pts != AV_NOPTS_VALUE)
877             break;
878     }
879     ogg_reset(s);
880     return pts;
881 }
882
883 static int ogg_read_seek(AVFormatContext *s, int stream_index,
884                          int64_t timestamp, int flags)
885 {
886     struct ogg *ogg       = s->priv_data;
887     struct ogg_stream *os = ogg->streams + stream_index;
888     int ret;
889
890     av_assert0(stream_index < ogg->nstreams);
891     // Ensure everything is reset even when seeking via
892     // the generated index.
893     ogg_reset(s);
894
895     // Try seeking to a keyframe first. If this fails (very possible),
896     // av_seek_frame will fall back to ignoring keyframes
897     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
898         && !(flags & AVSEEK_FLAG_ANY))
899         os->keyframe_seek = 1;
900
901     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
902     os  = ogg->streams + stream_index;
903     if (ret < 0)
904         os->keyframe_seek = 0;
905     return ret;
906 }
907
908 static int ogg_probe(AVProbeData *p)
909 {
910     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
911         return AVPROBE_SCORE_MAX;
912     return 0;
913 }
914
915 AVInputFormat ff_ogg_demuxer = {
916     .name           = "ogg",
917     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
918     .priv_data_size = sizeof(struct ogg),
919     .read_probe     = ogg_probe,
920     .read_header    = ogg_read_header,
921     .read_packet    = ogg_read_packet,
922     .read_close     = ogg_read_close,
923     .read_seek      = ogg_read_seek,
924     .read_timestamp = ogg_read_timestamp,
925     .extensions     = "ogg",
926     .flags          = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
927 };