oggdec: fix memleak with continuous streams.
[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
5780f41a 151ogg_new_stream (AVFormatContext *s, uint32_t serial, int new_avstream)
9146ca37
MR
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
5780f41a
CB
168 if (new_avstream) {
169 st = av_new_stream(s, idx);
170 if (!st)
171 return AVERROR(ENOMEM);
9146ca37 172
5780f41a
CB
173 av_set_pts_info(st, 64, 1, 1000000);
174 }
9146ca37
MR
175
176 return idx;
177}
178
179static int
77be08ee 180ogg_new_buf(struct ogg *ogg, int idx)
12a195e3 181{
77be08ee 182 struct ogg_stream *os = ogg->streams + idx;
ea02862a 183 uint8_t *nb = av_malloc(os->bufsize);
12a195e3
MR
184 int size = os->bufpos - os->pstart;
185 if(os->buf){
186 memcpy(nb, os->buf + os->pstart, size);
187 av_free(os->buf);
188 }
189 os->buf = nb;
190 os->bufpos = size;
191 os->pstart = 0;
192
193 return 0;
194}
195
196static int
9146ca37
MR
197ogg_read_page (AVFormatContext * s, int *str)
198{
ae628ec1 199 AVIOContext *bc = s->pb;
77be08ee
MR
200 struct ogg *ogg = s->priv_data;
201 struct ogg_stream *os;
9146ca37
MR
202 int i = 0;
203 int flags, nsegs;
204 uint64_t gp;
205 uint32_t serial;
206 uint32_t seq;
207 uint32_t crc;
208 int size, idx;
191e8ca7 209 uint8_t sync[4];
9146ca37
MR
210 int sp = 0;
211
b7effd4e 212 if (avio_read (bc, sync, 4) < 4)
9146ca37
MR
213 return -1;
214
215 do{
216 int c;
217
218 if (sync[sp & 3] == 'O' &&
219 sync[(sp + 1) & 3] == 'g' &&
220 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
221 break;
222
e5197539 223 c = avio_r8(bc);
66e5b1df 224 if (bc->eof_reached)
9146ca37
MR
225 return -1;
226 sync[sp++ & 3] = c;
227 }while (i++ < MAX_PAGE_SIZE);
228
229 if (i >= MAX_PAGE_SIZE){
230 av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
231 return -1;
232 }
233
e5197539 234 if (avio_r8(bc) != 0) /* version */
9146ca37
MR
235 return -1;
236
e5197539 237 flags = avio_r8(bc);
b7effd4e
AK
238 gp = avio_rl64 (bc);
239 serial = avio_rl32 (bc);
240 seq = avio_rl32 (bc);
241 crc = avio_rl32 (bc);
e5197539 242 nsegs = avio_r8(bc);
9146ca37
MR
243
244 idx = ogg_find_stream (ogg, serial);
245 if (idx < 0){
8f3eebd6 246 if (ogg->headers) {
dc713546
CB
247 int n;
248
249 for (n = 0; n < ogg->nstreams; n++) {
250 av_freep(&ogg->streams[n].buf);
251 av_freep(&ogg->streams[n].private);
252 }
253 ogg->curidx = -1;
254 ogg->nstreams = 0;
5780f41a
CB
255 idx = ogg_new_stream(s, serial, 0);
256 } else {
257 idx = ogg_new_stream(s, serial, 1);
47dec30e 258 }
9146ca37
MR
259 if (idx < 0)
260 return -1;
261 }
262
263 os = ogg->streams + idx;
a2704c97 264 os->page_pos = avio_tell(bc) - 27;
9146ca37 265
40c5e1fa 266 if(os->psize > 0)
12a195e3
MR
267 ogg_new_buf(ogg, idx);
268
b7effd4e 269 if (avio_read (bc, os->segments, nsegs) < nsegs)
9146ca37
MR
270 return -1;
271
272 os->nsegs = nsegs;
273 os->segp = 0;
274
275 size = 0;
276 for (i = 0; i < nsegs; i++)
277 size += os->segments[i];
278
ecc0027b 279 if (flags & OGG_FLAG_CONT || os->incomplete){
9146ca37
MR
280 if (!os->psize){
281 while (os->segp < os->nsegs){
282 int seg = os->segments[os->segp++];
283 os->pstart += seg;
284 if (seg < 255)
bad4a6bb 285 break;
9146ca37 286 }
73823cb9 287 os->sync_pos = os->page_pos;
9146ca37
MR
288 }
289 }else{
bad4a6bb 290 os->psize = 0;
73823cb9 291 os->sync_pos = os->page_pos;
9146ca37
MR
292 }
293
294 if (os->bufsize - os->bufpos < size){
2d2f443d 295 uint8_t *nb = av_malloc (os->bufsize *= 2);
9146ca37
MR
296 memcpy (nb, os->buf, os->bufpos);
297 av_free (os->buf);
298 os->buf = nb;
299 }
300
b7effd4e 301 if (avio_read (bc, os->buf + os->bufpos, size) < size)
9146ca37
MR
302 return -1;
303
9146ca37
MR
304 os->bufpos += size;
305 os->granule = gp;
306 os->flags = flags;
307
308 if (str)
309 *str = idx;
310
311 return 0;
312}
313
314static int
73823cb9 315ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpos)
9146ca37 316{
77be08ee 317 struct ogg *ogg = s->priv_data;
5e15c7d9 318 int idx, i;
77be08ee 319 struct ogg_stream *os;
9146ca37
MR
320 int complete = 0;
321 int segp = 0, psize = 0;
322
045dd4b9 323 av_dlog(s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
9146ca37
MR
324
325 do{
326 idx = ogg->curidx;
327
328 while (idx < 0){
329 if (ogg_read_page (s, &idx) < 0)
330 return -1;
331 }
332
333 os = ogg->streams + idx;
334
045dd4b9 335 av_dlog(s, AV_LOG_DEBUG,
9146ca37
MR
336 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
337 idx, os->pstart, os->psize, os->segp, os->nsegs);
9146ca37
MR
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
045dd4b9 369 av_dlog(s, AV_LOG_DEBUG,
9146ca37
MR
370 "ogg_packet: idx %i, frame size %i, start %i\n",
371 idx, os->psize, os->pstart);
9146ca37 372
adc725b5 373 if (os->granule == -1)
461628c6 374 av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
adc725b5 375
9146ca37 376 ogg->curidx = idx;
ecc0027b 377 os->incomplete = 0;
9146ca37 378
81b743eb
DC
379 if (os->header) {
380 os->header = os->codec->header (s, idx);
381 if (!os->header){
bad4a6bb
PR
382 os->segp = segp;
383 os->psize = psize;
365d8e47 384
6bd69e6a
RD
385 // We have reached the first non-header packet in this stream.
386 // Unfortunately more header packets may still follow for others,
387 // so we reset this later unless we are done with the headers
388 // for all streams.
bad4a6bb 389 ogg->headers = 1;
365d8e47
AC
390
391 // Update the header state for all streams and
392 // compute the data_offset.
6bd69e6a
RD
393 if (!s->data_offset)
394 s->data_offset = os->sync_pos;
365d8e47
AC
395 for (i = 0; i < ogg->nstreams; i++) {
396 struct ogg_stream *cur_os = ogg->streams + i;
365d8e47 397 if (cur_os->header > 0)
6bd69e6a 398 ogg->headers = 0;
365d8e47
AC
399
400 // if we have a partial non-header packet, its start is
401 // obviously at or after the data start
402 if (cur_os->incomplete)
403 s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
404 }
9146ca37 405 }else{
bad4a6bb
PR
406 os->pstart += os->psize;
407 os->psize = 0;
9146ca37 408 }
81b743eb 409 } else {
e1a794b2 410 os->pflags = 0;
15299b38 411 os->pduration = 0;
9146ca37
MR
412 if (os->codec && os->codec->packet)
413 os->codec->packet (s, idx);
414 if (str)
415 *str = idx;
12a195e3
MR
416 if (dstart)
417 *dstart = os->pstart;
418 if (dsize)
419 *dsize = os->psize;
73823cb9
DC
420 if (fpos)
421 *fpos = os->sync_pos;
12a195e3
MR
422 os->pstart += os->psize;
423 os->psize = 0;
73823cb9 424 os->sync_pos = os->page_pos;
9146ca37
MR
425 }
426
5e15c7d9
DC
427 // determine whether there are more complete packets in this page
428 // if not, the page's granule will apply to this packet
429 os->page_end = 1;
430 for (i = os->segp; i < os->nsegs; i++)
431 if (os->segments[i] < 255) {
432 os->page_end = 0;
433 break;
434 }
435
9146ca37
MR
436 if (os->segp == os->nsegs)
437 ogg->curidx = -1;
438
439 return 0;
440}
441
442static int
443ogg_get_headers (AVFormatContext * s)
444{
77be08ee 445 struct ogg *ogg = s->priv_data;
9146ca37
MR
446
447 do{
73823cb9 448 if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
9146ca37
MR
449 return -1;
450 }while (!ogg->headers);
451
045dd4b9 452 av_dlog(s, AV_LOG_DEBUG, "found headers\n");
9146ca37
MR
453
454 return 0;
455}
456
9146ca37
MR
457static int
458ogg_get_length (AVFormatContext * s)
459{
77be08ee 460 struct ogg *ogg = s->priv_data;
44a088ea 461 int i;
bc5c918e 462 int64_t size, end;
69599eea 463
8978feda 464 if(!s->pb->seekable)
69599eea 465 return 0;
9146ca37
MR
466
467// already set
468 if (s->duration != AV_NOPTS_VALUE)
469 return 0;
470
76aa876e 471 size = avio_size(s->pb);
56466d7b
MR
472 if(size < 0)
473 return 0;
ddd94932 474 end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
56466d7b 475
9146ca37 476 ogg_save (s);
6b4aa5da 477 avio_seek (s->pb, end, SEEK_SET);
9146ca37
MR
478
479 while (!ogg_read_page (s, &i)){
e22f2aaf 480 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
44a088ea
DC
481 ogg->streams[i].codec) {
482 s->streams[i]->duration =
483 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
484 if (s->streams[i]->start_time != AV_NOPTS_VALUE)
485 s->streams[i]->duration -= s->streams[i]->start_time;
486 }
9146ca37
MR
487 }
488
9146ca37
MR
489 ogg_restore (s, 0);
490
491 return 0;
492}
493
494
495static int
496ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
497{
77be08ee 498 struct ogg *ogg = s->priv_data;
c9da676d 499 int i;
9146ca37
MR
500 ogg->curidx = -1;
501 //linear headers seek from start
502 if (ogg_get_headers (s) < 0){
bad4a6bb 503 return -1;
9146ca37
MR
504 }
505
c9da676d
RD
506 for (i = 0; i < ogg->nstreams; i++)
507 if (ogg->streams[i].header < 0)
508 ogg->streams[i].codec = NULL;
509
9146ca37
MR
510 //linear granulepos seek from end
511 ogg_get_length (s);
512
513 //fill the extradata in the per codec callbacks
514 return 0;
515}
516
6abaa272
DC
517static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
518{
519 struct ogg *ogg = s->priv_data;
520 struct ogg_stream *os = ogg->streams + idx;
521 int64_t pts = AV_NOPTS_VALUE;
522
523 if (dts)
524 *dts = AV_NOPTS_VALUE;
525
526 if (os->lastpts != AV_NOPTS_VALUE) {
527 pts = os->lastpts;
528 os->lastpts = AV_NOPTS_VALUE;
529 }
530 if (os->lastdts != AV_NOPTS_VALUE) {
531 if (dts)
532 *dts = os->lastdts;
533 os->lastdts = AV_NOPTS_VALUE;
534 }
535 if (os->page_end) {
536 if (os->granule != -1LL) {
537 if (os->codec && os->codec->granule_is_start)
538 pts = ogg_gptopts(s, idx, os->granule, dts);
539 else
540 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
541 os->granule = -1LL;
adc725b5 542 }
6abaa272
DC
543 }
544 return pts;
545}
9146ca37
MR
546
547static int
548ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
549{
77be08ee
MR
550 struct ogg *ogg;
551 struct ogg_stream *os;
9146ca37 552 int idx = -1;
12a195e3 553 int pstart, psize;
d8b91fae 554 int64_t fpos, pts, dts;
9146ca37 555
115329f1 556 //Get an ogg packet
d8b91fae 557retry:
9146ca37 558 do{
73823cb9 559 if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
6f3e0b21 560 return AVERROR(EIO);
9146ca37
MR
561 }while (idx < 0 || !s->streams[idx]);
562
563 ogg = s->priv_data;
564 os = ogg->streams + idx;
565
d8b91fae
DC
566 // pflags might not be set until after this
567 pts = ogg_calc_pts(s, idx, &dts);
568
cc947f04 569 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
d8b91fae
DC
570 goto retry;
571 os->keyframe_seek = 0;
572
9146ca37 573 //Alloc a pkt
12a195e3 574 if (av_new_packet (pkt, psize) < 0)
6f3e0b21 575 return AVERROR(EIO);
9146ca37 576 pkt->stream_index = idx;
12a195e3 577 memcpy (pkt->data, os->buf + pstart, psize);
5e15c7d9 578
d8b91fae
DC
579 pkt->pts = pts;
580 pkt->dts = dts;
e1a794b2 581 pkt->flags = os->pflags;
15299b38 582 pkt->duration = os->pduration;
73823cb9 583 pkt->pos = fpos;
e1a794b2 584
12a195e3 585 return psize;
9146ca37
MR
586}
587
588
589static int
590ogg_read_close (AVFormatContext * s)
591{
77be08ee 592 struct ogg *ogg = s->priv_data;
9146ca37
MR
593 int i;
594
595 for (i = 0; i < ogg->nstreams; i++){
596 av_free (ogg->streams[i].buf);
1ed923ea 597 av_free (ogg->streams[i].private);
9146ca37
MR
598 }
599 av_free (ogg->streams);
600 return 0;
601}
602
603
9146ca37
MR
604static int64_t
605ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
606 int64_t pos_limit)
607{
77be08ee 608 struct ogg *ogg = s->priv_data;
d8b91fae 609 struct ogg_stream *os = ogg->streams + stream_index;
ae628ec1 610 AVIOContext *bc = s->pb;
a1f29b95
RD
611 int64_t pts = AV_NOPTS_VALUE;
612 int i;
6b4aa5da 613 avio_seek(bc, *pos_arg, SEEK_SET);
873d117e
DC
614 ogg_reset(ogg);
615
a2704c97 616 while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
873d117e
DC
617 if (i == stream_index) {
618 pts = ogg_calc_pts(s, i, NULL);
cc947f04 619 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
d8b91fae 620 pts = AV_NOPTS_VALUE;
a1f29b95 621 }
873d117e
DC
622 if (pts != AV_NOPTS_VALUE)
623 break;
a1f29b95
RD
624 }
625 ogg_reset(ogg);
626 return pts;
9146ca37 627}
9146ca37 628
d8b91fae
DC
629static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
630{
631 struct ogg *ogg = s->priv_data;
632 struct ogg_stream *os = ogg->streams + stream_index;
633 int ret;
634
635 // Try seeking to a keyframe first. If this fails (very possible),
636 // av_seek_frame will fall back to ignoring keyframes
72415b2a 637 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
d8b91fae
DC
638 && !(flags & AVSEEK_FLAG_ANY))
639 os->keyframe_seek = 1;
640
641 ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
642 if (ret < 0)
643 os->keyframe_seek = 0;
644 return ret;
645}
646
2e70e4aa
MR
647static int ogg_probe(AVProbeData *p)
648{
f95257d2 649 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
2e70e4aa 650 return AVPROBE_SCORE_MAX;
f95257d2 651 return 0;
2e70e4aa
MR
652}
653
c6610a21 654AVInputFormat ff_ogg_demuxer = {
b3bbc6fd
CB
655 .name = "ogg",
656 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
657 .priv_data_size = sizeof(struct ogg),
658 .read_probe = ogg_probe,
659 .read_header = ogg_read_header,
660 .read_packet = ogg_read_packet,
661 .read_close = ogg_read_close,
662 .read_seek = ogg_read_seek,
663 .read_timestamp = ogg_read_timestamp,
664 .extensions = "ogg",
665 .flags = AVFMT_GENERIC_INDEX,
9146ca37 666};