~noskcaj/ubuntu/saucy/libav/merge0.8.7-1

« back to all changes in this revision

Viewing changes to .pc/post-0.7.1/0062-oggdec-fix-out-of-bound-write-in-the-ogg-demuxer.patch/libavformat/oggdec.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2011-09-28 09:18:34 UTC
  • mfrom: (1.3.7 sid)
  • Revision ID: package-import@ubuntu.com-20110928091834-w415mnuh06h4zpvc
Tags: 4:0.7.1-7ubuntu2
Revert "Convert package to include multiarch support."

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Ogg bitstream support
 
3
 * Luca Barbato <lu_zero@gentoo.org>
 
4
 * Based on tcvp implementation
 
5
 *
 
6
 */
 
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
#include "oggdec.h"
 
35
#include "avformat.h"
 
36
#include "vorbiscomment.h"
 
37
 
 
38
#define MAX_PAGE_SIZE 65307
 
39
#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
 
40
 
 
41
static const struct ogg_codec * const ogg_codecs[] = {
 
42
    &ff_skeleton_codec,
 
43
    &ff_dirac_codec,
 
44
    &ff_speex_codec,
 
45
    &ff_vorbis_codec,
 
46
    &ff_theora_codec,
 
47
    &ff_flac_codec,
 
48
    &ff_old_dirac_codec,
 
49
    &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
    NULL
 
55
};
 
56
 
 
57
//FIXME We could avoid some structure duplication
 
58
static int ogg_save(AVFormatContext *s)
 
59
{
 
60
    struct ogg *ogg = s->priv_data;
 
61
    struct ogg_state *ost =
 
62
        av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
 
63
    int i;
 
64
    ost->pos = avio_tell (s->pb);
 
65
    ost->curidx = ogg->curidx;
 
66
    ost->next = ogg->state;
 
67
    ost->nstreams = ogg->nstreams;
 
68
    memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
 
69
 
 
70
    for (i = 0; i < ogg->nstreams; i++){
 
71
        struct ogg_stream *os = ogg->streams + i;
 
72
        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 ogg_restore(AVFormatContext *s, int discard)
 
83
{
 
84
    struct ogg *ogg = s->priv_data;
 
85
    AVIOContext *bc = s->pb;
 
86
    struct ogg_state *ost = ogg->state;
 
87
    int i;
 
88
 
 
89
    if (!ost)
 
90
        return 0;
 
91
 
 
92
    ogg->state = ost->next;
 
93
 
 
94
    if (!discard){
 
95
        for (i = 0; i < ogg->nstreams; i++)
 
96
            av_free (ogg->streams[i].buf);
 
97
 
 
98
        avio_seek (bc, ost->pos, SEEK_SET);
 
99
        ogg->curidx = ost->curidx;
 
100
        ogg->nstreams = ost->nstreams;
 
101
        memcpy(ogg->streams, ost->streams,
 
102
               ost->nstreams * sizeof(*ogg->streams));
 
103
    }
 
104
 
 
105
    av_free (ost);
 
106
 
 
107
    return 0;
 
108
}
 
109
 
 
110
static int ogg_reset(struct ogg *ogg)
 
111
{
 
112
    int i;
 
113
 
 
114
    for (i = 0; i < ogg->nstreams; i++){
 
115
        struct ogg_stream *os = ogg->streams + i;
 
116
        os->bufpos = 0;
 
117
        os->pstart = 0;
 
118
        os->psize = 0;
 
119
        os->granule = -1;
 
120
        os->lastpts = AV_NOPTS_VALUE;
 
121
        os->lastdts = AV_NOPTS_VALUE;
 
122
        os->sync_pos = -1;
 
123
        os->page_pos = 0;
 
124
        os->nsegs = 0;
 
125
        os->segp = 0;
 
126
        os->incomplete = 0;
 
127
    }
 
128
 
 
129
    ogg->curidx = -1;
 
130
 
 
131
    return 0;
 
132
}
 
133
 
 
134
static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
 
135
{
 
136
    int i;
 
137
 
 
138
    for (i = 0; ogg_codecs[i]; i++)
 
139
        if (size >= ogg_codecs[i]->magicsize &&
 
140
            !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
 
141
            return ogg_codecs[i];
 
142
 
 
143
    return NULL;
 
144
}
 
145
 
 
146
static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
 
147
{
 
148
 
 
149
    struct ogg *ogg = s->priv_data;
 
150
    int idx = ogg->nstreams++;
 
151
    AVStream *st;
 
152
    struct ogg_stream *os;
 
153
 
 
154
    ogg->streams = av_realloc (ogg->streams,
 
155
                               ogg->nstreams * sizeof (*ogg->streams));
 
156
    memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
 
157
    os = ogg->streams + idx;
 
158
    os->serial = serial;
 
159
    os->bufsize = DECODER_BUFFER_SIZE;
 
160
    os->buf = av_malloc(os->bufsize);
 
161
    os->header = -1;
 
162
 
 
163
    if (new_avstream) {
 
164
        st = av_new_stream(s, idx);
 
165
        if (!st)
 
166
            return AVERROR(ENOMEM);
 
167
 
 
168
        av_set_pts_info(st, 64, 1, 1000000);
 
169
    }
 
170
 
 
171
    return idx;
 
172
}
 
173
 
 
174
static int ogg_new_buf(struct ogg *ogg, int idx)
 
175
{
 
176
    struct ogg_stream *os = ogg->streams + idx;
 
177
    uint8_t *nb = av_malloc(os->bufsize);
 
178
    int size = os->bufpos - os->pstart;
 
179
    if(os->buf){
 
180
        memcpy(nb, os->buf + os->pstart, size);
 
181
        av_free(os->buf);
 
182
    }
 
183
    os->buf = nb;
 
184
    os->bufpos = size;
 
185
    os->pstart = 0;
 
186
 
 
187
    return 0;
 
188
}
 
189
 
 
190
static int ogg_read_page(AVFormatContext *s, int *str)
 
191
{
 
192
    AVIOContext *bc = s->pb;
 
193
    struct ogg *ogg = s->priv_data;
 
194
    struct ogg_stream *os;
 
195
    int i = 0;
 
196
    int flags, nsegs;
 
197
    uint64_t gp;
 
198
    uint32_t serial;
 
199
    int size, idx;
 
200
    uint8_t sync[4];
 
201
    int sp = 0;
 
202
 
 
203
    if (avio_read (bc, sync, 4) < 4)
 
204
        return -1;
 
205
 
 
206
    do{
 
207
        int c;
 
208
 
 
209
        if (sync[sp & 3] == 'O' &&
 
210
            sync[(sp + 1) & 3] == 'g' &&
 
211
            sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
 
212
            break;
 
213
 
 
214
        c = avio_r8(bc);
 
215
        if (bc->eof_reached)
 
216
            return -1;
 
217
        sync[sp++ & 3] = c;
 
218
    }while (i++ < MAX_PAGE_SIZE);
 
219
 
 
220
    if (i >= MAX_PAGE_SIZE){
 
221
        av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
 
222
        return -1;
 
223
    }
 
224
 
 
225
    if (avio_r8(bc) != 0)      /* version */
 
226
        return -1;
 
227
 
 
228
    flags = avio_r8(bc);
 
229
    gp = avio_rl64 (bc);
 
230
    serial = avio_rl32 (bc);
 
231
    avio_skip(bc, 8); /* seq, crc */
 
232
    nsegs = avio_r8(bc);
 
233
 
 
234
    idx = ogg_find_stream (ogg, serial);
 
235
    if (idx < 0){
 
236
        if (ogg->headers) {
 
237
            int n;
 
238
 
 
239
            for (n = 0; n < ogg->nstreams; n++) {
 
240
                av_freep(&ogg->streams[n].buf);
 
241
                if (!ogg->state || ogg->state->streams[n].private != ogg->streams[n].private)
 
242
                    av_freep(&ogg->streams[n].private);
 
243
            }
 
244
            ogg->curidx   = -1;
 
245
            ogg->nstreams = 0;
 
246
            idx = ogg_new_stream(s, serial, 0);
 
247
        } else {
 
248
            idx = ogg_new_stream(s, serial, 1);
 
249
        }
 
250
        if (idx < 0)
 
251
            return -1;
 
252
    }
 
253
 
 
254
    os = ogg->streams + idx;
 
255
    os->page_pos = avio_tell(bc) - 27;
 
256
 
 
257
    if(os->psize > 0)
 
258
        ogg_new_buf(ogg, idx);
 
259
 
 
260
    if (avio_read (bc, os->segments, nsegs) < nsegs)
 
261
        return -1;
 
262
 
 
263
    os->nsegs = nsegs;
 
264
    os->segp = 0;
 
265
 
 
266
    size = 0;
 
267
    for (i = 0; i < nsegs; i++)
 
268
        size += os->segments[i];
 
269
 
 
270
    if (flags & OGG_FLAG_CONT || os->incomplete){
 
271
        if (!os->psize){
 
272
            while (os->segp < os->nsegs){
 
273
                int seg = os->segments[os->segp++];
 
274
                os->pstart += seg;
 
275
                if (seg < 255)
 
276
                    break;
 
277
            }
 
278
            os->sync_pos = os->page_pos;
 
279
        }
 
280
    }else{
 
281
        os->psize = 0;
 
282
        os->sync_pos = os->page_pos;
 
283
    }
 
284
 
 
285
    if (os->bufsize - os->bufpos < size){
 
286
        uint8_t *nb = av_malloc (os->bufsize *= 2);
 
287
        memcpy (nb, os->buf, os->bufpos);
 
288
        av_free (os->buf);
 
289
        os->buf = nb;
 
290
    }
 
291
 
 
292
    if (avio_read (bc, os->buf + os->bufpos, size) < size)
 
293
        return -1;
 
294
 
 
295
    os->bufpos += size;
 
296
    os->granule = gp;
 
297
    os->flags = flags;
 
298
 
 
299
    if (str)
 
300
        *str = idx;
 
301
 
 
302
    return 0;
 
303
}
 
304
 
 
305
static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
 
306
                      int64_t *fpos)
 
307
{
 
308
    struct ogg *ogg = s->priv_data;
 
309
    int idx, i;
 
310
    struct ogg_stream *os;
 
311
    int complete = 0;
 
312
    int segp = 0, psize = 0;
 
313
 
 
314
    av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
 
315
 
 
316
    do{
 
317
        idx = ogg->curidx;
 
318
 
 
319
        while (idx < 0){
 
320
            if (ogg_read_page (s, &idx) < 0)
 
321
                return -1;
 
322
        }
 
323
 
 
324
        os = ogg->streams + idx;
 
325
 
 
326
        av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
 
327
                idx, os->pstart, os->psize, os->segp, os->nsegs);
 
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
            os->incomplete = 1;
 
356
        }
 
357
    }while (!complete);
 
358
 
 
359
    av_dlog(s, "ogg_packet: idx %i, frame size %i, start %i\n",
 
360
            idx, os->psize, os->pstart);
 
361
 
 
362
    if (os->granule == -1)
 
363
        av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
 
364
 
 
365
    ogg->curidx = idx;
 
366
    os->incomplete = 0;
 
367
 
 
368
    if (os->header) {
 
369
        os->header = os->codec->header (s, idx);
 
370
        if (!os->header){
 
371
            os->segp = segp;
 
372
            os->psize = psize;
 
373
 
 
374
            // We have reached the first non-header packet in this stream.
 
375
            // Unfortunately more header packets may still follow for others,
 
376
            // but if we continue with header parsing we may lose data packets.
 
377
            ogg->headers = 1;
 
378
 
 
379
            // Update the header state for all streams and
 
380
            // compute the data_offset.
 
381
            if (!s->data_offset)
 
382
                s->data_offset = os->sync_pos;
 
383
            for (i = 0; i < ogg->nstreams; i++) {
 
384
                struct ogg_stream *cur_os = ogg->streams + i;
 
385
 
 
386
                // if we have a partial non-header packet, its start is
 
387
                // obviously at or after the data start
 
388
                if (cur_os->incomplete)
 
389
                    s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
 
390
            }
 
391
        }else{
 
392
            os->pstart += os->psize;
 
393
            os->psize = 0;
 
394
        }
 
395
    } else {
 
396
        os->pflags = 0;
 
397
        os->pduration = 0;
 
398
        if (os->codec && os->codec->packet)
 
399
            os->codec->packet (s, idx);
 
400
        if (str)
 
401
            *str = idx;
 
402
        if (dstart)
 
403
            *dstart = os->pstart;
 
404
        if (dsize)
 
405
            *dsize = os->psize;
 
406
        if (fpos)
 
407
            *fpos = os->sync_pos;
 
408
        os->pstart += os->psize;
 
409
        os->psize = 0;
 
410
        os->sync_pos = os->page_pos;
 
411
    }
 
412
 
 
413
    // determine whether there are more complete packets in this page
 
414
    // if not, the page's granule will apply to this packet
 
415
    os->page_end = 1;
 
416
    for (i = os->segp; i < os->nsegs; i++)
 
417
        if (os->segments[i] < 255) {
 
418
            os->page_end = 0;
 
419
            break;
 
420
        }
 
421
 
 
422
    if (os->segp == os->nsegs)
 
423
        ogg->curidx = -1;
 
424
 
 
425
    return 0;
 
426
}
 
427
 
 
428
static int ogg_get_headers(AVFormatContext *s)
 
429
{
 
430
    struct ogg *ogg = s->priv_data;
 
431
 
 
432
    do{
 
433
        if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
 
434
            return -1;
 
435
    }while (!ogg->headers);
 
436
 
 
437
    av_dlog(s, "found headers\n");
 
438
 
 
439
    return 0;
 
440
}
 
441
 
 
442
static int ogg_get_length(AVFormatContext *s)
 
443
{
 
444
    struct ogg *ogg = s->priv_data;
 
445
    int i;
 
446
    int64_t size, end;
 
447
 
 
448
    if(!s->pb->seekable)
 
449
        return 0;
 
450
 
 
451
// already set
 
452
    if (s->duration != AV_NOPTS_VALUE)
 
453
        return 0;
 
454
 
 
455
    size = avio_size(s->pb);
 
456
    if(size < 0)
 
457
        return 0;
 
458
    end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
 
459
 
 
460
    ogg_save (s);
 
461
    avio_seek (s->pb, end, SEEK_SET);
 
462
 
 
463
    while (!ogg_read_page (s, &i)){
 
464
        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
 
465
            ogg->streams[i].codec) {
 
466
            s->streams[i]->duration =
 
467
                ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
 
468
            if (s->streams[i]->start_time != AV_NOPTS_VALUE)
 
469
                s->streams[i]->duration -= s->streams[i]->start_time;
 
470
        }
 
471
    }
 
472
 
 
473
    ogg_restore (s, 0);
 
474
 
 
475
    return 0;
 
476
}
 
477
 
 
478
static int ogg_read_header(AVFormatContext *s, AVFormatParameters *ap)
 
479
{
 
480
    struct ogg *ogg = s->priv_data;
 
481
    int i;
 
482
    ogg->curidx = -1;
 
483
    //linear headers seek from start
 
484
    if (ogg_get_headers (s) < 0){
 
485
        return -1;
 
486
    }
 
487
 
 
488
    for (i = 0; i < ogg->nstreams; i++)
 
489
        if (ogg->streams[i].header < 0)
 
490
            ogg->streams[i].codec = NULL;
 
491
 
 
492
    //linear granulepos seek from end
 
493
    ogg_get_length (s);
 
494
 
 
495
    //fill the extradata in the per codec callbacks
 
496
    return 0;
 
497
}
 
498
 
 
499
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
 
500
{
 
501
    struct ogg *ogg = s->priv_data;
 
502
    struct ogg_stream *os = ogg->streams + idx;
 
503
    int64_t pts = AV_NOPTS_VALUE;
 
504
 
 
505
    if (dts)
 
506
        *dts = AV_NOPTS_VALUE;
 
507
 
 
508
    if (os->lastpts != AV_NOPTS_VALUE) {
 
509
        pts = os->lastpts;
 
510
        os->lastpts = AV_NOPTS_VALUE;
 
511
    }
 
512
    if (os->lastdts != AV_NOPTS_VALUE) {
 
513
        if (dts)
 
514
            *dts = os->lastdts;
 
515
        os->lastdts = AV_NOPTS_VALUE;
 
516
    }
 
517
    if (os->page_end) {
 
518
        if (os->granule != -1LL) {
 
519
            if (os->codec && os->codec->granule_is_start)
 
520
                pts = ogg_gptopts(s, idx, os->granule, dts);
 
521
            else
 
522
                os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
 
523
            os->granule = -1LL;
 
524
        }
 
525
    }
 
526
    return pts;
 
527
}
 
528
 
 
529
static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
 
530
{
 
531
    struct ogg *ogg;
 
532
    struct ogg_stream *os;
 
533
    int idx = -1;
 
534
    int pstart, psize;
 
535
    int64_t fpos, pts, dts;
 
536
 
 
537
    //Get an ogg packet
 
538
retry:
 
539
    do{
 
540
        if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
 
541
            return AVERROR(EIO);
 
542
    }while (idx < 0 || !s->streams[idx]);
 
543
 
 
544
    ogg = s->priv_data;
 
545
    os = ogg->streams + idx;
 
546
 
 
547
    // pflags might not be set until after this
 
548
    pts = ogg_calc_pts(s, idx, &dts);
 
549
 
 
550
    if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
 
551
        goto retry;
 
552
    os->keyframe_seek = 0;
 
553
 
 
554
    //Alloc a pkt
 
555
    if (av_new_packet (pkt, psize) < 0)
 
556
        return AVERROR(EIO);
 
557
    pkt->stream_index = idx;
 
558
    memcpy (pkt->data, os->buf + pstart, psize);
 
559
 
 
560
    pkt->pts = pts;
 
561
    pkt->dts = dts;
 
562
    pkt->flags = os->pflags;
 
563
    pkt->duration = os->pduration;
 
564
    pkt->pos = fpos;
 
565
 
 
566
    return psize;
 
567
}
 
568
 
 
569
static int ogg_read_close(AVFormatContext *s)
 
570
{
 
571
    struct ogg *ogg = s->priv_data;
 
572
    int i;
 
573
 
 
574
    for (i = 0; i < ogg->nstreams; i++){
 
575
        av_free (ogg->streams[i].buf);
 
576
        av_free (ogg->streams[i].private);
 
577
    }
 
578
    av_free (ogg->streams);
 
579
    return 0;
 
580
}
 
581
 
 
582
static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
 
583
                                  int64_t *pos_arg, int64_t pos_limit)
 
584
{
 
585
    struct ogg *ogg = s->priv_data;
 
586
    AVIOContext *bc = s->pb;
 
587
    int64_t pts = AV_NOPTS_VALUE;
 
588
    int i = -1;
 
589
    avio_seek(bc, *pos_arg, SEEK_SET);
 
590
    ogg_reset(ogg);
 
591
 
 
592
    while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
 
593
        if (i == stream_index) {
 
594
            struct ogg_stream *os = ogg->streams + stream_index;
 
595
            pts = ogg_calc_pts(s, i, NULL);
 
596
            if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
 
597
                pts = AV_NOPTS_VALUE;
 
598
        }
 
599
        if (pts != AV_NOPTS_VALUE)
 
600
            break;
 
601
    }
 
602
    ogg_reset(ogg);
 
603
    return pts;
 
604
}
 
605
 
 
606
static int ogg_read_seek(AVFormatContext *s, int stream_index,
 
607
                         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
    if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
 
616
        && !(flags & AVSEEK_FLAG_ANY))
 
617
        os->keyframe_seek = 1;
 
618
 
 
619
    ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
 
620
    os = ogg->streams + stream_index;
 
621
    if (ret < 0)
 
622
        os->keyframe_seek = 0;
 
623
    return ret;
 
624
}
 
625
 
 
626
static int ogg_probe(AVProbeData *p)
 
627
{
 
628
    if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
 
629
        return AVPROBE_SCORE_MAX;
 
630
    return 0;
 
631
}
 
632
 
 
633
AVInputFormat ff_ogg_demuxer = {
 
634
    .name           = "ogg",
 
635
    .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
 
636
    .priv_data_size = sizeof(struct ogg),
 
637
    .read_probe     = ogg_probe,
 
638
    .read_header    = ogg_read_header,
 
639
    .read_packet    = ogg_read_packet,
 
640
    .read_close     = ogg_read_close,
 
641
    .read_seek      = ogg_read_seek,
 
642
    .read_timestamp = ogg_read_timestamp,
 
643
    .extensions     = "ogg",
 
644
    .flags          = AVFMT_GENERIC_INDEX,
 
645
};