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