Cosmetics: fix prototypes in oggdec
[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 ogg_save(AVFormatContext *s)
59 {
60 struct ogg *ogg = s->priv_data;
61 struct ogg_state *ost =
62 av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
63 int i;
64 ost->pos = avio_tell (s->pb);
65 ost->curidx = ogg->curidx;
66 ost->next = ogg->state;
67 ost->nstreams = ogg->nstreams;
68 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
69
70 for (i = 0; i < ogg->nstreams; i++){
71 struct ogg_stream *os = ogg->streams + i;
72 os->buf = av_malloc (os->bufsize);
73 memset (os->buf, 0, os->bufsize);
74 memcpy (os->buf, ost->streams[i].buf, os->bufpos);
75 }
76
77 ogg->state = ost;
78
79 return 0;
80 }
81
82 static int ogg_restore(AVFormatContext *s, int discard)
83 {
84 struct ogg *ogg = s->priv_data;
85 AVIOContext *bc = s->pb;
86 struct ogg_state *ost = ogg->state;
87 int i;
88
89 if (!ost)
90 return 0;
91
92 ogg->state = ost->next;
93
94 if (!discard){
95 for (i = 0; i < ogg->nstreams; i++)
96 av_free (ogg->streams[i].buf);
97
98 avio_seek (bc, ost->pos, SEEK_SET);
99 ogg->curidx = ost->curidx;
100 ogg->nstreams = ost->nstreams;
101 memcpy(ogg->streams, ost->streams,
102 ost->nstreams * sizeof(*ogg->streams));
103 }
104
105 av_free (ost);
106
107 return 0;
108 }
109
110 static int ogg_reset(struct ogg *ogg)
111 {
112 int i;
113
114 for (i = 0; i < ogg->nstreams; i++){
115 struct ogg_stream *os = ogg->streams + i;
116 os->bufpos = 0;
117 os->pstart = 0;
118 os->psize = 0;
119 os->granule = -1;
120 os->lastpts = AV_NOPTS_VALUE;
121 os->lastdts = AV_NOPTS_VALUE;
122 os->sync_pos = -1;
123 os->page_pos = 0;
124 os->nsegs = 0;
125 os->segp = 0;
126 os->incomplete = 0;
127 }
128
129 ogg->curidx = -1;
130
131 return 0;
132 }
133
134 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
135 {
136 int i;
137
138 for (i = 0; ogg_codecs[i]; i++)
139 if (size >= ogg_codecs[i]->magicsize &&
140 !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
141 return ogg_codecs[i];
142
143 return NULL;
144 }
145
146 static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream)
147 {
148
149 struct ogg *ogg = s->priv_data;
150 int idx = ogg->nstreams++;
151 AVStream *st;
152 struct ogg_stream *os;
153
154 ogg->streams = av_realloc (ogg->streams,
155 ogg->nstreams * sizeof (*ogg->streams));
156 memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
157 os = ogg->streams + idx;
158 os->serial = serial;
159 os->bufsize = DECODER_BUFFER_SIZE;
160 os->buf = av_malloc(os->bufsize);
161 os->header = -1;
162
163 if (new_avstream) {
164 st = av_new_stream(s, idx);
165 if (!st)
166 return AVERROR(ENOMEM);
167
168 av_set_pts_info(st, 64, 1, 1000000);
169 }
170
171 return idx;
172 }
173
174 static int ogg_new_buf(struct ogg *ogg, int idx)
175 {
176 struct ogg_stream *os = ogg->streams + idx;
177 uint8_t *nb = av_malloc(os->bufsize);
178 int size = os->bufpos - os->pstart;
179 if(os->buf){
180 memcpy(nb, os->buf + os->pstart, size);
181 av_free(os->buf);
182 }
183 os->buf = nb;
184 os->bufpos = size;
185 os->pstart = 0;
186
187 return 0;
188 }
189
190 static int ogg_read_page(AVFormatContext *s, int *str)
191 {
192 AVIOContext *bc = s->pb;
193 struct ogg *ogg = s->priv_data;
194 struct ogg_stream *os;
195 int i = 0;
196 int flags, nsegs;
197 uint64_t gp;
198 uint32_t serial;
199 uint32_t seq;
200 uint32_t crc;
201 int size, idx;
202 uint8_t sync[4];
203 int sp = 0;
204
205 if (avio_read (bc, sync, 4) < 4)
206 return -1;
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 (bc->eof_reached)
218 return -1;
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 -1;
225 }
226
227 if (avio_r8(bc) != 0) /* version */
228 return -1;
229
230 flags = avio_r8(bc);
231 gp = avio_rl64 (bc);
232 serial = avio_rl32 (bc);
233 seq = avio_rl32 (bc);
234 crc = avio_rl32 (bc);
235 nsegs = avio_r8(bc);
236
237 idx = ogg_find_stream (ogg, serial);
238 if (idx < 0){
239 if (ogg->headers) {
240 int n;
241
242 for (n = 0; n < ogg->nstreams; n++) {
243 av_freep(&ogg->streams[n].buf);
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 -1;
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 if (avio_read (bc, os->segments, nsegs) < nsegs)
263 return -1;
264
265 os->nsegs = nsegs;
266 os->segp = 0;
267
268 size = 0;
269 for (i = 0; i < nsegs; i++)
270 size += os->segments[i];
271
272 if (flags & OGG_FLAG_CONT || os->incomplete){
273 if (!os->psize){
274 while (os->segp < os->nsegs){
275 int seg = os->segments[os->segp++];
276 os->pstart += seg;
277 if (seg < 255)
278 break;
279 }
280 os->sync_pos = os->page_pos;
281 }
282 }else{
283 os->psize = 0;
284 os->sync_pos = os->page_pos;
285 }
286
287 if (os->bufsize - os->bufpos < size){
288 uint8_t *nb = av_malloc (os->bufsize *= 2);
289 memcpy (nb, os->buf, os->bufpos);
290 av_free (os->buf);
291 os->buf = nb;
292 }
293
294 if (avio_read (bc, os->buf + os->bufpos, size) < size)
295 return -1;
296
297 os->bufpos += size;
298 os->granule = gp;
299 os->flags = flags;
300
301 if (str)
302 *str = idx;
303
304 return 0;
305 }
306
307 static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize,
308 int64_t *fpos)
309 {
310 struct ogg *ogg = s->priv_data;
311 int idx, i;
312 struct ogg_stream *os;
313 int complete = 0;
314 int segp = 0, psize = 0;
315
316 av_dlog(s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
317
318 do{
319 idx = ogg->curidx;
320
321 while (idx < 0){
322 if (ogg_read_page (s, &idx) < 0)
323 return -1;
324 }
325
326 os = ogg->streams + idx;
327
328 av_dlog(s, AV_LOG_DEBUG,
329 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
330 idx, os->pstart, os->psize, os->segp, os->nsegs);
331
332 if (!os->codec){
333 if (os->header < 0){
334 os->codec = ogg_find_codec (os->buf, os->bufpos);
335 if (!os->codec){
336 os->header = 0;
337 return 0;
338 }
339 }else{
340 return 0;
341 }
342 }
343
344 segp = os->segp;
345 psize = os->psize;
346
347 while (os->segp < os->nsegs){
348 int ss = os->segments[os->segp++];
349 os->psize += ss;
350 if (ss < 255){
351 complete = 1;
352 break;
353 }
354 }
355
356 if (!complete && os->segp == os->nsegs){
357 ogg->curidx = -1;
358 os->incomplete = 1;
359 }
360 }while (!complete);
361
362 av_dlog(s, AV_LOG_DEBUG,
363 "ogg_packet: idx %i, frame size %i, start %i\n",
364 idx, os->psize, os->pstart);
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 // so we reset this later unless we are done with the headers
381 // for all streams.
382 ogg->headers = 1;
383
384 // Update the header state for all streams and
385 // compute the data_offset.
386 if (!s->data_offset)
387 s->data_offset = os->sync_pos;
388 for (i = 0; i < ogg->nstreams; i++) {
389 struct ogg_stream *cur_os = ogg->streams + i;
390 if (cur_os->header > 0)
391 ogg->headers = 0;
392
393 // if we have a partial non-header packet, its start is
394 // obviously at or after the data start
395 if (cur_os->incomplete)
396 s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos);
397 }
398 }else{
399 os->pstart += os->psize;
400 os->psize = 0;
401 }
402 } else {
403 os->pflags = 0;
404 os->pduration = 0;
405 if (os->codec && os->codec->packet)
406 os->codec->packet (s, idx);
407 if (str)
408 *str = idx;
409 if (dstart)
410 *dstart = os->pstart;
411 if (dsize)
412 *dsize = os->psize;
413 if (fpos)
414 *fpos = os->sync_pos;
415 os->pstart += os->psize;
416 os->psize = 0;
417 os->sync_pos = os->page_pos;
418 }
419
420 // determine whether there are more complete packets in this page
421 // if not, the page's granule will apply to this packet
422 os->page_end = 1;
423 for (i = os->segp; i < os->nsegs; i++)
424 if (os->segments[i] < 255) {
425 os->page_end = 0;
426 break;
427 }
428
429 if (os->segp == os->nsegs)
430 ogg->curidx = -1;
431
432 return 0;
433 }
434
435 static int ogg_get_headers(AVFormatContext *s)
436 {
437 struct ogg *ogg = s->priv_data;
438
439 do{
440 if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
441 return -1;
442 }while (!ogg->headers);
443
444 av_dlog(s, AV_LOG_DEBUG, "found headers\n");
445
446 return 0;
447 }
448
449 static int ogg_get_length(AVFormatContext *s)
450 {
451 struct ogg *ogg = s->priv_data;
452 int i;
453 int64_t size, end;
454
455 if(!s->pb->seekable)
456 return 0;
457
458 // already set
459 if (s->duration != AV_NOPTS_VALUE)
460 return 0;
461
462 size = avio_size(s->pb);
463 if(size < 0)
464 return 0;
465 end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
466
467 ogg_save (s);
468 avio_seek (s->pb, end, SEEK_SET);
469
470 while (!ogg_read_page (s, &i)){
471 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
472 ogg->streams[i].codec) {
473 s->streams[i]->duration =
474 ogg_gptopts (s, i, ogg->streams[i].granule, NULL);
475 if (s->streams[i]->start_time != AV_NOPTS_VALUE)
476 s->streams[i]->duration -= s->streams[i]->start_time;
477 }
478 }
479
480 ogg_restore (s, 0);
481
482 return 0;
483 }
484
485 static int ogg_read_header(AVFormatContext *s, AVFormatParameters *ap)
486 {
487 struct ogg *ogg = s->priv_data;
488 int i;
489 ogg->curidx = -1;
490 //linear headers seek from start
491 if (ogg_get_headers (s) < 0){
492 return -1;
493 }
494
495 for (i = 0; i < ogg->nstreams; i++)
496 if (ogg->streams[i].header < 0)
497 ogg->streams[i].codec = NULL;
498
499 //linear granulepos seek from end
500 ogg_get_length (s);
501
502 //fill the extradata in the per codec callbacks
503 return 0;
504 }
505
506 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
507 {
508 struct ogg *ogg = s->priv_data;
509 struct ogg_stream *os = ogg->streams + idx;
510 int64_t pts = AV_NOPTS_VALUE;
511
512 if (dts)
513 *dts = AV_NOPTS_VALUE;
514
515 if (os->lastpts != AV_NOPTS_VALUE) {
516 pts = os->lastpts;
517 os->lastpts = AV_NOPTS_VALUE;
518 }
519 if (os->lastdts != AV_NOPTS_VALUE) {
520 if (dts)
521 *dts = os->lastdts;
522 os->lastdts = AV_NOPTS_VALUE;
523 }
524 if (os->page_end) {
525 if (os->granule != -1LL) {
526 if (os->codec && os->codec->granule_is_start)
527 pts = ogg_gptopts(s, idx, os->granule, dts);
528 else
529 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
530 os->granule = -1LL;
531 }
532 }
533 return pts;
534 }
535
536 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
537 {
538 struct ogg *ogg;
539 struct ogg_stream *os;
540 int idx = -1;
541 int pstart, psize;
542 int64_t fpos, pts, dts;
543
544 //Get an ogg packet
545 retry:
546 do{
547 if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
548 return AVERROR(EIO);
549 }while (idx < 0 || !s->streams[idx]);
550
551 ogg = s->priv_data;
552 os = ogg->streams + idx;
553
554 // pflags might not be set until after this
555 pts = ogg_calc_pts(s, idx, &dts);
556
557 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
558 goto retry;
559 os->keyframe_seek = 0;
560
561 //Alloc a pkt
562 if (av_new_packet (pkt, psize) < 0)
563 return AVERROR(EIO);
564 pkt->stream_index = idx;
565 memcpy (pkt->data, os->buf + pstart, psize);
566
567 pkt->pts = pts;
568 pkt->dts = dts;
569 pkt->flags = os->pflags;
570 pkt->duration = os->pduration;
571 pkt->pos = fpos;
572
573 return psize;
574 }
575
576 static int ogg_read_close(AVFormatContext *s)
577 {
578 struct ogg *ogg = s->priv_data;
579 int i;
580
581 for (i = 0; i < ogg->nstreams; i++){
582 av_free (ogg->streams[i].buf);
583 av_free (ogg->streams[i].private);
584 }
585 av_free (ogg->streams);
586 return 0;
587 }
588
589 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
590 int64_t *pos_arg, int64_t pos_limit)
591 {
592 struct ogg *ogg = s->priv_data;
593 struct ogg_stream *os = ogg->streams + stream_index;
594 AVIOContext *bc = s->pb;
595 int64_t pts = AV_NOPTS_VALUE;
596 int i;
597 avio_seek(bc, *pos_arg, SEEK_SET);
598 ogg_reset(ogg);
599
600 while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
601 if (i == stream_index) {
602 pts = ogg_calc_pts(s, i, NULL);
603 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
604 pts = AV_NOPTS_VALUE;
605 }
606 if (pts != AV_NOPTS_VALUE)
607 break;
608 }
609 ogg_reset(ogg);
610 return pts;
611 }
612
613 static int ogg_read_seek(AVFormatContext *s, int stream_index,
614 int64_t timestamp, int flags)
615 {
616 struct ogg *ogg = s->priv_data;
617 struct ogg_stream *os = ogg->streams + stream_index;
618 int ret;
619
620 // Try seeking to a keyframe first. If this fails (very possible),
621 // av_seek_frame will fall back to ignoring keyframes
622 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
623 && !(flags & AVSEEK_FLAG_ANY))
624 os->keyframe_seek = 1;
625
626 ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
627 if (ret < 0)
628 os->keyframe_seek = 0;
629 return ret;
630 }
631
632 static int ogg_probe(AVProbeData *p)
633 {
634 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
635 return AVPROBE_SCORE_MAX;
636 return 0;
637 }
638
639 AVInputFormat ff_ogg_demuxer = {
640 .name = "ogg",
641 .long_name = NULL_IF_CONFIG_SMALL("Ogg"),
642 .priv_data_size = sizeof(struct ogg),
643 .read_probe = ogg_probe,
644 .read_header = ogg_read_header,
645 .read_packet = ogg_read_packet,
646 .read_close = ogg_read_close,
647 .read_seek = ogg_read_seek,
648 .read_timestamp = ogg_read_timestamp,
649 .extensions = "ogg",
650 .flags = AVFMT_GENERIC_INDEX,
651 };