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