Statistics
| Branch: | Revision:

ffmpeg / libavformat / oggdec.c @ 81b743eb

History | View | Annotate | Download (15.3 KB)

1 9146ca37 Måns Rullgård
/*
2
 * Ogg bitstream support
3
 * Luca Barbato <lu_zero@gentoo.org>
4
 * Based on tcvp implementation
5 115329f1 Diego Biurrun
 *
6 9146ca37 Måns Rullgård
 */
7
8
/**
9
    Copyright (C) 2005  Michael Ahlberg, Måns Rullgård
10

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

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

22
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
27
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29
    DEALINGS IN THE SOFTWARE.
30
**/
31
32
33
#include <stdio.h>
34 a0ddef24 Diego Biurrun
#include "oggdec.h"
35 9146ca37 Måns Rullgård
#include "avformat.h"
36
37
#define MAX_PAGE_SIZE 65307
38
#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
39
40 77be08ee Måns Rullgård
static const struct ogg_codec * const ogg_codecs[] = {
41 32ad8692 David Conrad
    &ff_skeleton_codec,
42 24ca518b David Conrad
    &ff_dirac_codec,
43 547ea47d Reimar Döffinger
    &ff_speex_codec,
44
    &ff_vorbis_codec,
45
    &ff_theora_codec,
46
    &ff_flac_codec,
47 24ca518b David Conrad
    &ff_old_dirac_codec,
48 547ea47d Reimar Döffinger
    &ff_old_flac_codec,
49
    &ff_ogm_video_codec,
50
    &ff_ogm_audio_codec,
51
    &ff_ogm_text_codec,
52
    &ff_ogm_old_codec,
53 9146ca37 Måns Rullgård
    NULL
54
};
55
56
//FIXME We could avoid some structure duplication
57
static int
58
ogg_save (AVFormatContext * s)
59
{
60 77be08ee Måns Rullgård
    struct ogg *ogg = s->priv_data;
61
    struct ogg_state *ost =
62 ad3aa874 Måns Rullgård
        av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
63 9146ca37 Måns Rullgård
    int i;
64 899681cd Björn Axelsson
    ost->pos = url_ftell (s->pb);
65 9146ca37 Måns Rullgård
    ost->curidx = ogg->curidx;
66
    ost->next = ogg->state;
67 20be72c8 Måns Rullgård
    ost->nstreams = ogg->nstreams;
68 9146ca37 Måns Rullgård
    memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
69
70
    for (i = 0; i < ogg->nstreams; i++){
71 77be08ee Måns Rullgård
        struct ogg_stream *os = ogg->streams + i;
72 9146ca37 Måns Rullgård
        os->buf = av_malloc (os->bufsize);
73
        memset (os->buf, 0, os->bufsize);
74
        memcpy (os->buf, ost->streams[i].buf, os->bufpos);
75
    }
76
77
    ogg->state = ost;
78
79
    return 0;
80
}
81
82
static int
83
ogg_restore (AVFormatContext * s, int discard)
84
{
85 77be08ee Måns Rullgård
    struct ogg *ogg = s->priv_data;
86 899681cd Björn Axelsson
    ByteIOContext *bc = s->pb;
87 77be08ee Måns Rullgård
    struct ogg_state *ost = ogg->state;
88 9146ca37 Måns Rullgård
    int i;
89
90
    if (!ost)
91
        return 0;
92
93
    ogg->state = ost->next;
94
95
    if (!discard){
96
        for (i = 0; i < ogg->nstreams; i++)
97
            av_free (ogg->streams[i].buf);
98
99
        url_fseek (bc, ost->pos, SEEK_SET);
100
        ogg->curidx = ost->curidx;
101 20be72c8 Måns Rullgård
        ogg->nstreams = ost->nstreams;
102
        memcpy(ogg->streams, ost->streams,
103
               ost->nstreams * sizeof(*ogg->streams));
104 9146ca37 Måns Rullgård
    }
105
106
    av_free (ost);
107
108
    return 0;
109
}
110
111
static int
112 77be08ee Måns Rullgård
ogg_reset (struct ogg * ogg)
113 9146ca37 Måns Rullgård
{
114
    int i;
115
116
    for (i = 0; i < ogg->nstreams; i++){
117 77be08ee Måns Rullgård
        struct ogg_stream *os = ogg->streams + i;
118 9146ca37 Måns Rullgård
        os->bufpos = 0;
119
        os->pstart = 0;
120
        os->psize = 0;
121
        os->granule = -1;
122 5e15c7d9 David Conrad
        os->lastpts = AV_NOPTS_VALUE;
123 2d4970d8 David Conrad
        os->lastdts = AV_NOPTS_VALUE;
124 73823cb9 David Conrad
        os->sync_pos = -1;
125
        os->page_pos = 0;
126 9146ca37 Måns Rullgård
        os->nsegs = 0;
127
        os->segp = 0;
128 ecc0027b David Conrad
        os->incomplete = 0;
129 9146ca37 Måns Rullgård
    }
130
131
    ogg->curidx = -1;
132
133
    return 0;
134
}
135
136 77be08ee Måns Rullgård
static const struct ogg_codec *
137 2d2f443d Måns Rullgård
ogg_find_codec (uint8_t * buf, int size)
138 9146ca37 Måns Rullgård
{
139
    int i;
140
141
    for (i = 0; ogg_codecs[i]; i++)
142
        if (size >= ogg_codecs[i]->magicsize &&
143
            !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
144
            return ogg_codecs[i];
145
146
    return NULL;
147
}
148
149
static int
150
ogg_new_stream (AVFormatContext * s, uint32_t serial)
151
{
152
153 77be08ee Måns Rullgård
    struct ogg *ogg = s->priv_data;
154 9146ca37 Måns Rullgård
    int idx = ogg->nstreams++;
155
    AVStream *st;
156 77be08ee Måns Rullgård
    struct ogg_stream *os;
157 9146ca37 Måns Rullgård
158
    ogg->streams = av_realloc (ogg->streams,
159
                               ogg->nstreams * sizeof (*ogg->streams));
160
    memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
161
    os = ogg->streams + idx;
162
    os->serial = serial;
163
    os->bufsize = DECODER_BUFFER_SIZE;
164 40c5e1fa Måns Rullgård
    os->buf = av_malloc(os->bufsize);
165 9146ca37 Måns Rullgård
    os->header = -1;
166
167
    st = av_new_stream (s, idx);
168
    if (!st)
169 769e10f0 Panagiotis Issaris
        return AVERROR(ENOMEM);
170 9146ca37 Måns Rullgård
171
    av_set_pts_info(st, 64, 1, 1000000);
172
173
    return idx;
174
}
175
176
static int
177 77be08ee Måns Rullgård
ogg_new_buf(struct ogg *ogg, int idx)
178 12a195e3 Måns Rullgård
{
179 77be08ee Måns Rullgård
    struct ogg_stream *os = ogg->streams + idx;
180 ea02862a Måns Rullgård
    uint8_t *nb = av_malloc(os->bufsize);
181 12a195e3 Måns Rullgård
    int size = os->bufpos - os->pstart;
182
    if(os->buf){
183
        memcpy(nb, os->buf + os->pstart, size);
184
        av_free(os->buf);
185
    }
186
    os->buf = nb;
187
    os->bufpos = size;
188
    os->pstart = 0;
189
190
    return 0;
191
}
192
193
static int
194 9146ca37 Måns Rullgård
ogg_read_page (AVFormatContext * s, int *str)
195
{
196 899681cd Björn Axelsson
    ByteIOContext *bc = s->pb;
197 77be08ee Måns Rullgård
    struct ogg *ogg = s->priv_data;
198
    struct ogg_stream *os;
199 9146ca37 Måns Rullgård
    int i = 0;
200
    int flags, nsegs;
201
    uint64_t gp;
202
    uint32_t serial;
203
    uint32_t seq;
204
    uint32_t crc;
205
    int size, idx;
206 191e8ca7 Måns Rullgård
    uint8_t sync[4];
207 9146ca37 Måns Rullgård
    int sp = 0;
208
209
    if (get_buffer (bc, sync, 4) < 4)
210
        return -1;
211
212
    do{
213
        int c;
214
215
        if (sync[sp & 3] == 'O' &&
216
            sync[(sp + 1) & 3] == 'g' &&
217
            sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
218
            break;
219
220
        c = url_fgetc (bc);
221
        if (c < 0)
222
            return -1;
223
        sync[sp++ & 3] = c;
224
    }while (i++ < MAX_PAGE_SIZE);
225
226
    if (i >= MAX_PAGE_SIZE){
227
        av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
228
        return -1;
229
    }
230
231
    if (url_fgetc (bc) != 0)      /* version */
232
        return -1;
233
234
    flags = url_fgetc (bc);
235
    gp = get_le64 (bc);
236
    serial = get_le32 (bc);
237
    seq = get_le32 (bc);
238
    crc = get_le32 (bc);
239
    nsegs = url_fgetc (bc);
240
241
    idx = ogg_find_stream (ogg, serial);
242
    if (idx < 0){
243
        idx = ogg_new_stream (s, serial);
244
        if (idx < 0)
245
            return -1;
246
    }
247
248
    os = ogg->streams + idx;
249 73823cb9 David Conrad
    os->page_pos = url_ftell(bc) - 27;
250 9146ca37 Måns Rullgård
251 40c5e1fa Måns Rullgård
    if(os->psize > 0)
252 12a195e3 Måns Rullgård
        ogg_new_buf(ogg, idx);
253
254 9146ca37 Måns Rullgård
    if (get_buffer (bc, os->segments, nsegs) < nsegs)
255
        return -1;
256
257
    os->nsegs = nsegs;
258
    os->segp = 0;
259
260
    size = 0;
261
    for (i = 0; i < nsegs; i++)
262
        size += os->segments[i];
263
264 ecc0027b David Conrad
    if (flags & OGG_FLAG_CONT || os->incomplete){
265 9146ca37 Måns Rullgård
        if (!os->psize){
266
            while (os->segp < os->nsegs){
267
                int seg = os->segments[os->segp++];
268
                os->pstart += seg;
269
                if (seg < 255)
270 bad4a6bb Peter Ross
                    break;
271 9146ca37 Måns Rullgård
            }
272 73823cb9 David Conrad
            os->sync_pos = os->page_pos;
273 9146ca37 Måns Rullgård
        }
274
    }else{
275 bad4a6bb Peter Ross
        os->psize = 0;
276 73823cb9 David Conrad
        os->sync_pos = os->page_pos;
277 9146ca37 Måns Rullgård
    }
278
279
    if (os->bufsize - os->bufpos < size){
280 2d2f443d Måns Rullgård
        uint8_t *nb = av_malloc (os->bufsize *= 2);
281 9146ca37 Måns Rullgård
        memcpy (nb, os->buf, os->bufpos);
282
        av_free (os->buf);
283
        os->buf = nb;
284
    }
285
286
    if (get_buffer (bc, os->buf + os->bufpos, size) < size)
287
        return -1;
288
289
    os->bufpos += size;
290
    os->granule = gp;
291
    os->flags = flags;
292
293
    if (str)
294
        *str = idx;
295
296
    return 0;
297
}
298
299
static int
300 73823cb9 David Conrad
ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpos)
301 9146ca37 Måns Rullgård
{
302 77be08ee Måns Rullgård
    struct ogg *ogg = s->priv_data;
303 5e15c7d9 David Conrad
    int idx, i;
304 77be08ee Måns Rullgård
    struct ogg_stream *os;
305 9146ca37 Måns Rullgård
    int complete = 0;
306
    int segp = 0, psize = 0;
307
308
#if 0
309
    av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
310
#endif
311
312
    do{
313
        idx = ogg->curidx;
314
315
        while (idx < 0){
316
            if (ogg_read_page (s, &idx) < 0)
317
                return -1;
318
        }
319
320
        os = ogg->streams + idx;
321
322
#if 0
323
        av_log (s, AV_LOG_DEBUG,
324
                "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
325
                idx, os->pstart, os->psize, os->segp, os->nsegs);
326
#endif
327
328
        if (!os->codec){
329
            if (os->header < 0){
330
                os->codec = ogg_find_codec (os->buf, os->bufpos);
331
                if (!os->codec){
332
                    os->header = 0;
333
                    return 0;
334
                }
335
            }else{
336
                return 0;
337
            }
338
        }
339
340
        segp = os->segp;
341
        psize = os->psize;
342
343
        while (os->segp < os->nsegs){
344
            int ss = os->segments[os->segp++];
345
            os->psize += ss;
346
            if (ss < 255){
347
                complete = 1;
348
                break;
349
            }
350
        }
351
352
        if (!complete && os->segp == os->nsegs){
353
            ogg->curidx = -1;
354 ecc0027b David Conrad
            os->incomplete = 1;
355 9146ca37 Måns Rullgård
        }
356
    }while (!complete);
357
358
#if 0
359
    av_log (s, AV_LOG_DEBUG,
360
            "ogg_packet: idx %i, frame size %i, start %i\n",
361
            idx, os->psize, os->pstart);
362
#endif
363
364
    ogg->curidx = idx;
365 ecc0027b David Conrad
    os->incomplete = 0;
366 9146ca37 Måns Rullgård
367 81b743eb David Conrad
    if (os->header) {
368
        os->header = os->codec->header (s, idx);
369
        if (!os->header){
370 bad4a6bb Peter Ross
            os->segp = segp;
371
            os->psize = psize;
372 81b743eb David Conrad
            if (!ogg->headers)
373
                s->data_offset = os->sync_pos;
374 bad4a6bb Peter Ross
            ogg->headers = 1;
375 9146ca37 Måns Rullgård
        }else{
376 bad4a6bb Peter Ross
            os->pstart += os->psize;
377
            os->psize = 0;
378 9146ca37 Måns Rullgård
        }
379 81b743eb David Conrad
    } else {
380 e1a794b2 Måns Rullgård
        os->pflags = 0;
381 15299b38 Justin Ruggles
        os->pduration = 0;
382 9146ca37 Måns Rullgård
        if (os->codec && os->codec->packet)
383
            os->codec->packet (s, idx);
384
        if (str)
385
            *str = idx;
386 12a195e3 Måns Rullgård
        if (dstart)
387
            *dstart = os->pstart;
388
        if (dsize)
389
            *dsize = os->psize;
390 73823cb9 David Conrad
        if (fpos)
391
            *fpos = os->sync_pos;
392 12a195e3 Måns Rullgård
        os->pstart += os->psize;
393
        os->psize = 0;
394 73823cb9 David Conrad
        os->sync_pos = os->page_pos;
395 9146ca37 Måns Rullgård
    }
396
397 5e15c7d9 David Conrad
    // determine whether there are more complete packets in this page
398
    // if not, the page's granule will apply to this packet
399
    os->page_end = 1;
400
    for (i = os->segp; i < os->nsegs; i++)
401
        if (os->segments[i] < 255) {
402
            os->page_end = 0;
403
            break;
404
        }
405
406 9146ca37 Måns Rullgård
    if (os->segp == os->nsegs)
407
        ogg->curidx = -1;
408
409
    return 0;
410
}
411
412
static int
413
ogg_get_headers (AVFormatContext * s)
414
{
415 77be08ee Måns Rullgård
    struct ogg *ogg = s->priv_data;
416 9146ca37 Måns Rullgård
417
    do{
418 73823cb9 David Conrad
        if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
419 9146ca37 Måns Rullgård
            return -1;
420
    }while (!ogg->headers);
421
422
#if 0
423
    av_log (s, AV_LOG_DEBUG, "found headers\n");
424
#endif
425
426
    return 0;
427
}
428
429
static int
430
ogg_get_length (AVFormatContext * s)
431
{
432 77be08ee Måns Rullgård
    struct ogg *ogg = s->priv_data;
433 9146ca37 Måns Rullgård
    int idx = -1, i;
434 bc5c918e Diego Biurrun
    int64_t size, end;
435 69599eea Måns Rullgård
436 ceeacce6 Aurelien Jacobs
    if(url_is_streamed(s->pb))
437 69599eea Måns Rullgård
        return 0;
438 9146ca37 Måns Rullgård
439
// already set
440
    if (s->duration != AV_NOPTS_VALUE)
441
        return 0;
442
443 899681cd Björn Axelsson
    size = url_fsize(s->pb);
444 56466d7b Måns Rullgård
    if(size < 0)
445
        return 0;
446 ddd94932 David Conrad
    end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
447 56466d7b Måns Rullgård
448 9146ca37 Måns Rullgård
    ogg_save (s);
449 899681cd Björn Axelsson
    url_fseek (s->pb, end, SEEK_SET);
450 9146ca37 Måns Rullgård
451
    while (!ogg_read_page (s, &i)){
452 e22f2aaf Måns Rullgård
        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
453
            ogg->streams[i].codec)
454 9146ca37 Måns Rullgård
            idx = i;
455
    }
456
457
    if (idx != -1){
458
        s->streams[idx]->duration =
459 2d4970d8 David Conrad
            ogg_gptopts (s, idx, ogg->streams[idx].granule, NULL);
460 77560b0e David Conrad
        if (s->streams[idx]->start_time != AV_NOPTS_VALUE)
461
            s->streams[idx]->duration -= s->streams[idx]->start_time;
462 9146ca37 Måns Rullgård
    }
463
464 56466d7b Måns Rullgård
    ogg->size = size;
465 9146ca37 Måns Rullgård
    ogg_restore (s, 0);
466
467
    return 0;
468
}
469
470
471
static int
472
ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
473
{
474 77be08ee Måns Rullgård
    struct ogg *ogg = s->priv_data;
475 c9da676d Reimar Döffinger
    int i;
476 9146ca37 Måns Rullgård
    ogg->curidx = -1;
477
    //linear headers seek from start
478
    if (ogg_get_headers (s) < 0){
479 bad4a6bb Peter Ross
        return -1;
480 9146ca37 Måns Rullgård
    }
481
482 c9da676d Reimar Döffinger
    for (i = 0; i < ogg->nstreams; i++)
483
        if (ogg->streams[i].header < 0)
484
            ogg->streams[i].codec = NULL;
485
486 9146ca37 Måns Rullgård
    //linear granulepos seek from end
487
    ogg_get_length (s);
488
489
    //fill the extradata in the per codec callbacks
490
    return 0;
491
}
492
493 6abaa272 David Conrad
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
494
{
495
    struct ogg *ogg = s->priv_data;
496
    struct ogg_stream *os = ogg->streams + idx;
497
    int64_t pts = AV_NOPTS_VALUE;
498
499
    if (dts)
500
        *dts = AV_NOPTS_VALUE;
501
502
    if (os->lastpts != AV_NOPTS_VALUE) {
503
        pts = os->lastpts;
504
        os->lastpts = AV_NOPTS_VALUE;
505
    }
506
    if (os->lastdts != AV_NOPTS_VALUE) {
507
        if (dts)
508
            *dts = os->lastdts;
509
        os->lastdts = AV_NOPTS_VALUE;
510
    }
511
    if (os->page_end) {
512
        if (os->granule != -1LL) {
513
            if (os->codec && os->codec->granule_is_start)
514
                pts = ogg_gptopts(s, idx, os->granule, dts);
515
            else
516
                os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
517
            os->granule = -1LL;
518
        } else
519
            av_log(s, AV_LOG_WARNING, "Packet is missing granule\n");
520
    }
521
    return pts;
522
}
523 9146ca37 Måns Rullgård
524
static int
525
ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
526
{
527 77be08ee Måns Rullgård
    struct ogg *ogg;
528
    struct ogg_stream *os;
529 9146ca37 Måns Rullgård
    int idx = -1;
530 12a195e3 Måns Rullgård
    int pstart, psize;
531 d8b91fae David Conrad
    int64_t fpos, pts, dts;
532 9146ca37 Måns Rullgård
533 115329f1 Diego Biurrun
    //Get an ogg packet
534 d8b91fae David Conrad
retry:
535 9146ca37 Måns Rullgård
    do{
536 73823cb9 David Conrad
        if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
537 6f3e0b21 Panagiotis Issaris
            return AVERROR(EIO);
538 9146ca37 Måns Rullgård
    }while (idx < 0 || !s->streams[idx]);
539
540
    ogg = s->priv_data;
541
    os = ogg->streams + idx;
542
543 d8b91fae David Conrad
    // pflags might not be set until after this
544
    pts = ogg_calc_pts(s, idx, &dts);
545
546
    if (os->keyframe_seek && !(os->pflags & PKT_FLAG_KEY))
547
        goto retry;
548
    os->keyframe_seek = 0;
549
550 9146ca37 Måns Rullgård
    //Alloc a pkt
551 12a195e3 Måns Rullgård
    if (av_new_packet (pkt, psize) < 0)
552 6f3e0b21 Panagiotis Issaris
        return AVERROR(EIO);
553 9146ca37 Måns Rullgård
    pkt->stream_index = idx;
554 12a195e3 Måns Rullgård
    memcpy (pkt->data, os->buf + pstart, psize);
555 5e15c7d9 David Conrad
556 d8b91fae David Conrad
    pkt->pts = pts;
557
    pkt->dts = dts;
558 e1a794b2 Måns Rullgård
    pkt->flags = os->pflags;
559 15299b38 Justin Ruggles
    pkt->duration = os->pduration;
560 73823cb9 David Conrad
    pkt->pos = fpos;
561 e1a794b2 Måns Rullgård
562 12a195e3 Måns Rullgård
    return psize;
563 9146ca37 Måns Rullgård
}
564
565
566
static int
567
ogg_read_close (AVFormatContext * s)
568
{
569 77be08ee Måns Rullgård
    struct ogg *ogg = s->priv_data;
570 9146ca37 Måns Rullgård
    int i;
571
572
    for (i = 0; i < ogg->nstreams; i++){
573
        av_free (ogg->streams[i].buf);
574 1ed923ea Måns Rullgård
        av_free (ogg->streams[i].private);
575 9146ca37 Måns Rullgård
    }
576
    av_free (ogg->streams);
577
    return 0;
578
}
579
580
581
static int64_t
582
ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
583
                    int64_t pos_limit)
584
{
585 77be08ee Måns Rullgård
    struct ogg *ogg = s->priv_data;
586 d8b91fae David Conrad
    struct ogg_stream *os = ogg->streams + stream_index;
587 899681cd Björn Axelsson
    ByteIOContext *bc = s->pb;
588 a1f29b95 Reimar Döffinger
    int64_t pts = AV_NOPTS_VALUE;
589
    int i;
590
    url_fseek(bc, *pos_arg, SEEK_SET);
591 873d117e David Conrad
    ogg_reset(ogg);
592
593
    while (url_ftell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
594
        if (i == stream_index) {
595
            pts = ogg_calc_pts(s, i, NULL);
596 d8b91fae David Conrad
            if (os->keyframe_seek && !(os->pflags & PKT_FLAG_KEY))
597
                pts = AV_NOPTS_VALUE;
598 a1f29b95 Reimar Döffinger
        }
599 873d117e David Conrad
        if (pts != AV_NOPTS_VALUE)
600
            break;
601 a1f29b95 Reimar Döffinger
    }
602
    ogg_reset(ogg);
603
    return pts;
604 9146ca37 Måns Rullgård
}
605
606 d8b91fae David Conrad
static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
607
{
608
    struct ogg *ogg = s->priv_data;
609
    struct ogg_stream *os = ogg->streams + stream_index;
610
    int ret;
611
612
    // Try seeking to a keyframe first. If this fails (very possible),
613
    // av_seek_frame will fall back to ignoring keyframes
614
    if (s->streams[stream_index]->codec->codec_type == CODEC_TYPE_VIDEO
615
        && !(flags & AVSEEK_FLAG_ANY))
616
        os->keyframe_seek = 1;
617
618
    ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
619
    if (ret < 0)
620
        os->keyframe_seek = 0;
621
    return ret;
622
}
623
624 2e70e4aa Måns Rullgård
static int ogg_probe(AVProbeData *p)
625
{
626
    if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
627
        p->buf[2] == 'g' && p->buf[3] == 'S' &&
628
        p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
629
        return AVPROBE_SCORE_MAX;
630
    else
631
        return 0;
632
}
633
634 ff70e601 Måns Rullgård
AVInputFormat ogg_demuxer = {
635 9146ca37 Måns Rullgård
    "ogg",
636 bde15e74 Stefano Sabatini
    NULL_IF_CONFIG_SMALL("Ogg"),
637 77be08ee Måns Rullgård
    sizeof (struct ogg),
638 2e70e4aa Måns Rullgård
    ogg_probe,
639 9146ca37 Måns Rullgård
    ogg_read_header,
640
    ogg_read_packet,
641
    ogg_read_close,
642 d8b91fae David Conrad
    ogg_read_seek,
643 a1f29b95 Reimar Döffinger
    ogg_read_timestamp,
644 9146ca37 Måns Rullgård
    .extensions = "ogg",
645 d7bb185f Justin Ruggles
    .metadata_conv = ff_vorbiscomment_metadata_conv,
646 9146ca37 Måns Rullgård
};