OSDN Git Service

Merge remote-tracking branch 'qatar/master'
[coroid/ffmpeg_saccubus.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_celt_codec,
49     &ff_old_dirac_codec,
50     &ff_old_flac_codec,
51     &ff_ogm_video_codec,
52     &ff_ogm_audio_codec,
53     &ff_ogm_text_codec,
54     &ff_ogm_old_codec,
55     NULL
56 };
57
58 //FIXME We could avoid some structure duplication
59 static int 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 = avio_tell (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 ogg_restore(AVFormatContext *s, int discard)
84 {
85     struct ogg *ogg = s->priv_data;
86     AVIOContext *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         avio_seek (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 ogg_reset(struct ogg *ogg)
112 {
113     int i;
114
115     for (i = 0; i < ogg->nstreams; i++){
116         struct ogg_stream *os = ogg->streams + i;
117         os->bufpos = 0;
118         os->pstart = 0;
119         os->psize = 0;
120         os->granule = -1;
121         os->lastpts = AV_NOPTS_VALUE;
122         os->lastdts = AV_NOPTS_VALUE;
123         os->sync_pos = -1;
124         os->page_pos = 0;
125         os->nsegs = 0;
126         os->segp = 0;
127         os->incomplete = 0;
128     }
129
130     ogg->curidx = -1;
131
132     return 0;
133 }
134
135 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
136 {
137     int i;
138
139     for (i = 0; ogg_codecs[i]; i++)
140         if (size >= ogg_codecs[i]->magicsize &&
141             !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
142             return ogg_codecs[i];
143
144     return NULL;
145 }
146
147 static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
148 {
149
150     struct ogg *ogg = s->priv_data;
151     int idx = ogg->nstreams++;
152     AVStream *st;
153     struct ogg_stream *os;
154
155     ogg->streams = av_realloc (ogg->streams,
156                                ogg->nstreams * sizeof (*ogg->streams));
157     memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
158     os = ogg->streams + idx;
159     os->serial = serial;
160     os->bufsize = DECODER_BUFFER_SIZE;
161     os->buf = av_malloc(os->bufsize);
162     os->header = -1;
163
164     if (new_avstream) {
165         st = av_new_stream(s, idx);
166         if (!st)
167             return AVERROR(ENOMEM);
168
169         av_set_pts_info(st, 64, 1, 1000000);
170     }
171
172     return idx;
173 }
174
175 static int ogg_new_buf(struct ogg *ogg, int idx)
176 {
177     struct ogg_stream *os = ogg->streams + idx;
178     uint8_t *nb = av_malloc(os->bufsize);
179     int size = os->bufpos - os->pstart;
180     if(os->buf){
181         memcpy(nb, os->buf + os->pstart, size);
182         av_free(os->buf);
183     }
184     os->buf = nb;
185     os->bufpos = size;
186     os->pstart = 0;
187
188     return 0;
189 }
190
191 static int ogg_read_page(AVFormatContext *s, int *str)
192 {
193     AVIOContext *bc = s->pb;
194     struct ogg *ogg = s->priv_data;
195     struct ogg_stream *os;
196     int ret, i = 0;
197     int flags, nsegs;
198     uint64_t gp;
199     uint32_t serial;
200     int size, idx;
201     uint8_t sync[4];
202     int sp = 0;
203
204     ret = avio_read(bc, sync, 4);
205     if (ret < 4)
206         return ret < 0 ? ret : AVERROR_EOF;
207
208     do{
209         int c;
210
211         if (sync[sp & 3] == 'O' &&
212             sync[(sp + 1) & 3] == 'g' &&
213             sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
214             break;
215
216         c = avio_r8(bc);
217         if (url_feof(bc))
218             return AVERROR_EOF;
219         sync[sp++ & 3] = c;
220     }while (i++ < MAX_PAGE_SIZE);
221
222     if (i >= MAX_PAGE_SIZE){
223         av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
224         return AVERROR_INVALIDDATA;
225     }
226
227     if (avio_r8(bc) != 0)      /* version */
228         return AVERROR_INVALIDDATA;
229
230     flags = avio_r8(bc);
231     gp = avio_rl64 (bc);
232     serial = avio_rl32 (bc);
233     avio_skip(bc, 8); /* seq, crc */
234     nsegs = avio_r8(bc);
235
236     idx = ogg_find_stream (ogg, serial);
237     if (idx < 0){
238         if (ogg->headers) {
239             int n;
240
241             for (n = 0; n < ogg->nstreams; n++) {
242                 av_freep(&ogg->streams[n].buf);
243                 if (!ogg->state || ogg->state->streams[n].private != ogg->streams[n].private)
244                     av_freep(&ogg->streams[n].private);
245             }
246             ogg->curidx   = -1;
247             ogg->nstreams = 0;
248             idx = ogg_new_stream(s, serial, 0);
249         } else {
250             idx = ogg_new_stream(s, serial, 1);
251         }
252         if (idx < 0)
253             return idx;
254     }
255
256     os = ogg->streams + idx;
257     os->page_pos = avio_tell(bc) - 27;
258
259     if(os->psize > 0)
260         ogg_new_buf(ogg, idx);
261
262     ret = avio_read(bc, os->segments, nsegs);
263     if (ret < nsegs)
264         return ret < 0 ? ret : AVERROR_EOF;
265
266     os->nsegs = nsegs;
267     os->segp = 0;
268
269     size = 0;
270     for (i = 0; i < nsegs; i++)
271         size += os->segments[i];
272
273     if (flags & OGG_FLAG_CONT || os->incomplete){
274         if (!os->psize){
275             while (os->segp < os->nsegs){
276                 int seg = os->segments[os->segp++];
277                 os->pstart += seg;
278                 if (seg < 255)
279                     break;
280             }
281             os->sync_pos = os->page_pos;
282         }
283     }else{
284         os->psize = 0;
285         os->sync_pos = os->page_pos;
286     }
287
288     if (os->bufsize - os->bufpos < size){
289         uint8_t *nb = av_malloc (os->bufsize *= 2);
290         memcpy (nb, os->buf, os->bufpos);
291         av_free (os->buf);
292         os->buf = nb;
293     }
294
295     ret = avio_read(bc, os->buf + os->bufpos, size);
296     if (ret < size)
297         return ret < 0 ? ret : AVERROR_EOF;
298
299     os->bufpos += size;
300     os->granule = gp;
301     os->flags = flags;
302
303     if (str)
304         *str = idx;
305
306     return 0;
307 }
308
309 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
310                       int64_t *fpos)
311 {
312     struct ogg *ogg = s->priv_data;
313     int idx, i, ret;
314     struct ogg_stream *os;
315     int complete = 0;
316     int segp = 0, psize = 0;
317
318     av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx);
319
320     do{
321         idx = ogg->curidx;
322
323         while (idx < 0){
324             ret = ogg_read_page(s, &idx);
325             if (ret < 0)
326                 return ret;
327         }
328
329         os = ogg->streams + idx;
330
331         av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
332                 idx, os->pstart, os->psize, os->segp, os->nsegs);
333
334         if (!os->codec){
335             if (os->header < 0){
336                 os->codec = ogg_find_codec (os->buf, os->bufpos);
337                 if (!os->codec){
338                     av_log(s, AV_LOG_WARNING, "Codec not found\n");
339                     os->header = 0;
340                     return 0;
341                 }
342             }else{
343                 return 0;
344             }
345         }
346
347         segp = os->segp;
348         psize = os->psize;
349
350         while (os->segp < os->nsegs){
351             int ss = os->segments[os->segp++];
352             os->psize += ss;
353             if (ss < 255){
354                 complete = 1;
355                 break;
356             }
357         }
358
359         if (!complete && os->segp == os->nsegs){
360             ogg->curidx = -1;
361             os->incomplete = 1;
362         }
363     }while (!complete);
364
365
366     if (os->granule == -1)
367         av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos);
368
369     ogg->curidx = idx;
370     os->incomplete = 0;
371
372     if (os->header) {
373         os->header = os->codec->header (s, idx);
374         if (!os->header){
375             os->segp = segp;
376             os->psize = psize;
377
378             // We have reached the first non-header packet in this stream.
379             // Unfortunately more header packets may still follow for others,
380             // but if we continue with header parsing we may lose data packets.
381             ogg->headers = 1;
382
383             // Update the header state for all streams and
384             // compute the data_offset.
385             if (!s->data_offset)
386                 s->data_offset = os->sync_pos;
387             for (i = 0; i < ogg->nstreams; i++) {
388                 struct ogg_stream *cur_os = ogg->streams + i;
389
390                 // if we have a partial non-header packet, its start is
391                 // obviously at or after the data start
392                 if (cur_os->incomplete)
393                     s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
394             }
395         }else{
396             os->pstart += os->psize;
397             os->psize = 0;
398         }
399     } else {
400         os->pflags = 0;
401         os->pduration = 0;
402         if (os->codec && os->codec->packet)
403             os->codec->packet (s, idx);
404         if (str)
405             *str = idx;
406         if (dstart)
407             *dstart = os->pstart;
408         if (dsize)
409             *dsize = os->psize;
410         if (fpos)
411             *fpos = os->sync_pos;
412         os->pstart += os->psize;
413         os->psize = 0;
414         if(os->pstart == os->bufpos)
415             os->bufpos = os->pstart = 0;
416         os->sync_pos = os->page_pos;
417     }
418
419     // determine whether there are more complete packets in this page
420     // if not, the page's granule will apply to this packet
421     os->page_end = 1;
422     for (i = os->segp; i < os->nsegs; i++)
423         if (os->segments[i] < 255) {
424             os->page_end = 0;
425             break;
426         }
427
428     if (os->segp == os->nsegs)
429         ogg->curidx = -1;
430
431     return 0;
432 }
433
434 static int ogg_get_headers(AVFormatContext *s)
435 {
436     struct ogg *ogg = s->priv_data;
437     int ret;
438
439     do{
440         ret = ogg_packet(s, NULL, NULL, NULL, NULL);
441         if (ret < 0)
442             return ret;
443     }while (!ogg->headers);
444
445     av_dlog(s, "found headers\n");
446
447     return 0;
448 }
449
450 static int ogg_get_length(AVFormatContext *s)
451 {
452     struct ogg *ogg = s->priv_data;
453     int i;
454     int64_t size, end;
455     int streams_left=0;
456
457     if(!s->pb->seekable)
458         return 0;
459
460 // already set
461     if (s->duration != AV_NOPTS_VALUE)
462         return 0;
463
464     size = avio_size(s->pb);
465     if(size < 0)
466         return 0;
467     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
468
469     ogg_save (s);
470     avio_seek (s->pb, end, SEEK_SET);
471
472     while (!ogg_read_page (s, &i)){
473         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
474             ogg->streams[i].codec) {
475             s->streams[i]->duration =
476                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
477             if (s->streams[i]->start_time != AV_NOPTS_VALUE){
478                 s->streams[i]->duration -= s->streams[i]->start_time;
479                 streams_left-= (ogg->streams[i].got_start==-1);
480                 ogg->streams[i].got_start= 1;
481             }else if(!ogg->streams[i].got_start){
482                 ogg->streams[i].got_start= -1;
483                 streams_left++;
484             }
485         }
486     }
487
488     ogg_restore (s, 0);
489
490     ogg_save (s);
491     avio_seek (s->pb, 0, SEEK_SET);
492     while (!ogg_read_page (s, &i)){
493         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
494             ogg->streams[i].codec) {
495             if(s->streams[i]->duration && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start){
496                 int64_t start= ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
497                 if(av_rescale_q(start, s->streams[i]->time_base, AV_TIME_BASE_Q) > AV_TIME_BASE)
498                     s->streams[i]->duration -= start;
499                 ogg->streams[i].got_start= 1;
500                 streams_left--;
501             }
502             if(streams_left<=0)
503                 break;
504         }
505     }
506     ogg_restore (s, 0);
507
508     return 0;
509 }
510
511 static int ogg_read_header(AVFormatContext *s, AVFormatParameters *ap)
512 {
513     struct ogg *ogg = s->priv_data;
514     int ret, i;
515     ogg->curidx = -1;
516     //linear headers seek from start
517     ret = ogg_get_headers(s);
518     if (ret < 0)
519         return ret;
520
521     for (i = 0; i < ogg->nstreams; i++)
522         if (ogg->streams[i].header < 0)
523             ogg->streams[i].codec = NULL;
524
525     //linear granulepos seek from end
526     ogg_get_length (s);
527
528     //fill the extradata in the per codec callbacks
529     return 0;
530 }
531
532 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
533 {
534     struct ogg *ogg = s->priv_data;
535     struct ogg_stream *os = ogg->streams + idx;
536     int64_t pts = AV_NOPTS_VALUE;
537
538     if (dts)
539         *dts = AV_NOPTS_VALUE;
540
541     if (os->lastpts != AV_NOPTS_VALUE) {
542         pts = os->lastpts;
543         os->lastpts = AV_NOPTS_VALUE;
544     }
545     if (os->lastdts != AV_NOPTS_VALUE) {
546         if (dts)
547             *dts = os->lastdts;
548         os->lastdts = AV_NOPTS_VALUE;
549     }
550     if (os->page_end) {
551         if (os->granule != -1LL) {
552             if (os->codec && os->codec->granule_is_start)
553                 pts = ogg_gptopts(s, idx, os->granule, dts);
554             else
555                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
556             os->granule = -1LL;
557         }
558     }
559     return pts;
560 }
561
562 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
563 {
564     struct ogg *ogg;
565     struct ogg_stream *os;
566     int idx = -1, ret;
567     int pstart, psize;
568     int64_t fpos, pts, dts;
569
570     //Get an ogg packet
571 retry:
572     do{
573         ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
574         if (ret < 0)
575             return ret;
576     }while (idx < 0 || !s->streams[idx]);
577
578     ogg = s->priv_data;
579     os = ogg->streams + idx;
580
581     // pflags might not be set until after this
582     pts = ogg_calc_pts(s, idx, &dts);
583
584     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
585         goto retry;
586     os->keyframe_seek = 0;
587
588     //Alloc a pkt
589     ret = av_new_packet(pkt, psize);
590     if (ret < 0)
591         return ret;
592     pkt->stream_index = idx;
593     memcpy (pkt->data, os->buf + pstart, psize);
594
595     pkt->pts = pts;
596     pkt->dts = dts;
597     pkt->flags = os->pflags;
598     pkt->duration = os->pduration;
599     pkt->pos = fpos;
600
601     return psize;
602 }
603
604 static int ogg_read_close(AVFormatContext *s)
605 {
606     struct ogg *ogg = s->priv_data;
607     int i;
608
609     for (i = 0; i < ogg->nstreams; i++){
610         av_free (ogg->streams[i].buf);
611         av_free (ogg->streams[i].private);
612     }
613     av_free (ogg->streams);
614     return 0;
615 }
616
617 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
618                                   int64_t *pos_arg, int64_t pos_limit)
619 {
620     struct ogg *ogg = s->priv_data;
621     AVIOContext *bc = s->pb;
622     int64_t pts = AV_NOPTS_VALUE;
623     int i = -1;
624     avio_seek(bc, *pos_arg, SEEK_SET);
625     ogg_reset(ogg);
626
627     while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
628         if (i == stream_index) {
629             struct ogg_stream *os = ogg->streams + stream_index;
630             pts = ogg_calc_pts(s, i, NULL);
631             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
632                 pts = AV_NOPTS_VALUE;
633         }
634         if (pts != AV_NOPTS_VALUE)
635             break;
636     }
637     ogg_reset(ogg);
638     return pts;
639 }
640
641 static int ogg_read_seek(AVFormatContext *s, int stream_index,
642                          int64_t timestamp, int flags)
643 {
644     struct ogg *ogg = s->priv_data;
645     struct ogg_stream *os = ogg->streams + stream_index;
646     int ret;
647
648     // Try seeking to a keyframe first. If this fails (very possible),
649     // av_seek_frame will fall back to ignoring keyframes
650     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
651         && !(flags & AVSEEK_FLAG_ANY))
652         os->keyframe_seek = 1;
653
654     ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
655     os = ogg->streams + stream_index;
656     if (ret < 0)
657         os->keyframe_seek = 0;
658     return ret;
659 }
660
661 static int ogg_probe(AVProbeData *p)
662 {
663     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
664         return AVPROBE_SCORE_MAX;
665     return 0;
666 }
667
668 AVInputFormat ff_ogg_demuxer = {
669     .name           = "ogg",
670     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
671     .priv_data_size = sizeof(struct ogg),
672     .read_probe     = ogg_probe,
673     .read_header    = ogg_read_header,
674     .read_packet    = ogg_read_packet,
675     .read_close     = ogg_read_close,
676     .read_seek      = ogg_read_seek,
677     .read_timestamp = ogg_read_timestamp,
678     .extensions     = "ogg",
679     .flags          = AVFMT_GENERIC_INDEX,
680 };