Be less picky on invalid frame_pred_frame_dct values.
[libav.git] / libavformat / oggdec.c
CommitLineData
9146ca37
MR
1/*
2 * Ogg bitstream support
3 * Luca Barbato <lu_zero@gentoo.org>
4 * Based on tcvp implementation
115329f1 5 *
9146ca37
MR
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>
a0ddef24 34#include "oggdec.h"
9146ca37
MR
35#include "avformat.h"
36
37#define MAX_PAGE_SIZE 65307
38#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
39
77be08ee 40static const struct ogg_codec * const ogg_codecs[] = {
547ea47d
RD
41 &ff_speex_codec,
42 &ff_vorbis_codec,
43 &ff_theora_codec,
44 &ff_flac_codec,
45 &ff_old_flac_codec,
46 &ff_ogm_video_codec,
47 &ff_ogm_audio_codec,
48 &ff_ogm_text_codec,
49 &ff_ogm_old_codec,
9146ca37
MR
50 NULL
51};
52
9146ca37
MR
53//FIXME We could avoid some structure duplication
54static int
55ogg_save (AVFormatContext * s)
56{
77be08ee
MR
57 struct ogg *ogg = s->priv_data;
58 struct ogg_state *ost =
ad3aa874 59 av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
9146ca37 60 int i;
899681cd 61 ost->pos = url_ftell (s->pb);
9146ca37
MR
62 ost->curidx = ogg->curidx;
63 ost->next = ogg->state;
20be72c8 64 ost->nstreams = ogg->nstreams;
9146ca37
MR
65 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
66
67 for (i = 0; i < ogg->nstreams; i++){
77be08ee 68 struct ogg_stream *os = ogg->streams + i;
9146ca37
MR
69 os->buf = av_malloc (os->bufsize);
70 memset (os->buf, 0, os->bufsize);
71 memcpy (os->buf, ost->streams[i].buf, os->bufpos);
72 }
73
74 ogg->state = ost;
75
76 return 0;
77}
78
79static int
80ogg_restore (AVFormatContext * s, int discard)
81{
77be08ee 82 struct ogg *ogg = s->priv_data;
899681cd 83 ByteIOContext *bc = s->pb;
77be08ee 84 struct ogg_state *ost = ogg->state;
9146ca37
MR
85 int i;
86
87 if (!ost)
88 return 0;
89
90 ogg->state = ost->next;
91
92 if (!discard){
93 for (i = 0; i < ogg->nstreams; i++)
94 av_free (ogg->streams[i].buf);
95
96 url_fseek (bc, ost->pos, SEEK_SET);
97 ogg->curidx = ost->curidx;
20be72c8
MR
98 ogg->nstreams = ost->nstreams;
99 memcpy(ogg->streams, ost->streams,
100 ost->nstreams * sizeof(*ogg->streams));
9146ca37
MR
101 }
102
103 av_free (ost);
104
105 return 0;
106}
107
108static int
77be08ee 109ogg_reset (struct ogg * ogg)
9146ca37
MR
110{
111 int i;
112
113 for (i = 0; i < ogg->nstreams; i++){
77be08ee 114 struct ogg_stream *os = ogg->streams + i;
9146ca37
MR
115 os->bufpos = 0;
116 os->pstart = 0;
117 os->psize = 0;
118 os->granule = -1;
119 os->lastgp = -1;
120 os->nsegs = 0;
121 os->segp = 0;
122 }
123
124 ogg->curidx = -1;
125
126 return 0;
127}
128
77be08ee 129static const struct ogg_codec *
2d2f443d 130ogg_find_codec (uint8_t * buf, int size)
9146ca37
MR
131{
132 int i;
133
134 for (i = 0; ogg_codecs[i]; i++)
135 if (size >= ogg_codecs[i]->magicsize &&
136 !memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
137 return ogg_codecs[i];
138
139 return NULL;
140}
141
142static int
77be08ee 143ogg_find_stream (struct ogg * ogg, int serial)
9146ca37
MR
144{
145 int i;
146
147 for (i = 0; i < ogg->nstreams; i++)
148 if (ogg->streams[i].serial == serial)
149 return i;
150
151 return -1;
152}
153
154static int
155ogg_new_stream (AVFormatContext * s, uint32_t serial)
156{
157
77be08ee 158 struct ogg *ogg = s->priv_data;
9146ca37
MR
159 int idx = ogg->nstreams++;
160 AVStream *st;
77be08ee 161 struct ogg_stream *os;
9146ca37
MR
162
163 ogg->streams = av_realloc (ogg->streams,
164 ogg->nstreams * sizeof (*ogg->streams));
165 memset (ogg->streams + idx, 0, sizeof (*ogg->streams));
166 os = ogg->streams + idx;
167 os->serial = serial;
168 os->bufsize = DECODER_BUFFER_SIZE;
40c5e1fa 169 os->buf = av_malloc(os->bufsize);
9146ca37
MR
170 os->header = -1;
171
172 st = av_new_stream (s, idx);
173 if (!st)
769e10f0 174 return AVERROR(ENOMEM);
9146ca37
MR
175
176 av_set_pts_info(st, 64, 1, 1000000);
9146ca37
MR
177
178 return idx;
179}
180
181static int
77be08ee 182ogg_new_buf(struct ogg *ogg, int idx)
12a195e3 183{
77be08ee 184 struct ogg_stream *os = ogg->streams + idx;
ea02862a 185 uint8_t *nb = av_malloc(os->bufsize);
12a195e3
MR
186 int size = os->bufpos - os->pstart;
187 if(os->buf){
188 memcpy(nb, os->buf + os->pstart, size);
189 av_free(os->buf);
190 }
191 os->buf = nb;
192 os->bufpos = size;
193 os->pstart = 0;
194
195 return 0;
196}
197
198static int
9146ca37
MR
199ogg_read_page (AVFormatContext * s, int *str)
200{
899681cd 201 ByteIOContext *bc = s->pb;
77be08ee
MR
202 struct ogg *ogg = s->priv_data;
203 struct ogg_stream *os;
9146ca37
MR
204 int i = 0;
205 int flags, nsegs;
206 uint64_t gp;
207 uint32_t serial;
208 uint32_t seq;
209 uint32_t crc;
210 int size, idx;
191e8ca7 211 uint8_t sync[4];
9146ca37
MR
212 int sp = 0;
213
214 if (get_buffer (bc, sync, 4) < 4)
215 return -1;
216
217 do{
218 int c;
219
220 if (sync[sp & 3] == 'O' &&
221 sync[(sp + 1) & 3] == 'g' &&
222 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
223 break;
224
225 c = url_fgetc (bc);
226 if (c < 0)
227 return -1;
228 sync[sp++ & 3] = c;
229 }while (i++ < MAX_PAGE_SIZE);
230
231 if (i >= MAX_PAGE_SIZE){
232 av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
233 return -1;
234 }
235
236 if (url_fgetc (bc) != 0) /* version */
237 return -1;
238
239 flags = url_fgetc (bc);
240 gp = get_le64 (bc);
241 serial = get_le32 (bc);
242 seq = get_le32 (bc);
243 crc = get_le32 (bc);
244 nsegs = url_fgetc (bc);
245
246 idx = ogg_find_stream (ogg, serial);
247 if (idx < 0){
248 idx = ogg_new_stream (s, serial);
249 if (idx < 0)
250 return -1;
251 }
252
253 os = ogg->streams + idx;
254
40c5e1fa 255 if(os->psize > 0)
12a195e3
MR
256 ogg_new_buf(ogg, idx);
257
9146ca37
MR
258 if (get_buffer (bc, os->segments, nsegs) < nsegs)
259 return -1;
260
261 os->nsegs = nsegs;
262 os->segp = 0;
263
264 size = 0;
265 for (i = 0; i < nsegs; i++)
266 size += os->segments[i];
267
268 if (flags & OGG_FLAG_CONT){
269 if (!os->psize){
270 while (os->segp < os->nsegs){
271 int seg = os->segments[os->segp++];
272 os->pstart += seg;
273 if (seg < 255)
bad4a6bb 274 break;
9146ca37
MR
275 }
276 }
277 }else{
bad4a6bb 278 os->psize = 0;
9146ca37
MR
279 }
280
281 if (os->bufsize - os->bufpos < size){
2d2f443d 282 uint8_t *nb = av_malloc (os->bufsize *= 2);
9146ca37
MR
283 memcpy (nb, os->buf, os->bufpos);
284 av_free (os->buf);
285 os->buf = nb;
286 }
287
288 if (get_buffer (bc, os->buf + os->bufpos, size) < size)
289 return -1;
290
291 os->lastgp = os->granule;
292 os->bufpos += size;
293 os->granule = gp;
294 os->flags = flags;
295
296 if (str)
297 *str = idx;
298
299 return 0;
300}
301
302static int
12a195e3 303ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize)
9146ca37 304{
77be08ee 305 struct ogg *ogg = s->priv_data;
9146ca37 306 int idx;
77be08ee 307 struct ogg_stream *os;
9146ca37
MR
308 int complete = 0;
309 int segp = 0, psize = 0;
310
311#if 0
312 av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
313#endif
314
315 do{
316 idx = ogg->curidx;
317
318 while (idx < 0){
319 if (ogg_read_page (s, &idx) < 0)
320 return -1;
321 }
322
323 os = ogg->streams + idx;
324
325#if 0
326 av_log (s, AV_LOG_DEBUG,
327 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
328 idx, os->pstart, os->psize, os->segp, os->nsegs);
329#endif
330
331 if (!os->codec){
332 if (os->header < 0){
333 os->codec = ogg_find_codec (os->buf, os->bufpos);
334 if (!os->codec){
335 os->header = 0;
336 return 0;
337 }
338 }else{
339 return 0;
340 }
341 }
342
343 segp = os->segp;
344 psize = os->psize;
345
346 while (os->segp < os->nsegs){
347 int ss = os->segments[os->segp++];
348 os->psize += ss;
349 if (ss < 255){
350 complete = 1;
351 break;
352 }
353 }
354
355 if (!complete && os->segp == os->nsegs){
9146ca37
MR
356 ogg->curidx = -1;
357 }
358 }while (!complete);
359
360#if 0
361 av_log (s, AV_LOG_DEBUG,
362 "ogg_packet: idx %i, frame size %i, start %i\n",
363 idx, os->psize, os->pstart);
364#endif
365
366 ogg->curidx = idx;
367
368 if (os->header < 0){
369 int hdr = os->codec->header (s, idx);
370 if (!hdr){
bad4a6bb
PR
371 os->header = os->seq;
372 os->segp = segp;
373 os->psize = psize;
374 ogg->headers = 1;
9146ca37 375 }else{
bad4a6bb
PR
376 os->pstart += os->psize;
377 os->psize = 0;
9146ca37
MR
378 }
379 }
380
381 if (os->header > -1 && os->seq > os->header){
e1a794b2 382 os->pflags = 0;
15299b38 383 os->pduration = 0;
9146ca37
MR
384 if (os->codec && os->codec->packet)
385 os->codec->packet (s, idx);
386 if (str)
387 *str = idx;
12a195e3
MR
388 if (dstart)
389 *dstart = os->pstart;
390 if (dsize)
391 *dsize = os->psize;
392 os->pstart += os->psize;
393 os->psize = 0;
9146ca37
MR
394 }
395
396 os->seq++;
397 if (os->segp == os->nsegs)
398 ogg->curidx = -1;
399
400 return 0;
401}
402
403static int
404ogg_get_headers (AVFormatContext * s)
405{
77be08ee 406 struct ogg *ogg = s->priv_data;
9146ca37
MR
407
408 do{
12a195e3 409 if (ogg_packet (s, NULL, NULL, NULL) < 0)
9146ca37
MR
410 return -1;
411 }while (!ogg->headers);
412
413#if 0
414 av_log (s, AV_LOG_DEBUG, "found headers\n");
415#endif
416
417 return 0;
418}
419
420static uint64_t
421ogg_gptopts (AVFormatContext * s, int i, uint64_t gp)
422{
77be08ee
MR
423 struct ogg *ogg = s->priv_data;
424 struct ogg_stream *os = ogg->streams + i;
9146ca37
MR
425 uint64_t pts = AV_NOPTS_VALUE;
426
1ed923ea 427 if(os->codec->gptopts){
bb270c08 428 pts = os->codec->gptopts(s, i, gp);
3644cb8f 429 } else {
1ed923ea 430 pts = gp;
9146ca37
MR
431 }
432
433 return pts;
434}
435
436
437static int
438ogg_get_length (AVFormatContext * s)
439{
77be08ee 440 struct ogg *ogg = s->priv_data;
9146ca37 441 int idx = -1, i;
bc5c918e 442 int64_t size, end;
69599eea 443
ceeacce6 444 if(url_is_streamed(s->pb))
69599eea 445 return 0;
9146ca37
MR
446
447// already set
448 if (s->duration != AV_NOPTS_VALUE)
449 return 0;
450
899681cd 451 size = url_fsize(s->pb);
56466d7b
MR
452 if(size < 0)
453 return 0;
ddd94932 454 end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
56466d7b 455
9146ca37 456 ogg_save (s);
899681cd 457 url_fseek (s->pb, end, SEEK_SET);
9146ca37
MR
458
459 while (!ogg_read_page (s, &i)){
e22f2aaf
MR
460 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
461 ogg->streams[i].codec)
9146ca37
MR
462 idx = i;
463 }
464
465 if (idx != -1){
466 s->streams[idx]->duration =
467 ogg_gptopts (s, idx, ogg->streams[idx].granule);
468 }
469
56466d7b 470 ogg->size = size;
9146ca37
MR
471 ogg_restore (s, 0);
472
473 return 0;
474}
475
476
477static int
478ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
479{
77be08ee 480 struct ogg *ogg = s->priv_data;
c9da676d 481 int i;
9146ca37
MR
482 ogg->curidx = -1;
483 //linear headers seek from start
484 if (ogg_get_headers (s) < 0){
bad4a6bb 485 return -1;
9146ca37
MR
486 }
487
c9da676d
RD
488 for (i = 0; i < ogg->nstreams; i++)
489 if (ogg->streams[i].header < 0)
490 ogg->streams[i].codec = NULL;
491
9146ca37
MR
492 //linear granulepos seek from end
493 ogg_get_length (s);
494
495 //fill the extradata in the per codec callbacks
496 return 0;
497}
498
499
500static int
501ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
502{
77be08ee
MR
503 struct ogg *ogg;
504 struct ogg_stream *os;
9146ca37 505 int idx = -1;
12a195e3 506 int pstart, psize;
9146ca37 507
115329f1 508 //Get an ogg packet
9146ca37 509 do{
12a195e3 510 if (ogg_packet (s, &idx, &pstart, &psize) < 0)
6f3e0b21 511 return AVERROR(EIO);
9146ca37
MR
512 }while (idx < 0 || !s->streams[idx]);
513
514 ogg = s->priv_data;
515 os = ogg->streams + idx;
516
517 //Alloc a pkt
12a195e3 518 if (av_new_packet (pkt, psize) < 0)
6f3e0b21 519 return AVERROR(EIO);
9146ca37 520 pkt->stream_index = idx;
12a195e3 521 memcpy (pkt->data, os->buf + pstart, psize);
9146ca37
MR
522 if (os->lastgp != -1LL){
523 pkt->pts = ogg_gptopts (s, idx, os->lastgp);
524 os->lastgp = -1;
525 }
12a195e3 526
e1a794b2 527 pkt->flags = os->pflags;
15299b38 528 pkt->duration = os->pduration;
e1a794b2 529
12a195e3 530 return psize;
9146ca37
MR
531}
532
533
534static int
535ogg_read_close (AVFormatContext * s)
536{
77be08ee 537 struct ogg *ogg = s->priv_data;
9146ca37
MR
538 int i;
539
540 for (i = 0; i < ogg->nstreams; i++){
541 av_free (ogg->streams[i].buf);
1ed923ea 542 av_free (ogg->streams[i].private);
9146ca37
MR
543 }
544 av_free (ogg->streams);
545 return 0;
546}
547
548
9146ca37
MR
549static int64_t
550ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
551 int64_t pos_limit)
552{
77be08ee 553 struct ogg *ogg = s->priv_data;
899681cd 554 ByteIOContext *bc = s->pb;
a1f29b95
RD
555 int64_t pts = AV_NOPTS_VALUE;
556 int i;
557 url_fseek(bc, *pos_arg, SEEK_SET);
558 while (url_ftell(bc) < pos_limit && !ogg_read_page (s, &i)) {
559 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
560 ogg->streams[i].codec && i == stream_index) {
561 pts = ogg_gptopts(s, i, ogg->streams[i].granule);
562 // FIXME: this is the position of the packet after the one with above
563 // pts.
564 *pos_arg = url_ftell(bc);
565 break;
566 }
567 }
568 ogg_reset(ogg);
569 return pts;
9146ca37 570}
9146ca37 571
2e70e4aa
MR
572static int ogg_probe(AVProbeData *p)
573{
2e70e4aa
MR
574 if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
575 p->buf[2] == 'g' && p->buf[3] == 'S' &&
576 p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
577 return AVPROBE_SCORE_MAX;
578 else
579 return 0;
580}
581
ff70e601 582AVInputFormat ogg_demuxer = {
9146ca37 583 "ogg",
bde15e74 584 NULL_IF_CONFIG_SMALL("Ogg"),
77be08ee 585 sizeof (struct ogg),
2e70e4aa 586 ogg_probe,
9146ca37
MR
587 ogg_read_header,
588 ogg_read_packet,
589 ogg_read_close,
ce3132be 590 NULL,
a1f29b95 591 ogg_read_timestamp,
9146ca37 592 .extensions = "ogg",
d7bb185f 593 .metadata_conv = ff_vorbiscomment_metadata_conv,
9146ca37 594};