configure: Add missing libavutil inter-library dependencies to .pc files.
[libav.git] / libavformat / oggdec.c
CommitLineData
9146ca37
MR
1/*
2 * Ogg bitstream support
3 * Luca Barbato <lu_zero@gentoo.org>
4 * Based on tcvp implementation
115329f1 5 *
9146ca37
MR
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>
a0ddef24 34#include "oggdec.h"
9146ca37 35#include "avformat.h"
66061a12 36#include "vorbiscomment.h"
9146ca37
MR
37
38#define MAX_PAGE_SIZE 65307
39#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
40
77be08ee 41static const struct ogg_codec * const ogg_codecs[] = {
32ad8692 42 &ff_skeleton_codec,
24ca518b 43 &ff_dirac_codec,
547ea47d
RD
44 &ff_speex_codec,
45 &ff_vorbis_codec,
46 &ff_theora_codec,
47 &ff_flac_codec,
24ca518b 48 &ff_old_dirac_codec,
547ea47d
RD
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,
9146ca37
MR
54 NULL
55};
56
9146ca37
MR
57//FIXME We could avoid some structure duplication
58static int
59ogg_save (AVFormatContext * s)
60{
77be08ee
MR
61 struct ogg *ogg = s->priv_data;
62 struct ogg_state *ost =
ad3aa874 63 av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
9146ca37 64 int i;
a2704c97 65 ost->pos = avio_tell (s->pb);
9146ca37
MR
66 ost->curidx = ogg->curidx;
67 ost->next = ogg->state;
20be72c8 68 ost->nstreams = ogg->nstreams;
9146ca37
MR
69 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
70
71 for (i = 0; i < ogg->nstreams; i++){
77be08ee 72 struct ogg_stream *os = ogg->streams + i;
9146ca37
MR
73 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
83static int
84ogg_restore (AVFormatContext * s, int discard)
85{
77be08ee 86 struct ogg *ogg = s->priv_data;
ae628ec1 87 AVIOContext *bc = s->pb;
77be08ee 88 struct ogg_state *ost = ogg->state;
9146ca37
MR
89 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
6b4aa5da 100 avio_seek (bc, ost->pos, SEEK_SET);
9146ca37 101 ogg->curidx = ost->curidx;
20be72c8
MR
102 ogg->nstreams = ost->nstreams;
103 memcpy(ogg->streams, ost->streams,
104 ost->nstreams * sizeof(*ogg->streams));
9146ca37
MR
105 }
106
107 av_free (ost);
108
109 return 0;
110}
111
112static int
77be08ee 113ogg_reset (struct ogg * ogg)
9146ca37
MR
114{
115 int i;
116
117 for (i = 0; i < ogg->nstreams; i++){
77be08ee 118 struct ogg_stream *os = ogg->streams + i;
9146ca37
MR
119 os->bufpos = 0;
120 os->pstart = 0;
121 os->psize = 0;
122 os->granule = -1;
5e15c7d9 123 os->lastpts = AV_NOPTS_VALUE;
2d4970d8 124 os->lastdts = AV_NOPTS_VALUE;
73823cb9
DC
125 os->sync_pos = -1;
126 os->page_pos = 0;
9146ca37
MR
127 os->nsegs = 0;
128 os->segp = 0;
ecc0027b 129 os->incomplete = 0;
9146ca37
MR
130 }
131
132 ogg->curidx = -1;
133
134 return 0;
135}
136
77be08ee 137static const struct ogg_codec *
2d2f443d 138ogg_find_codec (uint8_t * buf, int size)
9146ca37
MR
139{
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
150static int
9146ca37
MR
151ogg_new_stream (AVFormatContext * s, uint32_t serial)
152{
153
77be08ee 154 struct ogg *ogg = s->priv_data;
9146ca37
MR
155 int idx = ogg->nstreams++;
156 AVStream *st;
77be08ee 157 struct ogg_stream *os;
9146ca37
MR
158
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;
40c5e1fa 165 os->buf = av_malloc(os->bufsize);
9146ca37
MR
166 os->header = -1;
167
168 st = av_new_stream (s, idx);
169 if (!st)
769e10f0 170 return AVERROR(ENOMEM);
9146ca37
MR
171
172 av_set_pts_info(st, 64, 1, 1000000);
9146ca37
MR
173
174 return idx;
175}
176
177static int
77be08ee 178ogg_new_buf(struct ogg *ogg, int idx)
12a195e3 179{
77be08ee 180 struct ogg_stream *os = ogg->streams + idx;
ea02862a 181 uint8_t *nb = av_malloc(os->bufsize);
12a195e3
MR
182 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
194static int
9146ca37
MR
195ogg_read_page (AVFormatContext * s, int *str)
196{
ae628ec1 197 AVIOContext *bc = s->pb;
77be08ee
MR
198 struct ogg *ogg = s->priv_data;
199 struct ogg_stream *os;
9146ca37
MR
200 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;
191e8ca7 207 uint8_t sync[4];
9146ca37
MR
208 int sp = 0;
209
b7effd4e 210 if (avio_read (bc, sync, 4) < 4)
9146ca37
MR
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
e5197539 221 c = avio_r8(bc);
66e5b1df 222 if (bc->eof_reached)
9146ca37
MR
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
e5197539 232 if (avio_r8(bc) != 0) /* version */
9146ca37
MR
233 return -1;
234
e5197539 235 flags = avio_r8(bc);
b7effd4e
AK
236 gp = avio_rl64 (bc);
237 serial = avio_rl32 (bc);
238 seq = avio_rl32 (bc);
239 crc = avio_rl32 (bc);
e5197539 240 nsegs = avio_r8(bc);
9146ca37
MR
241
242 idx = ogg_find_stream (ogg, serial);
243 if (idx < 0){
8f3eebd6 244 if (ogg->headers) {
47dec30e
CB
245 int n;
246
247 for (n = 0; n < ogg->nstreams; n++) {
52512d0a
MN
248 av_freep(&ogg->streams[n].buf);
249 av_freep(&ogg->streams[n].private);
47dec30e
CB
250 }
251 ogg->curidx = -1;
252 ogg->nstreams = 0;
47dec30e 253 }
9146ca37
MR
254 idx = ogg_new_stream (s, serial);
255 if (idx < 0)
256 return -1;
257 }
258
259 os = ogg->streams + idx;
a2704c97 260 os->page_pos = avio_tell(bc) - 27;
9146ca37 261
40c5e1fa 262 if(os->psize > 0)
12a195e3
MR
263 ogg_new_buf(ogg, idx);
264
b7effd4e 265 if (avio_read (bc, os->segments, nsegs) < nsegs)
9146ca37
MR
266 return -1;
267
268 os->nsegs = nsegs;
269 os->segp = 0;
270
271 size = 0;
272 for (i = 0; i < nsegs; i++)
273 size += os->segments[i];
274
ecc0027b 275 if (flags & OGG_FLAG_CONT || os->incomplete){
9146ca37
MR
276 if (!os->psize){
277 while (os->segp < os->nsegs){
278 int seg = os->segments[os->segp++];
279 os->pstart += seg;
280 if (seg < 255)
bad4a6bb 281 break;
9146ca37 282 }
73823cb9 283 os->sync_pos = os->page_pos;
9146ca37
MR
284 }
285 }else{
bad4a6bb 286 os->psize = 0;
73823cb9 287 os->sync_pos = os->page_pos;
9146ca37
MR
288 }
289
290 if (os->bufsize - os->bufpos < size){
2d2f443d 291 uint8_t *nb = av_malloc (os->bufsize *= 2);
9146ca37
MR
292 memcpy (nb, os->buf, os->bufpos);
293 av_free (os->buf);
294 os->buf = nb;
295 }
296
b7effd4e 297 if (avio_read (bc, os->buf + os->bufpos, size) < size)
9146ca37
MR
298 return -1;
299
9146ca37
MR
300 os->bufpos += size;
301 os->granule = gp;
302 os->flags = flags;
303
304 if (str)
305 *str = idx;
306
307 return 0;
308}
309
310static int
73823cb9 311ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpos)
9146ca37 312{
77be08ee 313 struct ogg *ogg = s->priv_data;
5e15c7d9 314 int idx, i;
77be08ee 315 struct ogg_stream *os;
9146ca37
MR
316 int complete = 0;
317 int segp = 0, psize = 0;
318
319#if 0
320 av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
321#endif
322
323 do{
324 idx = ogg->curidx;
325
326 while (idx < 0){
327 if (ogg_read_page (s, &idx) < 0)
328 return -1;
329 }
330
331 os = ogg->streams + idx;
332
333#if 0
334 av_log (s, AV_LOG_DEBUG,
335 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
336 idx, os->pstart, os->psize, os->segp, os->nsegs);
337#endif
338
339 if (!os->codec){
340 if (os->header < 0){
341 os->codec = ogg_find_codec (os->buf, os->bufpos);
342 if (!os->codec){
343 os->header = 0;
344 return 0;
345 }
346 }else{
347 return 0;
348 }
349 }
350
351 segp = os->segp;
352 psize = os->psize;
353
354 while (os->segp < os->nsegs){
355 int ss = os->segments[os->segp++];
356 os->psize += ss;
357 if (ss < 255){
358 complete = 1;
359 break;
360 }
361 }
362
363 if (!complete && os->segp == os->nsegs){
9146ca37 364 ogg->curidx = -1;
ecc0027b 365 os->incomplete = 1;
9146ca37
MR
366 }
367 }while (!complete);
368
369#if 0
370 av_log (s, AV_LOG_DEBUG,
371 "ogg_packet: idx %i, frame size %i, start %i\n",
372 idx, os->psize, os->pstart);
373#endif
374
adc725b5 375 if (os->granule == -1)
461628c6 376 av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
adc725b5 377
9146ca37 378 ogg->curidx = idx;
ecc0027b 379 os->incomplete = 0;
9146ca37 380
81b743eb
DC
381 if (os->header) {
382 os->header = os->codec->header (s, idx);
383 if (!os->header){
bad4a6bb
PR
384 os->segp = segp;
385 os->psize = psize;
365d8e47 386
6bd69e6a
RD
387 // We have reached the first non-header packet in this stream.
388 // Unfortunately more header packets may still follow for others,
389 // so we reset this later unless we are done with the headers
390 // for all streams.
bad4a6bb 391 ogg->headers = 1;
365d8e47
AC
392
393 // Update the header state for all streams and
394 // compute the data_offset.
6bd69e6a
RD
395 if (!s->data_offset)
396 s->data_offset = os->sync_pos;
365d8e47
AC
397 for (i = 0; i < ogg->nstreams; i++) {
398 struct ogg_stream *cur_os = ogg->streams + i;
365d8e47 399 if (cur_os->header > 0)
6bd69e6a 400 ogg->headers = 0;
365d8e47
AC
401
402 // if we have a partial non-header packet, its start is
403 // obviously at or after the data start
404 if (cur_os->incomplete)
405 s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
406 }
9146ca37 407 }else{
bad4a6bb
PR
408 os->pstart += os->psize;
409 os->psize = 0;
9146ca37 410 }
81b743eb 411 } else {
e1a794b2 412 os->pflags = 0;
15299b38 413 os->pduration = 0;
9146ca37
MR
414 if (os->codec && os->codec->packet)
415 os->codec->packet (s, idx);
416 if (str)
417 *str = idx;
12a195e3
MR
418 if (dstart)
419 *dstart = os->pstart;
420 if (dsize)
421 *dsize = os->psize;
73823cb9
DC
422 if (fpos)
423 *fpos = os->sync_pos;
12a195e3
MR
424 os->pstart += os->psize;
425 os->psize = 0;
73823cb9 426 os->sync_pos = os->page_pos;
9146ca37
MR
427 }
428
5e15c7d9
DC
429 // determine whether there are more complete packets in this page
430 // if not, the page's granule will apply to this packet
431 os->page_end = 1;
432 for (i = os->segp; i < os->nsegs; i++)
433 if (os->segments[i] < 255) {
434 os->page_end = 0;
435 break;
436 }
437
9146ca37
MR
438 if (os->segp == os->nsegs)
439 ogg->curidx = -1;
440
441 return 0;
442}
443
444static int
445ogg_get_headers (AVFormatContext * s)
446{
77be08ee 447 struct ogg *ogg = s->priv_data;
9146ca37
MR
448
449 do{
73823cb9 450 if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
9146ca37
MR
451 return -1;
452 }while (!ogg->headers);
453
454#if 0
455 av_log (s, AV_LOG_DEBUG, "found headers\n");
456#endif
457
458 return 0;
459}
460
9146ca37
MR
461static int
462ogg_get_length (AVFormatContext * s)
463{
77be08ee 464 struct ogg *ogg = s->priv_data;
44a088ea 465 int i;
bc5c918e 466 int64_t size, end;
69599eea 467
8978feda 468 if(!s->pb->seekable)
69599eea 469 return 0;
9146ca37
MR
470
471// already set
472 if (s->duration != AV_NOPTS_VALUE)
473 return 0;
474
76aa876e 475 size = avio_size(s->pb);
56466d7b
MR
476 if(size < 0)
477 return 0;
ddd94932 478 end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
56466d7b 479
9146ca37 480 ogg_save (s);
6b4aa5da 481 avio_seek (s->pb, end, SEEK_SET);
9146ca37
MR
482
483 while (!ogg_read_page (s, &i)){
e22f2aaf 484 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
44a088ea
DC
485 ogg->streams[i].codec) {
486 s->streams[i]->duration =
487 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
488 if (s->streams[i]->start_time != AV_NOPTS_VALUE)
489 s->streams[i]->duration -= s->streams[i]->start_time;
490 }
9146ca37
MR
491 }
492
9146ca37
MR
493 ogg_restore (s, 0);
494
495 return 0;
496}
497
498
499static int
500ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
501{
77be08ee 502 struct ogg *ogg = s->priv_data;
c9da676d 503 int i;
9146ca37
MR
504 ogg->curidx = -1;
505 //linear headers seek from start
506 if (ogg_get_headers (s) < 0){
bad4a6bb 507 return -1;
9146ca37
MR
508 }
509
c9da676d
RD
510 for (i = 0; i < ogg->nstreams; i++)
511 if (ogg->streams[i].header < 0)
512 ogg->streams[i].codec = NULL;
513
9146ca37
MR
514 //linear granulepos seek from end
515 ogg_get_length (s);
516
517 //fill the extradata in the per codec callbacks
518 return 0;
519}
520
6abaa272
DC
521static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
522{
523 struct ogg *ogg = s->priv_data;
524 struct ogg_stream *os = ogg->streams + idx;
525 int64_t pts = AV_NOPTS_VALUE;
526
527 if (dts)
528 *dts = AV_NOPTS_VALUE;
529
530 if (os->lastpts != AV_NOPTS_VALUE) {
531 pts = os->lastpts;
532 os->lastpts = AV_NOPTS_VALUE;
533 }
534 if (os->lastdts != AV_NOPTS_VALUE) {
535 if (dts)
536 *dts = os->lastdts;
537 os->lastdts = AV_NOPTS_VALUE;
538 }
539 if (os->page_end) {
540 if (os->granule != -1LL) {
541 if (os->codec && os->codec->granule_is_start)
542 pts = ogg_gptopts(s, idx, os->granule, dts);
543 else
544 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
545 os->granule = -1LL;
adc725b5 546 }
6abaa272
DC
547 }
548 return pts;
549}
9146ca37
MR
550
551static int
552ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
553{
77be08ee
MR
554 struct ogg *ogg;
555 struct ogg_stream *os;
9146ca37 556 int idx = -1;
12a195e3 557 int pstart, psize;
d8b91fae 558 int64_t fpos, pts, dts;
9146ca37 559
115329f1 560 //Get an ogg packet
d8b91fae 561retry:
9146ca37 562 do{
73823cb9 563 if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
6f3e0b21 564 return AVERROR(EIO);
9146ca37
MR
565 }while (idx < 0 || !s->streams[idx]);
566
567 ogg = s->priv_data;
568 os = ogg->streams + idx;
569
d8b91fae
DC
570 // pflags might not be set until after this
571 pts = ogg_calc_pts(s, idx, &dts);
572
cc947f04 573 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
d8b91fae
DC
574 goto retry;
575 os->keyframe_seek = 0;
576
9146ca37 577 //Alloc a pkt
12a195e3 578 if (av_new_packet (pkt, psize) < 0)
6f3e0b21 579 return AVERROR(EIO);
9146ca37 580 pkt->stream_index = idx;
12a195e3 581 memcpy (pkt->data, os->buf + pstart, psize);
5e15c7d9 582
d8b91fae
DC
583 pkt->pts = pts;
584 pkt->dts = dts;
e1a794b2 585 pkt->flags = os->pflags;
15299b38 586 pkt->duration = os->pduration;
73823cb9 587 pkt->pos = fpos;
e1a794b2 588
12a195e3 589 return psize;
9146ca37
MR
590}
591
592
593static int
594ogg_read_close (AVFormatContext * s)
595{
77be08ee 596 struct ogg *ogg = s->priv_data;
9146ca37
MR
597 int i;
598
599 for (i = 0; i < ogg->nstreams; i++){
600 av_free (ogg->streams[i].buf);
1ed923ea 601 av_free (ogg->streams[i].private);
9146ca37
MR
602 }
603 av_free (ogg->streams);
604 return 0;
605}
606
607
9146ca37
MR
608static int64_t
609ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
610 int64_t pos_limit)
611{
77be08ee 612 struct ogg *ogg = s->priv_data;
d8b91fae 613 struct ogg_stream *os = ogg->streams + stream_index;
ae628ec1 614 AVIOContext *bc = s->pb;
a1f29b95
RD
615 int64_t pts = AV_NOPTS_VALUE;
616 int i;
6b4aa5da 617 avio_seek(bc, *pos_arg, SEEK_SET);
873d117e
DC
618 ogg_reset(ogg);
619
a2704c97 620 while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
873d117e
DC
621 if (i == stream_index) {
622 pts = ogg_calc_pts(s, i, NULL);
cc947f04 623 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
d8b91fae 624 pts = AV_NOPTS_VALUE;
a1f29b95 625 }
873d117e
DC
626 if (pts != AV_NOPTS_VALUE)
627 break;
a1f29b95
RD
628 }
629 ogg_reset(ogg);
630 return pts;
9146ca37 631}
9146ca37 632
d8b91fae
DC
633static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
634{
635 struct ogg *ogg = s->priv_data;
636 struct ogg_stream *os = ogg->streams + stream_index;
637 int ret;
638
639 // Try seeking to a keyframe first. If this fails (very possible),
640 // av_seek_frame will fall back to ignoring keyframes
72415b2a 641 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
d8b91fae
DC
642 && !(flags & AVSEEK_FLAG_ANY))
643 os->keyframe_seek = 1;
644
645 ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
646 if (ret < 0)
647 os->keyframe_seek = 0;
648 return ret;
649}
650
2e70e4aa
MR
651static int ogg_probe(AVProbeData *p)
652{
2e70e4aa
MR
653 if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
654 p->buf[2] == 'g' && p->buf[3] == 'S' &&
655 p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
656 return AVPROBE_SCORE_MAX;
657 else
658 return 0;
659}
660
c6610a21 661AVInputFormat ff_ogg_demuxer = {
9146ca37 662 "ogg",
bde15e74 663 NULL_IF_CONFIG_SMALL("Ogg"),
77be08ee 664 sizeof (struct ogg),
2e70e4aa 665 ogg_probe,
9146ca37
MR
666 ogg_read_header,
667 ogg_read_packet,
668 ogg_read_close,
d8b91fae 669 ogg_read_seek,
a1f29b95 670 ogg_read_timestamp,
9146ca37 671 .extensions = "ogg",
f1a05185 672 .flags = AVFMT_GENERIC_INDEX,
9146ca37 673};