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