]> 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             while (os->segp < os->nsegs){
286                 int seg = os->segments[os->segp++];
287                 os->pstart += seg;
288                 if (seg < 255)
289                     break;
290             }
291             os->sync_pos = os->page_pos;
292         }
293     }else{
294         os->psize = 0;
295         os->sync_pos = os->page_pos;
296     }
297
298     if (os->bufsize - os->bufpos < size){
299         uint8_t *nb = av_malloc (os->bufsize *= 2);
300         memcpy (nb, os->buf, os->bufpos);
301         av_free (os->buf);
302         os->buf = nb;
303     }
304
305     ret = avio_read(bc, os->buf + os->bufpos, size);
306     if (ret < size)
307         return ret < 0 ? ret : AVERROR_EOF;
308
309     os->bufpos += size;
310     os->granule = gp;
311     os->flags = flags;
312
313     if (str)
314         *str = idx;
315
316     return 0;
317 }
318
319 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
320                       int64_t *fpos)
321 {
322     struct ogg *ogg = s->priv_data;
323     int idx, i, ret;
324     struct ogg_stream *os;
325     int complete = 0;
326     int segp = 0, psize = 0;
327
328     av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
329
330     do{
331         idx = ogg->curidx;
332
333         while (idx < 0){
334             ret = ogg_read_page(s, &idx);
335             if (ret < 0)
336                 return ret;
337         }
338
339         os = ogg->streams + idx;
340
341         av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
342                 idx, os->pstart, os->psize, os->segp, os->nsegs);
343
344         if (!os->codec){
345             if (os->header < 0){
346                 os->codec = ogg_find_codec (os->buf, os->bufpos);
347                 if (!os->codec){
348                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
349                     os->header = 0;
350                     return 0;
351                 }
352             }else{
353                 return 0;
354             }
355         }
356
357         segp = os->segp;
358         psize = os->psize;
359
360         while (os->segp < os->nsegs){
361             int ss = os->segments[os->segp++];
362             os->psize += ss;
363             if (ss < 255){
364                 complete = 1;
365                 break;
366             }
367         }
368
369         if (!complete && os->segp == os->nsegs){
370             ogg->curidx = -1;
371             os->incomplete = 1;
372         }
373     }while (!complete);
374
375
376     if (os->granule == -1)
377         av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
378
379     ogg->curidx = idx;
380     os->incomplete = 0;
381
382     if (os->header) {
383         os->header = os->codec->header (s, idx);
384         if (!os->header){
385             os->segp = segp;
386             os->psize = psize;
387
388             // We have reached the first non-header packet in this stream.
389             // Unfortunately more header packets may still follow for others,
390             // but if we continue with header parsing we may lose data packets.
391             ogg->headers = 1;
392
393             // Update the header state for all streams and
394             // compute the data_offset.
395             if (!s->data_offset)
396                 s->data_offset = os->sync_pos;
397             for (i = 0; i < ogg->nstreams; i++) {
398                 struct ogg_stream *cur_os = ogg->streams + i;
399
400                 // if we have a partial non-header packet, its start is
401                 // obviously at or after the data start
402                 if (cur_os->incomplete)
403                     s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
404             }
405         }else{
406             os->pstart += os->psize;
407             os->psize = 0;
408         }
409     } else {
410         os->pflags = 0;
411         os->pduration = 0;
412         if (os->codec && os->codec->packet)
413             os->codec->packet (s, idx);
414         if (str)
415             *str = idx;
416         if (dstart)
417             *dstart = os->pstart;
418         if (dsize)
419             *dsize = os->psize;
420         if (fpos)
421             *fpos = os->sync_pos;
422         os->pstart += os->psize;
423         os->psize = 0;
424         if(os->pstart == os->bufpos)
425             os->bufpos = os->pstart = 0;
426         os->sync_pos = os->page_pos;
427     }
428
429     // determine whether there are more complete packets in this page
430     // if not, the page's granule will apply to this packet
431     os->page_end = 1;
432     for (i = os->segp; i < os->nsegs; i++)
433         if (os->segments[i] < 255) {
434             os->page_end = 0;
435             break;
436         }
437
438     if (os->segp == os->nsegs)
439         ogg->curidx = -1;
440
441     return 0;
442 }
443
444 static int ogg_get_headers(AVFormatContext *s)
445 {
446     struct ogg *ogg = s->priv_data;
447     int ret;
448
449     do{
450         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
451         if (ret < 0)
452             return ret;
453     }while (!ogg->headers);
454
455     av_dlog(s, "found headers\n");
456
457     return 0;
458 }
459
460 static int ogg_get_length(AVFormatContext *s)
461 {
462     struct ogg *ogg = s->priv_data;
463     int i;
464     int64_t size, end;
465     int streams_left=0;
466
467     if(!s->pb->seekable)
468         return 0;
469
470 // already set
471     if (s->duration != AV_NOPTS_VALUE)
472         return 0;
473
474     size = avio_size(s->pb);
475     if(size < 0)
476         return 0;
477     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
478
479     ogg_save (s);
480     avio_seek (s->pb, end, SEEK_SET);
481
482     while (!ogg_read_page (s, &i)){
483         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
484             ogg->streams[i].codec) {
485             s->streams[i]->duration =
486                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
487             if (s->streams[i]->start_time != AV_NOPTS_VALUE){
488                 s->streams[i]->duration -= s->streams[i]->start_time;
489                 streams_left-= (ogg->streams[i].got_start==-1);
490                 ogg->streams[i].got_start= 1;
491             }else if(!ogg->streams[i].got_start){
492                 ogg->streams[i].got_start= -1;
493                 streams_left++;
494             }
495         }
496     }
497
498     ogg_restore (s, 0);
499
500     ogg_save (s);
501     avio_seek (s->pb, 0, SEEK_SET);
502     while (!ogg_read_page (s, &i)){
503         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
504             ogg->streams[i].codec) {
505             if(s->streams[i]->duration && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start){
506                 int64_t start= ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
507                 if(av_rescale_q(start, s->streams[i]->time_base, AV_TIME_BASE_Q) > AV_TIME_BASE)
508                     s->streams[i]->duration -= start;
509                 ogg->streams[i].got_start= 1;
510                 streams_left--;
511             }
512             if(streams_left<=0)
513                 break;
514         }
515     }
516     ogg_restore (s, 0);
517
518     return 0;
519 }
520
521 static int ogg_read_header(AVFormatContext *s)
522 {
523     struct ogg *ogg = s->priv_data;
524     int ret, i;
525     ogg->curidx = -1;
526     //linear headers seek from start
527     ret = ogg_get_headers(s);
528     if (ret < 0)
529         return ret;
530
531     for (i = 0; i < ogg->nstreams; i++)
532         if (ogg->streams[i].header < 0)
533             ogg->streams[i].codec = NULL;
534
535     //linear granulepos seek from end
536     ogg_get_length (s);
537
538     //fill the extradata in the per codec callbacks
539     return 0;
540 }
541
542 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
543 {
544     struct ogg *ogg = s->priv_data;
545     struct ogg_stream *os = ogg->streams + idx;
546     int64_t pts = AV_NOPTS_VALUE;
547
548     if (dts)
549         *dts = AV_NOPTS_VALUE;
550
551     if (os->lastpts != AV_NOPTS_VALUE) {
552         pts = os->lastpts;
553         os->lastpts = AV_NOPTS_VALUE;
554     }
555     if (os->lastdts != AV_NOPTS_VALUE) {
556         if (dts)
557             *dts = os->lastdts;
558         os->lastdts = AV_NOPTS_VALUE;
559     }
560     if (os->page_end) {
561         if (os->granule != -1LL) {
562             if (os->codec && os->codec->granule_is_start)
563                 pts = ogg_gptopts(s, idx, os->granule, dts);
564             else
565                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
566             os->granule = -1LL;
567         }
568     }
569     return pts;
570 }
571
572 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
573 {
574     struct ogg *ogg;
575     struct ogg_stream *os;
576     int idx = -1, ret;
577     int pstart, psize;
578     int64_t fpos, pts, dts;
579
580     //Get an ogg packet
581 retry:
582     do{
583         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
584         if (ret < 0)
585             return ret;
586     }while (idx < 0 || !s->streams[idx]);
587
588     ogg = s->priv_data;
589     os = ogg->streams + idx;
590
591     // pflags might not be set until after this
592     pts = ogg_calc_pts(s, idx, &dts);
593
594     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
595         goto retry;
596     os->keyframe_seek = 0;
597
598     //Alloc a pkt
599     ret = av_new_packet(pkt, psize);
600     if (ret < 0)
601         return ret;
602     pkt->stream_index = idx;
603     memcpy (pkt->data, os->buf + pstart, psize);
604
605     pkt->pts = pts;
606     pkt->dts = dts;
607     pkt->flags = os->pflags;
608     pkt->duration = os->pduration;
609     pkt->pos = fpos;
610
611     return psize;
612 }
613
614 static int ogg_read_close(AVFormatContext *s)
615 {
616     struct ogg *ogg = s->priv_data;
617     int i;
618
619     for (i = 0; i < ogg->nstreams; i++){
620         av_free (ogg->streams[i].buf);
621         av_free (ogg->streams[i].private);
622     }
623     av_free (ogg->streams);
624     return 0;
625 }
626
627 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
628                                   int64_t *pos_arg, int64_t pos_limit)
629 {
630     struct ogg *ogg = s->priv_data;
631     AVIOContext *bc = s->pb;
632     int64_t pts = AV_NOPTS_VALUE;
633     int i = -1;
634     avio_seek(bc, *pos_arg, SEEK_SET);
635     ogg_reset(ogg);
636
637     while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
638         if (i == stream_index) {
639             struct ogg_stream *os = ogg->streams + stream_index;
640             pts = ogg_calc_pts(s, i, NULL);
641             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
642                 pts = AV_NOPTS_VALUE;
643         }
644         if (pts != AV_NOPTS_VALUE)
645             break;
646     }
647     ogg_reset(ogg);
648     return pts;
649 }
650
651 static int ogg_read_seek(AVFormatContext *s, int stream_index,
652                          int64_t timestamp, int flags)
653 {
654     struct ogg *ogg = s->priv_data;
655     struct ogg_stream *os = ogg->streams + stream_index;
656     int ret;
657
658     // Try seeking to a keyframe first. If this fails (very possible),
659     // av_seek_frame will fall back to ignoring keyframes
660     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
661         && !(flags & AVSEEK_FLAG_ANY))
662         os->keyframe_seek = 1;
663
664     ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
665     os = ogg->streams + stream_index;
666     if (ret < 0)
667         os->keyframe_seek = 0;
668     return ret;
669 }
670
671 static int ogg_probe(AVProbeData *p)
672 {
673     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
674         return AVPROBE_SCORE_MAX;
675     return 0;
676 }
677
678 AVInputFormat ff_ogg_demuxer = {
679     .name           = "ogg",
680     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
681     .priv_data_size = sizeof(struct ogg),
682     .read_probe     = ogg_probe,
683     .read_header    = ogg_read_header,
684     .read_packet    = ogg_read_packet,
685     .read_close     = ogg_read_close,
686     .read_seek      = ogg_read_seek,
687     .read_timestamp = ogg_read_timestamp,
688     .extensions     = "ogg",
689     .flags          = AVFMT_GENERIC_INDEX,
690 };