put_pixels16_l2_altivec and avg_pixels16_l2_altivec
[libav.git] / libavformat / ogg2.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>
34#include "ogg2.h"
35#include "avformat.h"
36
37#define MAX_PAGE_SIZE 65307
38#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
39
40static ogg_codec_t *ogg_codecs[] = {
41 &vorbis_codec,
1ed923ea 42 &theora_codec,
bcfc40ae 43 &flac_codec,
e1203ac0
MR
44 &ogm_video_codec,
45 &ogm_audio_codec,
46 &ogm_old_codec,
9146ca37
MR
47 NULL
48};
49
a9e35095 50#if 0 // CONFIG_MUXERS
9146ca37
MR
51static int
52ogg_write_header (AVFormatContext * avfcontext)
53{
54}
55
56static int
57ogg_write_packet (AVFormatContext * avfcontext, AVPacket * pkt)
58{
59}
60
61
62static int
63ogg_write_trailer (AVFormatContext * avfcontext)
64{
65}
66
67
68static 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};
a9e35095 80#endif //CONFIG_MUXERS
9146ca37
MR
81
82//FIXME We could avoid some structure duplication
83static int
84ogg_save (AVFormatContext * s)
85{
86 ogg_t *ogg = s->priv_data;
87 ogg_state_t *ost =
ad3aa874 88 av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams));
9146ca37
MR
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
107static int
108ogg_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
135static int
136ogg_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
156static ogg_codec_t *
2d2f443d 157ogg_find_codec (uint8_t * buf, int size)
9146ca37
MR
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
169static int
170ogg_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
181static int
182ogg_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->buf = av_malloc (os->bufsize);
197 memset (os->buf, 0, os->bufsize);
198 os->header = -1;
199
200 st = av_new_stream (s, idx);
201 if (!st)
202 return AVERROR_NOMEM;
203
204 av_set_pts_info(st, 64, 1, 1000000);
205 st->start_time = 0;
206
207 return idx;
208}
209
210static int
211ogg_read_page (AVFormatContext * s, int *str)
212{
213 ByteIOContext *bc = &s->pb;
214 ogg_t *ogg = s->priv_data;
215 ogg_stream_t *os;
216 int i = 0;
217 int flags, nsegs;
218 uint64_t gp;
219 uint32_t serial;
220 uint32_t seq;
221 uint32_t crc;
222 int size, idx;
223 char sync[4];
224 int sp = 0;
225
226 if (get_buffer (bc, sync, 4) < 4)
227 return -1;
228
229 do{
230 int c;
231
232 if (sync[sp & 3] == 'O' &&
233 sync[(sp + 1) & 3] == 'g' &&
234 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
235 break;
236
237 c = url_fgetc (bc);
238 if (c < 0)
239 return -1;
240 sync[sp++ & 3] = c;
241 }while (i++ < MAX_PAGE_SIZE);
242
243 if (i >= MAX_PAGE_SIZE){
244 av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n");
245 return -1;
246 }
247
248 if (url_fgetc (bc) != 0) /* version */
249 return -1;
250
251 flags = url_fgetc (bc);
252 gp = get_le64 (bc);
253 serial = get_le32 (bc);
254 seq = get_le32 (bc);
255 crc = get_le32 (bc);
256 nsegs = url_fgetc (bc);
257
258 idx = ogg_find_stream (ogg, serial);
259 if (idx < 0){
260 idx = ogg_new_stream (s, serial);
261 if (idx < 0)
262 return -1;
263 }
264
265 os = ogg->streams + idx;
266
267 if (get_buffer (bc, os->segments, nsegs) < nsegs)
268 return -1;
269
270 os->nsegs = nsegs;
271 os->segp = 0;
272
273 size = 0;
274 for (i = 0; i < nsegs; i++)
275 size += os->segments[i];
276
277 if (flags & OGG_FLAG_CONT){
278 if (!os->psize){
279 while (os->segp < os->nsegs){
280 int seg = os->segments[os->segp++];
281 os->pstart += seg;
282 if (seg < 255)
283 break;
284 }
285 }
286 }else{
287 os->psize = 0;
288 }
289
290 if (os->bufsize - os->bufpos < size){
2d2f443d 291 uint8_t *nb = av_malloc (os->bufsize *= 2);
9146ca37
MR
292 memset (nb, 0, os->bufsize);
293 memcpy (nb, os->buf, os->bufpos);
294 av_free (os->buf);
295 os->buf = nb;
296 }
297
298 if (get_buffer (bc, os->buf + os->bufpos, size) < size)
299 return -1;
300
301 os->lastgp = os->granule;
302 os->bufpos += size;
303 os->granule = gp;
304 os->flags = flags;
305
306 if (str)
307 *str = idx;
308
309 return 0;
310}
311
312static int
313ogg_packet (AVFormatContext * s, int *str)
314{
315 ogg_t *ogg = s->priv_data;
316 int idx;
317 ogg_stream_t *os;
318 int complete = 0;
319 int segp = 0, psize = 0;
320
321#if 0
322 av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx);
323#endif
324
325 do{
326 idx = ogg->curidx;
327
328 while (idx < 0){
329 if (ogg_read_page (s, &idx) < 0)
330 return -1;
331 }
332
333 os = ogg->streams + idx;
334
335#if 0
336 av_log (s, AV_LOG_DEBUG,
337 "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
338 idx, os->pstart, os->psize, os->segp, os->nsegs);
339#endif
340
341 if (!os->codec){
342 if (os->header < 0){
343 os->codec = ogg_find_codec (os->buf, os->bufpos);
344 if (!os->codec){
345 os->header = 0;
346 return 0;
347 }
348 }else{
349 return 0;
350 }
351 }
352
353 segp = os->segp;
354 psize = os->psize;
355
356 while (os->segp < os->nsegs){
357 int ss = os->segments[os->segp++];
358 os->psize += ss;
359 if (ss < 255){
360 complete = 1;
361 break;
362 }
363 }
364
365 if (!complete && os->segp == os->nsegs){
2d2f443d 366 uint8_t *nb = av_malloc (os->bufsize);
9146ca37
MR
367 int size = os->bufpos - os->pstart;
368 memset (nb, 0, os->bufsize);
369 memcpy (nb, os->buf + os->pstart, size);
370 av_free (os->buf);
371 os->buf = nb;
372 os->bufpos = size;
373 os->pstart = 0;
374 ogg->curidx = -1;
375 }
376 }while (!complete);
377
378#if 0
379 av_log (s, AV_LOG_DEBUG,
380 "ogg_packet: idx %i, frame size %i, start %i\n",
381 idx, os->psize, os->pstart);
382#endif
383
384 ogg->curidx = idx;
385
386 if (os->header < 0){
387 int hdr = os->codec->header (s, idx);
388 if (!hdr){
389 os->header = os->seq;
390 os->segp = segp;
391 os->psize = psize;
392 ogg->headers = 1;
393 }else{
394 os->pstart += os->psize;
395 os->psize = 0;
396 }
397 }
398
399 if (os->header > -1 && os->seq > os->header){
400 if (os->codec && os->codec->packet)
401 os->codec->packet (s, idx);
402 if (str)
403 *str = idx;
404 }
405
406 os->seq++;
407 if (os->segp == os->nsegs)
408 ogg->curidx = -1;
409
410 return 0;
411}
412
413static int
414ogg_get_headers (AVFormatContext * s)
415{
416 ogg_t *ogg = s->priv_data;
417
418 do{
419 if (ogg_packet (s, 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
430static uint64_t
431ogg_gptopts (AVFormatContext * s, int i, uint64_t gp)
432{
1ed923ea
MR
433 ogg_t *ogg = s->priv_data;
434 ogg_stream_t *os = ogg->streams + i;
9146ca37
MR
435 uint64_t pts = AV_NOPTS_VALUE;
436
1ed923ea 437 if(os->codec->gptopts){
bb270c08 438 pts = os->codec->gptopts(s, i, gp);
3644cb8f 439 } else {
1ed923ea 440 pts = gp;
9146ca37
MR
441 }
442
443 return pts;
444}
445
446
447static int
448ogg_get_length (AVFormatContext * s)
449{
450 ogg_t *ogg = s->priv_data;
9146ca37 451 int idx = -1, i;
69599eea
MR
452
453 if(s->pb.is_streamed)
454 return 0;
9146ca37
MR
455
456// already set
457 if (s->duration != AV_NOPTS_VALUE)
458 return 0;
459
460 ogg_save (s);
a965c478 461 url_fseek (&s->pb, -MAX_PAGE_SIZE, SEEK_END);
9146ca37
MR
462
463 while (!ogg_read_page (s, &i)){
464 if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0)
465 idx = i;
466 }
467
468 if (idx != -1){
469 s->streams[idx]->duration =
470 ogg_gptopts (s, idx, ogg->streams[idx].granule);
471 }
472
a965c478 473 ogg->size = url_fsize(&s->pb);
9146ca37
MR
474 ogg_restore (s, 0);
475
476 return 0;
477}
478
479
480static int
481ogg_read_header (AVFormatContext * s, AVFormatParameters * ap)
482{
483 ogg_t *ogg = s->priv_data;
484 ogg->curidx = -1;
485 //linear headers seek from start
486 if (ogg_get_headers (s) < 0){
487 return -1;
488 }
489
490 //linear granulepos seek from end
491 ogg_get_length (s);
492
493 //fill the extradata in the per codec callbacks
494 return 0;
495}
496
497
498static int
499ogg_read_packet (AVFormatContext * s, AVPacket * pkt)
500{
501 ogg_t *ogg;
502 ogg_stream_t *os;
503 int idx = -1;
504
115329f1 505 //Get an ogg packet
9146ca37
MR
506 do{
507 if (ogg_packet (s, &idx) < 0)
508 return AVERROR_IO;
509 }while (idx < 0 || !s->streams[idx]);
510
511 ogg = s->priv_data;
512 os = ogg->streams + idx;
513
514 //Alloc a pkt
515 if (av_new_packet (pkt, os->psize) < 0)
516 return AVERROR_IO;
517 pkt->stream_index = idx;
518 memcpy (pkt->data, os->buf + os->pstart, os->psize);
519 if (os->lastgp != -1LL){
520 pkt->pts = ogg_gptopts (s, idx, os->lastgp);
521 os->lastgp = -1;
522 }
523 //next
524 os->pstart += os->psize;
525 os->psize = 0;
526 return os->psize;
527}
528
529
530static int
531ogg_read_close (AVFormatContext * s)
532{
533 ogg_t *ogg = s->priv_data;
534 int i;
535
536 for (i = 0; i < ogg->nstreams; i++){
537 av_free (ogg->streams[i].buf);
1ed923ea 538 av_free (ogg->streams[i].private);
01f4895c 539 av_freep (&s->streams[i]->codec->extradata);
9146ca37
MR
540 }
541 av_free (ogg->streams);
542 return 0;
543}
544
545
546static int
547ogg_read_seek (AVFormatContext * s, int stream_index, int64_t target_ts,
548 int flags)
549{
550 ogg_t *ogg = s->priv_data;
551 ByteIOContext *bc = &s->pb;
552 uint64_t min = 0, max = ogg->size;
553 uint64_t tmin = 0, tmax = s->duration;
554 int64_t pts = AV_NOPTS_VALUE;
555
556 ogg_save (s);
557
558 while (min <= max){
17929c04 559 uint64_t p = min + (max - min) * (target_ts - tmin) / (tmax - tmin);
9146ca37
MR
560 int i = -1;
561
562 url_fseek (bc, p, SEEK_SET);
563
564 while (!ogg_read_page (s, &i)){
565 if (ogg->streams[i].granule != 0 && ogg->streams[i].granule != -1)
566 break;
567 }
568
569 if (i == -1)
570 break;
571
572 pts = ogg_gptopts (s, i, ogg->streams[i].granule);
573 p = url_ftell (bc);
574
575 if (ABS (pts - target_ts) < 1000000LL)
576 break;
577
578 if (pts > target_ts){
579 max = p;
580 tmax = pts;
581 }else{
582 min = p;
583 tmin = pts;
584 }
585 }
586
587 if (ABS (pts - target_ts) < 1000000LL){
588 ogg_restore (s, 1);
589 ogg_reset (ogg);
590 }else{
591 ogg_restore (s, 0);
592 pts = AV_NOPTS_VALUE;
593 }
594
595 return pts;
596
597#if 0
598 //later...
599 int64_t pos;
600 if (av_seek_frame_binary (s, stream_index, target_ts, flags) < 0)
601 return -1;
602 pos = url_ftell (&s->pb);
603 ogg_read_timestamp (s, stream_index, &pos, pos - 1);
604#endif
605
606}
607
608#if 0
609static int64_t
610ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg,
611 int64_t pos_limit)
612{
613 ogg_t *ogg = s->priv_data;
614 ByteIOContext *bc = &s->pb;
615 int64_t pos, pts;
616
617 if (*pos_arg < 0)
618 return AV_NOPTS_VALUE;
619
620 pos = *pos_arg;
621}
622#endif
623
2e70e4aa
MR
624static int ogg_probe(AVProbeData *p)
625{
626 if (p->buf_size < 6)
627 return 0;
628 if (p->buf[0] == 'O' && p->buf[1] == 'g' &&
629 p->buf[2] == 'g' && p->buf[3] == 'S' &&
630 p->buf[4] == 0x0 && p->buf[5] <= 0x7 )
631 return AVPROBE_SCORE_MAX;
632 else
633 return 0;
634}
635
9146ca37
MR
636static AVInputFormat ogg_iformat = {
637 "ogg",
638 "Ogg",
639 sizeof (ogg_t),
2e70e4aa 640 ogg_probe,
9146ca37
MR
641 ogg_read_header,
642 ogg_read_packet,
643 ogg_read_close,
644 ogg_read_seek,
115329f1 645// ogg_read_timestamp,
9146ca37
MR
646 .extensions = "ogg",
647};
648
649int
650ogg_init (void)
651{
a9e35095 652#if 0 // CONFIG_MUXERS
9146ca37
MR
653 av_register_output_format (&ogg_oformat);
654#endif
655 av_register_input_format (&ogg_iformat);
656 return 0;
657}