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