ff000e7a799771a1e08d19c06bdf06953325c6ef
[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 = url_ftell (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 ByteIOContext *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 url_fseek (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 ByteIOContext *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 (get_buffer (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 = url_fgetc (bc);
222 if (c < 0)
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 (url_fgetc (bc) != 0) /* version */
233 return -1;
234
235 flags = url_fgetc (bc);
236 gp = get_le64 (bc);
237 serial = get_le32 (bc);
238 seq = get_le32 (bc);
239 crc = get_le32 (bc);
240 nsegs = url_fgetc (bc);
241
242 idx = ogg_find_stream (ogg, serial);
243 if (idx < 0){
244 idx = ogg_new_stream (s, serial);
245 if (idx < 0)
246 return -1;
247 }
248
249 os = ogg->streams + idx;
250 os->page_pos = url_ftell(bc) - 27;
251
252 if(os->psize > 0)
253 ogg_new_buf(ogg, idx);
254
255 if (get_buffer (bc, os->segments, nsegs) < nsegs)
256 return -1;
257
258 os->nsegs = nsegs;
259 os->segp = 0;
260
261 size = 0;
262 for (i = 0; i < nsegs; i++)
263 size += os->segments[i];
264
265 if (flags & OGG_FLAG_CONT || os->incomplete){
266 if (!os->psize){
267 while (os->segp < os->nsegs){
268 int seg = os->segments[os->segp++];
269 os->pstart += seg;
270 if (seg < 255)
271 break;
272 }
273 os->sync_pos = os->page_pos;
274 }
275 }else{
276 os->psize = 0;
277 os->sync_pos = os->page_pos;
278 }
279
280 if (os->bufsize - os->bufpos < size){
281 uint8_t *nb = av_malloc (os->bufsize *= 2);
282 memcpy (nb, os->buf, os->bufpos);
283 av_free (os->buf);
284 os->buf = nb;
285 }
286
287 if (get_buffer (bc, os->buf + os->bufpos, size) < size)
288 return -1;
289
290 os->bufpos += size;
291 os->granule = gp;
292 os->flags = flags;
293
294 if (str)
295 *str = idx;
296
297 return 0;
298 }
299
300 static int
301 ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpos)
302 {
303 struct ogg *ogg = s->priv_data;
304 int idx, i;
305 struct ogg_stream *os;
306 int complete = 0;
307 int segp = 0, psize = 0;
308
309 #if 0
310 av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
311 #endif
312
313 do{
314 idx = ogg->curidx;
315
316 while (idx < 0){
317 if (ogg_read_page (s, &idx) < 0)
318 return -1;
319 }
320
321 os = ogg->streams + idx;
322
323 #if 0
324 av_log (s, AV_LOG_DEBUG,
325 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
326 idx, os->pstart, os->psize, os->segp, os->nsegs);
327 #endif
328
329 if (!os->codec){
330 if (os->header < 0){
331 os->codec = ogg_find_codec (os->buf, os->bufpos);
332 if (!os->codec){
333 os->header = 0;
334 return 0;
335 }
336 }else{
337 return 0;
338 }
339 }
340
341 segp = os->segp;
342 psize = os->psize;
343
344 while (os->segp < os->nsegs){
345 int ss = os->segments[os->segp++];
346 os->psize += ss;
347 if (ss < 255){
348 complete = 1;
349 break;
350 }
351 }
352
353 if (!complete && os->segp == os->nsegs){
354 ogg->curidx = -1;
355 os->incomplete = 1;
356 }
357 }while (!complete);
358
359 #if 0
360 av_log (s, AV_LOG_DEBUG,
361 "ogg_packet: idx %i, frame size %i, start %i\n",
362 idx, os->psize, os->pstart);
363 #endif
364
365 ogg->curidx = idx;
366 os->incomplete = 0;
367
368 if (os->header) {
369 os->header = os->codec->header (s, idx);
370 if (!os->header){
371 os->segp = segp;
372 os->psize = psize;
373 if (!ogg->headers)
374 s->data_offset = os->sync_pos;
375 ogg->headers = 1;
376 }else{
377 os->pstart += os->psize;
378 os->psize = 0;
379 }
380 } else {
381 os->pflags = 0;
382 os->pduration = 0;
383 if (os->codec && os->codec->packet)
384 os->codec->packet (s, idx);
385 if (str)
386 *str = idx;
387 if (dstart)
388 *dstart = os->pstart;
389 if (dsize)
390 *dsize = os->psize;
391 if (fpos)
392 *fpos = os->sync_pos;
393 os->pstart += os->psize;
394 os->psize = 0;
395 os->sync_pos = os->page_pos;
396 }
397
398 // determine whether there are more complete packets in this page
399 // if not, the page's granule will apply to this packet
400 os->page_end = 1;
401 for (i = os->segp; i < os->nsegs; i++)
402 if (os->segments[i] < 255) {
403 os->page_end = 0;
404 break;
405 }
406
407 if (os->segp == os->nsegs)
408 ogg->curidx = -1;
409
410 return 0;
411 }
412
413 static int
414 ogg_get_headers (AVFormatContext * s)
415 {
416 struct ogg *ogg = s->priv_data;
417
418 do{
419 if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0)
420 return -1;
421 }while (!ogg->headers);
422
423 #if 0
424 av_log (s, AV_LOG_DEBUG, "found headers\n");
425 #endif
426
427 return 0;
428 }
429
430 static int
431 ogg_get_length (AVFormatContext * s)
432 {
433 struct ogg *ogg = s->priv_data;
434 int idx = -1, i;
435 int64_t size, end;
436
437 if(url_is_streamed(s->pb))
438 return 0;
439
440 // already set
441 if (s->duration != AV_NOPTS_VALUE)
442 return 0;
443
444 size = url_fsize(s->pb);
445 if(size < 0)
446 return 0;
447 end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0;
448
449 ogg_save (s);
450 url_fseek (s->pb, end, SEEK_SET);
451
452 while (!ogg_read_page (s, &i)){
453 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
454 ogg->streams[i].codec)
455 idx = i;
456 }
457
458 if (idx != -1){
459 s->streams[idx]->duration =
460 ogg_gptopts (s, idx, ogg->streams[idx].granule, NULL);
461 if (s->streams[idx]->start_time != AV_NOPTS_VALUE)
462 s->streams[idx]->duration -= s->streams[idx]->start_time;
463 }
464
465 ogg_restore (s, 0);
466
467 return 0;
468 }
469
470
471 static int
472 ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
473 {
474 struct ogg *ogg = s->priv_data;
475 int i;
476 ogg->curidx = -1;
477 //linear headers seek from start
478 if (ogg_get_headers (s) < 0){
479 return -1;
480 }
481
482 for (i = 0; i < ogg->nstreams; i++)
483 if (ogg->streams[i].header < 0)
484 ogg->streams[i].codec = NULL;
485
486 //linear granulepos seek from end
487 ogg_get_length (s);
488
489 //fill the extradata in the per codec callbacks
490 return 0;
491 }
492
493 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
494 {
495 struct ogg *ogg = s->priv_data;
496 struct ogg_stream *os = ogg->streams + idx;
497 int64_t pts = AV_NOPTS_VALUE;
498
499 if (dts)
500 *dts = AV_NOPTS_VALUE;
501
502 if (os->lastpts != AV_NOPTS_VALUE) {
503 pts = os->lastpts;
504 os->lastpts = AV_NOPTS_VALUE;
505 }
506 if (os->lastdts != AV_NOPTS_VALUE) {
507 if (dts)
508 *dts = os->lastdts;
509 os->lastdts = AV_NOPTS_VALUE;
510 }
511 if (os->page_end) {
512 if (os->granule != -1LL) {
513 if (os->codec && os->codec->granule_is_start)
514 pts = ogg_gptopts(s, idx, os->granule, dts);
515 else
516 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
517 os->granule = -1LL;
518 } else
519 av_log(s, AV_LOG_WARNING, "Packet is missing granule\n");
520 }
521 return pts;
522 }
523
524 static int
525 ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
526 {
527 struct ogg *ogg;
528 struct ogg_stream *os;
529 int idx = -1;
530 int pstart, psize;
531 int64_t fpos, pts, dts;
532
533 //Get an ogg packet
534 retry:
535 do{
536 if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0)
537 return AVERROR(EIO);
538 }while (idx < 0 || !s->streams[idx]);
539
540 ogg = s->priv_data;
541 os = ogg->streams + idx;
542
543 // pflags might not be set until after this
544 pts = ogg_calc_pts(s, idx, &dts);
545
546 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
547 goto retry;
548 os->keyframe_seek = 0;
549
550 //Alloc a pkt
551 if (av_new_packet (pkt, psize) < 0)
552 return AVERROR(EIO);
553 pkt->stream_index = idx;
554 memcpy (pkt->data, os->buf + pstart, psize);
555
556 pkt->pts = pts;
557 pkt->dts = dts;
558 pkt->flags = os->pflags;
559 pkt->duration = os->pduration;
560 pkt->pos = fpos;
561
562 return psize;
563 }
564
565
566 static int
567 ogg_read_close (AVFormatContext * s)
568 {
569 struct ogg *ogg = s->priv_data;
570 int i;
571
572 for (i = 0; i < ogg->nstreams; i++){
573 av_free (ogg->streams[i].buf);
574 av_free (ogg->streams[i].private);
575 }
576 av_free (ogg->streams);
577 return 0;
578 }
579
580
581 static int64_t
582 ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
583 int64_t pos_limit)
584 {
585 struct ogg *ogg = s->priv_data;
586 struct ogg_stream *os = ogg->streams + stream_index;
587 ByteIOContext *bc = s->pb;
588 int64_t pts = AV_NOPTS_VALUE;
589 int i;
590 url_fseek(bc, *pos_arg, SEEK_SET);
591 ogg_reset(ogg);
592
593 while (url_ftell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) {
594 if (i == stream_index) {
595 pts = ogg_calc_pts(s, i, NULL);
596 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
597 pts = AV_NOPTS_VALUE;
598 }
599 if (pts != AV_NOPTS_VALUE)
600 break;
601 }
602 ogg_reset(ogg);
603 return pts;
604 }
605
606 static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
607 {
608 struct ogg *ogg = s->priv_data;
609 struct ogg_stream *os = ogg->streams + stream_index;
610 int ret;
611
612 // Try seeking to a keyframe first. If this fails (very possible),
613 // av_seek_frame will fall back to ignoring keyframes
614 if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO
615 && !(flags & AVSEEK_FLAG_ANY))
616 os->keyframe_seek = 1;
617
618 ret = av_seek_frame_binary(s, stream_index, timestamp, flags);
619 if (ret < 0)
620 os->keyframe_seek = 0;
621 return ret;
622 }
623
624 static int ogg_probe(AVProbeData *p)
625 {
626 if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
627 p->buf[2] == 'g' && p->buf[3] == 'S' &&
628 p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
629 return AVPROBE_SCORE_MAX;
630 else
631 return 0;
632 }
633
634 AVInputFormat ogg_demuxer = {
635 "ogg",
636 NULL_IF_CONFIG_SMALL("Ogg"),
637 sizeof (struct ogg),
638 ogg_probe,
639 ogg_read_header,
640 ogg_read_packet,
641 ogg_read_close,
642 ogg_read_seek,
643 ogg_read_timestamp,
644 .extensions = "ogg",
645 .metadata_conv = ff_vorbiscomment_metadata_conv,
646 };