oggdec: Pass packets to header() until the stream is done with them
[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 (os->header) {
368         os->header = os->codec->header (s, idx);
369         if (!os->header){
370             os->segp = segp;
371             os->psize = psize;
372             if (!ogg->headers)
373                 s->data_offset = os->sync_pos;
374             ogg->headers = 1;
375         }else{
376             os->pstart += os->psize;
377             os->psize = 0;
378         }
379     } else {
380         os->pflags = 0;
381         os->pduration = 0;
382         if (os->codec && os->codec->packet)
383             os->codec->packet (s, idx);
384         if (str)
385             *str = idx;
386         if (dstart)
387             *dstart = os->pstart;
388         if (dsize)
389             *dsize = os->psize;
390         if (fpos)
391             *fpos = os->sync_pos;
392         os->pstart += os->psize;
393         os->psize = 0;
394         os->sync_pos = os->page_pos;
395     }
396
397     // determine whether there are more complete packets in this page
398     // if not, the page's granule will apply to this packet
399     os->page_end = 1;
400     for (i = os->segp; i < os->nsegs; i++)
401         if (os->segments[i] < 255) {
402             os->page_end = 0;
403             break;
404         }
405
406     if (os->segp == os->nsegs)
407         ogg->curidx = -1;
408
409     return 0;
410 }
411
412 static int
413 ogg_get_headers (AVFormatContext * s)
414 {
415     struct ogg *ogg = s->priv_data;
416
417     do{
418         if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
419             return -1;
420     }while (!ogg->headers);
421
422 #if 0
423     av_log (s, AV_LOG_DEBUG, "found headers\n");
424 #endif
425
426     return 0;
427 }
428
429 static int
430 ogg_get_length (AVFormatContext * s)
431 {
432     struct ogg *ogg = s->priv_data;
433     int idx = -1, i;
434     int64_t size, end;
435
436     if(url_is_streamed(s->pb))
437         return 0;
438
439 // already set
440     if (s->duration != AV_NOPTS_VALUE)
441         return 0;
442
443     size = url_fsize(s->pb);
444     if(size < 0)
445         return 0;
446     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
447
448     ogg_save (s);
449     url_fseek (s->pb, end, SEEK_SET);
450
451     while (!ogg_read_page (s, &i)){
452         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
453             ogg->streams[i].codec)
454             idx = i;
455     }
456
457     if (idx != -1){
458         s->streams[idx]->duration =
459             ogg_gptopts (s, idx, ogg->streams[idx].granule, NULL);
460         if (s->streams[idx]->start_time != AV_NOPTS_VALUE)
461             s->streams[idx]->duration -= s->streams[idx]->start_time;
462     }
463
464     ogg->size = size;
465     ogg_restore (s, 0);
466
467     return 0;
468 }
469
470
471 static int
472 ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
473 {
474     struct ogg *ogg = s->priv_data;
475     int i;
476     ogg->curidx = -1;
477     //linear headers seek from start
478     if (ogg_get_headers (s) < 0){
479         return -1;
480     }
481
482     for (i = 0; i < ogg->nstreams; i++)
483         if (ogg->streams[i].header < 0)
484             ogg->streams[i].codec = NULL;
485
486     //linear granulepos seek from end
487     ogg_get_length (s);
488
489     //fill the extradata in the per codec callbacks
490     return 0;
491 }
492
493 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
494 {
495     struct ogg *ogg = s->priv_data;
496     struct ogg_stream *os = ogg->streams + idx;
497     int64_t pts = AV_NOPTS_VALUE;
498
499     if (dts)
500         *dts = AV_NOPTS_VALUE;
501
502     if (os->lastpts != AV_NOPTS_VALUE) {
503         pts = os->lastpts;
504         os->lastpts = AV_NOPTS_VALUE;
505     }
506     if (os->lastdts != AV_NOPTS_VALUE) {
507         if (dts)
508             *dts = os->lastdts;
509         os->lastdts = AV_NOPTS_VALUE;
510     }
511     if (os->page_end) {
512         if (os->granule != -1LL) {
513             if (os->codec && os->codec->granule_is_start)
514                 pts = ogg_gptopts(s, idx, os->granule, dts);
515             else
516                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
517             os->granule = -1LL;
518         } else
519             av_log(s, AV_LOG_WARNING, "Packet is missing granule\n");
520     }
521     return pts;
522 }
523
524 static int
525 ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
526 {
527     struct ogg *ogg;
528     struct ogg_stream *os;
529     int idx = -1;
530     int pstart, psize;
531     int64_t fpos, pts, dts;
532
533     //Get an ogg packet
534 retry:
535     do{
536         if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
537             return AVERROR(EIO);
538     }while (idx < 0 || !s->streams[idx]);
539
540     ogg = s->priv_data;
541     os = ogg->streams + idx;
542
543     // pflags might not be set until after this
544     pts = ogg_calc_pts(s, idx, &dts);
545
546     if (os->keyframe_seek && !(os->pflags & PKT_FLAG_KEY))
547         goto retry;
548     os->keyframe_seek = 0;
549
550     //Alloc a pkt
551     if (av_new_packet (pkt, psize) < 0)
552         return AVERROR(EIO);
553     pkt->stream_index = idx;
554     memcpy (pkt->data, os->buf + pstart, psize);
555
556     pkt->pts = pts;
557     pkt->dts = dts;
558     pkt->flags = os->pflags;
559     pkt->duration = os->pduration;
560     pkt->pos = fpos;
561
562     return psize;
563 }
564
565
566 static int
567 ogg_read_close (AVFormatContext * s)
568 {
569     struct ogg *ogg = s->priv_data;
570     int i;
571
572     for (i = 0; i < ogg->nstreams; i++){
573         av_free (ogg->streams[i].buf);
574         av_free (ogg->streams[i].private);
575     }
576     av_free (ogg->streams);
577     return 0;
578 }
579
580
581 static int64_t
582 ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
583                     int64_t pos_limit)
584 {
585     struct ogg *ogg = s->priv_data;
586     struct ogg_stream *os = ogg->streams + stream_index;
587     ByteIOContext *bc = s->pb;
588     int64_t pts = AV_NOPTS_VALUE;
589     int i;
590     url_fseek(bc, *pos_arg, SEEK_SET);
591     ogg_reset(ogg);
592
593     while (url_ftell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
594         if (i == stream_index) {
595             pts = ogg_calc_pts(s, i, NULL);
596             if (os->keyframe_seek && !(os->pflags & PKT_FLAG_KEY))
597                 pts = AV_NOPTS_VALUE;
598         }
599         if (pts != AV_NOPTS_VALUE)
600             break;
601     }
602     ogg_reset(ogg);
603     return pts;
604 }
605
606 static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
607 {
608     struct ogg *ogg = s->priv_data;
609     struct ogg_stream *os = ogg->streams + stream_index;
610     int ret;
611
612     // Try seeking to a keyframe first. If this fails (very possible),
613     // av_seek_frame will fall back to ignoring keyframes
614     if (s->streams[stream_index]->codec->codec_type == CODEC_TYPE_VIDEO
615         && !(flags & AVSEEK_FLAG_ANY))
616         os->keyframe_seek = 1;
617
618     ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
619     if (ret < 0)
620         os->keyframe_seek = 0;
621     return ret;
622 }
623
624 static int ogg_probe(AVProbeData *p)
625 {
626     if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
627         p->buf[2] == 'g' && p->buf[3] == 'S' &&
628         p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
629         return AVPROBE_SCORE_MAX;
630     else
631         return 0;
632 }
633
634 AVInputFormat ogg_demuxer = {
635     "ogg",
636     NULL_IF_CONFIG_SMALL("Ogg"),
637     sizeof (struct ogg),
638     ogg_probe,
639     ogg_read_header,
640     ogg_read_packet,
641     ogg_read_close,
642     ogg_read_seek,
643     ogg_read_timestamp,
644     .extensions = "ogg",
645     .metadata_conv = ff_vorbiscomment_metadata_conv,
646 };