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