]> git.sesse.net Git - ffmpeg/blob - libavformat/oggdec.c
Merge commit 'a1c699659d56b76c0bf399307f642c6fd6d28281'
[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     int invalid = 0;
731     if (psize) {
732         switch (s->streams[idx]->codec->codec_id) {
733         case AV_CODEC_ID_THEORA:
734             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
735         break;
736         case AV_CODEC_ID_VP8:
737             invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
738         }
739         if (invalid) {
740             os->pflags ^= AV_PKT_FLAG_KEY;
741             av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
742                    (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
743         }
744     }
745 }
746
747 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
748 {
749     struct ogg *ogg;
750     struct ogg_stream *os;
751     int idx, ret;
752     int pstart, psize;
753     int64_t fpos, pts, dts;
754
755     if (s->io_repositioned) {
756         ogg_reset(s);
757         s->io_repositioned = 0;
758     }
759
760     //Get an ogg packet
761 retry:
762     do {
763         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
764         if (ret < 0)
765             return ret;
766     } while (idx < 0 || !s->streams[idx]);
767
768     ogg = s->priv_data;
769     os  = ogg->streams + idx;
770
771     // pflags might not be set until after this
772     pts = ogg_calc_pts(s, idx, &dts);
773     ogg_validate_keyframe(s, idx, pstart, psize);
774
775     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
776         goto retry;
777     os->keyframe_seek = 0;
778
779     //Alloc a pkt
780     ret = av_new_packet(pkt, psize);
781     if (ret < 0)
782         return ret;
783     pkt->stream_index = idx;
784     memcpy(pkt->data, os->buf + pstart, psize);
785
786     pkt->pts      = pts;
787     pkt->dts      = dts;
788     pkt->flags    = os->pflags;
789     pkt->duration = os->pduration;
790     pkt->pos      = fpos;
791
792     if (os->end_trimming) {
793         uint8_t *side_data = av_packet_new_side_data(pkt,
794                                                      AV_PKT_DATA_SKIP_SAMPLES,
795                                                      10);
796         if(side_data == NULL) {
797             av_free_packet(pkt);
798             av_free(pkt);
799             return AVERROR(ENOMEM);
800         }
801         AV_WL32(side_data + 4, os->end_trimming);
802         os->end_trimming = 0;
803     }
804
805     if (os->new_metadata) {
806         uint8_t *side_data = av_packet_new_side_data(pkt,
807                                                      AV_PKT_DATA_METADATA_UPDATE,
808                                                      os->new_metadata_size);
809         memcpy(side_data, os->new_metadata, os->new_metadata_size);
810         av_freep(&os->new_metadata);
811         os->new_metadata_size = 0;
812     }
813
814     return psize;
815 }
816
817 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
818                                   int64_t *pos_arg, int64_t pos_limit)
819 {
820     struct ogg *ogg = s->priv_data;
821     AVIOContext *bc = s->pb;
822     int64_t pts     = AV_NOPTS_VALUE;
823     int64_t keypos  = -1;
824     int i;
825     int pstart, psize;
826     avio_seek(bc, *pos_arg, SEEK_SET);
827     ogg_reset(s);
828
829     while (   avio_tell(bc) <= pos_limit
830            && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
831         if (i == stream_index) {
832             struct ogg_stream *os = ogg->streams + stream_index;
833             // Dont trust the last timestamps of a ogm video
834             if (    (os->flags & OGG_FLAG_EOS)
835                 && !(os->flags & OGG_FLAG_BOS)
836                 && os->codec == &ff_ogm_video_codec)
837                 continue;
838             pts = ogg_calc_pts(s, i, NULL);
839             ogg_validate_keyframe(s, i, pstart, psize);
840             if (os->pflags & AV_PKT_FLAG_KEY) {
841                 keypos = *pos_arg;
842             } else if (os->keyframe_seek) {
843                 // if we had a previous keyframe but no pts for it,
844                 // return that keyframe with this pts value.
845                 if (keypos >= 0)
846                     *pos_arg = keypos;
847                 else
848                     pts = AV_NOPTS_VALUE;
849             }
850         }
851         if (pts != AV_NOPTS_VALUE)
852             break;
853     }
854     ogg_reset(s);
855     return pts;
856 }
857
858 static int ogg_read_seek(AVFormatContext *s, int stream_index,
859                          int64_t timestamp, int flags)
860 {
861     struct ogg *ogg       = s->priv_data;
862     struct ogg_stream *os = ogg->streams + stream_index;
863     int ret;
864
865     av_assert0(stream_index < ogg->nstreams);
866     // Ensure everything is reset even when seeking via
867     // the generated index.
868     ogg_reset(s);
869
870     // Try seeking to a keyframe first. If this fails (very possible),
871     // av_seek_frame will fall back to ignoring keyframes
872     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
873         && !(flags & AVSEEK_FLAG_ANY))
874         os->keyframe_seek = 1;
875
876     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
877     os  = ogg->streams + stream_index;
878     if (ret < 0)
879         os->keyframe_seek = 0;
880     return ret;
881 }
882
883 static int ogg_probe(AVProbeData *p)
884 {
885     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
886         return AVPROBE_SCORE_MAX;
887     return 0;
888 }
889
890 AVInputFormat ff_ogg_demuxer = {
891     .name           = "ogg",
892     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
893     .priv_data_size = sizeof(struct ogg),
894     .read_probe     = ogg_probe,
895     .read_header    = ogg_read_header,
896     .read_packet    = ogg_read_packet,
897     .read_close     = ogg_read_close,
898     .read_seek      = ogg_read_seek,
899     .read_timestamp = ogg_read_timestamp,
900     .extensions     = "ogg",
901     .flags          = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
902 };