Statistics
| Branch: | Revision:

ffmpeg / libavformat / ogg2.c @ 20cd83e2

History | View | Annotate | Download (15.4 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
#include "ogg2.h"
35
#include "avformat.h"
36
37
#define MAX_PAGE_SIZE 65307
38
#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
39
40
static ogg_codec_t *ogg_codecs[] = {
41
    &vorbis_codec,
42 1ed923ea Måns Rullgård
    &theora_codec,
43 bcfc40ae Måns Rullgård
    &flac_codec,
44 e1203ac0 Måns Rullgård
    &ogm_video_codec,
45
    &ogm_audio_codec,
46
    &ogm_old_codec,
47 9146ca37 Måns Rullgård
    NULL
48
};
49
50 a9e35095 Diego Biurrun
#if 0                           // CONFIG_MUXERS
51 9146ca37 Måns Rullgård
static int
52
ogg_write_header (AVFormatContext * avfcontext)
53
{
54
}
55

56
static int
57
ogg_write_packet (AVFormatContext * avfcontext, AVPacket * pkt)
58
{
59
}
60

61

62
static int
63
ogg_write_trailer (AVFormatContext * avfcontext)
64
{
65
}
66

67

68 ff70e601 Måns Rullgård
AVOutputFormat ogg_muxer = {
69 9146ca37 Måns Rullgård
    "ogg",
70
    "Ogg Vorbis",
71
    "audio/x-vorbis",
72
    "ogg",
73
    sizeof (OggContext),
74
    CODEC_ID_VORBIS,
75
    0,
76
    ogg_write_header,
77
    ogg_write_packet,
78
    ogg_write_trailer,
79
};
80 a9e35095 Diego Biurrun
#endif //CONFIG_MUXERS
81 9146ca37 Måns Rullgård
82
//FIXME We could avoid some structure duplication
83
static int
84
ogg_save (AVFormatContext * s)
85
{
86
    ogg_t *ogg = s->priv_data;
87
    ogg_state_t *ost =
88 ad3aa874 Måns Rullgård
        av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
89 9146ca37 Måns Rullgård
    int i;
90
    ost->pos = url_ftell (&s->pb);;
91
    ost->curidx = ogg->curidx;
92
    ost->next = ogg->state;
93
    memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
94
95
    for (i = 0; i < ogg->nstreams; i++){
96
        ogg_stream_t *os = ogg->streams + i;
97
        os->buf = av_malloc (os->bufsize);
98
        memset (os->buf, 0, os->bufsize);
99
        memcpy (os->buf, ost->streams[i].buf, os->bufpos);
100
    }
101
102
    ogg->state = ost;
103
104
    return 0;
105
}
106
107
static int
108
ogg_restore (AVFormatContext * s, int discard)
109
{
110
    ogg_t *ogg = s->priv_data;
111
    ByteIOContext *bc = &s->pb;
112
    ogg_state_t *ost = ogg->state;
113
    int i;
114
115
    if (!ost)
116
        return 0;
117
118
    ogg->state = ost->next;
119
120
    if (!discard){
121
        for (i = 0; i < ogg->nstreams; i++)
122
            av_free (ogg->streams[i].buf);
123
124
        url_fseek (bc, ost->pos, SEEK_SET);
125
        ogg->curidx = ost->curidx;
126
        memcpy (ogg->streams, ost->streams,
127
        ogg->nstreams * sizeof (*ogg->streams));
128
    }
129
130
    av_free (ost);
131
132
    return 0;
133
}
134
135
static int
136
ogg_reset (ogg_t * ogg)
137
{
138
    int i;
139
140
    for (i = 0; i < ogg->nstreams; i++){
141
        ogg_stream_t *os = ogg->streams + i;
142
        os->bufpos = 0;
143
        os->pstart = 0;
144
        os->psize = 0;
145
        os->granule = -1;
146
        os->lastgp = -1;
147
        os->nsegs = 0;
148
        os->segp = 0;
149
    }
150
151
    ogg->curidx = -1;
152
153
    return 0;
154
}
155
156
static ogg_codec_t *
157 2d2f443d Måns Rullgård
ogg_find_codec (uint8_t * buf, int size)
158 9146ca37 Måns Rullgård
{
159
    int i;
160
161
    for (i = 0; ogg_codecs[i]; i++)
162
        if (size >= ogg_codecs[i]->magicsize &&
163
            !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
164
            return ogg_codecs[i];
165
166
    return NULL;
167
}
168
169
static int
170
ogg_find_stream (ogg_t * ogg, int serial)
171
{
172
    int i;
173
174
    for (i = 0; i < ogg->nstreams; i++)
175
        if (ogg->streams[i].serial == serial)
176
            return i;
177
178
    return -1;
179
}
180
181
static int
182
ogg_new_stream (AVFormatContext * s, uint32_t serial)
183
{
184
185
    ogg_t *ogg = s->priv_data;
186
    int idx = ogg->nstreams++;
187
    AVStream *st;
188
    ogg_stream_t *os;
189
190
    ogg->streams = av_realloc (ogg->streams,
191
                               ogg->nstreams * sizeof (*ogg->streams));
192
    memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
193
    os = ogg->streams + idx;
194
    os->serial = serial;
195
    os->bufsize = DECODER_BUFFER_SIZE;
196 40c5e1fa Måns Rullgård
    os->buf = av_malloc(os->bufsize);
197 9146ca37 Måns Rullgård
    os->header = -1;
198
199
    st = av_new_stream (s, idx);
200
    if (!st)
201
        return AVERROR_NOMEM;
202
203
    av_set_pts_info(st, 64, 1, 1000000);
204
205
    return idx;
206
}
207
208
static int
209 12a195e3 Måns Rullgård
ogg_new_buf(ogg_t *ogg, int idx)
210
{
211
    ogg_stream_t *os = ogg->streams + idx;
212 ea02862a Måns Rullgård
    uint8_t *nb = av_malloc(os->bufsize);
213 12a195e3 Måns Rullgård
    int size = os->bufpos - os->pstart;
214
    if(os->buf){
215
        memcpy(nb, os->buf + os->pstart, size);
216
        av_free(os->buf);
217
    }
218
    os->buf = nb;
219
    os->bufpos = size;
220
    os->pstart = 0;
221
222
    return 0;
223
}
224
225
static int
226 9146ca37 Måns Rullgård
ogg_read_page (AVFormatContext * s, int *str)
227
{
228
    ByteIOContext *bc = &s->pb;
229
    ogg_t *ogg = s->priv_data;
230
    ogg_stream_t *os;
231
    int i = 0;
232
    int flags, nsegs;
233
    uint64_t gp;
234
    uint32_t serial;
235
    uint32_t seq;
236
    uint32_t crc;
237
    int size, idx;
238 191e8ca7 Måns Rullgård
    uint8_t sync[4];
239 9146ca37 Måns Rullgård
    int sp = 0;
240
241
    if (get_buffer (bc, sync, 4) < 4)
242
        return -1;
243
244
    do{
245
        int c;
246
247
        if (sync[sp & 3] == 'O' &&
248
            sync[(sp + 1) & 3] == 'g' &&
249
            sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
250
            break;
251
252
        c = url_fgetc (bc);
253
        if (c < 0)
254
            return -1;
255
        sync[sp++ & 3] = c;
256
    }while (i++ < MAX_PAGE_SIZE);
257
258
    if (i >= MAX_PAGE_SIZE){
259
        av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
260
        return -1;
261
    }
262
263
    if (url_fgetc (bc) != 0)      /* version */
264
        return -1;
265
266
    flags = url_fgetc (bc);
267
    gp = get_le64 (bc);
268
    serial = get_le32 (bc);
269
    seq = get_le32 (bc);
270
    crc = get_le32 (bc);
271
    nsegs = url_fgetc (bc);
272
273
    idx = ogg_find_stream (ogg, serial);
274
    if (idx < 0){
275
        idx = ogg_new_stream (s, serial);
276
        if (idx < 0)
277
            return -1;
278
    }
279
280
    os = ogg->streams + idx;
281
282 40c5e1fa Måns Rullgård
    if(os->psize > 0)
283 12a195e3 Måns Rullgård
        ogg_new_buf(ogg, idx);
284
285 9146ca37 Måns Rullgård
    if (get_buffer (bc, os->segments, nsegs) < nsegs)
286
        return -1;
287
288
    os->nsegs = nsegs;
289
    os->segp = 0;
290
291
    size = 0;
292
    for (i = 0; i < nsegs; i++)
293
        size += os->segments[i];
294
295
    if (flags & OGG_FLAG_CONT){
296
        if (!os->psize){
297
            while (os->segp < os->nsegs){
298
                int seg = os->segments[os->segp++];
299
                os->pstart += seg;
300
                if (seg < 255)
301
                  break;
302
            }
303
        }
304
    }else{
305
      os->psize = 0;
306
    }
307
308
    if (os->bufsize - os->bufpos < size){
309 2d2f443d Måns Rullgård
        uint8_t *nb = av_malloc (os->bufsize *= 2);
310 9146ca37 Måns Rullgård
        memcpy (nb, os->buf, os->bufpos);
311
        av_free (os->buf);
312
        os->buf = nb;
313
    }
314
315
    if (get_buffer (bc, os->buf + os->bufpos, size) < size)
316
        return -1;
317
318
    os->lastgp = os->granule;
319
    os->bufpos += size;
320
    os->granule = gp;
321
    os->flags = flags;
322
323
    if (str)
324
        *str = idx;
325
326
    return 0;
327
}
328
329
static int
330 12a195e3 Måns Rullgård
ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize)
331 9146ca37 Måns Rullgård
{
332
    ogg_t *ogg = s->priv_data;
333
    int idx;
334
    ogg_stream_t *os;
335
    int complete = 0;
336
    int segp = 0, psize = 0;
337
338
#if 0
339
    av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
340
#endif
341
342
    do{
343
        idx = ogg->curidx;
344
345
        while (idx < 0){
346
            if (ogg_read_page (s, &idx) < 0)
347
                return -1;
348
        }
349
350
        os = ogg->streams + idx;
351
352
#if 0
353
        av_log (s, AV_LOG_DEBUG,
354
                "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
355
                idx, os->pstart, os->psize, os->segp, os->nsegs);
356
#endif
357
358
        if (!os->codec){
359
            if (os->header < 0){
360
                os->codec = ogg_find_codec (os->buf, os->bufpos);
361
                if (!os->codec){
362
                    os->header = 0;
363
                    return 0;
364
                }
365
            }else{
366
                return 0;
367
            }
368
        }
369
370
        segp = os->segp;
371
        psize = os->psize;
372
373
        while (os->segp < os->nsegs){
374
            int ss = os->segments[os->segp++];
375
            os->psize += ss;
376
            if (ss < 255){
377
                complete = 1;
378
                break;
379
            }
380
        }
381
382
        if (!complete && os->segp == os->nsegs){
383
            ogg->curidx = -1;
384
        }
385
    }while (!complete);
386
387
#if 0
388
    av_log (s, AV_LOG_DEBUG,
389
            "ogg_packet: idx %i, frame size %i, start %i\n",
390
            idx, os->psize, os->pstart);
391
#endif
392
393
    ogg->curidx = idx;
394
395
    if (os->header < 0){
396
        int hdr = os->codec->header (s, idx);
397
        if (!hdr){
398
          os->header = os->seq;
399
          os->segp = segp;
400
          os->psize = psize;
401
          ogg->headers = 1;
402
        }else{
403
          os->pstart += os->psize;
404
          os->psize = 0;
405
        }
406
    }
407
408
    if (os->header > -1 && os->seq > os->header){
409
        if (os->codec && os->codec->packet)
410
            os->codec->packet (s, idx);
411
        if (str)
412
            *str = idx;
413 12a195e3 Måns Rullgård
        if (dstart)
414
            *dstart = os->pstart;
415
        if (dsize)
416
            *dsize = os->psize;
417
        os->pstart += os->psize;
418
        os->psize = 0;
419 9146ca37 Måns Rullgård
    }
420
421
    os->seq++;
422
    if (os->segp == os->nsegs)
423
        ogg->curidx = -1;
424
425
    return 0;
426
}
427
428
static int
429
ogg_get_headers (AVFormatContext * s)
430
{
431
    ogg_t *ogg = s->priv_data;
432
433
    do{
434 12a195e3 Måns Rullgård
        if (ogg_packet (s, NULL, NULL, NULL) < 0)
435 9146ca37 Måns Rullgård
            return -1;
436
    }while (!ogg->headers);
437
438
#if 0
439
    av_log (s, AV_LOG_DEBUG, "found headers\n");
440
#endif
441
442
    return 0;
443
}
444
445
static uint64_t
446
ogg_gptopts (AVFormatContext * s, int i, uint64_t gp)
447
{
448 1ed923ea Måns Rullgård
    ogg_t *ogg = s->priv_data;
449
    ogg_stream_t *os = ogg->streams + i;
450 9146ca37 Måns Rullgård
    uint64_t pts = AV_NOPTS_VALUE;
451
452 1ed923ea Måns Rullgård
    if(os->codec->gptopts){
453 bb270c08 Diego Biurrun
        pts = os->codec->gptopts(s, i, gp);
454 3644cb8f Måns Rullgård
    } else {
455 1ed923ea Måns Rullgård
        pts = gp;
456 9146ca37 Måns Rullgård
    }
457
458
    return pts;
459
}
460
461
462
static int
463
ogg_get_length (AVFormatContext * s)
464
{
465
    ogg_t *ogg = s->priv_data;
466
    int idx = -1, i;
467 56466d7b Måns Rullgård
    offset_t size, end;
468 69599eea Måns Rullgård
469
    if(s->pb.is_streamed)
470
        return 0;
471 9146ca37 Måns Rullgård
472
// already set
473
    if (s->duration != AV_NOPTS_VALUE)
474
        return 0;
475
476 56466d7b Måns Rullgård
    size = url_fsize(&s->pb);
477
    if(size < 0)
478
        return 0;
479
    end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: size;
480
481 9146ca37 Måns Rullgård
    ogg_save (s);
482 56466d7b Måns Rullgård
    url_fseek (&s->pb, end, SEEK_SET);
483 9146ca37 Måns Rullgård
484
    while (!ogg_read_page (s, &i)){
485
        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
486
            idx = i;
487
    }
488
489
    if (idx != -1){
490
        s->streams[idx]->duration =
491
            ogg_gptopts (s, idx, ogg->streams[idx].granule);
492
    }
493
494 56466d7b Måns Rullgård
    ogg->size = size;
495 9146ca37 Måns Rullgård
    ogg_restore (s, 0);
496 22ffac70 Reimar Döffinger
    ogg_save (s);
497 595da759 Aurelien Jacobs
    while (!ogg_read_page (s, &i)) {
498 22ffac70 Reimar Döffinger
        if (i == idx && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
499
            break;
500
    }
501
    if (i == idx) {
502
        s->streams[idx]->start_time = ogg_gptopts (s, idx, ogg->streams[idx].granule);
503
        s->streams[idx]->duration -= s->streams[idx]->start_time;
504
    }
505
    ogg_restore (s, 0);
506 9146ca37 Måns Rullgård
507
    return 0;
508
}
509
510
511
static int
512
ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
513
{
514
    ogg_t *ogg = s->priv_data;
515
    ogg->curidx = -1;
516
    //linear headers seek from start
517
    if (ogg_get_headers (s) < 0){
518
      return -1;
519
    }
520
521
    //linear granulepos seek from end
522
    ogg_get_length (s);
523
524
    //fill the extradata in the per codec callbacks
525
    return 0;
526
}
527
528
529
static int
530
ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
531
{
532
    ogg_t *ogg;
533
    ogg_stream_t *os;
534
    int idx = -1;
535 12a195e3 Måns Rullgård
    int pstart, psize;
536 9146ca37 Måns Rullgård
537 115329f1 Diego Biurrun
    //Get an ogg packet
538 9146ca37 Måns Rullgård
    do{
539 12a195e3 Måns Rullgård
        if (ogg_packet (s, &idx, &pstart, &psize) < 0)
540 9146ca37 Måns Rullgård
            return AVERROR_IO;
541
    }while (idx < 0 || !s->streams[idx]);
542
543
    ogg = s->priv_data;
544
    os = ogg->streams + idx;
545
546
    //Alloc a pkt
547 12a195e3 Måns Rullgård
    if (av_new_packet (pkt, psize) < 0)
548 9146ca37 Måns Rullgård
        return AVERROR_IO;
549
    pkt->stream_index = idx;
550 12a195e3 Måns Rullgård
    memcpy (pkt->data, os->buf + pstart, psize);
551 9146ca37 Måns Rullgård
    if (os->lastgp != -1LL){
552
        pkt->pts = ogg_gptopts (s, idx, os->lastgp);
553
        os->lastgp = -1;
554
    }
555 12a195e3 Måns Rullgård
556
    return psize;
557 9146ca37 Måns Rullgård
}
558
559
560
static int
561
ogg_read_close (AVFormatContext * s)
562
{
563
    ogg_t *ogg = s->priv_data;
564
    int i;
565
566
    for (i = 0; i < ogg->nstreams; i++){
567
        av_free (ogg->streams[i].buf);
568 1ed923ea Måns Rullgård
        av_free (ogg->streams[i].private);
569 9146ca37 Måns Rullgård
    }
570
    av_free (ogg->streams);
571
    return 0;
572
}
573
574
575
static int
576
ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
577
               int flags)
578
{
579 56466d7b Måns Rullgård
    AVStream *st = s->streams[stream_index];
580 9146ca37 Måns Rullgård
    ogg_t *ogg = s->priv_data;
581
    ByteIOContext *bc = &s->pb;
582
    uint64_t min = 0, max = ogg->size;
583 22ffac70 Reimar Döffinger
    uint64_t tmin = st->start_time, tmax = st->start_time + st->duration;
584 9146ca37 Måns Rullgård
    int64_t pts = AV_NOPTS_VALUE;
585
586
    ogg_save (s);
587
588 22ffac70 Reimar Döffinger
    if ((uint64_t)target_ts < tmin || target_ts < 0)
589
        target_ts = tmin;
590
    while (min <= max && tmin < tmax){
591 17929c04 Måns Rullgård
        uint64_t p = min + (max - min) * (target_ts - tmin) / (tmax - tmin);
592 9146ca37 Måns Rullgård
        int i = -1;
593
594
        url_fseek (bc, p, SEEK_SET);
595
596
        while (!ogg_read_page (s, &i)){
597 56466d7b Måns Rullgård
            if (i == stream_index && ogg->streams[i].granule != 0 &&
598
                ogg->streams[i].granule != -1)
599 9146ca37 Måns Rullgård
                break;
600
        }
601
602
        if (i == -1)
603
            break;
604
605
        pts = ogg_gptopts (s, i, ogg->streams[i].granule);
606
        p = url_ftell (bc);
607
608 c26abfa5 Diego Biurrun
        if (FFABS (pts - target_ts) * st->time_base.num < st->time_base.den)
609 9146ca37 Måns Rullgård
            break;
610
611
        if (pts > target_ts){
612 22ffac70 Reimar Döffinger
            if (max == p && tmax == pts) {
613
                // probably our tmin is wrong, causing us to always end up too late in the file
614
                tmin = (target_ts + tmin + 1) / 2;
615
                if (tmin == target_ts) {
616
                    url_fseek(bc, min, SEEK_SET);
617
                    break;
618
                }
619
            }
620 9146ca37 Måns Rullgård
            max = p;
621
            tmax = pts;
622
        }else{
623 22ffac70 Reimar Döffinger
            if (min == p && tmin == pts) {
624
                // probably our tmax is wrong, causing us to always end up too early in the file
625
                tmax = (target_ts + tmax) / 2;
626
                if (tmax == target_ts) {
627
                    url_fseek(bc, max, SEEK_SET);
628
                    break;
629
                }
630
            }
631 9146ca37 Måns Rullgård
            min = p;
632
            tmin = pts;
633
        }
634
    }
635
636 c26abfa5 Diego Biurrun
    if (FFABS (pts - target_ts) * st->time_base.num < st->time_base.den){
637 9146ca37 Måns Rullgård
        ogg_restore (s, 1);
638
        ogg_reset (ogg);
639
    }else{
640
        ogg_restore (s, 0);
641
        pts = AV_NOPTS_VALUE;
642
    }
643
644 22ffac70 Reimar Döffinger
    av_update_cur_dts(s, st, pts);
645
    return 0;
646 9146ca37 Måns Rullgård
647
#if 0
648
    //later...
649
    int64_t pos;
650
    if (av_seek_frame_binary (s, stream_index, target_ts, flags) < 0)
651
        return -1;
652
    pos = url_ftell (&s->pb);
653
    ogg_read_timestamp (s, stream_index, &pos, pos - 1);
654
#endif
655
656
}
657
658
#if 0
659
static int64_t
660
ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
661
                    int64_t pos_limit)
662
{
663
    ogg_t *ogg = s->priv_data;
664
    ByteIOContext *bc = &s->pb;
665
    int64_t pos, pts;
666

667
    if (*pos_arg < 0)
668
        return AV_NOPTS_VALUE;
669

670
    pos = *pos_arg;
671
}
672
#endif
673
674 2e70e4aa Måns Rullgård
static int ogg_probe(AVProbeData *p)
675
{
676
    if (p->buf_size < 6)
677
        return 0;
678
    if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
679
        p->buf[2] == 'g' && p->buf[3] == 'S' &&
680
        p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
681
        return AVPROBE_SCORE_MAX;
682
    else
683
        return 0;
684
}
685
686 ff70e601 Måns Rullgård
AVInputFormat ogg_demuxer = {
687 9146ca37 Måns Rullgård
    "ogg",
688
    "Ogg",
689
    sizeof (ogg_t),
690 2e70e4aa Måns Rullgård
    ogg_probe,
691 9146ca37 Måns Rullgård
    ogg_read_header,
692
    ogg_read_packet,
693
    ogg_read_close,
694
    ogg_read_seek,
695 115329f1 Diego Biurrun
// ogg_read_timestamp,
696 9146ca37 Måns Rullgård
    .extensions = "ogg",
697
};