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