lcd-m6sp.c: remove \r
[kugel-rb.git] / apps / codecs / libtremor / vorbisfile.c
blob1e0336603c7ba6460372e2ad3d8162e203c1f73c
1 /********************************************************************
2 * *
3 * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
4 * *
5 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
6 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * *
9 * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2003 *
10 * BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
11 * *
12 ********************************************************************
14 function: stdio-based convenience library for opening/seeking/decoding
15 last mod: $Id$
17 ********************************************************************/
19 #include "config-tremor.h"
20 #include <stdio.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <math.h>
24 #include "system.h"
26 #include "ivorbiscodec.h"
27 #include "ivorbisfile.h"
29 #include "os.h"
30 #include "misc.h"
32 /* A 'chained bitstream' is a Vorbis bitstream that contains more than
33 one logical bitstream arranged end to end (the only form of Ogg
34 multiplexing allowed in a Vorbis bitstream; grouping [parallel
35 multiplexing] is not allowed in Vorbis) */
37 /* A Vorbis file can be played beginning to end (streamed) without
38 worrying ahead of time about chaining (see decoder_example.c). If
39 we have the whole file, however, and want random access
40 (seeking/scrubbing) or desire to know the total length/time of a
41 file, we need to account for the possibility of chaining. */
43 /* We can handle things a number of ways; we can determine the entire
44 bitstream structure right off the bat, or find pieces on demand.
45 This example determines and caches structure for the entire
46 bitstream, but builds a virtual decoder on the fly when moving
47 between links in the chain. */
49 /* There are also different ways to implement seeking. Enough
50 information exists in an Ogg bitstream to seek to
51 sample-granularity positions in the output. Or, one can seek by
52 picking some portion of the stream roughly in the desired area if
53 we only want coarse navigation through the stream. */
55 /*************************************************************************
56 * Many, many internal helpers. The intention is not to be confusing;
57 * rampant duplication and monolithic function implementation would be
58 * harder to understand anyway. The high level functions are last. Begin
59 * grokking near the end of the file */
62 /* read a little more data from the file/pipe into the ogg_sync framer */
63 static long _get_data(OggVorbis_File *vf){
64 if(vf->datasource){
65 char *buffer=(char *)ogg_sync_bufferin(vf->oy,CHUNKSIZE);
66 long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource);
67 if(bytes>0)ogg_sync_wrote(vf->oy,bytes);
68 return(bytes);
69 }else
70 return(0);
73 /* save a tiny smidge of verbosity to make the code more readable */
74 static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
75 if(vf->datasource){
76 if(!(vf->callbacks.seek_func)||
77 (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1)
78 return OV_EREAD;
79 vf->offset=offset;
80 ogg_sync_reset(vf->oy);
81 }else{
82 /* shouldn't happen unless someone writes a broken callback */
83 return OV_EFAULT;
85 return 0;
88 /* The read/seek functions track absolute position within the stream */
90 /* from the head of the stream, get the next page. boundary specifies
91 if the function is allowed to fetch more data from the stream (and
92 how much) or only use internally buffered data.
94 boundary: -1) unbounded search
95 0) read no additional data; use cached only
96 n) search for a new page beginning for n bytes
98 return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
99 n) found a page at absolute offset n
101 produces a refcounted page */
103 static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
104 ogg_int64_t boundary){
105 if(boundary>0)boundary+=vf->offset;
106 while(1){
107 long more;
109 if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
110 more=ogg_sync_pageseek(vf->oy,og);
112 if(more<0){
113 /* skipped n bytes */
114 vf->offset-=more;
115 }else{
116 if(more==0){
117 /* send more paramedics */
118 if(!boundary)return(OV_FALSE);
120 long ret=_get_data(vf);
121 if(ret==0)return(OV_EOF);
122 if(ret<0)return(OV_EREAD);
124 }else{
125 /* got a page. Return the offset at the page beginning,
126 advance the internal offset past the page end */
127 ogg_int64_t ret=vf->offset;
128 vf->offset+=more;
129 return(ret);
136 /* find the latest page beginning before the current stream cursor
137 position. Much dirtier than the above as Ogg doesn't have any
138 backward search linkage. no 'readp' as it will certainly have to
139 read. */
140 /* returns offset or OV_EREAD, OV_FAULT and produces a refcounted page */
142 static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
143 ogg_int64_t begin=vf->offset;
144 ogg_int64_t end=begin;
145 ogg_int64_t ret;
146 ogg_int64_t offset=-1;
148 while(offset==-1){
149 begin-=CHUNKSIZE;
150 if(begin<0)
151 begin=0;
153 ret=_seek_helper(vf,begin);
154 if(ret)return(ret);
156 while(vf->offset<end){
157 ret=_get_next_page(vf,og,end-vf->offset);
158 if(ret==OV_EREAD)return(OV_EREAD);
159 if(ret<0){
160 break;
161 }else{
162 offset=ret;
167 /* In a fully compliant, non-multiplexed stream, we'll still be
168 holding the last page. In multiplexed (or noncompliant streams),
169 we will probably have to re-read the last page we saw */
170 if(og->header_len==0){
171 ogg_page_release(og);
172 ret=_seek_helper(vf,offset);
173 if(ret)return(ret);
175 ret=_get_next_page(vf,og,CHUNKSIZE);
176 if(ret<0)
177 /* this shouldn't be possible */
178 return(OV_EFAULT);
181 return(offset);
184 static void _add_serialno(ogg_page *og,ogg_uint32_t **serialno_list, int *n){
185 long s = ogg_page_serialno(og);
186 (*n)++;
188 if(*serialno_list){
189 *serialno_list = _ogg_realloc(*serialno_list, sizeof(**serialno_list)*(*n));
190 }else{
191 *serialno_list = _ogg_malloc(sizeof(**serialno_list));
194 (*serialno_list)[(*n)-1] = s;
197 /* returns nonzero if found */
198 static int _lookup_serialno(long s, ogg_uint32_t *serialno_list, int n){
199 if(serialno_list){
200 while(n--){
201 if(*serialno_list == (ogg_uint32_t) s) return 1;
202 serialno_list++;
205 return 0;
208 static int _lookup_page_serialno(ogg_page *og, ogg_uint32_t *serialno_list, int n){
209 long s = ogg_page_serialno(og);
210 return _lookup_serialno(s,serialno_list,n);
213 /* performs the same search as _get_prev_page, but prefers pages of
214 the specified serial number. If a page of the specified serialno is
215 spotted during the seek-back-and-read-forward, it will return the
216 info of last page of the matching serial number instead of the very
217 last page. If no page of the specified serialno is seen, it will
218 return the info of last page and alter *serialno. */
219 static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf,
220 ogg_uint32_t *serial_list, int serial_n,
221 int *serialno, ogg_int64_t *granpos){
222 ogg_page og={0,0,0,0};
223 ogg_int64_t begin=vf->offset;
224 ogg_int64_t end=begin;
225 ogg_int64_t ret;
227 ogg_int64_t prefoffset=-1;
228 ogg_int64_t offset=-1;
229 ogg_uint32_t ret_serialno=-1;
230 ogg_int64_t ret_gran=-1;
232 while(offset==-1){
233 begin-=CHUNKSIZE;
234 if(begin<0)
235 begin=0;
237 ret=_seek_helper(vf,begin);
238 if(ret)return(ret);
240 while(vf->offset<end){
241 ret=_get_next_page(vf,&og,end-vf->offset);
242 if(ret==OV_EREAD)return(OV_EREAD);
243 if(ret<0){
244 ogg_page_release(&og);
245 break;
246 }else{
247 ret_serialno=ogg_page_serialno(&og);
248 ret_gran=ogg_page_granulepos(&og);
249 offset=ret;
250 ogg_page_release(&og);
252 if(ret_serialno == (ogg_uint32_t) *serialno){
253 prefoffset=ret;
254 *granpos=ret_gran;
257 if(!_lookup_serialno(ret_serialno,serial_list,serial_n)){
258 /* we fell off the end of the link, which means we seeked
259 back too far and shouldn't have been looking in that link
260 to begin with. If we found the preferred serial number,
261 forget that we saw it. */
262 prefoffset=-1;
268 /* we're not interested in the page... just the serialno and granpos. */
269 if(prefoffset>=0)return(prefoffset);
271 *serialno = ret_serialno;
272 *granpos = ret_gran;
273 return(offset);
277 /* uses the local ogg_stream storage in vf; this is important for
278 non-streaming input sources */
279 /* consumes the page that's passed in (if any) */
281 static int _fetch_headers(OggVorbis_File *vf,
282 vorbis_info *vi,
283 vorbis_comment *vc,
284 ogg_uint32_t **serialno_list,
285 int *serialno_n,
286 ogg_page *og_ptr){
287 ogg_page og={0,0,0,0};
288 ogg_packet op={0,0,0,0,0,0};
289 int i,ret;
290 int allbos=0;
292 if(!og_ptr){
293 ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
294 if(llret==OV_EREAD)return(OV_EREAD);
295 if(llret<0)return OV_ENOTVORBIS;
296 og_ptr=&og;
299 vorbis_info_init(vi);
300 vorbis_comment_init(vc);
301 vf->ready_state=OPENED;
303 /* extract the serialnos of all BOS pages + the first set of vorbis
304 headers we see in the link */
306 while(ogg_page_bos(og_ptr)){
307 if(serialno_list){
308 if(_lookup_page_serialno(og_ptr,*serialno_list,*serialno_n)){
309 /* a dupe serialnumber in an initial header packet set == invalid stream */
310 if(*serialno_list)_ogg_free(*serialno_list);
311 *serialno_list=0;
312 *serialno_n=0;
313 ret=OV_EBADHEADER;
314 goto bail_header;
317 _add_serialno(og_ptr,serialno_list,serialno_n);
320 if(vf->ready_state<STREAMSET){
321 /* we don't have a vorbis stream in this link yet, so begin
322 prospective stream setup. We need a stream to get packets */
323 ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr));
324 ogg_stream_pagein(vf->os,og_ptr);
326 if(ogg_stream_packetout(vf->os,&op) > 0 &&
327 vorbis_synthesis_idheader(&op)){
328 /* vorbis header; continue setup */
329 vf->ready_state=STREAMSET;
330 if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
331 ret=OV_EBADHEADER;
332 goto bail_header;
337 /* get next page */
339 ogg_int64_t llret=_get_next_page(vf,og_ptr,CHUNKSIZE);
340 if(llret==OV_EREAD){
341 ret=OV_EREAD;
342 goto bail_header;
344 if(llret<0){
345 ret=OV_ENOTVORBIS;
346 goto bail_header;
349 /* if this page also belongs to our vorbis stream, submit it and break */
350 if(vf->ready_state==STREAMSET &&
351 (ogg_uint32_t) vf->os->serialno == ogg_page_serialno(og_ptr)){
352 ogg_stream_pagein(vf->os,og_ptr);
353 break;
358 if(vf->ready_state!=STREAMSET){
359 ret = OV_ENOTVORBIS;
360 goto bail_header;
363 while(1){
365 i=0;
366 while(i<2){ /* get a page loop */
368 while(i<2){ /* get a packet loop */
370 int result=ogg_stream_packetout(vf->os,&op);
371 if(result==0)break;
372 if(result==-1){
373 ret=OV_EBADHEADER;
374 goto bail_header;
377 if((ret=vorbis_synthesis_headerin(vi,vc,&op)))
378 goto bail_header;
380 i++;
383 while(i<2){
384 if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
385 ret=OV_EBADHEADER;
386 goto bail_header;
389 /* if this page belongs to the correct stream, go parse it */
390 if((ogg_uint32_t) vf->os->serialno == ogg_page_serialno(og_ptr)){
391 ogg_stream_pagein(vf->os,og_ptr);
392 break;
395 /* if we never see the final vorbis headers before the link
396 ends, abort */
397 if(ogg_page_bos(og_ptr)){
398 if(allbos){
399 ret = OV_EBADHEADER;
400 goto bail_header;
401 }else
402 allbos=1;
405 /* otherwise, keep looking */
409 ogg_packet_release(&op);
410 ogg_page_release(&og);
412 return 0;
415 bail_header:
416 ogg_packet_release(&op);
417 ogg_page_release(&og);
418 vorbis_info_clear(vi);
419 vorbis_comment_clear(vc);
420 vf->ready_state=OPENED;
422 return ret;
425 /* Starting from current cursor position, get initial PCM offset of
426 next page. Consumes the page in the process without decoding
427 audio, however this is only called during stream parsing upon
428 seekable open. */
429 static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
430 ogg_page og={0,0,0,0};
431 ogg_int64_t accumulated=0,pos;
432 long lastblock=-1;
433 int result;
434 int serialno = vf->os->serialno;
436 while(1){
437 ogg_packet op={0,0,0,0,0,0};
439 if(_get_next_page(vf,&og,-1)<0)
440 break; /* should not be possible unless the file is truncated/mangled */
442 if(ogg_page_bos(&og)) break;
443 if(ogg_page_serialno(&og)!=(ogg_uint32_t) serialno) continue;
444 pos=ogg_page_granulepos(&og);
446 /* count blocksizes of all frames in the page */
447 ogg_stream_pagein(vf->os,&og);
448 while((result=ogg_stream_packetout(vf->os,&op))){
449 if(result>0){ /* ignore holes */
450 long thisblock=vorbis_packet_blocksize(vi,&op);
451 if(lastblock!=-1)
452 accumulated+=(lastblock+thisblock)>>2;
453 lastblock=thisblock;
456 ogg_packet_release(&op);
458 if(pos!=-1){
459 /* pcm offset of last packet on the first audio page */
460 accumulated= pos-accumulated;
461 break;
465 /* less than zero? This is a stream with samples trimmed off
466 the beginning, a normal occurrence; set the offset to zero */
467 if(accumulated<0)accumulated=0;
469 ogg_page_release(&og);
470 return accumulated;
474 /* finds each bitstream link one at a time using a bisection search
475 (has to begin by knowing the offset of the lb's initial page).
476 Recurses for each link so it can alloc the link storage after
477 finding them all, then unroll and fill the cache at the same time */
478 static int _bisect_forward_serialno(OggVorbis_File *vf,
479 ogg_int64_t begin,
480 ogg_int64_t searched,
481 ogg_int64_t end,
482 ogg_int64_t endgran,
483 int endserial,
484 ogg_uint32_t *currentno_list,
485 int currentnos,
486 long m){
488 ogg_int64_t pcmoffset;
489 ogg_int64_t dataoffset=searched;
490 ogg_int64_t endsearched=end;
491 ogg_int64_t next=end;
492 ogg_int64_t searchgran=-1;
493 ogg_int64_t ret,last;
494 int serialno = vf->os->serialno;
496 /* invariants:
497 we have the headers and serialnos for the link beginning at 'begin'
498 we have the offset and granpos of the last page in the file (potentially
499 not a page we care about)
502 /* Is the last page in our list of current serialnumbers? */
503 if(_lookup_serialno(endserial,currentno_list,currentnos)){
505 /* last page is in the starting serialno list, so we've bisected
506 down to (or just started with) a single link. Now we need to
507 find the last vorbis page belonging to the first vorbis stream
508 for this link. */
510 while(endserial != serialno){
511 endserial = serialno;
512 vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&endserial,&endgran);
515 vf->links=m+1;
516 if(vf->offsets)_ogg_free(vf->offsets);
517 if(vf->serialnos)_ogg_free(vf->serialnos);
518 if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
520 vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
521 vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
522 vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
523 vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
524 vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
525 vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
527 vf->offsets[m+1]=end;
528 vf->offsets[m]=begin;
529 vf->pcmlengths[m*2+1]=endgran;
531 }else{
533 ogg_uint32_t *next_serialno_list=NULL;
534 int next_serialnos=0;
535 vorbis_info vi;
536 vorbis_comment vc;
538 /* the below guards against garbage seperating the last and
539 first pages of two links. */
540 while(searched<endsearched){
541 ogg_page og={0,0,0,0};
542 ogg_int64_t bisect;
544 if(endsearched-searched<CHUNKSIZE){
545 bisect=searched;
546 }else{
547 bisect=(searched+endsearched)/2;
550 ret=_seek_helper(vf,bisect);
551 if(ret)return(ret);
553 last=_get_next_page(vf,&og,-1);
554 if(last==OV_EREAD)return(OV_EREAD);
555 if(last<0 || !_lookup_page_serialno(&og,currentno_list,currentnos)){
556 endsearched=bisect;
557 if(last>=0)next=last;
558 }else{
559 searched=last+og.header_len+og.body_len;
561 ogg_page_release(&og);
564 /* Bisection point found */
566 /* for the time being, fetch end PCM offset the simple way */
568 int testserial = serialno+1;
569 vf->offset = next;
570 while(testserial != serialno){
571 testserial = serialno;
572 vf->offset=_get_prev_page_serial(vf,currentno_list,currentnos,&testserial,&searchgran);
576 if(vf->offset!=next){
577 ret=_seek_helper(vf,next);
578 if(ret)return(ret);
581 ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL);
582 if(ret)return(ret);
583 serialno = vf->os->serialno;
584 dataoffset = vf->offset;
586 /* this will consume a page, however the next bistection always
587 starts with a raw seek */
588 pcmoffset = _initial_pcmoffset(vf,&vi);
590 ret=_bisect_forward_serialno(vf,next,vf->offset,end,endgran,endserial,
591 next_serialno_list,next_serialnos,m+1);
592 if(ret)return(ret);
594 if(next_serialno_list)_ogg_free(next_serialno_list);
596 vf->offsets[m+1]=next;
597 vf->serialnos[m+1]=serialno;
598 vf->dataoffsets[m+1]=dataoffset;
600 vf->vi[m+1]=vi;
601 vf->vc[m+1]=vc;
603 vf->pcmlengths[m*2+1]=searchgran;
604 vf->pcmlengths[m*2+2]=pcmoffset;
605 vf->pcmlengths[m*2+3]-=pcmoffset;
608 return(0);
611 static int _make_decode_ready(OggVorbis_File *vf){
612 if(vf->ready_state>STREAMSET)return 0;
613 if(vf->ready_state<STREAMSET)return OV_EFAULT;
614 if(vf->seekable){
615 if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link))
616 return OV_EBADLINK;
617 }else{
618 if(vorbis_synthesis_init(&vf->vd,vf->vi))
619 return OV_EBADLINK;
621 vorbis_block_init(&vf->vd,&vf->vb);
622 vf->ready_state=INITSET;
623 vf->bittrack=0;
624 vf->samptrack=0;
625 return 0;
628 static int _open_seekable2(OggVorbis_File *vf){
629 ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1;
630 int endserial=vf->os->serialno;
631 int serialno=vf->os->serialno;
633 /* we're partially open and have a first link header state in
634 storage in vf */
636 /* fetch initial PCM offset */
637 ogg_int64_t pcmoffset = _initial_pcmoffset(vf,vf->vi);
639 /* we can seek, so set out learning all about this file */
640 if(vf->callbacks.seek_func && vf->callbacks.tell_func){
641 (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
642 vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
643 }else{
644 vf->offset=vf->end=-1;
647 /* If seek_func is implemented, tell_func must also be implemented */
648 if(vf->end==-1) return(OV_EINVAL);
650 /* Get the offset of the last page of the physical bitstream, or, if
651 we're lucky the last vorbis page of this link as most OggVorbis
652 files will contain a single logical bitstream */
653 end=_get_prev_page_serial(vf,vf->serialnos+2,vf->serialnos[1],&endserial,&endgran);
654 if(end<0)return(end);
656 /* now determine bitstream structure recursively */
657 if(_bisect_forward_serialno(vf,0,dataoffset,vf->offset,endgran,endserial,
658 vf->serialnos+2,vf->serialnos[1],0)<0)return(OV_EREAD);
660 vf->offsets[0]=0;
661 vf->serialnos[0]=serialno;
662 vf->dataoffsets[0]=dataoffset;
663 vf->pcmlengths[0]=pcmoffset;
664 vf->pcmlengths[1]-=pcmoffset;
666 return(ov_raw_seek(vf,dataoffset));
669 /* clear out the current logical bitstream decoder */
670 static void _decode_clear(OggVorbis_File *vf){
671 vorbis_dsp_clear(&vf->vd);
672 vorbis_block_clear(&vf->vb);
673 vf->ready_state=OPENED;
676 /* fetch and process a packet. Handles the case where we're at a
677 bitstream boundary and dumps the decoding machine. If the decoding
678 machine is unloaded, it loads it. It also keeps pcm_offset up to
679 date (seek and read both use this. seek uses a special hack with
680 readp).
682 return: <0) error, OV_HOLE (lost packet) or OV_EOF
683 0) need more data (only if readp==0)
684 1) got a packet
687 STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
688 int readp,
689 int spanp) ICODE_ATTR_TREMOR_NOT_MDCT;
690 STATICIRAM_NOT_MDCT int _fetch_and_process_packet(OggVorbis_File *vf,
691 int readp,
692 int spanp){
693 ogg_page og={0,0,0,0};
694 ogg_packet op={0,0,0,0,0,0};
695 int ret=0;
697 /* handle one packet. Try to fetch it from current stream state */
698 /* extract packets from page */
699 while(1){
701 if(vf->ready_state==STREAMSET){
702 ret=_make_decode_ready(vf);
703 if(ret<0) goto cleanup;
706 /* process a packet if we can. If the machine isn't loaded,
707 neither is a page */
708 if(vf->ready_state==INITSET){
709 while(1) {
710 int result=ogg_stream_packetout(vf->os,&op);
711 ogg_int64_t granulepos;
713 if(result==-1){
714 ret=OV_HOLE; /* hole in the data. */
715 goto cleanup;
717 if(result>0){
718 /* got a packet. process it */
719 granulepos=op.granulepos;
720 if(!vorbis_synthesis(&vf->vb,&op,1)){ /* lazy check for lazy
721 header handling. The
722 header packets aren't
723 audio, so if/when we
724 submit them,
725 vorbis_synthesis will
726 reject them */
728 /* suck in the synthesis data and track bitrate */
730 int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
731 /* for proper use of libvorbis within libvorbisfile,
732 oldsamples will always be zero. */
733 if(oldsamples){
734 ret=OV_EFAULT;
735 goto cleanup;
738 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
739 vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
740 vf->bittrack+=op.bytes*8;
743 /* update the pcm offset. */
744 if(granulepos!=-1 && !op.e_o_s){
745 int link=(vf->seekable?vf->current_link:0);
746 int i,samples;
748 /* this packet has a pcm_offset on it (the last packet
749 completed on a page carries the offset) After processing
750 (above), we know the pcm position of the *last* sample
751 ready to be returned. Find the offset of the *first*
753 As an aside, this trick is inaccurate if we begin
754 reading anew right at the last page; the end-of-stream
755 granulepos declares the last frame in the stream, and the
756 last packet of the last page may be a partial frame.
757 So, we need a previous granulepos from an in-sequence page
758 to have a reference point. Thus the !op.e_o_s clause
759 above */
761 if(vf->seekable && link>0)
762 granulepos-=vf->pcmlengths[link*2];
763 if(granulepos<0)granulepos=0; /* actually, this
764 shouldn't be possible
765 here unless the stream
766 is very broken */
768 samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
770 granulepos-=samples;
771 for(i=0;i<link;i++)
772 granulepos+=vf->pcmlengths[i*2+1];
773 vf->pcm_offset=granulepos;
775 ret=1;
776 goto cleanup;
779 else
780 break;
784 if(vf->ready_state>=OPENED){
785 ogg_int64_t lret;
787 while(1){
788 /* the loop is not strictly necessary, but there's no sense in
789 doing the extra checks of the larger loop for the common
790 case in a multiplexed bistream where the page is simply
791 part of a different logical bitstream; keep reading until
792 we get one with the correct serialno */
794 if(!readp){
795 ret=0;
796 goto cleanup;
798 if((lret=_get_next_page(vf,&og,-1))<0){
799 ret=OV_EOF; /* eof. leave unitialized */
800 goto cleanup;
803 /* bitrate tracking; add the header's bytes here, the body bytes
804 are done by packet above */
805 vf->bittrack+=og.header_len*8;
807 if(vf->ready_state==INITSET){
808 if(vf->current_serialno!=ogg_page_serialno(&og)){
810 /* two possibilities:
811 1) our decoding just traversed a bitstream boundary
812 2) another stream is multiplexed into this logical section */
814 if(ogg_page_bos(&og)){
815 /* boundary case */
816 if(!spanp){
817 ret=OV_EOF;
818 goto cleanup;
821 _decode_clear(vf);
823 if(!vf->seekable){
824 vorbis_info_clear(vf->vi);
825 vorbis_comment_clear(vf->vc);
827 break;
829 }else
830 continue; /* possibility #2 */
833 break;
837 /* Do we need to load a new machine before submitting the page? */
838 /* This is different in the seekable and non-seekable cases.
840 In the seekable case, we already have all the header
841 information loaded and cached; we just initialize the machine
842 with it and continue on our merry way.
844 In the non-seekable (streaming) case, we'll only be at a
845 boundary if we just left the previous logical bitstream and
846 we're now nominally at the header of the next bitstream
849 if(vf->ready_state!=INITSET){
850 int link;
852 if(vf->ready_state<STREAMSET){
853 if(vf->seekable){
854 long serialno=ogg_page_serialno(&og);
856 /* match the serialno to bitstream section. We use this rather than
857 offset positions to avoid problems near logical bitstream
858 boundaries */
860 for(link=0;link<vf->links;link++)
861 if(vf->serialnos[link]==(ogg_uint32_t) serialno)break;
863 if(link==vf->links) continue; /* not the desired Vorbis
864 bitstream section; keep
865 trying */
867 vf->current_serialno=serialno;
868 vf->current_link=link;
870 ogg_stream_reset_serialno(vf->os,vf->current_serialno);
871 vf->ready_state=STREAMSET;
873 }else{
874 /* we're streaming */
875 /* fetch the three header packets, build the info struct */
877 int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og);
878 if(ret) goto cleanup;
879 vf->current_serialno=vf->os->serialno;
880 vf->current_link++;
881 link=0;
886 /* the buffered page is the data we want, and we're ready for it;
887 add it to the stream state */
888 ogg_stream_pagein(vf->os,&og);
890 cleanup:
891 ogg_packet_release(&op);
892 ogg_page_release(&og);
893 return ret;
896 static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
897 long ibytes, ov_callbacks callbacks){
898 int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
899 ogg_uint32_t *serialno_list=NULL;
900 int serialno_list_size=0;
901 int ret;
903 memset(vf,0,sizeof(*vf));
904 vf->datasource=f;
905 vf->callbacks = callbacks;
907 /* init the framing state */
908 vf->oy=ogg_sync_create();
910 /* perhaps some data was previously read into a buffer for testing
911 against other stream types. Allow initialization from this
912 previously read data (especially as we may be reading from a
913 non-seekable stream) */
914 if(initial){
915 unsigned char *buffer=ogg_sync_bufferin(vf->oy,ibytes);
916 memcpy(buffer,initial,ibytes);
917 ogg_sync_wrote(vf->oy,ibytes);
920 /* can we seek? Stevens suggests the seek test was portable */
921 if(offsettest!=-1)vf->seekable=1;
923 /* No seeking yet; Set up a 'single' (current) logical bitstream
924 entry for partial open */
925 vf->links=1;
926 vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
927 vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
928 vf->os=ogg_stream_create(-1); /* fill in the serialno later */
930 /* Fetch all BOS pages, store the vorbis header and all seen serial
931 numbers, load subsequent vorbis setup headers */
932 if((ret=_fetch_headers(vf,vf->vi,vf->vc,&serialno_list,&serialno_list_size,NULL))<0){
933 vf->datasource=NULL;
934 ov_clear(vf);
935 }else{
936 /* serial number list for first link needs to be held somewhere
937 for second stage of seekable stream open; this saves having to
938 seek/reread first link's serialnumber data then. */
939 vf->serialnos=_ogg_calloc(serialno_list_size+2,sizeof(*vf->serialnos));
940 vf->serialnos[0]=vf->current_serialno;
941 vf->serialnos[1]=serialno_list_size;
942 memcpy(vf->serialnos+2,serialno_list,serialno_list_size*sizeof(*vf->serialnos));
944 vf->offsets=_ogg_calloc(1,sizeof(*vf->offsets));
945 vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets));
946 vf->offsets[0]=0;
947 vf->dataoffsets[0]=vf->offset;
948 vf->current_serialno=vf->os->serialno;
950 vf->ready_state=PARTOPEN;
952 if(serialno_list)_ogg_free(serialno_list);
953 return(ret);
956 static int _ov_open2(OggVorbis_File *vf){
957 if(vf->ready_state < OPENED)
958 vf->ready_state=OPENED;
959 if(vf->seekable){
960 int ret=_open_seekable2(vf);
961 if(ret){
962 vf->datasource=NULL;
963 ov_clear(vf);
965 return(ret);
967 return 0;
971 /* clear out the OggVorbis_File struct */
972 int ov_clear(OggVorbis_File *vf){
973 if(vf){
974 vorbis_block_clear(&vf->vb);
975 vorbis_dsp_clear(&vf->vd);
976 ogg_stream_destroy(vf->os);
978 if(vf->vi && vf->links){
979 int i;
980 for(i=0;i<vf->links;i++){
981 vorbis_info_clear(vf->vi+i);
982 vorbis_comment_clear(vf->vc+i);
984 _ogg_free(vf->vi);
985 _ogg_free(vf->vc);
987 if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
988 if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
989 if(vf->serialnos)_ogg_free(vf->serialnos);
990 if(vf->offsets)_ogg_free(vf->offsets);
991 ogg_sync_destroy(vf->oy);
993 if(vf->datasource && vf->callbacks.close_func)
994 (vf->callbacks.close_func)(vf->datasource);
995 memset(vf,0,sizeof(*vf));
997 #ifdef DEBUG_LEAKS
998 _VDBG_dump();
999 #endif
1000 return(0);
1003 /* inspects the OggVorbis file and finds/documents all the logical
1004 bitstreams contained in it. Tries to be tolerant of logical
1005 bitstream sections that are truncated/woogie.
1007 return: -1) error
1008 0) OK
1011 int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
1012 ov_callbacks callbacks){
1013 #if defined(CPU_COLDFIRE)
1014 /* this seems to be the closest we get to an init function, let's init emac
1015 here. rounding is disabled because of MULT31_SHIFT15, which will be
1016 inaccurate with rounding in its current incarnation */
1017 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
1018 #endif
1019 int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
1020 if(ret)return ret;
1021 return _ov_open2(vf);
1024 /* returns: total PCM length (samples) of content if i==-1 PCM length
1025 (samples) of that logical bitstream for i==0 to n
1026 OV_EINVAL if the stream is not seekable (we can't know the
1027 length) or only partially open
1029 ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
1030 if(vf->ready_state<OPENED)return(OV_EINVAL);
1031 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1032 if(i<0){
1033 ogg_int64_t acc=0;
1034 int i;
1035 for(i=0;i<vf->links;i++)
1036 acc+=ov_pcm_total(vf,i);
1037 return(acc);
1038 }else{
1039 return(vf->pcmlengths[i*2+1]);
1043 /* returns: total milliseconds of content if i==-1
1044 milliseconds in that logical bitstream for i==0 to n
1045 OV_EINVAL if the stream is not seekable (we can't know the
1046 length) or only partially open
1048 ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){
1049 if(vf->ready_state<OPENED)return(OV_EINVAL);
1050 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1051 if(i<0){
1052 ogg_int64_t acc=0;
1053 int i;
1054 for(i=0;i<vf->links;i++)
1055 acc+=ov_time_total(vf,i);
1056 return(acc);
1057 }else{
1058 return(((ogg_int64_t)vf->pcmlengths[i*2+1])*1000/vf->vi[i].rate);
1062 /* seek to an offset relative to the *compressed* data. This also
1063 scans packets to update the PCM cursor. It will cross a logical
1064 bitstream boundary, but only if it can't get any packets out of the
1065 tail of the bitstream we seek to (so no surprises).
1067 returns zero on success, nonzero on failure */
1069 int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1070 ogg_stream_state *work_os=NULL;
1071 ogg_page og={0,0,0,0};
1072 ogg_packet op={0,0,0,0,0,0};
1073 int ret;
1075 if(vf->ready_state<OPENED)return(OV_EINVAL);
1076 if(!vf->seekable)
1077 return(OV_ENOSEEK); /* don't dump machine if we can't seek */
1079 if(pos<0 || pos>vf->end)return(OV_EINVAL);
1081 /* don't yet clear out decoding machine (if it's initialized), in
1082 the case we're in the same link. Restart the decode lapping, and
1083 let _fetch_and_process_packet deal with a potential bitstream
1084 boundary */
1085 vf->pcm_offset=-1;
1086 ogg_stream_reset_serialno(vf->os,
1087 vf->current_serialno); /* must set serialno */
1088 vorbis_synthesis_restart(&vf->vd);
1090 ret=_seek_helper(vf,pos);
1091 if(ret)goto seek_error;
1093 /* we need to make sure the pcm_offset is set, but we don't want to
1094 advance the raw cursor past good packets just to get to the first
1095 with a granulepos. That's not equivalent behavior to beginning
1096 decoding as immediately after the seek position as possible.
1098 So, a hack. We use two stream states; a local scratch state and
1099 the shared vf->os stream state. We use the local state to
1100 scan, and the shared state as a buffer for later decode.
1102 Unfortuantely, on the last page we still advance to last packet
1103 because the granulepos on the last page is not necessarily on a
1104 packet boundary, and we need to make sure the granpos is
1105 correct.
1109 int lastblock=0;
1110 int accblock=0;
1111 int thisblock;
1112 int lastflag=0;
1113 int firstflag=0;
1114 ogg_int64_t pagepos=-1;
1116 work_os=ogg_stream_create(vf->current_serialno); /* get the memory ready */
1117 while(1){
1118 if(vf->ready_state>=STREAMSET){
1119 /* snarf/scan a packet if we can */
1120 int result=ogg_stream_packetout(work_os,&op);
1122 if(result>0){
1124 if(vf->vi[vf->current_link].codec_setup){
1125 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1126 if(thisblock<0){
1127 ogg_stream_packetout(vf->os,NULL);
1128 thisblock=0;
1129 }else{
1131 /* We can't get a guaranteed correct pcm position out of the
1132 last page in a stream because it might have a 'short'
1133 granpos, which can only be detected in the presence of a
1134 preceeding page. However, if the last page is also the first
1135 page, the granpos rules of a first page take precedence. Not
1136 only that, but for first==last, the EOS page must be treated
1137 as if its a normal first page for the stream to open/play. */
1138 if(lastflag && !firstflag)
1139 ogg_stream_packetout(vf->os,NULL);
1140 else
1141 if(lastblock)accblock+=(lastblock+thisblock)>>2;
1144 if(op.granulepos!=-1){
1145 int i,link=vf->current_link;
1146 ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
1147 if(granulepos<0)granulepos=0;
1149 for(i=0;i<link;i++)
1150 granulepos+=vf->pcmlengths[i*2+1];
1151 vf->pcm_offset=granulepos-accblock;
1152 if(vf->pcm_offset<0)vf->pcm_offset=0;
1153 break;
1155 lastblock=thisblock;
1156 continue;
1157 }else
1158 ogg_stream_packetout(vf->os,NULL);
1162 if(!lastblock){
1163 pagepos=_get_next_page(vf,&og,-1);
1164 if(pagepos<0){
1165 vf->pcm_offset=ov_pcm_total(vf,-1);
1166 break;
1168 }else{
1169 /* huh? Bogus stream with packets but no granulepos */
1170 vf->pcm_offset=-1;
1171 break;
1174 /* has our decoding just traversed a bitstream boundary? */
1175 if(vf->ready_state>=STREAMSET){
1176 if(vf->current_serialno!=ogg_page_serialno(&og)){
1177 /* two possibilities:
1178 1) our decoding just traversed a bitstream boundary
1179 2) another stream is multiplexed into this logical section? */
1181 if(ogg_page_bos(&og)){
1182 /* we traversed */
1183 _decode_clear(vf); /* clear out stream state */
1184 ogg_stream_destroy(work_os);
1185 } /* else, do nothing; next loop will scoop another page */
1189 if(vf->ready_state<STREAMSET){
1190 int link;
1191 long serialno = ogg_page_serialno(&og);
1193 for(link=0;link<vf->links;link++)
1194 if(vf->serialnos[link]==vf->current_serialno)break;
1196 if(link==vf->links) continue; /* not the desired Vorbis
1197 bitstream section; keep
1198 trying */
1199 vf->current_link=link;
1200 vf->current_serialno=serialno;
1201 ogg_stream_reset_serialno(vf->os,vf->current_serialno);
1202 ogg_stream_reset_serialno(work_os,vf->current_serialno);
1203 vf->ready_state=STREAMSET;
1204 firstflag=(pagepos<=vf->dataoffsets[link]);
1208 ogg_page dup;
1209 ogg_page_dup(&dup,&og);
1210 lastflag=ogg_page_eos(&og);
1211 ogg_stream_pagein(vf->os,&og);
1212 ogg_stream_pagein(work_os,&dup);
1217 ogg_packet_release(&op);
1218 ogg_page_release(&og);
1219 ogg_stream_destroy(work_os);
1220 vf->bittrack=0;
1221 vf->samptrack=0;
1222 return(0);
1224 seek_error:
1225 ogg_packet_release(&op);
1226 ogg_page_release(&og);
1228 /* dump the machine so we're in a known state */
1229 vf->pcm_offset=-1;
1230 ogg_stream_destroy(work_os);
1231 _decode_clear(vf);
1232 return OV_EBADLINK;
1235 /* Page granularity seek (faster than sample granularity because we
1236 don't do the last bit of decode to find a specific sample).
1238 Seek to the last [granule marked] page preceeding the specified pos
1239 location, such that decoding past the returned point will quickly
1240 arrive at the requested position. */
1241 int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1242 int link=-1;
1243 ogg_int64_t result=0;
1244 ogg_int64_t total=ov_pcm_total(vf,-1);
1245 ogg_page og={0,0,0,0};
1246 ogg_packet op={0,0,0,0,0,0};
1248 if(vf->ready_state<OPENED)return(OV_EINVAL);
1249 if(!vf->seekable)return(OV_ENOSEEK);
1250 if(pos<0 || pos>total)return(OV_EINVAL);
1252 /* which bitstream section does this pcm offset occur in? */
1253 for(link=vf->links-1;link>=0;link--){
1254 total-=vf->pcmlengths[link*2+1];
1255 if(pos>=total)break;
1258 /* search within the logical bitstream for the page with the highest
1259 pcm_pos preceeding (or equal to) pos. There is a danger here;
1260 missing pages or incorrect frame number information in the
1261 bitstream could make our task impossible. Account for that (it
1262 would be an error condition) */
1264 /* new search algorithm by HB (Nicholas Vinen) */
1266 ogg_int64_t end=vf->offsets[link+1];
1267 ogg_int64_t begin=vf->offsets[link];
1268 ogg_int64_t begintime = vf->pcmlengths[link*2];
1269 ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
1270 ogg_int64_t target=pos-total+begintime;
1271 ogg_int64_t best=begin;
1273 while(begin<end){
1274 ogg_int64_t bisect;
1276 if(end-begin<CHUNKSIZE){
1277 bisect=begin;
1278 }else{
1279 /* take a (pretty decent) guess. */
1280 bisect=begin +
1281 (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
1282 if(bisect<=begin)
1283 bisect=begin+1;
1286 _seek_helper(vf,bisect);
1288 while(begin<end){
1289 result=_get_next_page(vf,&og,end-vf->offset);
1290 if(result==OV_EREAD) goto seek_error;
1291 if(result<0){
1292 if(bisect<=begin+1)
1293 end=begin; /* found it */
1294 else{
1295 if(bisect==0) goto seek_error;
1296 bisect-=CHUNKSIZE;
1297 if(bisect<=begin)bisect=begin+1;
1298 _seek_helper(vf,bisect);
1300 }else{
1301 ogg_int64_t granulepos=ogg_page_granulepos(&og);
1302 if(granulepos==-1)continue;
1303 if(granulepos<target){
1304 best=result; /* raw offset of packet with granulepos */
1305 begin=vf->offset; /* raw offset of next page */
1306 begintime=granulepos;
1308 if(target-begintime>44100)break;
1309 bisect=begin; /* *not* begin + 1 */
1310 }else{
1311 if(bisect<=begin+1)
1312 end=begin; /* found it */
1313 else{
1314 if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
1315 end=result;
1316 bisect-=CHUNKSIZE; /* an endless loop otherwise. */
1317 if(bisect<=begin)bisect=begin+1;
1318 _seek_helper(vf,bisect);
1319 }else{
1320 end=result;
1321 endtime=granulepos;
1322 break;
1330 /* found our page. seek to it, update pcm offset. Easier case than
1331 raw_seek, don't keep packets preceeding granulepos. */
1334 /* seek */
1335 result=_seek_helper(vf,best);
1336 vf->pcm_offset=-1;
1337 if(result) goto seek_error;
1338 result=_get_next_page(vf,&og,-1);
1339 if(result<0) goto seek_error;
1341 if(link!=vf->current_link){
1342 /* Different link; dump entire decode machine */
1343 _decode_clear(vf);
1345 vf->current_link=link;
1346 vf->current_serialno=ogg_page_serialno(&og);
1347 vf->ready_state=STREAMSET;
1349 }else{
1350 vorbis_synthesis_restart(&vf->vd);
1353 ogg_stream_reset_serialno(vf->os,vf->current_serialno);
1354 ogg_stream_pagein(vf->os,&og);
1356 /* pull out all but last packet; the one with granulepos */
1357 while(1){
1358 result=ogg_stream_packetpeek(vf->os,&op);
1359 if(result==0){
1360 /* !!! the packet finishing this page originated on a
1361 preceeding page. Keep fetching previous pages until we
1362 get one with a granulepos or without the 'continued' flag
1363 set. Then just use raw_seek for simplicity. */
1365 result=_seek_helper(vf,best);
1366 if(result<0) goto seek_error;
1368 while(1){
1369 result=_get_prev_page(vf,&og);
1370 if(result<0) goto seek_error;
1371 if(ogg_page_serialno(&og)==vf->current_serialno &&
1372 (ogg_page_granulepos(&og)>-1 ||
1373 !ogg_page_continued(&og))){
1374 return ov_raw_seek(vf,result);
1376 vf->offset=result;
1379 if(result<0){
1380 result = OV_EBADPACKET;
1381 goto seek_error;
1383 if(op.granulepos!=-1){
1384 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1385 if(vf->pcm_offset<0)vf->pcm_offset=0;
1386 vf->pcm_offset+=total;
1387 break;
1388 }else
1389 result=ogg_stream_packetout(vf->os,NULL);
1394 /* verify result */
1395 if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1396 result=OV_EFAULT;
1397 goto seek_error;
1399 vf->bittrack=0;
1400 vf->samptrack=0;
1402 ogg_page_release(&og);
1403 ogg_packet_release(&op);
1404 return(0);
1406 seek_error:
1408 ogg_page_release(&og);
1409 ogg_packet_release(&op);
1411 /* dump machine so we're in a known state */
1412 vf->pcm_offset=-1;
1413 _decode_clear(vf);
1414 return (int)result;
1417 /* seek to a sample offset relative to the decompressed pcm stream
1418 returns zero on success, nonzero on failure */
1420 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1421 ogg_packet op={0,0,0,0,0,0};
1422 ogg_page og={0,0,0,0};
1423 int thisblock,lastblock=0;
1424 int ret=ov_pcm_seek_page(vf,pos);
1425 if(ret<0)return(ret);
1426 _make_decode_ready(vf);
1428 /* discard leading packets we don't need for the lapping of the
1429 position we want; don't decode them */
1431 while(1){
1433 int ret=ogg_stream_packetpeek(vf->os,&op);
1434 if(ret>0){
1435 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1436 if(thisblock<0){
1437 ogg_stream_packetout(vf->os,NULL);
1438 continue; /* non audio packet */
1440 if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1442 if(vf->pcm_offset+((thisblock+
1443 vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
1445 /* remove the packet from packet queue and track its granulepos */
1446 ogg_stream_packetout(vf->os,NULL);
1447 vorbis_synthesis(&vf->vb,&op,0); /* set up a vb with
1448 only tracking, no
1449 pcm_decode */
1450 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
1452 /* end of logical stream case is hard, especially with exact
1453 length positioning. */
1455 if(op.granulepos>-1){
1456 int i;
1457 /* always believe the stream markers */
1458 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1459 if(vf->pcm_offset<0)vf->pcm_offset=0;
1460 for(i=0;i<vf->current_link;i++)
1461 vf->pcm_offset+=vf->pcmlengths[i*2+1];
1464 lastblock=thisblock;
1466 }else{
1467 if(ret<0 && ret!=OV_HOLE)break;
1469 /* suck in a new page */
1470 if(_get_next_page(vf,&og,-1)<0)break;
1471 if(ogg_page_bos(&og))_decode_clear(vf);
1473 if(vf->ready_state<STREAMSET){
1474 long serialno=ogg_page_serialno(&og);
1475 int link;
1477 for(link=0;link<vf->links;link++)
1478 if(vf->serialnos[link]==(ogg_uint32_t) serialno)break;
1479 if(link==vf->links) continue;
1480 vf->current_link=link;
1482 vf->ready_state=STREAMSET;
1483 vf->current_serialno=ogg_page_serialno(&og);
1484 ogg_stream_reset_serialno(vf->os,serialno);
1485 ret=_make_decode_ready(vf);
1486 if(ret){
1487 ogg_page_release(&og);
1488 ogg_packet_release(&op);
1489 return ret;
1491 lastblock=0;
1494 ogg_stream_pagein(vf->os,&og);
1498 vf->bittrack=0;
1499 vf->samptrack=0;
1500 /* discard samples until we reach the desired position. Crossing a
1501 logical bitstream boundary with abandon is OK. */
1502 while(vf->pcm_offset<pos){
1503 ogg_int64_t target=pos-vf->pcm_offset;
1504 long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
1506 if(samples>target)samples=target;
1507 vorbis_synthesis_read(&vf->vd,samples);
1508 vf->pcm_offset+=samples;
1510 if(samples<target)
1511 if(_fetch_and_process_packet(vf,1,1)<=0)
1512 vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1515 ogg_page_release(&og);
1516 ogg_packet_release(&op);
1517 return 0;
1520 /* seek to a playback time relative to the decompressed pcm stream
1521 returns zero on success, nonzero on failure */
1522 int ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){
1523 /* translate time to PCM position and call ov_pcm_seek */
1525 int link=-1;
1526 ogg_int64_t pcm_total=0;
1527 ogg_int64_t time_total=0;
1529 if(vf->ready_state<OPENED)return(OV_EINVAL);
1530 if(!vf->seekable)return(OV_ENOSEEK);
1531 if(milliseconds<0)return(OV_EINVAL);
1533 /* which bitstream section does this time offset occur in? */
1534 for(link=0;link<vf->links;link++){
1535 ogg_int64_t addsec = ov_time_total(vf,link);
1536 if(milliseconds<time_total+addsec)break;
1537 time_total+=addsec;
1538 pcm_total+=vf->pcmlengths[link*2+1];
1541 if(link==vf->links)return(OV_EINVAL);
1543 /* enough information to convert time offset to pcm offset */
1545 ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000;
1546 return(ov_pcm_seek(vf,target));
1550 /* tell the current stream offset cursor. Note that seek followed by
1551 tell will likely not give the set offset due to caching */
1552 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1553 if(vf->ready_state<OPENED)return(OV_EINVAL);
1554 return(vf->offset);
1557 /* return time offset (milliseconds) of next PCM sample to be read */
1558 ogg_int64_t ov_time_tell(OggVorbis_File *vf){
1559 int link=0;
1560 ogg_int64_t pcm_total=0;
1561 ogg_int64_t time_total=0;
1563 if(vf->ready_state<OPENED)return(OV_EINVAL);
1564 if(vf->seekable){
1565 pcm_total=ov_pcm_total(vf,-1);
1566 time_total=ov_time_total(vf,-1);
1568 /* which bitstream section does this time offset occur in? */
1569 for(link=vf->links-1;link>=0;link--){
1570 pcm_total-=vf->pcmlengths[link*2+1];
1571 time_total-=ov_time_total(vf,link);
1572 if(vf->pcm_offset>=pcm_total)break;
1576 return(time_total+(1000*vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1579 /* link: -1) return the vorbis_info struct for the bitstream section
1580 currently being decoded
1581 0-n) to request information for a specific bitstream section
1583 In the case of a non-seekable bitstream, any call returns the
1584 current bitstream. NULL in the case that the machine is not
1585 initialized */
1587 vorbis_info *ov_info(OggVorbis_File *vf,int link){
1588 if(vf->seekable){
1589 if(link<0)
1590 if(vf->ready_state>=STREAMSET)
1591 return vf->vi+vf->current_link;
1592 else
1593 return vf->vi;
1594 else
1595 if(link>=vf->links)
1596 return NULL;
1597 else
1598 return vf->vi+link;
1599 }else{
1600 return vf->vi;
1604 /* input values: pcm_channels) a float vector per channel of output
1605 length) the sample length being read by the app
1607 return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1608 0) EOF
1609 n) number of samples of PCM actually returned. The
1610 below works on a packet-by-packet basis, so the
1611 return length is not related to the 'length' passed
1612 in, just guaranteed to fit.
1614 *section) set to the logical bitstream number */
1616 long ov_read_fixed(OggVorbis_File *vf,ogg_int32_t ***pcm_channels,int length,
1617 int *bitstream){
1618 if(vf->ready_state<OPENED)return(OV_EINVAL);
1620 while(1){
1621 if(vf->ready_state==INITSET){
1622 ogg_int32_t **pcm;
1623 long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1624 if(samples){
1625 if(pcm_channels)*pcm_channels=pcm;
1626 if(samples>length)samples=length;
1627 vorbis_synthesis_read(&vf->vd,samples);
1628 vf->pcm_offset+=samples;
1629 if(bitstream)*bitstream=vf->current_link;
1630 return samples;
1635 /* suck in another packet */
1637 int ret=_fetch_and_process_packet(vf,1,1);
1638 if(ret==OV_EOF)return(0);
1639 if(ret<=0)return(ret);