Statistics
| Branch: | Revision:

ffmpeg / libavformat / oggdec.c @ 72415b2a

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