~ubuntu-branches/ubuntu/raring/libav/raring-security

« 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-10-01 00:22:07 UTC
  • mfrom: (1.3.8 sid)
  • Revision ID: package-import@ubuntu.com-20111001002207-tnxz39i0rwr5ufy9
Tags: 4:0.7.2-1ubuntu1
* Merge from debian, remaining changes:
  - don't build against libfaad, libdirac, librtmp and libopenjpeg,
    lame, xvid, x264  (all in universe)
  - not installing into multiarch directories
* This new upstream release has basically merged in all 70 patches that
  are present in 4:0.7.1-7ubuntu2, plus some additional, similarily
  focused ones.

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
 
};