]> git.sesse.net Git - ffmpeg/blob - libavformat/oggdec.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavformat / oggdec.c
1 /*
2  * Ogg bitstream support
3  * Luca Barbato <lu_zero@gentoo.org>
4  * Based on tcvp implementation
5  */
6
7 /*
8     Copyright (C) 2005  Michael Ahlberg, Måns Rullgård
9
10     Permission is hereby granted, free of charge, to any person
11     obtaining a copy of this software and associated documentation
12     files (the "Software"), to deal in the Software without
13     restriction, including without limitation the rights to use, copy,
14     modify, merge, publish, distribute, sublicense, and/or sell copies
15     of the Software, and to permit persons to whom the Software is
16     furnished to do so, subject to the following conditions:
17
18     The above copyright notice and this permission notice shall be
19     included in all copies or substantial portions of the Software.
20
21     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28     DEALINGS IN THE SOFTWARE.
29  */
30
31 #include <stdio.h>
32 #include "libavutil/avassert.h"
33 #include "oggdec.h"
34 #include "avformat.h"
35 #include "internal.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_celt_codec,
49     &ff_old_dirac_codec,
50     &ff_old_flac_codec,
51     &ff_ogm_video_codec,
52     &ff_ogm_audio_codec,
53     &ff_ogm_text_codec,
54     &ff_ogm_old_codec,
55     NULL
56 };
57
58 //FIXME We could avoid some structure duplication
59 static int ogg_save(AVFormatContext *s)
60 {
61     struct ogg *ogg = s->priv_data;
62     struct ogg_state *ost =
63         av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
64     int i;
65     ost->pos = avio_tell (s->pb);
66     ost->curidx = ogg->curidx;
67     ost->next = ogg->state;
68     ost->nstreams = ogg->nstreams;
69     memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
70
71     for (i = 0; i < ogg->nstreams; i++){
72         struct ogg_stream *os = ogg->streams + i;
73         os->buf = av_mallocz (os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
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         struct ogg_stream *old_streams = ogg->streams;
96
97         for (i = 0; i < ogg->nstreams; i++)
98             av_free (ogg->streams[i].buf);
99
100         avio_seek (bc, ost->pos, SEEK_SET);
101         ogg->curidx = ost->curidx;
102         ogg->nstreams = ost->nstreams;
103         ogg->streams = av_realloc (ogg->streams,
104                                    ogg->nstreams * sizeof (*ogg->streams));
105
106         if (ogg->streams) {
107             memcpy(ogg->streams, ost->streams,
108                    ost->nstreams * sizeof(*ogg->streams));
109         } else {
110             av_free(old_streams);
111             ogg->nstreams = 0;
112         }
113     }
114
115     av_free (ost);
116
117     return 0;
118 }
119
120 static int ogg_reset(AVFormatContext *s)
121 {
122     struct ogg *ogg = s->priv_data;
123     int i;
124     int64_t start_pos = avio_tell(s->pb);
125
126     for (i = 0; i < ogg->nstreams; i++){
127         struct ogg_stream *os = ogg->streams + i;
128         os->bufpos = 0;
129         os->pstart = 0;
130         os->psize = 0;
131         os->granule = -1;
132         os->lastpts = AV_NOPTS_VALUE;
133         os->lastdts = AV_NOPTS_VALUE;
134         os->sync_pos = -1;
135         os->page_pos = 0;
136         os->nsegs = 0;
137         os->segp = 0;
138         os->incomplete = 0;
139         if (start_pos <= s->data_offset) {
140             os->lastpts = 0;
141         }
142     }
143
144     ogg->curidx = -1;
145
146     return 0;
147 }
148
149 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
150 {
151     int i;
152
153     for (i = 0; ogg_codecs[i]; i++)
154         if (size >= ogg_codecs[i]->magicsize &&
155             !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
156             return ogg_codecs[i];
157
158     return NULL;
159 }
160
161 static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
162 {
163
164     struct ogg *ogg = s->priv_data;
165     int idx = ogg->nstreams++;
166     AVStream *st;
167     struct ogg_stream *os;
168
169     ogg->streams = av_realloc (ogg->streams,
170                                ogg->nstreams * sizeof (*ogg->streams));
171     memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
172     os = ogg->streams + idx;
173     os->serial = serial;
174     os->bufsize = DECODER_BUFFER_SIZE;
175     os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
176     os->header = -1;
177
178     if (new_avstream) {
179         st = avformat_new_stream(s, NULL);
180         if (!st)
181             return AVERROR(ENOMEM);
182
183         st->id = idx;
184         avpriv_set_pts_info(st, 64, 1, 1000000);
185     }
186
187     return idx;
188 }
189
190 static int ogg_new_buf(struct ogg *ogg, int idx)
191 {
192     struct ogg_stream *os = ogg->streams + idx;
193     uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE);
194     int size = os->bufpos - os->pstart;
195     if(os->buf){
196         memcpy(nb, os->buf + os->pstart, size);
197         av_free(os->buf);
198     }
199     os->buf = nb;
200     os->bufpos = size;
201     os->pstart = 0;
202
203     return 0;
204 }
205
206 static int ogg_read_page(AVFormatContext *s, int *str)
207 {
208     AVIOContext *bc = s->pb;
209     struct ogg *ogg = s->priv_data;
210     struct ogg_stream *os;
211     int ret, i = 0;
212     int flags, nsegs;
213     uint64_t gp;
214     uint32_t serial;
215     int size, idx;
216     uint8_t sync[4];
217     int sp = 0;
218
219     ret = avio_read(bc, sync, 4);
220     if (ret < 4)
221         return ret < 0 ? ret : AVERROR_EOF;
222
223     do{
224         int c;
225
226         if (sync[sp & 3] == 'O' &&
227             sync[(sp + 1) & 3] == 'g' &&
228             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
229             break;
230
231         c = avio_r8(bc);
232         if (url_feof(bc))
233             return AVERROR_EOF;
234         sync[sp++ & 3] = c;
235     }while (i++ < MAX_PAGE_SIZE);
236
237     if (i >= MAX_PAGE_SIZE){
238         av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
239         return AVERROR_INVALIDDATA;
240     }
241
242     if (avio_r8(bc) != 0){      /* version */
243         av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n");
244         return AVERROR_INVALIDDATA;
245     }
246
247     flags = avio_r8(bc);
248     gp = avio_rl64 (bc);
249     serial = avio_rl32 (bc);
250     avio_skip(bc, 8); /* seq, crc */
251     nsegs = avio_r8(bc);
252
253     idx = ogg_find_stream (ogg, serial);
254     if (idx < 0){
255         if (ogg->headers) {
256             int n;
257
258             if (ogg->nstreams != 1) {
259                 av_log_missing_feature(s, "Changing stream parameters in multistream ogg is", 0);
260                 return idx;
261             }
262
263             for (n = 0; n < ogg->nstreams; n++) {
264                 av_freep(&ogg->streams[n].buf);
265                 if (!ogg->state || ogg->state->streams[n].private != ogg->streams[n].private)
266                     av_freep(&ogg->streams[n].private);
267             }
268             ogg->curidx   = -1;
269             ogg->nstreams = 0;
270             idx = ogg_new_stream(s, serial, 0);
271         } else {
272             idx = ogg_new_stream(s, serial, 1);
273         }
274         if (idx < 0) {
275             av_log (s, AV_LOG_ERROR, "failed to create stream (OOM?)\n");
276             return idx;
277         }
278     }
279
280     os = ogg->streams + idx;
281     os->page_pos = avio_tell(bc) - 27;
282
283     if(os->psize > 0)
284         ogg_new_buf(ogg, idx);
285
286     ret = avio_read(bc, os->segments, nsegs);
287     if (ret < nsegs)
288         return ret < 0 ? ret : AVERROR_EOF;
289
290     os->nsegs = nsegs;
291     os->segp = 0;
292
293     size = 0;
294     for (i = 0; i < nsegs; i++)
295         size += os->segments[i];
296
297     if (flags & OGG_FLAG_CONT || os->incomplete){
298         if (!os->psize){
299             // If this is the very first segment we started
300             // playback in the middle of a continuation packet.
301             // Discard it since we missed the start of it.
302             while (os->segp < os->nsegs){
303                 int seg = os->segments[os->segp++];
304                 os->pstart += seg;
305                 if (seg < 255)
306                     break;
307             }
308             os->sync_pos = os->page_pos;
309         }
310     }else{
311         os->psize = 0;
312         os->sync_pos = os->page_pos;
313     }
314
315     if (os->bufsize - os->bufpos < size){
316         uint8_t *nb = av_malloc ((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE);
317         memcpy (nb, os->buf, os->bufpos);
318         av_free (os->buf);
319         os->buf = nb;
320     }
321
322     ret = avio_read(bc, os->buf + os->bufpos, size);
323     if (ret < size)
324         return ret < 0 ? ret : AVERROR_EOF;
325
326     os->bufpos += size;
327     os->granule = gp;
328     os->flags = flags;
329
330     memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE);
331     if (str)
332         *str = idx;
333
334     return 0;
335 }
336
337 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
338                       int64_t *fpos)
339 {
340     struct ogg *ogg = s->priv_data;
341     int idx, i, ret;
342     struct ogg_stream *os;
343     int complete = 0;
344     int segp = 0, psize = 0;
345
346     av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
347
348     do{
349         idx = ogg->curidx;
350
351         while (idx < 0){
352             ret = ogg_read_page(s, &idx);
353             if (ret < 0)
354                 return ret;
355         }
356
357         os = ogg->streams + idx;
358
359         av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
360                 idx, os->pstart, os->psize, os->segp, os->nsegs);
361
362         if (!os->codec){
363             if (os->header < 0){
364                 os->codec = ogg_find_codec (os->buf, os->bufpos);
365                 if (!os->codec){
366                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
367                     os->header = 0;
368                     return 0;
369                 }
370             }else{
371                 return 0;
372             }
373         }
374
375         segp = os->segp;
376         psize = os->psize;
377
378         while (os->segp < os->nsegs){
379             int ss = os->segments[os->segp++];
380             os->psize += ss;
381             if (ss < 255){
382                 complete = 1;
383                 break;
384             }
385         }
386
387         if (!complete && os->segp == os->nsegs){
388             ogg->curidx = -1;
389             // Do not set incomplete for empty packets.
390             // Together with the code in ogg_read_page
391             // that discards all continuation of empty packets
392             // we would get an infinite loop.
393             os->incomplete = !!os->psize;
394         }
395     }while (!complete);
396
397
398     if (os->granule == -1)
399         av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
400
401     ogg->curidx = idx;
402     os->incomplete = 0;
403
404     if (os->header) {
405         os->header = os->codec->header (s, idx);
406         if (!os->header){
407             os->segp = segp;
408             os->psize = psize;
409
410             // We have reached the first non-header packet in this stream.
411             // Unfortunately more header packets may still follow for others,
412             // but if we continue with header parsing we may lose data packets.
413             ogg->headers = 1;
414
415             // Update the header state for all streams and
416             // compute the data_offset.
417             if (!s->data_offset)
418                 s->data_offset = os->sync_pos;
419             for (i = 0; i < ogg->nstreams; i++) {
420                 struct ogg_stream *cur_os = ogg->streams + i;
421
422                 // if we have a partial non-header packet, its start is
423                 // obviously at or after the data start
424                 if (cur_os->incomplete)
425                     s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
426             }
427         }else{
428             os->pstart += os->psize;
429             os->psize = 0;
430         }
431     } else {
432         os->pflags = 0;
433         os->pduration = 0;
434         if (os->codec && os->codec->packet)
435             os->codec->packet (s, idx);
436         if (str)
437             *str = idx;
438         if (dstart)
439             *dstart = os->pstart;
440         if (dsize)
441             *dsize = os->psize;
442         if (fpos)
443             *fpos = os->sync_pos;
444         os->pstart += os->psize;
445         os->psize = 0;
446         if(os->pstart == os->bufpos)
447             os->bufpos = os->pstart = 0;
448         os->sync_pos = os->page_pos;
449     }
450
451     // determine whether there are more complete packets in this page
452     // if not, the page's granule will apply to this packet
453     os->page_end = 1;
454     for (i = os->segp; i < os->nsegs; i++)
455         if (os->segments[i] < 255) {
456             os->page_end = 0;
457             break;
458         }
459
460     if (os->segp == os->nsegs)
461         ogg->curidx = -1;
462
463     return 0;
464 }
465
466 static int ogg_get_headers(AVFormatContext *s)
467 {
468     struct ogg *ogg = s->priv_data;
469     int ret;
470
471     do{
472         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
473         if (ret < 0)
474             return ret;
475     }while (!ogg->headers);
476
477     av_dlog(s, "found headers\n");
478
479     return 0;
480 }
481
482 static int ogg_get_length(AVFormatContext *s)
483 {
484     struct ogg *ogg = s->priv_data;
485     int i;
486     int64_t size, end;
487     int streams_left=0;
488
489     if(!s->pb->seekable)
490         return 0;
491
492 // already set
493     if (s->duration != AV_NOPTS_VALUE)
494         return 0;
495
496     size = avio_size(s->pb);
497     if(size < 0)
498         return 0;
499     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
500
501     ogg_save (s);
502     avio_seek (s->pb, end, SEEK_SET);
503
504     while (!ogg_read_page (s, &i)){
505         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
506             ogg->streams[i].codec) {
507             s->streams[i]->duration =
508                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
509             if (s->streams[i]->start_time != AV_NOPTS_VALUE){
510                 s->streams[i]->duration -= s->streams[i]->start_time;
511                 streams_left-= (ogg->streams[i].got_start==-1);
512                 ogg->streams[i].got_start= 1;
513             }else if(!ogg->streams[i].got_start){
514                 ogg->streams[i].got_start= -1;
515                 streams_left++;
516             }
517         }
518     }
519
520     ogg_restore (s, 0);
521
522     ogg_save (s);
523     avio_seek (s->pb, 0, SEEK_SET);
524     while (!ogg_read_page (s, &i)){
525         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
526             ogg->streams[i].codec) {
527             if(s->streams[i]->duration && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start){
528                 int64_t start= ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
529                 if(av_rescale_q(start, s->streams[i]->time_base, AV_TIME_BASE_Q) > AV_TIME_BASE)
530                     s->streams[i]->duration -= start;
531                 ogg->streams[i].got_start= 1;
532                 streams_left--;
533             }
534             if(streams_left<=0)
535                 break;
536         }
537     }
538     ogg_restore (s, 0);
539
540     return 0;
541 }
542
543 static int ogg_read_header(AVFormatContext *s)
544 {
545     struct ogg *ogg = s->priv_data;
546     int ret, i;
547     ogg->curidx = -1;
548     //linear headers seek from start
549     ret = ogg_get_headers(s);
550     if (ret < 0)
551         return ret;
552
553     for (i = 0; i < ogg->nstreams; i++)
554         if (ogg->streams[i].header < 0)
555             ogg->streams[i].codec = NULL;
556
557     //linear granulepos seek from end
558     ogg_get_length (s);
559
560     //fill the extradata in the per codec callbacks
561     return 0;
562 }
563
564 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
565 {
566     struct ogg *ogg = s->priv_data;
567     struct ogg_stream *os = ogg->streams + idx;
568     int64_t pts = AV_NOPTS_VALUE;
569
570     if (dts)
571         *dts = AV_NOPTS_VALUE;
572
573     if (os->lastpts != AV_NOPTS_VALUE) {
574         pts = os->lastpts;
575         os->lastpts = AV_NOPTS_VALUE;
576     }
577     if (os->lastdts != AV_NOPTS_VALUE) {
578         if (dts)
579             *dts = os->lastdts;
580         os->lastdts = AV_NOPTS_VALUE;
581     }
582     if (os->page_end) {
583         if (os->granule != -1LL) {
584             if (os->codec && os->codec->granule_is_start)
585                 pts = ogg_gptopts(s, idx, os->granule, dts);
586             else
587                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
588             os->granule = -1LL;
589         }
590     }
591     return pts;
592 }
593
594 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
595 {
596     struct ogg *ogg = s->priv_data;
597     struct ogg_stream *os = ogg->streams + idx;
598     if (psize && s->streams[idx]->codec->codec_id == CODEC_ID_THEORA) {
599         if (!!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40)) {
600             os->pflags ^= AV_PKT_FLAG_KEY;
601             av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
602                    (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
603         }
604     }
605 }
606
607 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
608 {
609     struct ogg *ogg;
610     struct ogg_stream *os;
611     int idx = -1, ret;
612     int pstart, psize;
613     int64_t fpos, pts, dts;
614
615     //Get an ogg packet
616 retry:
617     do{
618         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
619         if (ret < 0)
620             return ret;
621     }while (idx < 0 || !s->streams[idx]);
622
623     ogg = s->priv_data;
624     os = ogg->streams + idx;
625
626     // pflags might not be set until after this
627     pts = ogg_calc_pts(s, idx, &dts);
628     ogg_validate_keyframe(s, idx, pstart, psize);
629
630     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
631         goto retry;
632     os->keyframe_seek = 0;
633
634     //Alloc a pkt
635     ret = av_new_packet(pkt, psize);
636     if (ret < 0)
637         return ret;
638     pkt->stream_index = idx;
639     memcpy (pkt->data, os->buf + pstart, psize);
640
641     pkt->pts = pts;
642     pkt->dts = dts;
643     pkt->flags = os->pflags;
644     pkt->duration = os->pduration;
645     pkt->pos = fpos;
646
647     return psize;
648 }
649
650 static int ogg_read_close(AVFormatContext *s)
651 {
652     struct ogg *ogg = s->priv_data;
653     int i;
654
655     for (i = 0; i < ogg->nstreams; i++){
656         av_free (ogg->streams[i].buf);
657         av_free (ogg->streams[i].private);
658     }
659     av_free (ogg->streams);
660     return 0;
661 }
662
663 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
664                                   int64_t *pos_arg, int64_t pos_limit)
665 {
666     struct ogg *ogg = s->priv_data;
667     AVIOContext *bc = s->pb;
668     int64_t pts = AV_NOPTS_VALUE;
669     int64_t keypos = -1;
670     int i = -1;
671     int pstart, psize;
672     avio_seek(bc, *pos_arg, SEEK_SET);
673     ogg_reset(s);
674
675     while (avio_tell(bc) <= pos_limit && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
676         if (i == stream_index) {
677             struct ogg_stream *os = ogg->streams + stream_index;
678             pts = ogg_calc_pts(s, i, NULL);
679             ogg_validate_keyframe(s, i, pstart, psize);
680             if (os->pflags & AV_PKT_FLAG_KEY) {
681                 keypos = *pos_arg;
682             } else if (os->keyframe_seek) {
683                 // if we had a previous keyframe but no pts for it,
684                 // return that keyframe with this pts value.
685                 if (keypos >= 0)
686                     *pos_arg = keypos;
687                 else
688                     pts = AV_NOPTS_VALUE;
689             }
690         }
691         if (pts != AV_NOPTS_VALUE)
692             break;
693     }
694     ogg_reset(s);
695     return pts;
696 }
697
698 static int ogg_read_seek(AVFormatContext *s, int stream_index,
699                          int64_t timestamp, int flags)
700 {
701     struct ogg *ogg = s->priv_data;
702     struct ogg_stream *os = ogg->streams + stream_index;
703     int ret;
704
705     av_assert0(stream_index < ogg->nstreams);
706     // Ensure everything is reset even when seeking via
707     // the generated index.
708     ogg_reset(s);
709
710     // Try seeking to a keyframe first. If this fails (very possible),
711     // av_seek_frame will fall back to ignoring keyframes
712     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
713         && !(flags & AVSEEK_FLAG_ANY))
714         os->keyframe_seek = 1;
715
716     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
717     os = ogg->streams + stream_index;
718     if (ret < 0)
719         os->keyframe_seek = 0;
720     return ret;
721 }
722
723 static int ogg_probe(AVProbeData *p)
724 {
725     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
726         return AVPROBE_SCORE_MAX;
727     return 0;
728 }
729
730 AVInputFormat ff_ogg_demuxer = {
731     .name           = "ogg",
732     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
733     .priv_data_size = sizeof(struct ogg),
734     .read_probe     = ogg_probe,
735     .read_header    = ogg_read_header,
736     .read_packet    = ogg_read_packet,
737     .read_close     = ogg_read_close,
738     .read_seek      = ogg_read_seek,
739     .read_timestamp = ogg_read_timestamp,
740     .extensions     = "ogg",
741     .flags          = AVFMT_GENERIC_INDEX,
742 };