]> git.sesse.net Git - ffmpeg/blob - libavformat/oggdec.c
oggdec: fix demuxing chained audio streams
[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 /**
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
59 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_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
83 static int
84 ogg_restore (AVFormatContext * s, int discard)
85 {
86     struct ogg *ogg = s->priv_data;
87     AVIOContext *bc = s->pb;
88     struct ogg_state *ost = ogg->state;
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
100         avio_seek (bc, ost->pos, SEEK_SET);
101         ogg->curidx = ost->curidx;
102         ogg->nstreams = ost->nstreams;
103         memcpy(ogg->streams, ost->streams,
104                ost->nstreams * sizeof(*ogg->streams));
105     }
106
107     av_free (ost);
108
109     return 0;
110 }
111
112 static int
113 ogg_reset (struct ogg * ogg)
114 {
115     int i;
116
117     for (i = 0; i < ogg->nstreams; i++){
118         struct ogg_stream *os = ogg->streams + i;
119         os->bufpos = 0;
120         os->pstart = 0;
121         os->psize = 0;
122         os->granule = -1;
123         os->lastpts = AV_NOPTS_VALUE;
124         os->lastdts = AV_NOPTS_VALUE;
125         os->sync_pos = -1;
126         os->page_pos = 0;
127         os->nsegs = 0;
128         os->segp = 0;
129         os->incomplete = 0;
130     }
131
132     ogg->curidx = -1;
133
134     return 0;
135 }
136
137 static const struct ogg_codec *
138 ogg_find_codec (uint8_t * buf, int size)
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
150 static int
151 ogg_new_stream (AVFormatContext * s, uint32_t serial)
152 {
153
154     struct ogg *ogg = s->priv_data;
155     int idx = ogg->nstreams++;
156     AVStream *st;
157     struct ogg_stream *os;
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;
165     os->buf = av_malloc(os->bufsize);
166     os->header = -1;
167     os->page_begin = 1;
168
169     st = av_new_stream (s, idx);
170     if (!st)
171         return AVERROR(ENOMEM);
172
173     av_set_pts_info(st, 64, 1, 1000000);
174
175     return idx;
176 }
177
178 static int
179 ogg_new_buf(struct ogg *ogg, int idx)
180 {
181     struct ogg_stream *os = ogg->streams + idx;
182     uint8_t *nb = av_malloc(os->bufsize);
183     int size = os->bufpos - os->pstart;
184     if(os->buf){
185         memcpy(nb, os->buf + os->pstart, size);
186         av_free(os->buf);
187     }
188     os->buf = nb;
189     os->bufpos = size;
190     os->pstart = 0;
191
192     return 0;
193 }
194
195 static int
196 ogg_read_page (AVFormatContext * s, int *str)
197 {
198     AVIOContext *bc = s->pb;
199     struct ogg *ogg = s->priv_data;
200     struct ogg_stream *os;
201     int i = 0;
202     int flags, nsegs;
203     uint64_t gp;
204     uint32_t serial;
205     uint32_t seq;
206     uint32_t crc;
207     int size, idx;
208     uint8_t sync[4];
209     int sp = 0;
210
211     if (avio_read (bc, sync, 4) < 4)
212         return -1;
213
214     do{
215         int c;
216
217         if (sync[sp & 3] == 'O' &&
218             sync[(sp + 1) & 3] == 'g' &&
219             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
220             break;
221
222         c = avio_r8(bc);
223         if (bc->eof_reached)
224             return -1;
225         sync[sp++ & 3] = c;
226     }while (i++ < MAX_PAGE_SIZE);
227
228     if (i >= MAX_PAGE_SIZE){
229         av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
230         return -1;
231     }
232
233     if (avio_r8(bc) != 0)      /* version */
234         return -1;
235
236     flags = avio_r8(bc);
237     gp = avio_rl64 (bc);
238     serial = avio_rl32 (bc);
239     seq = avio_rl32 (bc);
240     crc = avio_rl32 (bc);
241     nsegs = avio_r8(bc);
242
243     idx = ogg_find_stream (ogg, serial);
244     if (idx < 0){
245         for (i = 0; i < ogg->nstreams; i++) {
246             if (!ogg->streams[i].page_begin) {
247                 int n;
248
249                 for (n = 0; n < ogg->nstreams; n++) {
250                     av_free(ogg->streams[n].buf);
251                     av_free(ogg->streams[n].private);
252                 }
253                 ogg->curidx   = -1;
254                 ogg->nstreams = 0;
255                 break;
256             }
257         }
258         idx = ogg_new_stream (s, serial);
259         if (idx < 0)
260             return -1;
261     }
262
263     os = ogg->streams + idx;
264     if (!(flags & OGG_FLAG_BOS))
265         os->page_begin = 0;
266     os->page_pos = avio_tell(bc) - 27;
267
268     if(os->psize > 0)
269         ogg_new_buf(ogg, idx);
270
271     if (avio_read (bc, os->segments, nsegs) < nsegs)
272         return -1;
273
274     os->nsegs = nsegs;
275     os->segp = 0;
276
277     size = 0;
278     for (i = 0; i < nsegs; i++)
279         size += os->segments[i];
280
281     if (flags & OGG_FLAG_CONT || os->incomplete){
282         if (!os->psize){
283             while (os->segp < os->nsegs){
284                 int seg = os->segments[os->segp++];
285                 os->pstart += seg;
286                 if (seg < 255)
287                     break;
288             }
289             os->sync_pos = os->page_pos;
290         }
291     }else{
292         os->psize = 0;
293         os->sync_pos = os->page_pos;
294     }
295
296     if (os->bufsize - os->bufpos < size){
297         uint8_t *nb = av_malloc (os->bufsize *= 2);
298         memcpy (nb, os->buf, os->bufpos);
299         av_free (os->buf);
300         os->buf = nb;
301     }
302
303     if (avio_read (bc, os->buf + os->bufpos, size) < size)
304         return -1;
305
306     os->bufpos += size;
307     os->granule = gp;
308     os->flags = flags;
309
310     if (str)
311         *str = idx;
312
313     return 0;
314 }
315
316 static int
317 ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpos)
318 {
319     struct ogg *ogg = s->priv_data;
320     int idx, i;
321     struct ogg_stream *os;
322     int complete = 0;
323     int segp = 0, psize = 0;
324
325 #if 0
326     av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
327 #endif
328
329     do{
330         idx = ogg->curidx;
331
332         while (idx < 0){
333             if (ogg_read_page (s, &idx) < 0)
334                 return -1;
335         }
336
337         os = ogg->streams + idx;
338
339 #if 0
340         av_log (s, AV_LOG_DEBUG,
341                 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
342                 idx, os->pstart, os->psize, os->segp, os->nsegs);
343 #endif
344
345         if (!os->codec){
346             if (os->header < 0){
347                 os->codec = ogg_find_codec (os->buf, os->bufpos);
348                 if (!os->codec){
349                     os->header = 0;
350                     return 0;
351                 }
352             }else{
353                 return 0;
354             }
355         }
356
357         segp = os->segp;
358         psize = os->psize;
359
360         while (os->segp < os->nsegs){
361             int ss = os->segments[os->segp++];
362             os->psize += ss;
363             if (ss < 255){
364                 complete = 1;
365                 break;
366             }
367         }
368
369         if (!complete && os->segp == os->nsegs){
370             ogg->curidx = -1;
371             os->incomplete = 1;
372         }
373     }while (!complete);
374
375 #if 0
376     av_log (s, AV_LOG_DEBUG,
377             "ogg_packet: idx %i, frame size %i, start %i\n",
378             idx, os->psize, os->pstart);
379 #endif
380
381     if (os->granule == -1)
382         av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
383
384     ogg->curidx = idx;
385     os->incomplete = 0;
386
387     if (os->header) {
388         os->header = os->codec->header (s, idx);
389         if (!os->header){
390             os->segp = segp;
391             os->psize = psize;
392
393             // We have reached the first non-header packet in this stream.
394             // Unfortunately more header packets may still follow for others,
395             // so we reset this later unless we are done with the headers
396             // for all streams.
397             ogg->headers = 1;
398
399             // Update the header state for all streams and
400             // compute the data_offset.
401             if (!s->data_offset)
402                 s->data_offset = os->sync_pos;
403             for (i = 0; i < ogg->nstreams; i++) {
404                 struct ogg_stream *cur_os = ogg->streams + i;
405                 if (cur_os->header > 0)
406                     ogg->headers = 0;
407
408                 // if we have a partial non-header packet, its start is
409                 // obviously at or after the data start
410                 if (cur_os->incomplete)
411                     s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
412             }
413         }else{
414             os->pstart += os->psize;
415             os->psize = 0;
416         }
417     } else {
418         os->pflags = 0;
419         os->pduration = 0;
420         if (os->codec && os->codec->packet)
421             os->codec->packet (s, idx);
422         if (str)
423             *str = idx;
424         if (dstart)
425             *dstart = os->pstart;
426         if (dsize)
427             *dsize = os->psize;
428         if (fpos)
429             *fpos = os->sync_pos;
430         os->pstart += os->psize;
431         os->psize = 0;
432         os->sync_pos = os->page_pos;
433     }
434
435     // determine whether there are more complete packets in this page
436     // if not, the page's granule will apply to this packet
437     os->page_end = 1;
438     for (i = os->segp; i < os->nsegs; i++)
439         if (os->segments[i] < 255) {
440             os->page_end = 0;
441             break;
442         }
443
444     if (os->segp == os->nsegs)
445         ogg->curidx = -1;
446
447     return 0;
448 }
449
450 static int
451 ogg_get_headers (AVFormatContext * s)
452 {
453     struct ogg *ogg = s->priv_data;
454
455     do{
456         if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
457             return -1;
458     }while (!ogg->headers);
459
460 #if 0
461     av_log (s, AV_LOG_DEBUG, "found headers\n");
462 #endif
463
464     return 0;
465 }
466
467 static int
468 ogg_get_length (AVFormatContext * s)
469 {
470     struct ogg *ogg = s->priv_data;
471     int i;
472     int64_t size, end;
473
474     if(!s->pb->seekable)
475         return 0;
476
477 // already set
478     if (s->duration != AV_NOPTS_VALUE)
479         return 0;
480
481     size = avio_size(s->pb);
482     if(size < 0)
483         return 0;
484     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
485
486     ogg_save (s);
487     avio_seek (s->pb, end, SEEK_SET);
488
489     while (!ogg_read_page (s, &i)){
490         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
491             ogg->streams[i].codec) {
492             s->streams[i]->duration =
493                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
494             if (s->streams[i]->start_time != AV_NOPTS_VALUE)
495                 s->streams[i]->duration -= s->streams[i]->start_time;
496         }
497     }
498
499     ogg_restore (s, 0);
500
501     return 0;
502 }
503
504
505 static int
506 ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
507 {
508     struct ogg *ogg = s->priv_data;
509     int i;
510     ogg->curidx = -1;
511     //linear headers seek from start
512     if (ogg_get_headers (s) < 0){
513         return -1;
514     }
515
516     for (i = 0; i < ogg->nstreams; i++)
517         if (ogg->streams[i].header < 0)
518             ogg->streams[i].codec = NULL;
519
520     //linear granulepos seek from end
521     ogg_get_length (s);
522
523     //fill the extradata in the per codec callbacks
524     return 0;
525 }
526
527 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
528 {
529     struct ogg *ogg = s->priv_data;
530     struct ogg_stream *os = ogg->streams + idx;
531     int64_t pts = AV_NOPTS_VALUE;
532
533     if (dts)
534         *dts = AV_NOPTS_VALUE;
535
536     if (os->lastpts != AV_NOPTS_VALUE) {
537         pts = os->lastpts;
538         os->lastpts = AV_NOPTS_VALUE;
539     }
540     if (os->lastdts != AV_NOPTS_VALUE) {
541         if (dts)
542             *dts = os->lastdts;
543         os->lastdts = AV_NOPTS_VALUE;
544     }
545     if (os->page_end) {
546         if (os->granule != -1LL) {
547             if (os->codec && os->codec->granule_is_start)
548                 pts = ogg_gptopts(s, idx, os->granule, dts);
549             else
550                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
551             os->granule = -1LL;
552         }
553     }
554     return pts;
555 }
556
557 static int
558 ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
559 {
560     struct ogg *ogg;
561     struct ogg_stream *os;
562     int idx = -1;
563     int pstart, psize;
564     int64_t fpos, pts, dts;
565
566     //Get an ogg packet
567 retry:
568     do{
569         if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
570             return AVERROR(EIO);
571     }while (idx < 0 || !s->streams[idx]);
572
573     ogg = s->priv_data;
574     os = ogg->streams + idx;
575
576     // pflags might not be set until after this
577     pts = ogg_calc_pts(s, idx, &dts);
578
579     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
580         goto retry;
581     os->keyframe_seek = 0;
582
583     //Alloc a pkt
584     if (av_new_packet (pkt, psize) < 0)
585         return AVERROR(EIO);
586     pkt->stream_index = idx;
587     memcpy (pkt->data, os->buf + pstart, psize);
588
589     pkt->pts = pts;
590     pkt->dts = dts;
591     pkt->flags = os->pflags;
592     pkt->duration = os->pduration;
593     pkt->pos = fpos;
594
595     return psize;
596 }
597
598
599 static int
600 ogg_read_close (AVFormatContext * s)
601 {
602     struct ogg *ogg = s->priv_data;
603     int i;
604
605     for (i = 0; i < ogg->nstreams; i++){
606         av_free (ogg->streams[i].buf);
607         av_free (ogg->streams[i].private);
608     }
609     av_free (ogg->streams);
610     return 0;
611 }
612
613
614 static int64_t
615 ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
616                     int64_t pos_limit)
617 {
618     struct ogg *ogg = s->priv_data;
619     struct ogg_stream *os = ogg->streams + stream_index;
620     AVIOContext *bc = s->pb;
621     int64_t pts = AV_NOPTS_VALUE;
622     int i;
623     avio_seek(bc, *pos_arg, SEEK_SET);
624     ogg_reset(ogg);
625
626     while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
627         if (i == stream_index) {
628             pts = ogg_calc_pts(s, i, NULL);
629             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
630                 pts = AV_NOPTS_VALUE;
631         }
632         if (pts != AV_NOPTS_VALUE)
633             break;
634     }
635     ogg_reset(ogg);
636     return pts;
637 }
638
639 static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
640 {
641     struct ogg *ogg = s->priv_data;
642     struct ogg_stream *os = ogg->streams + stream_index;
643     int ret;
644
645     // Try seeking to a keyframe first. If this fails (very possible),
646     // av_seek_frame will fall back to ignoring keyframes
647     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
648         && !(flags & AVSEEK_FLAG_ANY))
649         os->keyframe_seek = 1;
650
651     ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
652     if (ret < 0)
653         os->keyframe_seek = 0;
654     return ret;
655 }
656
657 static int ogg_probe(AVProbeData *p)
658 {
659     if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
660         p->buf[2] == 'g' && p->buf[3] == 'S' &&
661         p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
662         return AVPROBE_SCORE_MAX;
663     else
664         return 0;
665 }
666
667 AVInputFormat ff_ogg_demuxer = {
668     "ogg",
669     NULL_IF_CONFIG_SMALL("Ogg"),
670     sizeof (struct ogg),
671     ogg_probe,
672     ogg_read_header,
673     ogg_read_packet,
674     ogg_read_close,
675     ogg_read_seek,
676     ogg_read_timestamp,
677     .extensions = "ogg",
678     .flags = AVFMT_GENERIC_INDEX,
679 };