oggdec.c 26.2 KB
Newer Older
1 2 3 4 5 6
/*
 * Ogg bitstream support
 * Luca Barbato <lu_zero@gentoo.org>
 * Based on tcvp implementation
 */

7
/*
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
    Copyright (C) 2005  Michael Ahlberg, Måns Rullgård

    Permission is hereby granted, free of charge, to any person
    obtaining a copy of this software and associated documentation
    files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use, copy,
    modify, merge, publish, distribute, sublicense, and/or sell copies
    of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    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 40 41

#define MAX_PAGE_SIZE 65307
#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE

42
static const struct ogg_codec * const ogg_codecs[] = {
43
    &ff_skeleton_codec,
44
    &ff_daala_codec,
45
    &ff_dirac_codec,
46 47 48 49
    &ff_speex_codec,
    &ff_vorbis_codec,
    &ff_theora_codec,
    &ff_flac_codec,
50
    &ff_celt_codec,
51
    &ff_opus_codec,
52
    &ff_vp8_codec,
53
    &ff_old_dirac_codec,
54 55 56 57 58
    &ff_old_flac_codec,
    &ff_ogm_video_codec,
    &ff_ogm_audio_codec,
    &ff_ogm_text_codec,
    &ff_ogm_old_codec,
59 60 61
    NULL
};

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, int discard);
65

66
//FIXME We could avoid some structure duplication
67
static int ogg_save(AVFormatContext *s)
68
{
69 70
    struct ogg *ogg = s->priv_data;
    struct ogg_state *ost =
71
        av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
72
    int i;
73
    int ret = 0;
74 75 76 77

    if (!ost)
        return AVERROR(ENOMEM);

78 79 80
    ost->pos      = avio_tell(s->pb);
    ost->curidx   = ogg->curidx;
    ost->next     = ogg->state;
81
    ost->nstreams = ogg->nstreams;
82 83
    memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));

84
    for (i = 0; i < ogg->nstreams; i++) {
85
        struct ogg_stream *os = ogg->streams + i;
86
        os->buf = av_mallocz(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
87 88 89 90
        if (os->buf)
            memcpy(os->buf, ost->streams[i].buf, os->bufpos);
        else
            ret = AVERROR(ENOMEM);
91 92
        os->new_metadata      = NULL;
        os->new_metadata_size = 0;
93 94 95 96
    }

    ogg->state = ost;

97 98 99 100
    if (ret < 0)
        ogg_restore(s, 0);

    return ret;
101 102
}

103
static int ogg_restore(AVFormatContext *s, int discard)
104
{
105
    struct ogg *ogg = s->priv_data;
106
    AVIOContext *bc = s->pb;
107
    struct ogg_state *ost = ogg->state;
108
    int i, err;
109 110 111 112 113 114

    if (!ost)
        return 0;

    ogg->state = ost->next;

115
    if (!discard) {
116

117
        for (i = 0; i < ogg->nstreams; i++)
118
            av_freep(&ogg->streams[i].buf);
119

120
        avio_seek(bc, ost->pos, SEEK_SET);
121
        ogg->page_pos = -1;
122
        ogg->curidx   = ost->curidx;
123
        ogg->nstreams = ost->nstreams;
124 125 126 127 128
        if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams,
                                     sizeof(*ogg->streams))) < 0) {
            ogg->nstreams = 0;
            return err;
        } else
129 130
            memcpy(ogg->streams, ost->streams,
                   ost->nstreams * sizeof(*ogg->streams));
131 132
    }

133
    av_free(ost);
134 135 136 137

    return 0;
}

138
static int ogg_reset(AVFormatContext *s)
139
{
140
    struct ogg *ogg = s->priv_data;
141
    int i;
142
    int64_t start_pos = avio_tell(s->pb);
143

144
    for (i = 0; i < ogg->nstreams; i++) {
145
        struct ogg_stream *os = ogg->streams + i;
146 147 148 149 150 151 152 153 154 155
        os->bufpos     = 0;
        os->pstart     = 0;
        os->psize      = 0;
        os->granule    = -1;
        os->lastpts    = AV_NOPTS_VALUE;
        os->lastdts    = AV_NOPTS_VALUE;
        os->sync_pos   = -1;
        os->page_pos   = 0;
        os->nsegs      = 0;
        os->segp       = 0;
156
        os->incomplete = 0;
157
        os->got_data = 0;
158
        if (start_pos <= s->internal->data_offset) {
159 160
            os->lastpts = 0;
        }
161
        os->end_trimming = 0;
162 163
        av_freep(&os->new_metadata);
        os->new_metadata_size = 0;
164 165
    }

166
    ogg->page_pos = -1;
167 168 169 170 171
    ogg->curidx = -1;

    return 0;
}

172
static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
173 174 175 176 177
{
    int i;

    for (i = 0; ogg_codecs[i]; i++)
        if (size >= ogg_codecs[i]->magicsize &&
178
            !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
179 180 181 182 183
            return ogg_codecs[i];

    return NULL;
}

184 185 186 187 188
/**
 * Replace the current stream with a new one. This is a typical webradio
 * situation where a new audio stream spawn (identified with a new serial) and
 * must replace the previous one (track switch).
 */
189
static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs)
190
{
191 192
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os;
193
    const struct ogg_codec *codec;
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
    int i = 0;

    if (s->pb->seekable) {
        uint8_t magic[8];
        int64_t pos = avio_tell(s->pb);
        avio_skip(s->pb, nsegs);
        avio_read(s->pb, magic, sizeof(magic));
        avio_seek(s->pb, pos, SEEK_SET);
        codec = ogg_find_codec(magic, sizeof(magic));
        if (!codec) {
            av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
            return AVERROR_INVALIDDATA;
        }
        for (i = 0; i < ogg->nstreams; i++) {
            if (ogg->streams[i].codec == codec)
                break;
        }
        if (i >= ogg->nstreams)
            return ogg_new_stream(s, serial);
    } else if (ogg->nstreams != 1) {
214
        avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
215 216 217
        return AVERROR_PATCHWELCOME;
    }

218
    os = &ogg->streams[i];
219

220
    os->serial  = serial;
221
    return i;
222

223
#if 0
224
    buf     = os->buf;
225
    bufsize = os->bufsize;
226
    codec   = os->codec;
227

228 229
    if (!ogg->state || ogg->state->streams[i].private != os->private)
        av_freep(&ogg->streams[i].private);
230 231 232 233

    /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
     * also re-use the ogg_stream allocated buffer */
    memset(os, 0, sizeof(*os));
234
    os->serial  = serial;
235
    os->bufsize = bufsize;
236 237 238
    os->buf     = buf;
    os->header  = -1;
    os->codec   = codec;
239

240
    return i;
241
#endif
242
}
243

244 245
static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
{
246
    struct ogg *ogg = s->priv_data;
247
    int idx         = ogg->nstreams;
248
    AVStream *st;
249
    struct ogg_stream *os;
250
    size_t size;
251

252 253 254 255 256 257
    if (ogg->state) {
        av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
               "in between Ogg context save/restore operations.\n");
        return AVERROR_BUG;
    }

258
    /* Allocate and init a new Ogg Stream */
259 260 261
    if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
        !(os = av_realloc(ogg->streams, size)))
        return AVERROR(ENOMEM);
262 263
    ogg->streams = os;
    os           = ogg->streams + idx;
264
    memset(os, 0, sizeof(*os));
265 266
    os->serial        = serial;
    os->bufsize       = DECODER_BUFFER_SIZE;
267
    os->buf           = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
268
    os->header        = -1;
269
    os->start_granule = OGG_NOGRANULE_VALUE;
270 271
    if (!os->buf)
        return AVERROR(ENOMEM);
272

273 274 275 276 277 278 279 280
    /* Create the associated AVStream */
    st = avformat_new_stream(s, NULL);
    if (!st) {
        av_freep(&os->buf);
        return AVERROR(ENOMEM);
    }
    st->id = idx;
    avpriv_set_pts_info(st, 64, 1, 1000000);
281

282
    ogg->nstreams++;
283 284 285
    return idx;
}

286
static int ogg_new_buf(struct ogg *ogg, int idx)
287
{
288
    struct ogg_stream *os = ogg->streams + idx;
289
    uint8_t *nb = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
290
    int size = os->bufpos - os->pstart;
291

292 293 294
    if (!nb)
        return AVERROR(ENOMEM);

295
    if (os->buf) {
296 297 298
        memcpy(nb, os->buf + os->pstart, size);
        av_free(os->buf);
    }
299 300

    os->buf    = nb;
301 302 303 304 305 306
    os->bufpos = size;
    os->pstart = 0;

    return 0;
}

307 308 309 310 311 312 313 314 315 316
static int data_packets_seen(const struct ogg *ogg)
{
    int i;

    for (i = 0; i < ogg->nstreams; i++)
        if (ogg->streams[i].got_data)
            return 1;
    return 0;
}

317
static int ogg_read_page(AVFormatContext *s, int *sid)
318
{
319
    AVIOContext *bc = s->pb;
320 321
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os;
322
    int ret, i = 0;
323 324 325 326
    int flags, nsegs;
    uint64_t gp;
    uint32_t serial;
    int size, idx;
327
    uint8_t sync[4];
328 329
    int sp = 0;

330
    ret = avio_read(bc, sync, 4);
331 332
    if (ret < 4)
        return ret < 0 ? ret : AVERROR_EOF;
333

334
    do {
335 336 337 338 339 340 341
        int c;

        if (sync[sp & 3] == 'O' &&
            sync[(sp + 1) & 3] == 'g' &&
            sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
            break;

342 343 344 345 346 347
        if(!i && bc->seekable && ogg->page_pos > 0) {
            memset(sync, 0, 4);
            avio_seek(bc, ogg->page_pos+4, SEEK_SET);
            ogg->page_pos = -1;
        }

348
        c = avio_r8(bc);
349

350
        if (avio_feof(bc))
351
            return AVERROR_EOF;
352

353
        sync[sp++ & 3] = c;
354
    } while (i++ < MAX_PAGE_SIZE);
355

356 357
    if (i >= MAX_PAGE_SIZE) {
        av_log(s, AV_LOG_INFO, "cannot find sync word\n");
358
        return AVERROR_INVALIDDATA;
359 360
    }

361
    if (avio_r8(bc) != 0) {      /* version */
362
        av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
363
        return AVERROR_INVALIDDATA;
364
    }
365

366 367 368
    flags  = avio_r8(bc);
    gp     = avio_rl64(bc);
    serial = avio_rl32(bc);
Mans Rullgard's avatar
Mans Rullgard committed
369
    avio_skip(bc, 8); /* seq, crc */
370
    nsegs  = avio_r8(bc);
371

372 373
    idx = ogg_find_stream(ogg, serial);
    if (idx < 0) {
374
        if (data_packets_seen(ogg))
375
            idx = ogg_replace_stream(s, serial, nsegs);
376 377
        else
            idx = ogg_new_stream(s, serial);
378

379
        if (idx < 0) {
380
            av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
381
            return idx;
382
        }
383 384 385
    }

    os = ogg->streams + idx;
386
    ogg->page_pos =
387
    os->page_pos = avio_tell(bc) - 27;
388

389 390 391 392 393
    if (os->psize > 0) {
        ret = ogg_new_buf(ogg, idx);
        if (ret < 0)
            return ret;
    }
394

395
    ret = avio_read(bc, os->segments, nsegs);
396 397
    if (ret < nsegs)
        return ret < 0 ? ret : AVERROR_EOF;
398 399

    os->nsegs = nsegs;
400
    os->segp  = 0;
401 402 403 404 405

    size = 0;
    for (i = 0; i < nsegs; i++)
        size += os->segments[i];

406 407 408
    if (!(flags & OGG_FLAG_BOS))
        os->got_data = 1;

409 410
    if (flags & OGG_FLAG_CONT || os->incomplete) {
        if (!os->psize) {
411 412 413
            // If this is the very first segment we started
            // playback in the middle of a continuation packet.
            // Discard it since we missed the start of it.
414
            while (os->segp < os->nsegs) {
415 416 417
                int seg = os->segments[os->segp++];
                os->pstart += seg;
                if (seg < 255)
418
                    break;
419
            }
420
            os->sync_pos = os->page_pos;
421
        }
422 423
    } else {
        os->psize    = 0;
424
        os->sync_pos = os->page_pos;
425 426
    }

427
    if (os->bufsize - os->bufpos < size) {
428
        uint8_t *nb = av_malloc((os->bufsize *= 2) + AV_INPUT_BUFFER_PADDING_SIZE);
429 430
        if (!nb)
            return AVERROR(ENOMEM);
431 432
        memcpy(nb, os->buf, os->bufpos);
        av_free(os->buf);
433 434 435
        os->buf = nb;
    }

436
    ret = avio_read(bc, os->buf + os->bufpos, size);
437 438
    if (ret < size)
        return ret < 0 ? ret : AVERROR_EOF;
439 440 441

    os->bufpos += size;
    os->granule = gp;
442
    os->flags   = flags;
443

444
    memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
445 446
    if (sid)
        *sid = idx;
447 448 449 450

    return 0;
}

451 452
/**
 * @brief find the next Ogg packet
453
 * @param *sid is set to the stream for the packet or -1 if there is
454 455 456 457
 *             no matching stream, in that case assume all other return
 *             values to be uninitialized.
 * @return negative value on error or EOF.
 */
458
static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
459
                      int64_t *fpos)
460
{
461
    struct ogg *ogg = s->priv_data;
462
    int idx, i, ret;
463
    struct ogg_stream *os;
464
    int complete = 0;
465
    int segp     = 0, psize = 0;
466

467
    av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
468 469
    if (sid)
        *sid = -1;
470

471
    do {
472 473
        idx = ogg->curidx;

474
        while (idx < 0) {
475
            ret = ogg_read_page(s, &idx);
476 477
            if (ret < 0)
                return ret;
478 479 480 481
        }

        os = ogg->streams + idx;

482
        av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
483 484
                idx, os->pstart, os->psize, os->segp, os->nsegs);

485 486 487 488
        if (!os->codec) {
            if (os->header < 0) {
                os->codec = ogg_find_codec(os->buf, os->bufpos);
                if (!os->codec) {
489
                    av_log(s, AV_LOG_WARNING, "Codec not found\n");
490 491 492
                    os->header = 0;
                    return 0;
                }
493
            } else {
494 495 496 497
                return 0;
            }
        }

498
        segp  = os->segp;
499 500
        psize = os->psize;

501
        while (os->segp < os->nsegs) {
502 503
            int ss = os->segments[os->segp++];
            os->psize += ss;
504
            if (ss < 255) {
505 506 507 508 509
                complete = 1;
                break;
            }
        }

510 511
        if (!complete && os->segp == os->nsegs) {
            ogg->curidx    = -1;
512 513 514 515 516
            // Do not set incomplete for empty packets.
            // Together with the code in ogg_read_page
            // that discards all continuation of empty packets
            // we would get an infinite loop.
            os->incomplete = !!os->psize;
517
        }
518
    } while (!complete);
519 520


521
    if (os->granule == -1)
522 523 524
        av_log(s, AV_LOG_WARNING,
               "Page at %"PRId64" is missing granule\n",
               os->page_pos);
525

526
    ogg->curidx    = idx;
527
    os->incomplete = 0;
528

529
    if (os->header) {
530 531 532
        os->header = os->codec->header(s, idx);
        if (!os->header) {
            os->segp  = segp;
533
            os->psize = psize;
534

535 536
            // We have reached the first non-header packet in this stream.
            // Unfortunately more header packets may still follow for others,
537
            // but if we continue with header parsing we may lose data packets.
538
            ogg->headers = 1;
539 540 541

            // Update the header state for all streams and
            // compute the data_offset.
542 543
            if (!s->internal->data_offset)
                s->internal->data_offset = os->sync_pos;
544

545 546 547 548 549 550
            for (i = 0; i < ogg->nstreams; i++) {
                struct ogg_stream *cur_os = ogg->streams + i;

                // if we have a partial non-header packet, its start is
                // obviously at or after the data start
                if (cur_os->incomplete)
551
                    s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
552
            }
553
        } else {
554
            os->nb_header++;
555
            os->pstart += os->psize;
556
            os->psize   = 0;
557
        }
558
    } else {
559
        os->pflags    = 0;
560
        os->pduration = 0;
561
        if (os->codec && os->codec->packet)
562
            os->codec->packet(s, idx);
563 564
        if (sid)
            *sid = idx;
565 566 567 568
        if (dstart)
            *dstart = os->pstart;
        if (dsize)
            *dsize = os->psize;
569 570
        if (fpos)
            *fpos = os->sync_pos;
571 572
        os->pstart  += os->psize;
        os->psize    = 0;
573 574
        if(os->pstart == os->bufpos)
            os->bufpos = os->pstart = 0;
575
        os->sync_pos = os->page_pos;
576 577
    }

David Conrad's avatar
David Conrad committed
578 579 580 581 582 583 584 585 586
    // determine whether there are more complete packets in this page
    // if not, the page's granule will apply to this packet
    os->page_end = 1;
    for (i = os->segp; i < os->nsegs; i++)
        if (os->segments[i] < 255) {
            os->page_end = 0;
            break;
        }

587 588 589 590 591 592
    if (os->segp == os->nsegs)
        ogg->curidx = -1;

    return 0;
}

593
static int ogg_get_length(AVFormatContext *s)
594
{
595
    struct ogg *ogg = s->priv_data;
596
    int i, ret;
597
    int64_t size, end;
598
    int streams_left=0;
599

600
    if (!s->pb->seekable)
601
        return 0;
602 603 604 605 606

// already set
    if (s->duration != AV_NOPTS_VALUE)
        return 0;

607
    size = avio_size(s->pb);
608
    if (size < 0)
Måns Rullgård's avatar
Måns Rullgård committed
609
        return 0;
610
    end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
Måns Rullgård's avatar
Måns Rullgård committed
611

612 613 614
    ret = ogg_save(s);
    if (ret < 0)
        return ret;
615
    avio_seek(s->pb, end, SEEK_SET);
616
    ogg->page_pos = -1;
617

618
    while (!ogg_read_page(s, &i)) {
619
        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
620 621
            ogg->streams[i].codec) {
            s->streams[i]->duration =
622
                ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
623
            if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
624
                s->streams[i]->duration -= s->streams[i]->start_time;
625 626
                streams_left-= (ogg->streams[i].got_start==-1);
                ogg->streams[i].got_start= 1;
627
            } else if(!ogg->streams[i].got_start) {
628 629 630
                ogg->streams[i].got_start= -1;
                streams_left++;
            }
631
        }
632 633
    }

634
    ogg_restore(s, 0);
635

636 637 638 639
    ret = ogg_save(s);
    if (ret < 0)
        return ret;

640
    avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
641
    ogg_reset(s);
642 643 644 645
    while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
        int64_t pts;
        if (i < 0) continue;
        pts = ogg_calc_pts(s, i, NULL);
646 647
        if (s->streams[i]->duration == AV_NOPTS_VALUE)
            continue;
648
        if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
649 650 651
            s->streams[i]->duration -= pts;
            ogg->streams[i].got_start= 1;
            streams_left--;
652
        }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
653 654
            ogg->streams[i].got_start= 1;
            streams_left--;
655
        }
jan gerber's avatar
jan gerber committed
656 657 658
    }
    ogg_restore (s, 0);

659 660 661
    return 0;
}

662 663 664 665 666 667
static int ogg_read_close(AVFormatContext *s)
{
    struct ogg *ogg = s->priv_data;
    int i;

    for (i = 0; i < ogg->nstreams; i++) {
668
        av_freep(&ogg->streams[i].buf);
669 670 671 672
        if (ogg->streams[i].codec &&
            ogg->streams[i].codec->cleanup) {
            ogg->streams[i].codec->cleanup(s, i);
        }
673
        av_freep(&ogg->streams[i].private);
674
        av_freep(&ogg->streams[i].new_metadata);
675
    }
676 677 678

    ogg->nstreams = 0;

679
    av_freep(&ogg->streams);
680 681 682
    return 0;
}

683
static int ogg_read_header(AVFormatContext *s)
684
{
685
    struct ogg *ogg = s->priv_data;
686
    int ret, i;
687

688
    ogg->curidx = -1;
689

690
    //linear headers seek from start
691 692
    do {
        ret = ogg_packet(s, NULL, NULL, NULL, NULL);
693 694
        if (ret < 0) {
            ogg_read_close(s);
695
            return ret;
696
        }
697
    } while (!ogg->headers);
698
    av_log(s, AV_LOG_TRACE, "found headers\n");
699

700 701 702
    for (i = 0; i < ogg->nstreams; i++) {
        struct ogg_stream *os = ogg->streams + i;

703 704
        if (ogg->streams[i].header < 0) {
            av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
705
            ogg->streams[i].codec = NULL;
706
            av_freep(&ogg->streams[i].private);
707
        } else if (os->codec && os->nb_header < os->codec->nb_header) {
708 709 710 711 712 713
            av_log(s, AV_LOG_WARNING,
                   "Headers mismatch for stream %d: "
                   "expected %d received %d.\n",
                   i, os->codec->nb_header, os->nb_header);
            if (s->error_recognition & AV_EF_EXPLODE)
                return AVERROR_INVALIDDATA;
714
        }
715 716 717
        if (os->start_granule != OGG_NOGRANULE_VALUE)
            os->lastpts = s->streams[i]->start_time =
                ogg_gptopts(s, i, os->start_granule, NULL);
718
    }
719

720
    //linear granulepos seek from end
721 722 723 724 725
    ret = ogg_get_length(s);
    if (ret < 0) {
        ogg_read_close(s);
        return ret;
    }
726 727 728 729

    return 0;
}

730 731
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
{
732
    struct ogg *ogg       = s->priv_data;
733
    struct ogg_stream *os = ogg->streams + idx;
734
    int64_t pts           = AV_NOPTS_VALUE;
735 736 737 738 739

    if (dts)
        *dts = AV_NOPTS_VALUE;

    if (os->lastpts != AV_NOPTS_VALUE) {
740
        pts         = os->lastpts;
741 742 743 744 745 746 747 748 749 750 751 752 753 754
        os->lastpts = AV_NOPTS_VALUE;
    }
    if (os->lastdts != AV_NOPTS_VALUE) {
        if (dts)
            *dts = os->lastdts;
        os->lastdts = AV_NOPTS_VALUE;
    }
    if (os->page_end) {
        if (os->granule != -1LL) {
            if (os->codec && os->codec->granule_is_start)
                pts = ogg_gptopts(s, idx, os->granule, dts);
            else
                os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
            os->granule = -1LL;
755
        }
756 757 758
    }
    return pts;
}
759

760 761 762 763
static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
{
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os = ogg->streams + idx;
764 765
    int invalid = 0;
    if (psize) {
766
        switch (s->streams[idx]->codecpar->codec_id) {
767 768 769 770 771 772 773
        case AV_CODEC_ID_THEORA:
            invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
        break;
        case AV_CODEC_ID_VP8:
            invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
        }
        if (invalid) {
774
            os->pflags ^= AV_PKT_FLAG_KEY;
775 776
            av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
                   (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
777 778 779 780
        }
    }
}

781
static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
782
{
783 784
    struct ogg *ogg;
    struct ogg_stream *os;
785
    int idx, ret;
786
    int pstart, psize;
David Conrad's avatar
David Conrad committed
787
    int64_t fpos, pts, dts;
788

789 790 791 792 793
    if (s->io_repositioned) {
        ogg_reset(s);
        s->io_repositioned = 0;
    }

794
    //Get an ogg packet
David Conrad's avatar
David Conrad committed
795
retry:
796
    do {
797
        ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
798 799
        if (ret < 0)
            return ret;
800
    } while (idx < 0 || !s->streams[idx]);
801 802

    ogg = s->priv_data;
803
    os  = ogg->streams + idx;
804

David Conrad's avatar
David Conrad committed
805 806
    // pflags might not be set until after this
    pts = ogg_calc_pts(s, idx, &dts);
807
    ogg_validate_keyframe(s, idx, pstart, psize);
David Conrad's avatar
David Conrad committed
808

809
    if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
David Conrad's avatar
David Conrad committed
810 811 812
        goto retry;
    os->keyframe_seek = 0;

813
    //Alloc a pkt
814
    ret = av_new_packet(pkt, psize);
815 816
    if (ret < 0)
        return ret;
817
    pkt->stream_index = idx;
818
    memcpy(pkt->data, os->buf + pstart, psize);
David Conrad's avatar
David Conrad committed
819

820 821 822
    pkt->pts      = pts;
    pkt->dts      = dts;
    pkt->flags    = os->pflags;
823
    pkt->duration = os->pduration;
824
    pkt->pos      = fpos;
825

826 827 828 829
    if (os->end_trimming) {
        uint8_t *side_data = av_packet_new_side_data(pkt,
                                                     AV_PKT_DATA_SKIP_SAMPLES,
                                                     10);
830
        if(!side_data)
831
            goto fail;
832
        AV_WL32(side_data + 4, os->end_trimming);
833
        os->end_trimming = 0;
834 835
    }

836 837 838 839
    if (os->new_metadata) {
        uint8_t *side_data = av_packet_new_side_data(pkt,
                                                     AV_PKT_DATA_METADATA_UPDATE,
                                                     os->new_metadata_size);
840
        if(!side_data)
841 842
            goto fail;

843 844 845 846 847
        memcpy(side_data, os->new_metadata, os->new_metadata_size);
        av_freep(&os->new_metadata);
        os->new_metadata_size = 0;
    }

848
    return psize;
849
fail:
850
    av_packet_unref(pkt);
851
    return AVERROR(ENOMEM);
852 853
}

854 855
static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
                                  int64_t *pos_arg, int64_t pos_limit)
856
{
857
    struct ogg *ogg = s->priv_data;
858
    AVIOContext *bc = s->pb;
859
    int64_t pts     = AV_NOPTS_VALUE;
860
    int64_t keypos  = -1;
861
    int i;
862
    int pstart, psize;
863
    avio_seek(bc, *pos_arg, SEEK_SET);
864
    ogg_reset(s);
865

866 867
    while (   avio_tell(bc) <= pos_limit
           && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
868
        if (i == stream_index) {
869
            struct ogg_stream *os = ogg->streams + stream_index;
Lou Logan's avatar
Lou Logan committed
870
            // Do not trust the last timestamps of an ogm video
871 872 873 874
            if (    (os->flags & OGG_FLAG_EOS)
                && !(os->flags & OGG_FLAG_BOS)
                && os->codec == &ff_ogm_video_codec)
                continue;
875
            pts = ogg_calc_pts(s, i, NULL);
876
            ogg_validate_keyframe(s, i, pstart, psize);
877 878 879 880 881 882 883 884 885 886
            if (os->pflags & AV_PKT_FLAG_KEY) {
                keypos = *pos_arg;
            } else if (os->keyframe_seek) {
                // if we had a previous keyframe but no pts for it,
                // return that keyframe with this pts value.
                if (keypos >= 0)
                    *pos_arg = keypos;
                else
                    pts = AV_NOPTS_VALUE;
            }
887
        }
888 889
        if (pts != AV_NOPTS_VALUE)
            break;
890
    }
891
    ogg_reset(s);
892
    return pts;
893 894
}

895 896
static int ogg_read_seek(AVFormatContext *s, int stream_index,
                         int64_t timestamp, int flags)
David Conrad's avatar
David Conrad committed
897
{
898
    struct ogg *ogg       = s->priv_data;
David Conrad's avatar
David Conrad committed
899 900 901
    struct ogg_stream *os = ogg->streams + stream_index;
    int ret;

902
    av_assert0(stream_index < ogg->nstreams);
903 904
    // Ensure everything is reset even when seeking via
    // the generated index.
905
    ogg_reset(s);
906

David Conrad's avatar
David Conrad committed
907 908
    // Try seeking to a keyframe first. If this fails (very possible),
    // av_seek_frame will fall back to ignoring keyframes
909
    if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
David Conrad's avatar
David Conrad committed
910 911 912
        && !(flags & AVSEEK_FLAG_ANY))
        os->keyframe_seek = 1;

913
    ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
914
    ogg_reset(s);
915
    os  = ogg->streams + stream_index;
David Conrad's avatar
David Conrad committed
916 917 918 919 920
    if (ret < 0)
        os->keyframe_seek = 0;
    return ret;
}

921 922
static int ogg_probe(AVProbeData *p)
{
923
    if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
924
        return AVPROBE_SCORE_MAX;
925
    return 0;
926 927
}

928
AVInputFormat ff_ogg_demuxer = {
929 930 931 932 933 934 935 936 937 938
    .name           = "ogg",
    .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
    .priv_data_size = sizeof(struct ogg),
    .read_probe     = ogg_probe,
    .read_header    = ogg_read_header,
    .read_packet    = ogg_read_packet,
    .read_close     = ogg_read_close,
    .read_seek      = ogg_read_seek,
    .read_timestamp = ogg_read_timestamp,
    .extensions     = "ogg",
939
    .flags          = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
940
};