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