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