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