oggdec.c 25.4 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_dirac_codec,
45 46 47 48
    &ff_speex_codec,
    &ff_vorbis_codec,
    &ff_theora_codec,
    &ff_flac_codec,
49
    &ff_celt_codec,
50
    &ff_opus_codec,
51
    &ff_vp8_codec,
52
    &ff_old_dirac_codec,
53 54 55 56 57
    &ff_old_flac_codec,
    &ff_ogm_video_codec,
    &ff_ogm_audio_codec,
    &ff_ogm_text_codec,
    &ff_ogm_old_codec,
58 59 60
    NULL
};

61
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts);
62
static int ogg_new_stream(AVFormatContext *s, uint32_t serial);
63

64
//FIXME We could avoid some structure duplication
65
static int ogg_save(AVFormatContext *s)
66
{
67 68
    struct ogg *ogg = s->priv_data;
    struct ogg_state *ost =
69
        av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
70
    int i;
71 72 73
    ost->pos      = avio_tell(s->pb);
    ost->curidx   = ogg->curidx;
    ost->next     = ogg->state;
74
    ost->nstreams = ogg->nstreams;
75 76
    memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));

77
    for (i = 0; i < ogg->nstreams; i++) {
78
        struct ogg_stream *os = ogg->streams + i;
79 80
        os->buf = av_mallocz(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
        memcpy(os->buf, ost->streams[i].buf, os->bufpos);
81 82
        os->new_metadata      = NULL;
        os->new_metadata_size = 0;
83 84 85 86 87 88 89
    }

    ogg->state = ost;

    return 0;
}

90
static int ogg_restore(AVFormatContext *s, int discard)
91
{
92
    struct ogg *ogg = s->priv_data;
93
    AVIOContext *bc = s->pb;
94
    struct ogg_state *ost = ogg->state;
95
    int i, err;
96 97 98 99 100 101

    if (!ost)
        return 0;

    ogg->state = ost->next;

102
    if (!discard) {
103

104
        for (i = 0; i < ogg->nstreams; i++)
105
            av_freep(&ogg->streams[i].buf);
106

107
        avio_seek(bc, ost->pos, SEEK_SET);
108
        ogg->page_pos = -1;
109
        ogg->curidx   = ost->curidx;
110
        ogg->nstreams = ost->nstreams;
111 112 113 114 115
        if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams,
                                     sizeof(*ogg->streams))) < 0) {
            ogg->nstreams = 0;
            return err;
        } else
116 117
            memcpy(ogg->streams, ost->streams,
                   ost->nstreams * sizeof(*ogg->streams));
118 119
    }

120
    av_free(ost);
121 122 123 124

    return 0;
}

125
static int ogg_reset(AVFormatContext *s)
126
{
127
    struct ogg *ogg = s->priv_data;
128
    int i;
129
    int64_t start_pos = avio_tell(s->pb);
130

131
    for (i = 0; i < ogg->nstreams; i++) {
132
        struct ogg_stream *os = ogg->streams + i;
133 134 135 136 137 138 139 140 141 142
        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;
143
        os->incomplete = 0;
144
        os->got_data = 0;
145 146 147
        if (start_pos <= s->data_offset) {
            os->lastpts = 0;
        }
148
        os->end_trimming = 0;
149 150
        av_freep(&os->new_metadata);
        os->new_metadata_size = 0;
151 152
    }

153
    ogg->page_pos = -1;
154 155 156 157 158
    ogg->curidx = -1;

    return 0;
}

159
static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
160 161 162 163 164
{
    int i;

    for (i = 0; ogg_codecs[i]; i++)
        if (size >= ogg_codecs[i]->magicsize &&
165
            !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
166 167 168 169 170
            return ogg_codecs[i];

    return NULL;
}

171 172 173 174 175
/**
 * 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).
 */
176
static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int nsegs)
177
{
178 179
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os;
180
    const struct ogg_codec *codec;
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
    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) {
201
        avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
202 203 204
        return AVERROR_PATCHWELCOME;
    }

205
    os = &ogg->streams[i];
206

207
    os->serial  = serial;
208
    return i;
209

210
#if 0
211
    buf     = os->buf;
212
    bufsize = os->bufsize;
213
    codec   = os->codec;
214

215 216
    if (!ogg->state || ogg->state->streams[i].private != os->private)
        av_freep(&ogg->streams[i].private);
217 218 219 220

    /* 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));
221
    os->serial  = serial;
222
    os->bufsize = bufsize;
223 224 225
    os->buf     = buf;
    os->header  = -1;
    os->codec   = codec;
226

227
    return i;
228
#endif
229
}
230

231 232
static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
{
233
    struct ogg *ogg = s->priv_data;
234
    int idx         = ogg->nstreams;
235
    AVStream *st;
236
    struct ogg_stream *os;
237
    size_t size;
238

239 240 241 242 243 244
    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;
    }

245
    /* Allocate and init a new Ogg Stream */
246 247 248
    if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
        !(os = av_realloc(ogg->streams, size)))
        return AVERROR(ENOMEM);
249 250
    ogg->streams = os;
    os           = ogg->streams + idx;
251
    memset(os, 0, sizeof(*os));
252 253 254 255
    os->serial        = serial;
    os->bufsize       = DECODER_BUFFER_SIZE;
    os->buf           = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
    os->header        = -1;
256
    os->start_granule = OGG_NOGRANULE_VALUE;
257 258
    if (!os->buf)
        return AVERROR(ENOMEM);
259

260 261 262 263 264 265 266 267
    /* 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);
268

269
    ogg->nstreams++;
270 271 272
    return idx;
}

273
static int ogg_new_buf(struct ogg *ogg, int idx)
274
{
275
    struct ogg_stream *os = ogg->streams + idx;
276
    uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
277
    int size = os->bufpos - os->pstart;
278 279

    if (os->buf) {
280 281 282
        memcpy(nb, os->buf + os->pstart, size);
        av_free(os->buf);
    }
283 284

    os->buf    = nb;
285 286 287 288 289 290
    os->bufpos = size;
    os->pstart = 0;

    return 0;
}

291 292 293 294 295 296 297 298 299 300
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;
}

301
static int ogg_read_page(AVFormatContext *s, int *sid)
302
{
303
    AVIOContext *bc = s->pb;
304 305
    struct ogg *ogg = s->priv_data;
    struct ogg_stream *os;
306
    int ret, i = 0;
307 308 309 310
    int flags, nsegs;
    uint64_t gp;
    uint32_t serial;
    int size, idx;
311
    uint8_t sync[4];
312 313
    int sp = 0;

314
    ret = avio_read(bc, sync, 4);
315 316
    if (ret < 4)
        return ret < 0 ? ret : AVERROR_EOF;
317

318
    do {
319 320 321 322 323 324 325
        int c;

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

326 327 328 329 330 331
        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;
        }

332
        c = avio_r8(bc);
333

334
        if (url_feof(bc))
335
            return AVERROR_EOF;
336

337
        sync[sp++ & 3] = c;
338
    } while (i++ < MAX_PAGE_SIZE);
339

340 341
    if (i >= MAX_PAGE_SIZE) {
        av_log(s, AV_LOG_INFO, "cannot find sync word\n");
342
        return AVERROR_INVALIDDATA;
343 344
    }

345
    if (avio_r8(bc) != 0) {      /* version */
346
        av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
347
        return AVERROR_INVALIDDATA;
348
    }
349

350 351 352
    flags  = avio_r8(bc);
    gp     = avio_rl64(bc);
    serial = avio_rl32(bc);
Mans Rullgard's avatar
Mans Rullgard committed
353
    avio_skip(bc, 8); /* seq, crc */
354
    nsegs  = avio_r8(bc);
355

356 357
    idx = ogg_find_stream(ogg, serial);
    if (idx < 0) {
358
        if (data_packets_seen(ogg))
359
            idx = ogg_replace_stream(s, serial, nsegs);
360 361
        else
            idx = ogg_new_stream(s, serial);
362

363
        if (idx < 0) {
364
            av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
365
            return idx;
366
        }
367 368 369
    }

    os = ogg->streams + idx;
370
    ogg->page_pos =
371
    os->page_pos = avio_tell(bc) - 27;
372

373
    if (os->psize > 0)
374 375
        ogg_new_buf(ogg, idx);

376
    ret = avio_read(bc, os->segments, nsegs);
377 378
    if (ret < nsegs)
        return ret < 0 ? ret : AVERROR_EOF;
379 380

    os->nsegs = nsegs;
381
    os->segp  = 0;
382 383 384 385 386

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

387 388 389
    if (!(flags & OGG_FLAG_BOS))
        os->got_data = 1;

390 391
    if (flags & OGG_FLAG_CONT || os->incomplete) {
        if (!os->psize) {
392 393 394
            // 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.
395
            while (os->segp < os->nsegs) {
396 397 398
                int seg = os->segments[os->segp++];
                os->pstart += seg;
                if (seg < 255)
399
                    break;
400
            }
401
            os->sync_pos = os->page_pos;
402
        }
403 404
    } else {
        os->psize    = 0;
405
        os->sync_pos = os->page_pos;
406 407
    }

408 409
    if (os->bufsize - os->bufpos < size) {
        uint8_t *nb = av_malloc((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
410 411
        if (!nb)
            return AVERROR(ENOMEM);
412 413
        memcpy(nb, os->buf, os->bufpos);
        av_free(os->buf);
414 415 416
        os->buf = nb;
    }

417
    ret = avio_read(bc, os->buf + os->bufpos, size);
418 419
    if (ret < size)
        return ret < 0 ? ret : AVERROR_EOF;
420 421 422

    os->bufpos += size;
    os->granule = gp;
423
    os->flags   = flags;
424

425
    memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
426 427
    if (sid)
        *sid = idx;
428 429 430 431

    return 0;
}

432 433
/**
 * @brief find the next Ogg packet
434
 * @param *sid is set to the stream for the packet or -1 if there is
435 436 437 438
 *             no matching stream, in that case assume all other return
 *             values to be uninitialized.
 * @return negative value on error or EOF.
 */
439
static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
440
                      int64_t *fpos)
441
{
442
    struct ogg *ogg = s->priv_data;
443
    int idx, i, ret;
444
    struct ogg_stream *os;
445
    int complete = 0;
446
    int segp     = 0, psize = 0;
447

Stefano Sabatini's avatar
Stefano Sabatini committed
448
    av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
449 450
    if (sid)
        *sid = -1;
451

452
    do {
453 454
        idx = ogg->curidx;

455
        while (idx < 0) {
456
            ret = ogg_read_page(s, &idx);
457 458
            if (ret < 0)
                return ret;
459 460 461 462
        }

        os = ogg->streams + idx;

Stefano Sabatini's avatar
Stefano Sabatini committed
463
        av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
464 465
                idx, os->pstart, os->psize, os->segp, os->nsegs);

466 467 468 469
        if (!os->codec) {
            if (os->header < 0) {
                os->codec = ogg_find_codec(os->buf, os->bufpos);
                if (!os->codec) {
470
                    av_log(s, AV_LOG_WARNING, "Codec not found\n");
471 472 473
                    os->header = 0;
                    return 0;
                }
474
            } else {
475 476 477 478
                return 0;
            }
        }

479
        segp  = os->segp;
480 481
        psize = os->psize;

482
        while (os->segp < os->nsegs) {
483 484
            int ss = os->segments[os->segp++];
            os->psize += ss;
485
            if (ss < 255) {
486 487 488 489 490
                complete = 1;
                break;
            }
        }

491 492
        if (!complete && os->segp == os->nsegs) {
            ogg->curidx    = -1;
493 494 495 496 497
            // 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;
498
        }
499
    } while (!complete);
500 501


502
    if (os->granule == -1)
503 504 505
        av_log(s, AV_LOG_WARNING,
               "Page at %"PRId64" is missing granule\n",
               os->page_pos);
506

507
    ogg->curidx    = idx;
508
    os->incomplete = 0;
509

510
    if (os->header) {
511 512 513
        os->header = os->codec->header(s, idx);
        if (!os->header) {
            os->segp  = segp;
514
            os->psize = psize;
515

516 517
            // We have reached the first non-header packet in this stream.
            // Unfortunately more header packets may still follow for others,
518
            // but if we continue with header parsing we may lose data packets.
519
            ogg->headers = 1;
520 521 522

            // Update the header state for all streams and
            // compute the data_offset.
523 524
            if (!s->data_offset)
                s->data_offset = os->sync_pos;
525

526 527 528 529 530 531 532 533
            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)
                    s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
            }
534
        } else {
535
            os->nb_header++;
536
            os->pstart += os->psize;
537
            os->psize   = 0;
538
        }
539
    } else {
540
        os->pflags    = 0;
541
        os->pduration = 0;
542
        if (os->codec && os->codec->packet)
543
            os->codec->packet(s, idx);
544 545
        if (sid)
            *sid = idx;
546 547 548 549
        if (dstart)
            *dstart = os->pstart;
        if (dsize)
            *dsize = os->psize;
550 551
        if (fpos)
            *fpos = os->sync_pos;
552 553
        os->pstart  += os->psize;
        os->psize    = 0;
554 555
        if(os->pstart == os->bufpos)
            os->bufpos = os->pstart = 0;
556
        os->sync_pos = os->page_pos;
557 558
    }

David Conrad's avatar
David Conrad committed
559 560 561 562 563 564 565 566 567
    // 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;
        }

568 569 570 571 572 573
    if (os->segp == os->nsegs)
        ogg->curidx = -1;

    return 0;
}

574
static int ogg_get_length(AVFormatContext *s)
575
{
576
    struct ogg *ogg = s->priv_data;
577
    int i;
578
    int64_t size, end;
579
    int streams_left=0;
580

581
    if (!s->pb->seekable)
582
        return 0;
583 584 585 586 587

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

588
    size = avio_size(s->pb);
589
    if (size < 0)
Måns Rullgård's avatar
Måns Rullgård committed
590
        return 0;
591
    end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
Måns Rullgård's avatar
Måns Rullgård committed
592

593 594
    ogg_save(s);
    avio_seek(s->pb, end, SEEK_SET);
595
    ogg->page_pos = -1;
596

597
    while (!ogg_read_page(s, &i)) {
598
        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
599 600
            ogg->streams[i].codec) {
            s->streams[i]->duration =
601
                ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
602
            if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
603
                s->streams[i]->duration -= s->streams[i]->start_time;
604 605
                streams_left-= (ogg->streams[i].got_start==-1);
                ogg->streams[i].got_start= 1;
606
            } else if(!ogg->streams[i].got_start) {
607 608 609
                ogg->streams[i].got_start= -1;
                streams_left++;
            }
610
        }
611 612
    }

613
    ogg_restore(s, 0);
614

jan gerber's avatar
jan gerber committed
615
    ogg_save (s);
616
    avio_seek (s->pb, s->data_offset, SEEK_SET);
617
    ogg_reset(s);
618 619 620 621
    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);
622
        if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
623 624 625
            s->streams[i]->duration -= pts;
            ogg->streams[i].got_start= 1;
            streams_left--;
626
        }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
627 628
            ogg->streams[i].got_start= 1;
            streams_left--;
629
        }
jan gerber's avatar
jan gerber committed
630 631 632
    }
    ogg_restore (s, 0);

633 634 635
    return 0;
}

636 637 638 639 640 641
static int ogg_read_close(AVFormatContext *s)
{
    struct ogg *ogg = s->priv_data;
    int i;

    for (i = 0; i < ogg->nstreams; i++) {
642
        av_freep(&ogg->streams[i].buf);
643 644 645 646
        if (ogg->streams[i].codec &&
            ogg->streams[i].codec->cleanup) {
            ogg->streams[i].codec->cleanup(s, i);
        }
647
        av_freep(&ogg->streams[i].private);
648
        av_freep(&ogg->streams[i].new_metadata);
649
    }
650 651 652

    ogg->nstreams = 0;

653
    av_freep(&ogg->streams);
654 655 656
    return 0;
}

657
static int ogg_read_header(AVFormatContext *s)
658
{
659
    struct ogg *ogg = s->priv_data;
660
    int ret, i;
661

662
    ogg->curidx = -1;
663

664
    //linear headers seek from start
665 666
    do {
        ret = ogg_packet(s, NULL, NULL, NULL, NULL);
667 668
        if (ret < 0) {
            ogg_read_close(s);
669
            return ret;
670
        }
671 672
    } while (!ogg->headers);
    av_dlog(s, "found headers\n");
673

674 675 676
    for (i = 0; i < ogg->nstreams; i++) {
        struct ogg_stream *os = ogg->streams + i;

677 678
        if (ogg->streams[i].header < 0) {
            av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
679
            ogg->streams[i].codec = NULL;
680
        } else if (os->codec && os->nb_header < os->codec->nb_header) {
681 682 683 684 685 686
            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;
687
        }
688 689 690
        if (os->start_granule != OGG_NOGRANULE_VALUE)
            os->lastpts = s->streams[i]->start_time =
                ogg_gptopts(s, i, os->start_granule, NULL);
691
    }
692

693
    //linear granulepos seek from end
694
    ogg_get_length(s);
695 696 697 698

    return 0;
}

699 700
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
{
701
    struct ogg *ogg       = s->priv_data;
702
    struct ogg_stream *os = ogg->streams + idx;
703
    int64_t pts           = AV_NOPTS_VALUE;
704 705 706 707 708

    if (dts)
        *dts = AV_NOPTS_VALUE;

    if (os->lastpts != AV_NOPTS_VALUE) {
709
        pts         = os->lastpts;
710 711 712 713 714 715 716 717 718 719 720 721 722 723
        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;
724
        }
725 726 727
    }
    return pts;
}
728

729 730 731 732
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;
733 734 735 736 737 738 739 740 741 742
    int invalid = 0;
    if (psize) {
        switch (s->streams[idx]->codec->codec_id) {
        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) {
743
            os->pflags ^= AV_PKT_FLAG_KEY;
744 745
            av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
                   (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
746 747 748 749
        }
    }
}

750
static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
751
{
752 753
    struct ogg *ogg;
    struct ogg_stream *os;
754
    int idx, ret;
755
    int pstart, psize;
David Conrad's avatar
David Conrad committed
756
    int64_t fpos, pts, dts;
757

758 759 760 761 762
    if (s->io_repositioned) {
        ogg_reset(s);
        s->io_repositioned = 0;
    }

763
    //Get an ogg packet
David Conrad's avatar
David Conrad committed
764
retry:
765
    do {
766
        ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
767 768
        if (ret < 0)
            return ret;
769
    } while (idx < 0 || !s->streams[idx]);
770 771

    ogg = s->priv_data;
772
    os  = ogg->streams + idx;
773

David Conrad's avatar
David Conrad committed
774 775
    // pflags might not be set until after this
    pts = ogg_calc_pts(s, idx, &dts);
776
    ogg_validate_keyframe(s, idx, pstart, psize);
David Conrad's avatar
David Conrad committed
777

778
    if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
David Conrad's avatar
David Conrad committed
779 780 781
        goto retry;
    os->keyframe_seek = 0;

782
    //Alloc a pkt
783
    ret = av_new_packet(pkt, psize);
784 785
    if (ret < 0)
        return ret;
786
    pkt->stream_index = idx;
787
    memcpy(pkt->data, os->buf + pstart, psize);
David Conrad's avatar
David Conrad committed
788

789 790 791
    pkt->pts      = pts;
    pkt->dts      = dts;
    pkt->flags    = os->pflags;
792
    pkt->duration = os->pduration;
793
    pkt->pos      = fpos;
794

795 796 797 798
    if (os->end_trimming) {
        uint8_t *side_data = av_packet_new_side_data(pkt,
                                                     AV_PKT_DATA_SKIP_SAMPLES,
                                                     10);
799 800
        if(side_data == NULL)
            goto fail;
801
        AV_WL32(side_data + 4, os->end_trimming);
802
        os->end_trimming = 0;
803 804
    }

805 806 807 808
    if (os->new_metadata) {
        uint8_t *side_data = av_packet_new_side_data(pkt,
                                                     AV_PKT_DATA_METADATA_UPDATE,
                                                     os->new_metadata_size);
809 810 811
        if(side_data == NULL)
            goto fail;

812 813 814 815 816
        memcpy(side_data, os->new_metadata, os->new_metadata_size);
        av_freep(&os->new_metadata);
        os->new_metadata_size = 0;
    }

817
    return psize;
818 819 820 821
fail:
    av_free_packet(pkt);
    av_free(pkt);
    return AVERROR(ENOMEM);
822 823
}

824 825
static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
                                  int64_t *pos_arg, int64_t pos_limit)
826
{
827
    struct ogg *ogg = s->priv_data;
828
    AVIOContext *bc = s->pb;
829
    int64_t pts     = AV_NOPTS_VALUE;
830
    int64_t keypos  = -1;
831
    int i;
832
    int pstart, psize;
833
    avio_seek(bc, *pos_arg, SEEK_SET);
834
    ogg_reset(s);
835

836 837
    while (   avio_tell(bc) <= pos_limit
           && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
838
        if (i == stream_index) {
839
            struct ogg_stream *os = ogg->streams + stream_index;
840 841 842 843 844
            // Dont trust the last timestamps of a ogm video
            if (    (os->flags & OGG_FLAG_EOS)
                && !(os->flags & OGG_FLAG_BOS)
                && os->codec == &ff_ogm_video_codec)
                continue;
845
            pts = ogg_calc_pts(s, i, NULL);
846
            ogg_validate_keyframe(s, i, pstart, psize);
847 848 849 850 851 852 853 854 855 856
            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;
            }
857
        }
858 859
        if (pts != AV_NOPTS_VALUE)
            break;
860
    }
861
    ogg_reset(s);
862
    return pts;
863 864
}

865 866
static int ogg_read_seek(AVFormatContext *s, int stream_index,
                         int64_t timestamp, int flags)
David Conrad's avatar
David Conrad committed
867
{
868
    struct ogg *ogg       = s->priv_data;
David Conrad's avatar
David Conrad committed
869 870 871
    struct ogg_stream *os = ogg->streams + stream_index;
    int ret;

872
    av_assert0(stream_index < ogg->nstreams);
873 874
    // Ensure everything is reset even when seeking via
    // the generated index.
875
    ogg_reset(s);
876

David Conrad's avatar
David Conrad committed
877 878
    // Try seeking to a keyframe first. If this fails (very possible),
    // av_seek_frame will fall back to ignoring keyframes
879
    if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
David Conrad's avatar
David Conrad committed
880 881 882
        && !(flags & AVSEEK_FLAG_ANY))
        os->keyframe_seek = 1;

883
    ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
884
    os  = ogg->streams + stream_index;
David Conrad's avatar
David Conrad committed
885 886 887 888 889
    if (ret < 0)
        os->keyframe_seek = 0;
    return ret;
}

890 891
static int ogg_probe(AVProbeData *p)
{
892
    if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
893
        return AVPROBE_SCORE_MAX;
894
    return 0;
895 896
}

897
AVInputFormat ff_ogg_demuxer = {
898 899 900 901 902 903 904 905 906 907
    .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",
908
    .flags          = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
909
};