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