oggdec: Fix duration calculation if the last page in a file has no granule
[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 #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 = url_ftell (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     ByteIOContext *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         url_fseek (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     ByteIOContext *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 (get_buffer (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 = url_fgetc (bc);
222         if (c < 0)
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 (url_fgetc (bc) != 0)      /* version */
233         return -1;
234
235     flags = url_fgetc (bc);
236     gp = get_le64 (bc);
237     serial = get_le32 (bc);
238     seq = get_le32 (bc);
239     crc = get_le32 (bc);
240     nsegs = url_fgetc (bc);
241
242     idx = ogg_find_stream (ogg, serial);
243     if (idx < 0){
244         idx = ogg_new_stream (s, serial);
245         if (idx < 0)
246             return -1;
247     }
248
249     os = ogg->streams + idx;
250     os->page_pos = url_ftell(bc) - 27;
251
252     if(os->psize > 0)
253         ogg_new_buf(ogg, idx);
254
255     if (get_buffer (bc, os->segments, nsegs) < nsegs)
256         return -1;
257
258     os->nsegs = nsegs;
259     os->segp = 0;
260
261     size = 0;
262     for (i = 0; i < nsegs; i++)
263         size += os->segments[i];
264
265     if (flags & OGG_FLAG_CONT || os->incomplete){
266         if (!os->psize){
267             while (os->segp < os->nsegs){
268                 int seg = os->segments[os->segp++];
269                 os->pstart += seg;
270                 if (seg < 255)
271                     break;
272             }
273             os->sync_pos = os->page_pos;
274         }
275     }else{
276         os->psize = 0;
277         os->sync_pos = os->page_pos;
278     }
279
280     if (os->bufsize - os->bufpos < size){
281         uint8_t *nb = av_malloc (os->bufsize *= 2);
282         memcpy (nb, os->buf, os->bufpos);
283         av_free (os->buf);
284         os->buf = nb;
285     }
286
287     if (get_buffer (bc, os->buf + os->bufpos, size) < size)
288         return -1;
289
290     os->bufpos += size;
291     os->granule = gp;
292     os->flags = flags;
293
294     if (str)
295         *str = idx;
296
297     return 0;
298 }
299
300 static int
301 ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpos)
302 {
303     struct ogg *ogg = s->priv_data;
304     int idx, i;
305     struct ogg_stream *os;
306     int complete = 0;
307     int segp = 0, psize = 0;
308
309 #if 0
310     av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
311 #endif
312
313     do{
314         idx = ogg->curidx;
315
316         while (idx < 0){
317             if (ogg_read_page (s, &idx) < 0)
318                 return -1;
319         }
320
321         os = ogg->streams + idx;
322
323 #if 0
324         av_log (s, AV_LOG_DEBUG,
325                 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
326                 idx, os->pstart, os->psize, os->segp, os->nsegs);
327 #endif
328
329         if (!os->codec){
330             if (os->header < 0){
331                 os->codec = ogg_find_codec (os->buf, os->bufpos);
332                 if (!os->codec){
333                     os->header = 0;
334                     return 0;
335                 }
336             }else{
337                 return 0;
338             }
339         }
340
341         segp = os->segp;
342         psize = os->psize;
343
344         while (os->segp < os->nsegs){
345             int ss = os->segments[os->segp++];
346             os->psize += ss;
347             if (ss < 255){
348                 complete = 1;
349                 break;
350             }
351         }
352
353         if (!complete && os->segp == os->nsegs){
354             ogg->curidx = -1;
355             os->incomplete = 1;
356         }
357     }while (!complete);
358
359 #if 0
360     av_log (s, AV_LOG_DEBUG,
361             "ogg_packet: idx %i, frame size %i, start %i\n",
362             idx, os->psize, os->pstart);
363 #endif
364
365     ogg->curidx = idx;
366     os->incomplete = 0;
367
368     if (os->header) {
369         os->header = os->codec->header (s, idx);
370         if (!os->header){
371             os->segp = segp;
372             os->psize = psize;
373             if (!ogg->headers)
374                 s->data_offset = os->sync_pos;
375             ogg->headers = 1;
376         }else{
377             os->pstart += os->psize;
378             os->psize = 0;
379         }
380     } else {
381         os->pflags = 0;
382         os->pduration = 0;
383         if (os->codec && os->codec->packet)
384             os->codec->packet (s, idx);
385         if (str)
386             *str = idx;
387         if (dstart)
388             *dstart = os->pstart;
389         if (dsize)
390             *dsize = os->psize;
391         if (fpos)
392             *fpos = os->sync_pos;
393         os->pstart += os->psize;
394         os->psize = 0;
395         os->sync_pos = os->page_pos;
396     }
397
398     // determine whether there are more complete packets in this page
399     // if not, the page's granule will apply to this packet
400     os->page_end = 1;
401     for (i = os->segp; i < os->nsegs; i++)
402         if (os->segments[i] < 255) {
403             os->page_end = 0;
404             break;
405         }
406
407     if (os->segp == os->nsegs)
408         ogg->curidx = -1;
409
410     return 0;
411 }
412
413 static int
414 ogg_get_headers (AVFormatContext * s)
415 {
416     struct ogg *ogg = s->priv_data;
417
418     do{
419         if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
420             return -1;
421     }while (!ogg->headers);
422
423 #if 0
424     av_log (s, AV_LOG_DEBUG, "found headers\n");
425 #endif
426
427     return 0;
428 }
429
430 static int
431 ogg_get_length (AVFormatContext * s)
432 {
433     struct ogg *ogg = s->priv_data;
434     int i;
435     int64_t size, end;
436
437     if(url_is_streamed(s->pb))
438         return 0;
439
440 // already set
441     if (s->duration != AV_NOPTS_VALUE)
442         return 0;
443
444     size = url_fsize(s->pb);
445     if(size < 0)
446         return 0;
447     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
448
449     ogg_save (s);
450     url_fseek (s->pb, end, SEEK_SET);
451
452     while (!ogg_read_page (s, &i)){
453         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
454             ogg->streams[i].codec) {
455             s->streams[i]->duration =
456                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
457             if (s->streams[i]->start_time != AV_NOPTS_VALUE)
458                 s->streams[i]->duration -= s->streams[i]->start_time;
459         }
460     }
461
462     ogg_restore (s, 0);
463
464     return 0;
465 }
466
467
468 static int
469 ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
470 {
471     struct ogg *ogg = s->priv_data;
472     int i;
473     ogg->curidx = -1;
474     //linear headers seek from start
475     if (ogg_get_headers (s) < 0){
476         return -1;
477     }
478
479     for (i = 0; i < ogg->nstreams; i++)
480         if (ogg->streams[i].header < 0)
481             ogg->streams[i].codec = NULL;
482
483     //linear granulepos seek from end
484     ogg_get_length (s);
485
486     //fill the extradata in the per codec callbacks
487     return 0;
488 }
489
490 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
491 {
492     struct ogg *ogg = s->priv_data;
493     struct ogg_stream *os = ogg->streams + idx;
494     int64_t pts = AV_NOPTS_VALUE;
495
496     if (dts)
497         *dts = AV_NOPTS_VALUE;
498
499     if (os->lastpts != AV_NOPTS_VALUE) {
500         pts = os->lastpts;
501         os->lastpts = AV_NOPTS_VALUE;
502     }
503     if (os->lastdts != AV_NOPTS_VALUE) {
504         if (dts)
505             *dts = os->lastdts;
506         os->lastdts = AV_NOPTS_VALUE;
507     }
508     if (os->page_end) {
509         if (os->granule != -1LL) {
510             if (os->codec && os->codec->granule_is_start)
511                 pts = ogg_gptopts(s, idx, os->granule, dts);
512             else
513                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
514             os->granule = -1LL;
515         } else
516             av_log(s, AV_LOG_WARNING, "Packet is missing granule\n");
517     }
518     return pts;
519 }
520
521 static int
522 ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
523 {
524     struct ogg *ogg;
525     struct ogg_stream *os;
526     int idx = -1;
527     int pstart, psize;
528     int64_t fpos, pts, dts;
529
530     //Get an ogg packet
531 retry:
532     do{
533         if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
534             return AVERROR(EIO);
535     }while (idx < 0 || !s->streams[idx]);
536
537     ogg = s->priv_data;
538     os = ogg->streams + idx;
539
540     // pflags might not be set until after this
541     pts = ogg_calc_pts(s, idx, &dts);
542
543     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
544         goto retry;
545     os->keyframe_seek = 0;
546
547     //Alloc a pkt
548     if (av_new_packet (pkt, psize) < 0)
549         return AVERROR(EIO);
550     pkt->stream_index = idx;
551     memcpy (pkt->data, os->buf + pstart, psize);
552
553     pkt->pts = pts;
554     pkt->dts = dts;
555     pkt->flags = os->pflags;
556     pkt->duration = os->pduration;
557     pkt->pos = fpos;
558
559     return psize;
560 }
561
562
563 static int
564 ogg_read_close (AVFormatContext * s)
565 {
566     struct ogg *ogg = s->priv_data;
567     int i;
568
569     for (i = 0; i < ogg->nstreams; i++){
570         av_free (ogg->streams[i].buf);
571         av_free (ogg->streams[i].private);
572     }
573     av_free (ogg->streams);
574     return 0;
575 }
576
577
578 static int64_t
579 ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
580                     int64_t pos_limit)
581 {
582     struct ogg *ogg = s->priv_data;
583     struct ogg_stream *os = ogg->streams + stream_index;
584     ByteIOContext *bc = s->pb;
585     int64_t pts = AV_NOPTS_VALUE;
586     int i;
587     url_fseek(bc, *pos_arg, SEEK_SET);
588     ogg_reset(ogg);
589
590     while (url_ftell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
591         if (i == stream_index) {
592             pts = ogg_calc_pts(s, i, NULL);
593             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
594                 pts = AV_NOPTS_VALUE;
595         }
596         if (pts != AV_NOPTS_VALUE)
597             break;
598     }
599     ogg_reset(ogg);
600     return pts;
601 }
602
603 static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
604 {
605     struct ogg *ogg = s->priv_data;
606     struct ogg_stream *os = ogg->streams + stream_index;
607     int ret;
608
609     // Try seeking to a keyframe first. If this fails (very possible),
610     // av_seek_frame will fall back to ignoring keyframes
611     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
612         && !(flags & AVSEEK_FLAG_ANY))
613         os->keyframe_seek = 1;
614
615     ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
616     if (ret < 0)
617         os->keyframe_seek = 0;
618     return ret;
619 }
620
621 static int ogg_probe(AVProbeData *p)
622 {
623     if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
624         p->buf[2] == 'g' && p->buf[3] == 'S' &&
625         p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
626         return AVPROBE_SCORE_MAX;
627     else
628         return 0;
629 }
630
631 AVInputFormat ogg_demuxer = {
632     "ogg",
633     NULL_IF_CONFIG_SMALL("Ogg"),
634     sizeof (struct ogg),
635     ogg_probe,
636     ogg_read_header,
637     ogg_read_packet,
638     ogg_read_close,
639     ogg_read_seek,
640     ogg_read_timestamp,
641     .extensions = "ogg",
642     .metadata_conv = ff_vorbiscomment_metadata_conv,
643 };