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
456     if(!s->pb->seekable)
457         return 0;
458
459 // already set
460     if (s->duration != AV_NOPTS_VALUE)
461         return 0;
462
463     size = avio_size(s->pb);
464     if(size < 0)
465         return 0;
466     end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
467
468     ogg_save (s);
469     avio_seek (s->pb, end, SEEK_SET);
470
471     while (!ogg_read_page (s, &i)){
472         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
473             ogg->streams[i].codec) {
474             s->streams[i]->duration =
475                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
476             if (s->streams[i]->start_time != AV_NOPTS_VALUE)
477                 s->streams[i]->duration -= s->streams[i]->start_time;
478         }
479     }
480
481     ogg_restore (s, 0);
482
483     ogg_save (s);
484     avio_seek (s->pb, 0, SEEK_SET);
485     while (!ogg_read_page (s, &i)){
486         if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
487             ogg->streams[i].codec) {
488             s->streams[i]->duration -=
489                 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
490             break;
491         }
492     }
493     ogg_restore (s, 0);
494
495     return 0;
496 }
497
498 static int ogg_read_header(AVFormatContext *s, AVFormatParameters *ap)
499 {
500     struct ogg *ogg = s->priv_data;
501     int ret, i;
502     ogg->curidx = -1;
503     //linear headers seek from start
504     ret = ogg_get_headers (s);
505     if (ret < 0){
506         return ret;
507     }
508
509     for (i = 0; i < ogg->nstreams; i++)
510         if (ogg->streams[i].header < 0)
511             ogg->streams[i].codec = NULL;
512
513     //linear granulepos seek from end
514     ogg_get_length (s);
515
516     //fill the extradata in the per codec callbacks
517     return 0;
518 }
519
520 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
521 {
522     struct ogg *ogg = s->priv_data;
523     struct ogg_stream *os = ogg->streams + idx;
524     int64_t pts = AV_NOPTS_VALUE;
525
526     if (dts)
527         *dts = AV_NOPTS_VALUE;
528
529     if (os->lastpts != AV_NOPTS_VALUE) {
530         pts = os->lastpts;
531         os->lastpts = AV_NOPTS_VALUE;
532     }
533     if (os->lastdts != AV_NOPTS_VALUE) {
534         if (dts)
535             *dts = os->lastdts;
536         os->lastdts = AV_NOPTS_VALUE;
537     }
538     if (os->page_end) {
539         if (os->granule != -1LL) {
540             if (os->codec && os->codec->granule_is_start)
541                 pts = ogg_gptopts(s, idx, os->granule, dts);
542             else
543                 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
544             os->granule = -1LL;
545         }
546     }
547     return pts;
548 }
549
550 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
551 {
552     struct ogg *ogg;
553     struct ogg_stream *os;
554     int idx = -1, ret;
555     int pstart, psize;
556     int64_t fpos, pts, dts;
557
558     //Get an ogg packet
559 retry:
560     do{
561         ret = ogg_packet (s, &idx, &pstart, &psize, &fpos);
562         if (ret < 0)
563             return ret;
564     }while (idx < 0 || !s->streams[idx]);
565
566     ogg = s->priv_data;
567     os = ogg->streams + idx;
568
569     // pflags might not be set until after this
570     pts = ogg_calc_pts(s, idx, &dts);
571
572     if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
573         goto retry;
574     os->keyframe_seek = 0;
575
576     //Alloc a pkt
577     ret = av_new_packet (pkt, psize);
578     if (ret < 0)
579         return ret;
580     pkt->stream_index = idx;
581     memcpy (pkt->data, os->buf + pstart, psize);
582
583     pkt->pts = pts;
584     pkt->dts = dts;
585     pkt->flags = os->pflags;
586     pkt->duration = os->pduration;
587     pkt->pos = fpos;
588
589     return psize;
590 }
591
592 static int ogg_read_close(AVFormatContext *s)
593 {
594     struct ogg *ogg = s->priv_data;
595     int i;
596
597     for (i = 0; i < ogg->nstreams; i++){
598         av_free (ogg->streams[i].buf);
599         av_free (ogg->streams[i].private);
600     }
601     av_free (ogg->streams);
602     return 0;
603 }
604
605 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
606                                   int64_t *pos_arg, int64_t pos_limit)
607 {
608     struct ogg *ogg = s->priv_data;
609     struct ogg_stream *os = ogg->streams + stream_index;
610     AVIOContext *bc = s->pb;
611     int64_t pts = AV_NOPTS_VALUE;
612     int i;
613     avio_seek(bc, *pos_arg, SEEK_SET);
614     ogg_reset(ogg);
615
616     while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
617         if (i == stream_index) {
618             pts = ogg_calc_pts(s, i, NULL);
619             if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
620                 pts = AV_NOPTS_VALUE;
621         }
622         if (pts != AV_NOPTS_VALUE)
623             break;
624     }
625     ogg_reset(ogg);
626     return pts;
627 }
628
629 static int ogg_read_seek(AVFormatContext *s, int stream_index,
630                          int64_t timestamp, int flags)
631 {
632     struct ogg *ogg = s->priv_data;
633     struct ogg_stream *os = ogg->streams + stream_index;
634     int ret;
635
636     // Try seeking to a keyframe first. If this fails (very possible),
637     // av_seek_frame will fall back to ignoring keyframes
638     if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
639         && !(flags & AVSEEK_FLAG_ANY))
640         os->keyframe_seek = 1;
641
642     ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
643     if (ret < 0)
644         os->keyframe_seek = 0;
645     return ret;
646 }
647
648 static int ogg_probe(AVProbeData *p)
649 {
650     if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
651         return AVPROBE_SCORE_MAX;
652     return 0;
653 }
654
655 AVInputFormat ff_ogg_demuxer = {
656     .name           = "ogg",
657     .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
658     .priv_data_size = sizeof(struct ogg),
659     .read_probe     = ogg_probe,
660     .read_header    = ogg_read_header,
661     .read_packet    = ogg_read_packet,
662     .read_close     = ogg_read_close,
663     .read_seek      = ogg_read_seek,
664     .read_timestamp = ogg_read_timestamp,
665     .extensions     = "ogg",
666     .flags          = AVFMT_GENERIC_INDEX,
667 };