]> git.sesse.net Git - ffmpeg/blob - libavformat/oggdec.c
Merge remote-tracking branch 'qatar/master'
[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     Copyright (C) 2005  Michael Ahlberg, Måns Rullgård
9
10     Permission is hereby granted, free of charge, to any person
11     obtaining a copy of this software and associated documentation
12     files (the "Software"), to deal in the Software without
13     restriction, including without limitation the rights to use, copy,
14     modify, merge, publish, distribute, sublicense, and/or sell copies
15     of the Software, and to permit persons to whom the Software is
16     furnished to do so, subject to the following conditions:
17
18     The above copyright notice and this permission notice shall be
19     included in all copies or substantial portions of the Software.
20
21     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28     DEALINGS IN THE SOFTWARE.
29  */
30
31 #include <stdio.h>
32 #include "oggdec.h"
33 #include "avformat.h"
34 #include "internal.h"
35 #include "vorbiscomment.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_celt_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         struct ogg_stream *old_streams = ogg->streams;
96
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         ogg->streams = av_realloc (ogg->streams,
104                                    ogg->nstreams * sizeof (*ogg->streams));
105
106         if (ogg->streams) {
107             memcpy(ogg->streams, ost->streams,
108                    ost->nstreams * sizeof(*ogg->streams));
109         } else {
110             av_free(old_streams);
111             ogg->nstreams = 0;
112         }
113     }
114
115     av_free (ost);
116
117     return 0;
118 }
119
120 static int ogg_reset(struct ogg *ogg)
121 {
122     int i;
123
124     for (i = 0; i < ogg->nstreams; i++){
125         struct ogg_stream *os = ogg->streams + i;
126         os->bufpos = 0;
127         os->pstart = 0;
128         os->psize = 0;
129         os->granule = -1;
130         os->lastpts = AV_NOPTS_VALUE;
131         os->lastdts = AV_NOPTS_VALUE;
132         os->sync_pos = -1;
133         os->page_pos = 0;
134         os->nsegs = 0;
135         os->segp = 0;
136         os->incomplete = 0;
137     }
138
139     ogg->curidx = -1;
140
141     return 0;
142 }
143
144 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
145 {
146     int i;
147
148     for (i = 0; ogg_codecs[i]; i++)
149         if (size >= ogg_codecs[i]->magicsize &&
150             !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
151             return ogg_codecs[i];
152
153     return NULL;
154 }
155
156 static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
157 {
158
159     struct ogg *ogg = s->priv_data;
160     int idx = ogg->nstreams++;
161     AVStream *st;
162     struct ogg_stream *os;
163
164     ogg->streams = av_realloc (ogg->streams,
165                                ogg->nstreams * sizeof (*ogg->streams));
166     memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
167     os = ogg->streams + idx;
168     os->serial = serial;
169     os->bufsize = DECODER_BUFFER_SIZE;
170     os->buf = av_malloc(os->bufsize);
171     os->header = -1;
172
173     if (new_avstream) {
174         st = avformat_new_stream(s, NULL);
175         if (!st)
176             return AVERROR(ENOMEM);
177
178         st->id = idx;
179         avpriv_set_pts_info(st, 64, 1, 1000000);
180     }
181
182     return idx;
183 }
184
185 static int ogg_new_buf(struct ogg *ogg, int idx)
186 {
187     struct ogg_stream *os = ogg->streams + idx;
188     uint8_t *nb = av_malloc(os->bufsize);
189     int size = os->bufpos - os->pstart;
190     if(os->buf){
191         memcpy(nb, os->buf + os->pstart, size);
192         av_free(os->buf);
193     }
194     os->buf = nb;
195     os->bufpos = size;
196     os->pstart = 0;
197
198     return 0;
199 }
200
201 static int ogg_read_page(AVFormatContext *s, int *str)
202 {
203     AVIOContext *bc = s->pb;
204     struct ogg *ogg = s->priv_data;
205     struct ogg_stream *os;
206     int ret, i = 0;
207     int flags, nsegs;
208     uint64_t gp;
209     uint32_t serial;
210     int size, idx;
211     uint8_t sync[4];
212     int sp = 0;
213
214     ret = avio_read(bc, sync, 4);
215     if (ret < 4)
216         return ret < 0 ? ret : AVERROR_EOF;
217
218     do{
219         int c;
220
221         if (sync[sp & 3] == 'O' &&
222             sync[(sp + 1) & 3] == 'g' &&
223             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
224             break;
225
226         c = avio_r8(bc);
227         if (url_feof(bc))
228             return AVERROR_EOF;
229         sync[sp++ & 3] = c;
230     }while (i++ < MAX_PAGE_SIZE);
231
232     if (i >= MAX_PAGE_SIZE){
233         av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
234         return AVERROR_INVALIDDATA;
235     }
236
237     if (avio_r8(bc) != 0)      /* version */
238         return AVERROR_INVALIDDATA;
239
240     flags = avio_r8(bc);
241     gp = avio_rl64 (bc);
242     serial = avio_rl32 (bc);
243     avio_skip(bc, 8); /* seq, crc */
244     nsegs = avio_r8(bc);
245
246     idx = ogg_find_stream (ogg, serial);
247     if (idx < 0){
248         if (ogg->headers) {
249             int n;
250
251             for (n = 0; n < ogg->nstreams; n++) {
252                 av_freep(&ogg->streams[n].buf);
253                 if (!ogg->state || ogg->state->streams[n].private != ogg->streams[n].private)
254                     av_freep(&ogg->streams[n].private);
255             }
256             ogg->curidx   = -1;
257             ogg->nstreams = 0;
258             idx = ogg_new_stream(s, serial, 0);
259         } else {
260             idx = ogg_new_stream(s, serial, 1);
261         }
262         if (idx < 0)
263             return idx;
264     }
265
266     os = ogg->streams + idx;
267     os->page_pos = avio_tell(bc) - 27;
268
269     if(os->psize > 0)
270         ogg_new_buf(ogg, idx);
271
272     ret = avio_read(bc, os->segments, nsegs);
273     if (ret < nsegs)
274         return ret < 0 ? ret : AVERROR_EOF;
275
276     os->nsegs = nsegs;
277     os->segp = 0;
278
279     size = 0;
280     for (i = 0; i < nsegs; i++)
281         size += os->segments[i];
282
283     if (flags & OGG_FLAG_CONT || os->incomplete){
284         if (!os->psize){
285             // If this is the very first segment we started
286             // playback in the middle of a continuation packet.
287             // Discard it since we missed the start of it.
288             while (os->segp < os->nsegs){
289                 int seg = os->segments[os->segp++];
290                 os->pstart += seg;
291                 if (seg < 255)
292                     break;
293             }
294             os->sync_pos = os->page_pos;
295         }
296     }else{
297         os->psize = 0;
298         os->sync_pos = os->page_pos;
299     }
300
301     if (os->bufsize - os->bufpos < size){
302         uint8_t *nb = av_malloc (os->bufsize *= 2);
303         memcpy (nb, os->buf, os->bufpos);
304         av_free (os->buf);
305         os->buf = nb;
306     }
307
308     ret = avio_read(bc, os->buf + os->bufpos, size);
309     if (ret < size)
310         return ret < 0 ? ret : AVERROR_EOF;
311
312     os->bufpos += size;
313     os->granule = gp;
314     os->flags = flags;
315
316     if (str)
317         *str = idx;
318
319     return 0;
320 }
321
322 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
323                       int64_t *fpos)
324 {
325     struct ogg *ogg = s->priv_data;
326     int idx, i, ret;
327     struct ogg_stream *os;
328     int complete = 0;
329     int segp = 0, psize = 0;
330
331     av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
332
333     do{
334         idx = ogg->curidx;
335
336         while (idx < 0){
337             ret = ogg_read_page(s, &idx);
338             if (ret < 0)
339                 return ret;
340         }
341
342         os = ogg->streams + idx;
343
344         av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
345                 idx, os->pstart, os->psize, os->segp, os->nsegs);
346
347         if (!os->codec){
348             if (os->header < 0){
349                 os->codec = ogg_find_codec (os->buf, os->bufpos);
350                 if (!os->codec){
351                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
352                     os->header = 0;
353                     return 0;
354                 }
355             }else{
356                 return 0;
357             }
358         }
359
360         segp = os->segp;
361         psize = os->psize;
362
363         while (os->segp < os->nsegs){
364             int ss = os->segments[os->segp++];
365             os->psize += ss;
366             if (ss < 255){
367                 complete = 1;
368                 break;
369             }
370         }
371
372         if (!complete && os->segp == os->nsegs){
373             ogg->curidx = -1;
374             // Do not set incomplete for empty packets.
375             // Together with the code in ogg_read_page
376             // that discards all continuation of empty packets
377             // we would get an infinite loop.
378             os->incomplete = !!os->psize;
379         }
380     }while (!complete);
381
382
383     if (os->granule == -1)
384         av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
385
386     ogg->curidx = idx;
387     os->incomplete = 0;
388
389     if (os->header) {
390         os->header = os->codec->header (s, idx);
391         if (!os->header){
392             os->segp = segp;
393             os->psize = psize;
394
395             // We have reached the first non-header packet in this stream.
396             // Unfortunately more header packets may still follow for others,
397             // but if we continue with header parsing we may lose data packets.
398             ogg->headers = 1;
399
400             // Update the header state for all streams and
401             // compute the data_offset.
402             if (!s->data_offset)
403                 s->data_offset = os->sync_pos;
404             for (i = 0; i < ogg->nstreams; i++) {
405                 struct ogg_stream *cur_os = ogg->streams + i;
406
407                 // if we have a partial non-header packet, its start is
408                 // obviously at or after the data start
409                 if (cur_os->incomplete)
410                     s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
411             }
412         }else{
413             os->pstart += os->psize;
414             os->psize = 0;
415         }
416     } else {
417         os->pflags = 0;
418         os->pduration = 0;
419         if (os->codec && os->codec->packet)
420             os->codec->packet (s, idx);
421         if (str)
422             *str = idx;
423         if (dstart)
424             *dstart = os->pstart;
425         if (dsize)
426             *dsize = os->psize;
427         if (fpos)
428             *fpos = os->sync_pos;
429         os->pstart += os->psize;
430         os->psize = 0;
431         if(os->pstart == os->bufpos)
432             os->bufpos = os->pstart = 0;
433         os->sync_pos = os->page_pos;
434     }
435
436     // determine whether there are more complete packets in this page
437     // if not, the page's granule will apply to this packet
438     os->page_end = 1;
439     for (i = os->segp; i < os->nsegs; i++)
440         if (os->segments[i] < 255) {
441             os->page_end = 0;
442             break;
443         }
444
445     if (os->segp == os->nsegs)
446         ogg->curidx = -1;
447
448     return 0;
449 }
450
451 static int ogg_get_headers(AVFormatContext *s)
452 {
453     struct ogg *ogg = s->priv_data;
454     int ret;
455
456     do{
457         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
458         if (ret < 0)
459             return ret;
460     }while (!ogg->headers);
461
462     av_dlog(s, "found headers\n");
463
464     return 0;
465 }
466
467 static int ogg_get_length(AVFormatContext *s)
468 {
469     struct ogg *ogg = s->priv_data;
470     int i;
471     int64_t size, end;
472     int streams_left=0;
473
474     if(!s->pb->seekable)
475         return 0;
476
477 // already set
478     if (s->duration != AV_NOPTS_VALUE)
479         return 0;
480
481     size = avio_size(s->pb);
482     if(size < 0)
483         return 0;
484     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
485
486     ogg_save (s);
487     avio_seek (s->pb, end, SEEK_SET);
488
489     while (!ogg_read_page (s, &i)){
490         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
491             ogg->streams[i].codec) {
492             s->streams[i]->duration =
493                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
494             if (s->streams[i]->start_time != AV_NOPTS_VALUE){
495                 s->streams[i]->duration -= s->streams[i]->start_time;
496                 streams_left-= (ogg->streams[i].got_start==-1);
497                 ogg->streams[i].got_start= 1;
498             }else if(!ogg->streams[i].got_start){
499                 ogg->streams[i].got_start= -1;
500                 streams_left++;
501             }
502         }
503     }
504
505     ogg_restore (s, 0);
506
507     ogg_save (s);
508     avio_seek (s->pb, 0, SEEK_SET);
509     while (!ogg_read_page (s, &i)){
510         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
511             ogg->streams[i].codec) {
512             if(s->streams[i]->duration && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start){
513                 int64_t start= ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
514                 if(av_rescale_q(start, s->streams[i]->time_base, AV_TIME_BASE_Q) > AV_TIME_BASE)
515                     s->streams[i]->duration -= start;
516                 ogg->streams[i].got_start= 1;
517                 streams_left--;
518             }
519             if(streams_left<=0)
520                 break;
521         }
522     }
523     ogg_restore (s, 0);
524
525     return 0;
526 }
527
528 static int ogg_read_header(AVFormatContext *s)
529 {
530     struct ogg *ogg = s->priv_data;
531     int ret, i;
532     ogg->curidx = -1;
533     //linear headers seek from start
534     ret = ogg_get_headers(s);
535     if (ret < 0)
536         return ret;
537
538     for (i = 0; i < ogg->nstreams; i++)
539         if (ogg->streams[i].header < 0)
540             ogg->streams[i].codec = NULL;
541
542     //linear granulepos seek from end
543     ogg_get_length (s);
544
545     //fill the extradata in the per codec callbacks
546     return 0;
547 }
548
549 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
550 {
551     struct ogg *ogg = s->priv_data;
552     struct ogg_stream *os = ogg->streams + idx;
553     int64_t pts = AV_NOPTS_VALUE;
554
555     if (dts)
556         *dts = AV_NOPTS_VALUE;
557
558     if (os->lastpts != AV_NOPTS_VALUE) {
559         pts = os->lastpts;
560         os->lastpts = AV_NOPTS_VALUE;
561     }
562     if (os->lastdts != AV_NOPTS_VALUE) {
563         if (dts)
564             *dts = os->lastdts;
565         os->lastdts = AV_NOPTS_VALUE;
566     }
567     if (os->page_end) {
568         if (os->granule != -1LL) {
569             if (os->codec && os->codec->granule_is_start)
570                 pts = ogg_gptopts(s, idx, os->granule, dts);
571             else
572                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
573             os->granule = -1LL;
574         }
575     }
576     return pts;
577 }
578
579 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
580 {
581     struct ogg *ogg = s->priv_data;
582     struct ogg_stream *os = ogg->streams + idx;
583     if (psize && s->streams[idx]->codec->codec_id == CODEC_ID_THEORA) {
584         if (!!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40)) {
585             os->pflags ^= AV_PKT_FLAG_KEY;
586             av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
587                    (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
588         }
589     }
590 }
591
592 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
593 {
594     struct ogg *ogg;
595     struct ogg_stream *os;
596     int idx = -1, ret;
597     int pstart, psize;
598     int64_t fpos, pts, dts;
599
600     //Get an ogg packet
601 retry:
602     do{
603         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
604         if (ret < 0)
605             return ret;
606     }while (idx < 0 || !s->streams[idx]);
607
608     ogg = s->priv_data;
609     os = ogg->streams + idx;
610
611     // pflags might not be set until after this
612     pts = ogg_calc_pts(s, idx, &dts);
613     ogg_validate_keyframe(s, idx, pstart, psize);
614
615     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
616         goto retry;
617     os->keyframe_seek = 0;
618
619     //Alloc a pkt
620     ret = av_new_packet(pkt, psize);
621     if (ret < 0)
622         return ret;
623     pkt->stream_index = idx;
624     memcpy (pkt->data, os->buf + pstart, psize);
625
626     pkt->pts = pts;
627     pkt->dts = dts;
628     pkt->flags = os->pflags;
629     pkt->duration = os->pduration;
630     pkt->pos = fpos;
631
632     return psize;
633 }
634
635 static int ogg_read_close(AVFormatContext *s)
636 {
637     struct ogg *ogg = s->priv_data;
638     int i;
639
640     for (i = 0; i < ogg->nstreams; i++){
641         av_free (ogg->streams[i].buf);
642         av_free (ogg->streams[i].private);
643     }
644     av_free (ogg->streams);
645     return 0;
646 }
647
648 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
649                                   int64_t *pos_arg, int64_t pos_limit)
650 {
651     struct ogg *ogg = s->priv_data;
652     AVIOContext *bc = s->pb;
653     int64_t pts = AV_NOPTS_VALUE;
654     int64_t keypos = -1;
655     int i = -1;
656     int pstart, psize;
657     avio_seek(bc, *pos_arg, SEEK_SET);
658     ogg_reset(ogg);
659
660     while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
661         if (i == stream_index) {
662             struct ogg_stream *os = ogg->streams + stream_index;
663             pts = ogg_calc_pts(s, i, NULL);
664             ogg_validate_keyframe(s, i, pstart, psize);
665             if (os->pflags & AV_PKT_FLAG_KEY) {
666                 keypos = *pos_arg;
667             } else if (os->keyframe_seek) {
668                 // if we had a previous keyframe but no pts for it,
669                 // return that keyframe with this pts value.
670                 if (keypos >= 0)
671                     *pos_arg = keypos;
672                 else
673                     pts = AV_NOPTS_VALUE;
674             }
675         }
676         if (pts != AV_NOPTS_VALUE)
677             break;
678     }
679     ogg_reset(ogg);
680     return pts;
681 }
682
683 static int ogg_read_seek(AVFormatContext *s, int stream_index,
684                          int64_t timestamp, int flags)
685 {
686     struct ogg *ogg = s->priv_data;
687     struct ogg_stream *os = ogg->streams + stream_index;
688     int ret;
689
690     // Ensure everything is reset even when seeking via
691     // the generated index.
692     ogg_reset(ogg);
693
694     // Try seeking to a keyframe first. If this fails (very possible),
695     // av_seek_frame will fall back to ignoring keyframes
696     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
697         && !(flags & AVSEEK_FLAG_ANY))
698         os->keyframe_seek = 1;
699
700     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
701     os = ogg->streams + stream_index;
702     if (ret < 0)
703         os->keyframe_seek = 0;
704     return ret;
705 }
706
707 static int ogg_probe(AVProbeData *p)
708 {
709     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
710         return AVPROBE_SCORE_MAX;
711     return 0;
712 }
713
714 AVInputFormat ff_ogg_demuxer = {
715     .name           = "ogg",
716     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
717     .priv_data_size = sizeof(struct ogg),
718     .read_probe     = ogg_probe,
719     .read_header    = ogg_read_header,
720     .read_packet    = ogg_read_packet,
721     .read_close     = ogg_read_close,
722     .read_seek      = ogg_read_seek,
723     .read_timestamp = ogg_read_timestamp,
724     .extensions     = "ogg",
725     .flags          = AVFMT_GENERIC_INDEX,
726 };