fda1eb2633f5e1d5529e48f86b8baccd5d260972
[ffmpeg.git] / 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
37 #define MAX_PAGE_SIZE 65307
38 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
39
40 static const struct ogg_codec * const ogg_codecs[] = {
41     &ff_skeleton_codec,
42     &ff_dirac_codec,
43     &ff_speex_codec,
44     &ff_vorbis_codec,
45     &ff_theora_codec,
46     &ff_flac_codec,
47     &ff_old_dirac_codec,
48     &ff_old_flac_codec,
49     &ff_ogm_video_codec,
50     &ff_ogm_audio_codec,
51     &ff_ogm_text_codec,
52     &ff_ogm_old_codec,
53     NULL
54 };
55
56 //FIXME We could avoid some structure duplication
57 static int
58 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 = url_ftell (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
83 ogg_restore (AVFormatContext * s, int discard)
84 {
85     struct ogg *ogg = s->priv_data;
86     ByteIOContext *bc = s->pb;
87     struct ogg_state *ost = ogg->state;
88     int i;
89
90     if (!ost)
91         return 0;
92
93     ogg->state = ost->next;
94
95     if (!discard){
96         for (i = 0; i < ogg->nstreams; i++)
97             av_free (ogg->streams[i].buf);
98
99         url_fseek (bc, ost->pos, SEEK_SET);
100         ogg->curidx = ost->curidx;
101         ogg->nstreams = ost->nstreams;
102         memcpy(ogg->streams, ost->streams,
103                ost->nstreams * sizeof(*ogg->streams));
104     }
105
106     av_free (ost);
107
108     return 0;
109 }
110
111 static int
112 ogg_reset (struct ogg * ogg)
113 {
114     int i;
115
116     for (i = 0; i < ogg->nstreams; i++){
117         struct ogg_stream *os = ogg->streams + i;
118         os->bufpos = 0;
119         os->pstart = 0;
120         os->psize = 0;
121         os->granule = -1;
122         os->lastpts = AV_NOPTS_VALUE;
123         os->lastdts = AV_NOPTS_VALUE;
124         os->sync_pos = -1;
125         os->page_pos = 0;
126         os->nsegs = 0;
127         os->segp = 0;
128         os->incomplete = 0;
129     }
130
131     ogg->curidx = -1;
132
133     return 0;
134 }
135
136 static const struct ogg_codec *
137 ogg_find_codec (uint8_t * buf, int size)
138 {
139     int i;
140
141     for (i = 0; ogg_codecs[i]; i++)
142         if (size >= ogg_codecs[i]->magicsize &&
143             !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
144             return ogg_codecs[i];
145
146     return NULL;
147 }
148
149 static int
150 ogg_new_stream (AVFormatContext * s, uint32_t serial)
151 {
152
153     struct ogg *ogg = s->priv_data;
154     int idx = ogg->nstreams++;
155     AVStream *st;
156     struct ogg_stream *os;
157
158     ogg->streams = av_realloc (ogg->streams,
159                                ogg->nstreams * sizeof (*ogg->streams));
160     memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
161     os = ogg->streams + idx;
162     os->serial = serial;
163     os->bufsize = DECODER_BUFFER_SIZE;
164     os->buf = av_malloc(os->bufsize);
165     os->header = -1;
166
167     st = av_new_stream (s, idx);
168     if (!st)
169         return AVERROR(ENOMEM);
170
171     av_set_pts_info(st, 64, 1, 1000000);
172
173     return idx;
174 }
175
176 static int
177 ogg_new_buf(struct ogg *ogg, int idx)
178 {
179     struct ogg_stream *os = ogg->streams + idx;
180     uint8_t *nb = av_malloc(os->bufsize);
181     int size = os->bufpos - os->pstart;
182     if(os->buf){
183         memcpy(nb, os->buf + os->pstart, size);
184         av_free(os->buf);
185     }
186     os->buf = nb;
187     os->bufpos = size;
188     os->pstart = 0;
189
190     return 0;
191 }
192
193 static int
194 ogg_read_page (AVFormatContext * s, int *str)
195 {
196     ByteIOContext *bc = s->pb;
197     struct ogg *ogg = s->priv_data;
198     struct ogg_stream *os;
199     int i = 0;
200     int flags, nsegs;
201     uint64_t gp;
202     uint32_t serial;
203     uint32_t seq;
204     uint32_t crc;
205     int size, idx;
206     uint8_t sync[4];
207     int sp = 0;
208
209     if (get_buffer (bc, sync, 4) < 4)
210         return -1;
211
212     do{
213         int c;
214
215         if (sync[sp & 3] == 'O' &&
216             sync[(sp + 1) & 3] == 'g' &&
217             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
218             break;
219
220         c = url_fgetc (bc);
221         if (c < 0)
222             return -1;
223         sync[sp++ & 3] = c;
224     }while (i++ < MAX_PAGE_SIZE);
225
226     if (i >= MAX_PAGE_SIZE){
227         av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
228         return -1;
229     }
230
231     if (url_fgetc (bc) != 0)      /* version */
232         return -1;
233
234     flags = url_fgetc (bc);
235     gp = get_le64 (bc);
236     serial = get_le32 (bc);
237     seq = get_le32 (bc);
238     crc = get_le32 (bc);
239     nsegs = url_fgetc (bc);
240
241     idx = ogg_find_stream (ogg, serial);
242     if (idx < 0){
243         idx = ogg_new_stream (s, serial);
244         if (idx < 0)
245             return -1;
246     }
247
248     os = ogg->streams + idx;
249     os->page_pos = url_ftell(bc) - 27;
250
251     if(os->psize > 0)
252         ogg_new_buf(ogg, idx);
253
254     if (get_buffer (bc, os->segments, nsegs) < nsegs)
255         return -1;
256
257     os->nsegs = nsegs;
258     os->segp = 0;
259
260     size = 0;
261     for (i = 0; i < nsegs; i++)
262         size += os->segments[i];
263
264     if (flags & OGG_FLAG_CONT || os->incomplete){
265         if (!os->psize){
266             while (os->segp < os->nsegs){
267                 int seg = os->segments[os->segp++];
268                 os->pstart += seg;
269                 if (seg < 255)
270                     break;
271             }
272             os->sync_pos = os->page_pos;
273         }
274     }else{
275         os->psize = 0;
276         os->sync_pos = os->page_pos;
277     }
278
279     if (os->bufsize - os->bufpos < size){
280         uint8_t *nb = av_malloc (os->bufsize *= 2);
281         memcpy (nb, os->buf, os->bufpos);
282         av_free (os->buf);
283         os->buf = nb;
284     }
285
286     if (get_buffer (bc, os->buf + os->bufpos, size) < size)
287         return -1;
288
289     os->bufpos += size;
290     os->granule = gp;
291     os->flags = flags;
292
293     if (str)
294         *str = idx;
295
296     return 0;
297 }
298
299 static int
300 ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpos)
301 {
302     struct ogg *ogg = s->priv_data;
303     int idx, i;
304     struct ogg_stream *os;
305     int complete = 0;
306     int segp = 0, psize = 0;
307
308 #if 0
309     av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
310 #endif
311
312     do{
313         idx = ogg->curidx;
314
315         while (idx < 0){
316             if (ogg_read_page (s, &idx) < 0)
317                 return -1;
318         }
319
320         os = ogg->streams + idx;
321
322 #if 0
323         av_log (s, AV_LOG_DEBUG,
324                 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
325                 idx, os->pstart, os->psize, os->segp, os->nsegs);
326 #endif
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 #if 0
359     av_log (s, AV_LOG_DEBUG,
360             "ogg_packet: idx %i, frame size %i, start %i\n",
361             idx, os->psize, os->pstart);
362 #endif
363
364     ogg->curidx = idx;
365     os->incomplete = 0;
366
367     if (!ogg->headers){
368         int hdr = os->codec->header (s, idx);
369         os->header = os->seq;
370         if (!hdr){
371             os->segp = segp;
372             os->psize = psize;
373             ogg->headers = 1;
374             s->data_offset = os->sync_pos;
375         }else{
376             os->pstart += os->psize;
377             os->psize = 0;
378         }
379     }
380
381     if (os->header > -1 && os->seq > os->header){
382         os->pflags = 0;
383         os->pduration = 0;
384         if (os->codec && os->codec->packet)
385             os->codec->packet (s, idx);
386         if (str)
387             *str = idx;
388         if (dstart)
389             *dstart = os->pstart;
390         if (dsize)
391             *dsize = os->psize;
392         if (fpos)
393             *fpos = os->sync_pos;
394         os->pstart += os->psize;
395         os->psize = 0;
396         os->sync_pos = os->page_pos;
397     }
398
399     // determine whether there are more complete packets in this page
400     // if not, the page's granule will apply to this packet
401     os->page_end = 1;
402     for (i = os->segp; i < os->nsegs; i++)
403         if (os->segments[i] < 255) {
404             os->page_end = 0;
405             break;
406         }
407
408     os->seq++;
409     if (os->segp == os->nsegs)
410         ogg->curidx = -1;
411
412     return 0;
413 }
414
415 static int
416 ogg_get_headers (AVFormatContext * s)
417 {
418     struct ogg *ogg = s->priv_data;
419
420     do{
421         if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
422             return -1;
423     }while (!ogg->headers);
424
425 #if 0
426     av_log (s, AV_LOG_DEBUG, "found headers\n");
427 #endif
428
429     return 0;
430 }
431
432 static int
433 ogg_get_length (AVFormatContext * s)
434 {
435     struct ogg *ogg = s->priv_data;
436     int idx = -1, i;
437     int64_t size, end;
438
439     if(url_is_streamed(s->pb))
440         return 0;
441
442 // already set
443     if (s->duration != AV_NOPTS_VALUE)
444         return 0;
445
446     size = url_fsize(s->pb);
447     if(size < 0)
448         return 0;
449     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
450
451     ogg_save (s);
452     url_fseek (s->pb, end, SEEK_SET);
453
454     while (!ogg_read_page (s, &i)){
455         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
456             ogg->streams[i].codec)
457             idx = i;
458     }
459
460     if (idx != -1){
461         s->streams[idx]->duration =
462             ogg_gptopts (s, idx, ogg->streams[idx].granule, NULL);
463         if (s->streams[idx]->start_time != AV_NOPTS_VALUE)
464             s->streams[idx]->duration -= s->streams[idx]->start_time;
465     }
466
467     ogg->size = size;
468     ogg_restore (s, 0);
469
470     return 0;
471 }
472
473
474 static int
475 ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
476 {
477     struct ogg *ogg = s->priv_data;
478     int i;
479     ogg->curidx = -1;
480     //linear headers seek from start
481     if (ogg_get_headers (s) < 0){
482         return -1;
483     }
484
485     for (i = 0; i < ogg->nstreams; i++)
486         if (ogg->streams[i].header < 0)
487             ogg->streams[i].codec = NULL;
488
489     //linear granulepos seek from end
490     ogg_get_length (s);
491
492     //fill the extradata in the per codec callbacks
493     return 0;
494 }
495
496 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
497 {
498     struct ogg *ogg = s->priv_data;
499     struct ogg_stream *os = ogg->streams + idx;
500     int64_t pts = AV_NOPTS_VALUE;
501
502     if (dts)
503         *dts = AV_NOPTS_VALUE;
504
505     if (os->lastpts != AV_NOPTS_VALUE) {
506         pts = os->lastpts;
507         os->lastpts = AV_NOPTS_VALUE;
508     }
509     if (os->lastdts != AV_NOPTS_VALUE) {
510         if (dts)
511             *dts = os->lastdts;
512         os->lastdts = AV_NOPTS_VALUE;
513     }
514     if (os->page_end) {
515         if (os->granule != -1LL) {
516             if (os->codec && os->codec->granule_is_start)
517                 pts = ogg_gptopts(s, idx, os->granule, dts);
518             else
519                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
520             os->granule = -1LL;
521         } else
522             av_log(s, AV_LOG_WARNING, "Packet is missing granule\n");
523     }
524     return pts;
525 }
526
527 static int
528 ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
529 {
530     struct ogg *ogg;
531     struct ogg_stream *os;
532     int idx = -1;
533     int pstart, psize;
534     int64_t fpos, pts, dts;
535
536     //Get an ogg packet
537 retry:
538     do{
539         if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
540             return AVERROR(EIO);
541     }while (idx < 0 || !s->streams[idx]);
542
543     ogg = s->priv_data;
544     os = ogg->streams + idx;
545
546     // pflags might not be set until after this
547     pts = ogg_calc_pts(s, idx, &dts);
548
549     if (os->keyframe_seek && !(os->pflags & PKT_FLAG_KEY))
550         goto retry;
551     os->keyframe_seek = 0;
552
553     //Alloc a pkt
554     if (av_new_packet (pkt, psize) < 0)
555         return AVERROR(EIO);
556     pkt->stream_index = idx;
557     memcpy (pkt->data, os->buf + pstart, psize);
558
559     pkt->pts = pts;
560     pkt->dts = dts;
561     pkt->flags = os->pflags;
562     pkt->duration = os->pduration;
563     pkt->pos = fpos;
564
565     return psize;
566 }
567
568
569 static int
570 ogg_read_close (AVFormatContext * s)
571 {
572     struct ogg *ogg = s->priv_data;
573     int i;
574
575     for (i = 0; i < ogg->nstreams; i++){
576         av_free (ogg->streams[i].buf);
577         av_free (ogg->streams[i].private);
578     }
579     av_free (ogg->streams);
580     return 0;
581 }
582
583
584 static int64_t
585 ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
586                     int64_t pos_limit)
587 {
588     struct ogg *ogg = s->priv_data;
589     struct ogg_stream *os = ogg->streams + stream_index;
590     ByteIOContext *bc = s->pb;
591     int64_t pts = AV_NOPTS_VALUE;
592     int i;
593     url_fseek(bc, *pos_arg, SEEK_SET);
594     ogg_reset(ogg);
595
596     while (url_ftell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
597         if (i == stream_index) {
598             pts = ogg_calc_pts(s, i, NULL);
599             if (os->keyframe_seek && !(os->pflags & PKT_FLAG_KEY))
600                 pts = AV_NOPTS_VALUE;
601         }
602         if (pts != AV_NOPTS_VALUE)
603             break;
604     }
605     ogg_reset(ogg);
606     return pts;
607 }
608
609 static int ogg_read_seek(AVFormatContext *s, int stream_index, 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 == CODEC_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 (p->buf[0] == 'O' && p->buf[1] == 'g' &&
630         p->buf[2] == 'g' && p->buf[3] == 'S' &&
631         p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
632         return AVPROBE_SCORE_MAX;
633     else
634         return 0;
635 }
636
637 AVInputFormat ogg_demuxer = {
638     "ogg",
639     NULL_IF_CONFIG_SMALL("Ogg"),
640     sizeof (struct ogg),
641     ogg_probe,
642     ogg_read_header,
643     ogg_read_packet,
644     ogg_read_close,
645     ogg_read_seek,
646     ogg_read_timestamp,
647     .extensions = "ogg",
648     .metadata_conv = ff_vorbiscomment_metadata_conv,
649 };