9cb3d8ca62458020a3f4466c040b4cdbec54610f
[libav.git] / libavformat / ogg2.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 "ogg2.h"
35 #include "avformat.h"
36
37 #define MAX_PAGE_SIZE 65307
38 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
39
40 static ogg_codec_t *ogg_codecs[] = {
41 &vorbis_codec,
42 &theora_codec,
43 &flac_codec,
44 &ogm_video_codec,
45 &ogm_audio_codec,
46 &ogm_old_codec,
47 NULL
48 };
49
50 #if 0 // CONFIG_MUXERS
51 static int
52 ogg_write_header (AVFormatContext * avfcontext)
53 {
54 }
55
56 static int
57 ogg_write_packet (AVFormatContext * avfcontext, AVPacket * pkt)
58 {
59 }
60
61
62 static int
63 ogg_write_trailer (AVFormatContext * avfcontext)
64 {
65 }
66
67
68 static AVOutputFormat ogg_oformat = {
69 "ogg",
70 "Ogg Vorbis",
71 "audio/x-vorbis",
72 "ogg",
73 sizeof (OggContext),
74 CODEC_ID_VORBIS,
75 0,
76 ogg_write_header,
77 ogg_write_packet,
78 ogg_write_trailer,
79 };
80 #endif //CONFIG_MUXERS
81
82 //FIXME We could avoid some structure duplication
83 static int
84 ogg_save (AVFormatContext * s)
85 {
86 ogg_t *ogg = s->priv_data;
87 ogg_state_t *ost =
88 av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
89 int i;
90 ost->pos = url_ftell (&s->pb);;
91 ost->curidx = ogg->curidx;
92 ost->next = ogg->state;
93 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
94
95 for (i = 0; i < ogg->nstreams; i++){
96 ogg_stream_t *os = ogg->streams + i;
97 os->buf = av_malloc (os->bufsize);
98 memset (os->buf, 0, os->bufsize);
99 memcpy (os->buf, ost->streams[i].buf, os->bufpos);
100 }
101
102 ogg->state = ost;
103
104 return 0;
105 }
106
107 static int
108 ogg_restore (AVFormatContext * s, int discard)
109 {
110 ogg_t *ogg = s->priv_data;
111 ByteIOContext *bc = &s->pb;
112 ogg_state_t *ost = ogg->state;
113 int i;
114
115 if (!ost)
116 return 0;
117
118 ogg->state = ost->next;
119
120 if (!discard){
121 for (i = 0; i < ogg->nstreams; i++)
122 av_free (ogg->streams[i].buf);
123
124 url_fseek (bc, ost->pos, SEEK_SET);
125 ogg->curidx = ost->curidx;
126 memcpy (ogg->streams, ost->streams,
127 ogg->nstreams * sizeof (*ogg->streams));
128 }
129
130 av_free (ost);
131
132 return 0;
133 }
134
135 static int
136 ogg_reset (ogg_t * ogg)
137 {
138 int i;
139
140 for (i = 0; i < ogg->nstreams; i++){
141 ogg_stream_t *os = ogg->streams + i;
142 os->bufpos = 0;
143 os->pstart = 0;
144 os->psize = 0;
145 os->granule = -1;
146 os->lastgp = -1;
147 os->nsegs = 0;
148 os->segp = 0;
149 }
150
151 ogg->curidx = -1;
152
153 return 0;
154 }
155
156 static ogg_codec_t *
157 ogg_find_codec (uint8_t * buf, int size)
158 {
159 int i;
160
161 for (i = 0; ogg_codecs[i]; i++)
162 if (size >= ogg_codecs[i]->magicsize &&
163 !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
164 return ogg_codecs[i];
165
166 return NULL;
167 }
168
169 static int
170 ogg_find_stream (ogg_t * ogg, int serial)
171 {
172 int i;
173
174 for (i = 0; i < ogg->nstreams; i++)
175 if (ogg->streams[i].serial == serial)
176 return i;
177
178 return -1;
179 }
180
181 static int
182 ogg_new_stream (AVFormatContext * s, uint32_t serial)
183 {
184
185 ogg_t *ogg = s->priv_data;
186 int idx = ogg->nstreams++;
187 AVStream *st;
188 ogg_stream_t *os;
189
190 ogg->streams = av_realloc (ogg->streams,
191 ogg->nstreams * sizeof (*ogg->streams));
192 memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
193 os = ogg->streams + idx;
194 os->serial = serial;
195 os->bufsize = DECODER_BUFFER_SIZE;
196 os->header = -1;
197
198 st = av_new_stream (s, idx);
199 if (!st)
200 return AVERROR_NOMEM;
201
202 av_set_pts_info(st, 64, 1, 1000000);
203 st->start_time = 0;
204
205 return idx;
206 }
207
208 static int
209 ogg_new_buf(ogg_t *ogg, int idx)
210 {
211 ogg_stream_t *os = ogg->streams + idx;
212 u_char *nb = av_malloc(os->bufsize);
213 int size = os->bufpos - os->pstart;
214 if(os->buf){
215 memcpy(nb, os->buf + os->pstart, size);
216 av_free(os->buf);
217 }
218 os->buf = nb;
219 os->bufpos = size;
220 os->pstart = 0;
221
222 return 0;
223 }
224
225 static int
226 ogg_read_page (AVFormatContext * s, int *str)
227 {
228 ByteIOContext *bc = &s->pb;
229 ogg_t *ogg = s->priv_data;
230 ogg_stream_t *os;
231 int i = 0;
232 int flags, nsegs;
233 uint64_t gp;
234 uint32_t serial;
235 uint32_t seq;
236 uint32_t crc;
237 int size, idx;
238 char sync[4];
239 int sp = 0;
240
241 if (get_buffer (bc, sync, 4) < 4)
242 return -1;
243
244 do{
245 int c;
246
247 if (sync[sp & 3] == 'O' &&
248 sync[(sp + 1) & 3] == 'g' &&
249 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
250 break;
251
252 c = url_fgetc (bc);
253 if (c < 0)
254 return -1;
255 sync[sp++ & 3] = c;
256 }while (i++ < MAX_PAGE_SIZE);
257
258 if (i >= MAX_PAGE_SIZE){
259 av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
260 return -1;
261 }
262
263 if (url_fgetc (bc) != 0) /* version */
264 return -1;
265
266 flags = url_fgetc (bc);
267 gp = get_le64 (bc);
268 serial = get_le32 (bc);
269 seq = get_le32 (bc);
270 crc = get_le32 (bc);
271 nsegs = url_fgetc (bc);
272
273 idx = ogg_find_stream (ogg, serial);
274 if (idx < 0){
275 idx = ogg_new_stream (s, serial);
276 if (idx < 0)
277 return -1;
278 }
279
280 os = ogg->streams + idx;
281
282 if(os->segp == os->nsegs)
283 ogg_new_buf(ogg, idx);
284
285 if (get_buffer (bc, os->segments, nsegs) < nsegs)
286 return -1;
287
288 os->nsegs = nsegs;
289 os->segp = 0;
290
291 size = 0;
292 for (i = 0; i < nsegs; i++)
293 size += os->segments[i];
294
295 if (flags & OGG_FLAG_CONT){
296 if (!os->psize){
297 while (os->segp < os->nsegs){
298 int seg = os->segments[os->segp++];
299 os->pstart += seg;
300 if (seg < 255)
301 break;
302 }
303 }
304 }else{
305 os->psize = 0;
306 }
307
308 if (os->bufsize - os->bufpos < size){
309 uint8_t *nb = av_malloc (os->bufsize *= 2);
310 memset (nb, 0, os->bufsize);
311 memcpy (nb, os->buf, os->bufpos);
312 av_free (os->buf);
313 os->buf = nb;
314 }
315
316 if (get_buffer (bc, os->buf + os->bufpos, size) < size)
317 return -1;
318
319 os->lastgp = os->granule;
320 os->bufpos += size;
321 os->granule = gp;
322 os->flags = flags;
323
324 if (str)
325 *str = idx;
326
327 return 0;
328 }
329
330 static int
331 ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize)
332 {
333 ogg_t *ogg = s->priv_data;
334 int idx;
335 ogg_stream_t *os;
336 int complete = 0;
337 int segp = 0, psize = 0;
338
339 #if 0
340 av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
341 #endif
342
343 do{
344 idx = ogg->curidx;
345
346 while (idx < 0){
347 if (ogg_read_page (s, &idx) < 0)
348 return -1;
349 }
350
351 os = ogg->streams + idx;
352
353 #if 0
354 av_log (s, AV_LOG_DEBUG,
355 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
356 idx, os->pstart, os->psize, os->segp, os->nsegs);
357 #endif
358
359 if (!os->codec){
360 if (os->header < 0){
361 os->codec = ogg_find_codec (os->buf, os->bufpos);
362 if (!os->codec){
363 os->header = 0;
364 return 0;
365 }
366 }else{
367 return 0;
368 }
369 }
370
371 segp = os->segp;
372 psize = os->psize;
373
374 while (os->segp < os->nsegs){
375 int ss = os->segments[os->segp++];
376 os->psize += ss;
377 if (ss < 255){
378 complete = 1;
379 break;
380 }
381 }
382
383 if (!complete && os->segp == os->nsegs){
384 ogg->curidx = -1;
385 }
386 }while (!complete);
387
388 #if 0
389 av_log (s, AV_LOG_DEBUG,
390 "ogg_packet: idx %i, frame size %i, start %i\n",
391 idx, os->psize, os->pstart);
392 #endif
393
394 ogg->curidx = idx;
395
396 if (os->header < 0){
397 int hdr = os->codec->header (s, idx);
398 if (!hdr){
399 os->header = os->seq;
400 os->segp = segp;
401 os->psize = psize;
402 ogg->headers = 1;
403 }else{
404 os->pstart += os->psize;
405 os->psize = 0;
406 }
407 }
408
409 if (os->header > -1 && os->seq > os->header){
410 if (os->codec && os->codec->packet)
411 os->codec->packet (s, idx);
412 if (str)
413 *str = idx;
414 if (dstart)
415 *dstart = os->pstart;
416 if (dsize)
417 *dsize = os->psize;
418 os->pstart += os->psize;
419 os->psize = 0;
420 }
421
422 os->seq++;
423 if (os->segp == os->nsegs)
424 ogg->curidx = -1;
425
426 return 0;
427 }
428
429 static int
430 ogg_get_headers (AVFormatContext * s)
431 {
432 ogg_t *ogg = s->priv_data;
433
434 do{
435 if (ogg_packet (s, NULL, NULL, NULL) < 0)
436 return -1;
437 }while (!ogg->headers);
438
439 #if 0
440 av_log (s, AV_LOG_DEBUG, "found headers\n");
441 #endif
442
443 return 0;
444 }
445
446 static uint64_t
447 ogg_gptopts (AVFormatContext * s, int i, uint64_t gp)
448 {
449 ogg_t *ogg = s->priv_data;
450 ogg_stream_t *os = ogg->streams + i;
451 uint64_t pts = AV_NOPTS_VALUE;
452
453 if(os->codec->gptopts){
454 pts = os->codec->gptopts(s, i, gp);
455 } else {
456 pts = gp;
457 }
458
459 return pts;
460 }
461
462
463 static int
464 ogg_get_length (AVFormatContext * s)
465 {
466 ogg_t *ogg = s->priv_data;
467 int idx = -1, i;
468 offset_t size, end;
469
470 if(s->pb.is_streamed)
471 return 0;
472
473 // already set
474 if (s->duration != AV_NOPTS_VALUE)
475 return 0;
476
477 size = url_fsize(&s->pb);
478 if(size < 0)
479 return 0;
480 end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: size;
481
482 ogg_save (s);
483 url_fseek (&s->pb, end, SEEK_SET);
484
485 while (!ogg_read_page (s, &i)){
486 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
487 idx = i;
488 }
489
490 if (idx != -1){
491 s->streams[idx]->duration =
492 ogg_gptopts (s, idx, ogg->streams[idx].granule);
493 }
494
495 ogg->size = size;
496 ogg_restore (s, 0);
497
498 return 0;
499 }
500
501
502 static int
503 ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
504 {
505 ogg_t *ogg = s->priv_data;
506 ogg->curidx = -1;
507 //linear headers seek from start
508 if (ogg_get_headers (s) < 0){
509 return -1;
510 }
511
512 //linear granulepos seek from end
513 ogg_get_length (s);
514
515 //fill the extradata in the per codec callbacks
516 return 0;
517 }
518
519
520 static int
521 ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
522 {
523 ogg_t *ogg;
524 ogg_stream_t *os;
525 int idx = -1;
526 int pstart, psize;
527
528 //Get an ogg packet
529 do{
530 if (ogg_packet (s, &idx, &pstart, &psize) < 0)
531 return AVERROR_IO;
532 }while (idx < 0 || !s->streams[idx]);
533
534 ogg = s->priv_data;
535 os = ogg->streams + idx;
536
537 //Alloc a pkt
538 if (av_new_packet (pkt, psize) < 0)
539 return AVERROR_IO;
540 pkt->stream_index = idx;
541 memcpy (pkt->data, os->buf + pstart, psize);
542 if (os->lastgp != -1LL){
543 pkt->pts = ogg_gptopts (s, idx, os->lastgp);
544 os->lastgp = -1;
545 }
546
547 return psize;
548 }
549
550
551 static int
552 ogg_read_close (AVFormatContext * s)
553 {
554 ogg_t *ogg = s->priv_data;
555 int i;
556
557 for (i = 0; i < ogg->nstreams; i++){
558 av_free (ogg->streams[i].buf);
559 av_free (ogg->streams[i].private);
560 }
561 av_free (ogg->streams);
562 return 0;
563 }
564
565
566 static int
567 ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
568 int flags)
569 {
570 AVStream *st = s->streams[stream_index];
571 ogg_t *ogg = s->priv_data;
572 ByteIOContext *bc = &s->pb;
573 uint64_t min = 0, max = ogg->size;
574 uint64_t tmin = 0, tmax = st->duration;
575 int64_t pts = AV_NOPTS_VALUE;
576
577 ogg_save (s);
578
579 while (min <= max){
580 uint64_t p = min + (max - min) * (target_ts - tmin) / (tmax - tmin);
581 int i = -1;
582
583 url_fseek (bc, p, SEEK_SET);
584
585 while (!ogg_read_page (s, &i)){
586 if (i == stream_index && ogg->streams[i].granule != 0 &&
587 ogg->streams[i].granule != -1)
588 break;
589 }
590
591 if (i == -1)
592 break;
593
594 pts = ogg_gptopts (s, i, ogg->streams[i].granule);
595 p = url_ftell (bc);
596
597 if (ABS (pts - target_ts) * st->time_base.num < st->time_base.den)
598 break;
599
600 if (pts > target_ts){
601 max = p;
602 tmax = pts;
603 }else{
604 min = p;
605 tmin = pts;
606 }
607 }
608
609 if (ABS (pts - target_ts) * st->time_base.num < st->time_base.den){
610 ogg_restore (s, 1);
611 ogg_reset (ogg);
612 }else{
613 ogg_restore (s, 0);
614 pts = AV_NOPTS_VALUE;
615 }
616
617 return pts;
618
619 #if 0
620 //later...
621 int64_t pos;
622 if (av_seek_frame_binary (s, stream_index, target_ts, flags) < 0)
623 return -1;
624 pos = url_ftell (&s->pb);
625 ogg_read_timestamp (s, stream_index, &pos, pos - 1);
626 #endif
627
628 }
629
630 #if 0
631 static int64_t
632 ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
633 int64_t pos_limit)
634 {
635 ogg_t *ogg = s->priv_data;
636 ByteIOContext *bc = &s->pb;
637 int64_t pos, pts;
638
639 if (*pos_arg < 0)
640 return AV_NOPTS_VALUE;
641
642 pos = *pos_arg;
643 }
644 #endif
645
646 static int ogg_probe(AVProbeData *p)
647 {
648 if (p->buf_size < 6)
649 return 0;
650 if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
651 p->buf[2] == 'g' && p->buf[3] == 'S' &&
652 p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
653 return AVPROBE_SCORE_MAX;
654 else
655 return 0;
656 }
657
658 static AVInputFormat ogg_iformat = {
659 "ogg",
660 "Ogg",
661 sizeof (ogg_t),
662 ogg_probe,
663 ogg_read_header,
664 ogg_read_packet,
665 ogg_read_close,
666 ogg_read_seek,
667 // ogg_read_timestamp,
668 .extensions = "ogg",
669 };
670
671 int
672 ogg_init (void)
673 {
674 #if 0 // CONFIG_MUXERS
675 av_register_output_format (&ogg_oformat);
676 #endif
677 av_register_input_format (&ogg_iformat);
678 return 0;
679 }