1 /********************************************************************
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
9 * by the XIPHOPHORUS Company http://www.xiph.org/ *
11 ********************************************************************
13 function: stdio-based convenience library for opening/seeking/decoding
14 last mod: $Id: vorbisfile.c,v 1.45 2001/05/27 06:44:01 xiphmont Exp $
16 ********************************************************************/
24 #include "vorbis/codec.h"
25 #include "vorbis/vorbisfile.h"
30 /* A 'chained bitstream' is a Vorbis bitstream that contains more than
31 one logical bitstream arranged end to end (the only form of Ogg
32 multiplexing allowed in a Vorbis bitstream; grouping [parallel
33 multiplexing] is not allowed in Vorbis) */
35 /* A Vorbis file can be played beginning to end (streamed) without
36 worrying ahead of time about chaining (see decoder_example.c). If
37 we have the whole file, however, and want random access
38 (seeking/scrubbing) or desire to know the total length/time of a
39 file, we need to account for the possibility of chaining. */
41 /* We can handle things a number of ways; we can determine the entire
42 bitstream structure right off the bat, or find pieces on demand.
43 This example determines and caches structure for the entire
44 bitstream, but builds a virtual decoder on the fly when moving
45 between links in the chain. */
47 /* There are also different ways to implement seeking. Enough
48 information exists in an Ogg bitstream to seek to
49 sample-granularity positions in the output. Or, one can seek by
50 picking some portion of the stream roughly in the desired area if
51 we only want course navigation through the stream. */
53 /*************************************************************************
54 * Many, many internal helpers. The intention is not to be confusing;
55 * rampant duplication and monolithic function implementation would be
56 * harder to understand anyway. The high level functions are last. Begin
57 * grokking near the end of the file */
59 /* read a little more data from the file/pipe into the ogg_sync framer */
60 #define CHUNKSIZE 8500 /* a shade over 8k; anyone using pages well
61 over 8k gets what they deserve */
62 static long _get_data(OggVorbis_File *vf){
65 char *buffer=ogg_sync_buffer(&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 if(bytes==0 && errno)return(-1);
74 /* save a tiny smidge of verbosity to make the code more readable */
75 static void _seek_helper(OggVorbis_File *vf,long offset){
77 (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET);
79 ogg_sync_reset(&vf->oy);
81 /* shouldn't happen unless someone writes a broken callback */
86 /* The read/seek functions track absolute position within the stream */
88 /* from the head of the stream, get the next page. boundary specifies
89 if the function is allowed to fetch more data from the stream (and
90 how much) or only use internally buffered data.
92 boundary: -1) unbounded search
93 0) read no additional data; use cached only
94 n) search for a new page beginning for n bytes
96 return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
97 n) found a page at absolute offset n */
99 static long _get_next_page(OggVorbis_File *vf,ogg_page *og,int boundary){
100 if(boundary>0)boundary+=vf->offset;
104 if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
105 more=ogg_sync_pageseek(&vf->oy,og);
108 /* skipped n bytes */
112 /* send more paramedics */
113 if(!boundary)return(OV_FALSE);
115 long ret=_get_data(vf);
116 if(ret==0)return(OV_EOF);
117 if(ret<0)return(OV_EREAD);
120 /* got a page. Return the offset at the page beginning,
121 advance the internal offset past the page end */
131 /* find the latest page beginning before the current stream cursor
132 position. Much dirtier than the above as Ogg doesn't have any
133 backward search linkage. no 'readp' as it will certainly have to
135 /* returns offset or OV_EREAD, OV_FAULT */
136 static long _get_prev_page(OggVorbis_File *vf,ogg_page *og){
137 long begin=vf->offset;
143 _seek_helper(vf,begin);
144 while(vf->offset<begin+CHUNKSIZE){
145 ret=_get_next_page(vf,og,begin+CHUNKSIZE-vf->offset);
146 if(ret==OV_EREAD)return(OV_EREAD);
155 /* we have the offset. Actually snork and hold the page now */
156 _seek_helper(vf,offset);
157 ret=_get_next_page(vf,og,CHUNKSIZE);
159 /* this shouldn't be possible */
165 /* finds each bitstream link one at a time using a bisection search
166 (has to begin by knowing the offset of the lb's initial page).
167 Recurses for each link so it can alloc the link storage after
168 finding them all, then unroll and fill the cache at the same time */
169 static int _bisect_forward_serialno(OggVorbis_File *vf,
175 long endsearched=end;
180 /* the below guards against garbage seperating the last and
181 first pages of two links. */
182 while(searched<endsearched){
185 if(endsearched-searched<CHUNKSIZE){
188 bisect=(searched+endsearched)/2;
191 _seek_helper(vf,bisect);
192 ret=_get_next_page(vf,&og,-1);
193 if(ret==OV_EREAD)return(OV_EREAD);
194 if(ret<0 || ogg_page_serialno(&og)!=currentno){
198 searched=ret+og.header_len+og.body_len;
202 _seek_helper(vf,next);
203 ret=_get_next_page(vf,&og,-1);
204 if(ret==OV_EREAD)return(OV_EREAD);
206 if(searched>=end || ret<0){
208 vf->offsets=_ogg_malloc((m+2)*sizeof(ogg_int64_t));
209 vf->offsets[m+1]=searched;
211 ret=_bisect_forward_serialno(vf,next,vf->offset,
212 end,ogg_page_serialno(&og),m+1);
213 if(ret==OV_EREAD)return(OV_EREAD);
216 vf->offsets[m]=begin;
220 /* uses the local ogg_stream storage in vf; this is important for
221 non-streaming input sources */
222 static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
223 long *serialno,ogg_page *og_ptr){
229 ret=_get_next_page(vf,&og,CHUNKSIZE);
230 if(ret==OV_EREAD)return(OV_EREAD);
231 if(ret<0)return OV_ENOTVORBIS;
235 if(serialno)*serialno=ogg_page_serialno(og_ptr);
236 ogg_stream_init(&vf->os,ogg_page_serialno(og_ptr));
237 vf->ready_state=STREAMSET;
239 /* extract the initial header from the first page and verify that the
240 Ogg bitstream is in fact Vorbis data */
242 vorbis_info_init(vi);
243 vorbis_comment_init(vc);
247 ogg_stream_pagein(&vf->os,og_ptr);
249 int result=ogg_stream_packetout(&vf->os,&op);
255 if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
261 if(_get_next_page(vf,og_ptr,1)<0){
269 vorbis_info_clear(vi);
270 vorbis_comment_clear(vc);
271 ogg_stream_clear(&vf->os);
275 /* last step of the OggVorbis_File initialization; get all the
276 vorbis_info structs and PCM positions. Only called by the seekable
277 initialization (local stream storage is hacked slightly; pay
278 attention to how that's done) */
280 /* this is void and does not propogate errors up because we want to be
281 able to open and use damaged bitstreams as well as we can. Just
282 watch out for missing information for links in the OggVorbis_File
284 static void _prefetch_all_headers(OggVorbis_File *vf, long dataoffset){
288 vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(vorbis_info));
289 vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(vorbis_info));
290 vf->dataoffsets=_ogg_malloc(vf->links*sizeof(ogg_int64_t));
291 vf->pcmlengths=_ogg_malloc(vf->links*sizeof(ogg_int64_t));
292 vf->serialnos=_ogg_malloc(vf->links*sizeof(long));
294 for(i=0;i<vf->links;i++){
296 /* we already grabbed the initial header earlier. Just set the offset */
297 vf->dataoffsets[i]=dataoffset;
300 /* seek to the location of the initial header */
302 _seek_helper(vf,vf->offsets[i]);
303 if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){
304 vf->dataoffsets[i]=-1;
306 vf->dataoffsets[i]=vf->offset;
307 ogg_stream_clear(&vf->os);
311 /* get the serial number and PCM length of this link. To do this,
312 get the last page of the stream */
314 long end=vf->offsets[i+1];
315 _seek_helper(vf,end);
318 ret=_get_prev_page(vf,&og);
320 /* this should not be possible */
321 vorbis_info_clear(vf->vi+i);
322 vorbis_comment_clear(vf->vc+i);
325 if(ogg_page_granulepos(&og)!=-1){
326 vf->serialnos[i]=ogg_page_serialno(&og);
327 vf->pcmlengths[i]=ogg_page_granulepos(&og);
336 static void _make_decode_ready(OggVorbis_File *vf){
337 if(vf->ready_state!=STREAMSET)return;
339 vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link);
341 vorbis_synthesis_init(&vf->vd,vf->vi);
343 vorbis_block_init(&vf->vd,&vf->vb);
344 vf->ready_state=INITSET;
348 static int _open_seekable2(OggVorbis_File *vf){
349 long serialno=vf->current_serialno,end;
350 long dataoffset=vf->offset;
353 /* we're partially open and have a first link header state in
355 /* we can seek, so set out learning all about this file */
356 (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
357 vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
359 /* We get the offset for the last page of the physical bitstream.
360 Most OggVorbis files will contain a single logical bitstream */
361 end=_get_prev_page(vf,&og);
367 /* more than one logical bitstream? */
368 if(ogg_page_serialno(&og)!=serialno){
370 /* Chained bitstream. Bisect-search each logical bitstream
371 section. Do so based on serial number only */
372 if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0){
379 /* Only one logical bitstream */
380 if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0)){
387 /* the initial header memory is referenced by vf after; don't free it */
388 _prefetch_all_headers(vf,dataoffset);
389 return(ov_raw_seek(vf,0));
392 /* clear out the current logical bitstream decoder */
393 static void _decode_clear(OggVorbis_File *vf){
394 ogg_stream_clear(&vf->os);
395 vorbis_dsp_clear(&vf->vd);
396 vorbis_block_clear(&vf->vb);
397 vf->ready_state=OPENED;
403 /* fetch and process a packet. Handles the case where we're at a
404 bitstream boundary and dumps the decoding machine. If the decoding
405 machine is unloaded, it loads it. It also keeps pcm_offset up to
406 date (seek and read both use this. seek uses a special hack with
409 return: <0) error, OV_HOLE (lost packet) or OV_EOF
410 0) need more data (only if readp==0)
414 static int _process_packet(OggVorbis_File *vf,int readp){
417 /* handle one packet. Try to fetch it from current stream state */
418 /* extract packets from page */
421 /* process a packet if we can. If the machine isn't loaded,
423 if(vf->ready_state==INITSET){
425 int result=ogg_stream_packetout(&vf->os,&op);
426 ogg_int64_t granulepos;
428 if(result==-1)return(OV_HOLE); /* hole in the data. */
430 /* got a packet. process it */
431 granulepos=op.granulepos;
432 if(!vorbis_synthesis(&vf->vb,&op)){ /* lazy check for lazy
434 header packets aren't
437 vorbis_synthesis will
440 /* suck in the synthesis data and track bitrate */
442 int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
443 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
444 vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
445 vf->bittrack+=op.bytes*8;
448 /* update the pcm offset. */
449 if(granulepos!=-1 && !op.e_o_s){
450 int link=(vf->seekable?vf->current_link:0);
453 /* this packet has a pcm_offset on it (the last packet
454 completed on a page carries the offset) After processing
455 (above), we know the pcm position of the *last* sample
456 ready to be returned. Find the offset of the *first*
458 As an aside, this trick is inaccurate if we begin
459 reading anew right at the last page; the end-of-stream
460 granulepos declares the last frame in the stream, and the
461 last packet of the last page may be a partial frame.
462 So, we need a previous granulepos from an in-sequence page
463 to have a reference point. Thus the !op.e_o_s clause
466 samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
470 granulepos+=vf->pcmlengths[i];
471 vf->pcm_offset=granulepos;
478 if(vf->ready_state>=STREAMSET){
480 if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* eof.
483 /* bitrate tracking; add the header's bytes here, the body bytes
484 are done by packet above */
485 vf->bittrack+=og.header_len*8;
487 /* has our decoding just traversed a bitstream boundary? */
488 if(vf->ready_state==INITSET){
489 if(vf->current_serialno!=ogg_page_serialno(&og)){
493 vorbis_info_clear(vf->vi);
494 vorbis_comment_clear(vf->vc);
500 /* Do we need to load a new machine before submitting the page? */
501 /* This is different in the seekable and non-seekable cases.
503 In the seekable case, we already have all the header
504 information loaded and cached; we just initialize the machine
505 with it and continue on our merry way.
507 In the non-seekable (streaming) case, we'll only be at a
508 boundary if we just left the previous logical bitstream and
509 we're now nominally at the header of the next bitstream
512 if(vf->ready_state!=INITSET){
515 if(vf->ready_state<STREAMSET){
517 vf->current_serialno=ogg_page_serialno(&og);
519 /* match the serialno to bitstream section. We use this rather than
520 offset positions to avoid problems near logical bitstream
522 for(link=0;link<vf->links;link++)
523 if(vf->serialnos[link]==vf->current_serialno)break;
524 if(link==vf->links)return(OV_EBADLINK); /* sign of a bogus
529 vf->current_link=link;
531 ogg_stream_init(&vf->os,vf->current_serialno);
532 ogg_stream_reset(&vf->os);
533 vf->ready_state=STREAMSET;
536 /* we're streaming */
537 /* fetch the three header packets, build the info struct */
539 _fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og);
545 _make_decode_ready(vf);
547 ogg_stream_pagein(&vf->os,&og);
551 static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
552 if(f==NULL)return(-1);
553 return fseek(f,(int)off,whence);
556 static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
557 long ibytes, ov_callbacks callbacks){
558 long offset=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
561 memset(vf,0,sizeof(OggVorbis_File));
563 vf->callbacks = callbacks;
565 /* init the framing state */
566 ogg_sync_init(&vf->oy);
568 /* perhaps some data was previously read into a buffer for testing
569 against other stream types. Allow initialization from this
570 previously read data (as we may be reading from a non-seekable
573 char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
574 memcpy(buffer,initial,ibytes);
575 ogg_sync_wrote(&vf->oy,ibytes);
578 /* can we seek? Stevens suggests the seek test was portable */
579 if(offset!=-1)vf->seekable=1;
581 /* No seeking yet; Set up a 'single' (current) logical bitstream
582 entry for partial open */
584 vf->vi=_ogg_calloc(vf->links,sizeof(vorbis_info));
585 vf->vc=_ogg_calloc(vf->links,sizeof(vorbis_info));
587 /* Try to fetch the headers, maintaining all the storage */
588 if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0){
592 vf->ready_state=PARTOPEN;
596 static int _ov_open2(OggVorbis_File *vf){
597 vf->ready_state=OPENED;
599 int ret=_open_seekable2(vf);
610 /* clear out the OggVorbis_File struct */
611 int ov_clear(OggVorbis_File *vf){
613 vorbis_block_clear(&vf->vb);
614 vorbis_dsp_clear(&vf->vd);
615 ogg_stream_clear(&vf->os);
617 if(vf->vi && vf->links){
619 for(i=0;i<vf->links;i++){
620 vorbis_info_clear(vf->vi+i);
621 vorbis_comment_clear(vf->vc+i);
626 if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
627 if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
628 if(vf->serialnos)_ogg_free(vf->serialnos);
629 if(vf->offsets)_ogg_free(vf->offsets);
630 ogg_sync_clear(&vf->oy);
631 if(vf->datasource)(vf->callbacks.close_func)(vf->datasource);
632 memset(vf,0,sizeof(OggVorbis_File));
640 /* inspects the OggVorbis file and finds/documents all the logical
641 bitstreams contained in it. Tries to be tolerant of logical
642 bitstream sections that are truncated/woogie.
648 int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
649 ov_callbacks callbacks){
650 int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
652 return _ov_open2(vf);
655 int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
656 ov_callbacks callbacks = {
657 (size_t (*)(void *, size_t, size_t, void *)) fread,
658 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
659 (int (*)(void *)) fclose,
660 (long (*)(void *)) ftell
663 return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
666 /* Only partially open the vorbis file; test for Vorbisness, and load
667 the headers for the first chain. Do not seek (although test for
668 seekability). Use ov_test_open to finish opening the file, else
669 ov_clear to close/free it. Same return codes as open. */
671 int ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
672 ov_callbacks callbacks)
674 return _ov_open1(f,vf,initial,ibytes,callbacks);
677 int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
678 ov_callbacks callbacks = {
679 (size_t (*)(void *, size_t, size_t, void *)) fread,
680 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
681 (int (*)(void *)) fclose,
682 (long (*)(void *)) ftell
685 return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
688 int ov_test_open(OggVorbis_File *vf){
689 if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
690 return _ov_open2(vf);
693 /* How many logical bitstreams in this physical bitstream? */
694 long ov_streams(OggVorbis_File *vf){
698 /* Is the FILE * associated with vf seekable? */
699 long ov_seekable(OggVorbis_File *vf){
703 /* returns the bitrate for a given logical bitstream or the entire
704 physical bitstream. If the file is open for random access, it will
705 find the *actual* average bitrate. If the file is streaming, it
706 returns the nominal bitrate (if set) else the average of the
707 upper/lower bounds (if set) else -1 (unset).
709 If you want the actual bitrate field settings, get them from the
710 vorbis_info structs */
712 long ov_bitrate(OggVorbis_File *vf,int i){
713 if(vf->ready_state<OPENED)return(OV_EINVAL);
714 if(i>=vf->links)return(OV_EINVAL);
715 if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
719 for(i=0;i<vf->links;i++)
720 bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
721 return(rint(bits/ov_time_total(vf,-1)));
724 /* return the actual bitrate */
725 return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i)));
727 /* return nominal if set */
728 if(vf->vi[i].bitrate_nominal>0){
729 return vf->vi[i].bitrate_nominal;
731 if(vf->vi[i].bitrate_upper>0){
732 if(vf->vi[i].bitrate_lower>0){
733 return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
735 return vf->vi[i].bitrate_upper;
744 /* returns the actual bitrate since last call. returns -1 if no
745 additional data to offer since last call (or at beginning of stream),
746 EINVAL if stream is only partially open
748 long ov_bitrate_instant(OggVorbis_File *vf){
749 int link=(vf->seekable?vf->current_link:0);
751 if(vf->ready_state<OPENED)return(OV_EINVAL);
752 if(vf->samptrack==0)return(OV_FALSE);
753 ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
760 long ov_serialnumber(OggVorbis_File *vf,int i){
761 if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
762 if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
764 return(vf->current_serialno);
766 return(vf->serialnos[i]);
770 /* returns: total raw (compressed) length of content if i==-1
771 raw (compressed) length of that logical bitstream for i==0 to n
772 OV_EINVAL if the stream is not seekable (we can't know the length)
773 or if stream is only partially open
775 ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
776 if(vf->ready_state<OPENED)return(OV_EINVAL);
777 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
781 for(i=0;i<vf->links;i++)
782 acc+=ov_raw_total(vf,i);
785 return(vf->offsets[i+1]-vf->offsets[i]);
789 /* returns: total PCM length (samples) of content if i==-1 PCM length
790 (samples) of that logical bitstream for i==0 to n
791 OV_EINVAL if the stream is not seekable (we can't know the
792 length) or only partially open
794 ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
795 if(vf->ready_state<OPENED)return(OV_EINVAL);
796 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
800 for(i=0;i<vf->links;i++)
801 acc+=ov_pcm_total(vf,i);
804 return(vf->pcmlengths[i]);
808 /* returns: total seconds of content if i==-1
809 seconds in that logical bitstream for i==0 to n
810 OV_EINVAL if the stream is not seekable (we can't know the
811 length) or only partially open
813 double ov_time_total(OggVorbis_File *vf,int i){
814 if(vf->ready_state<OPENED)return(OV_EINVAL);
815 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
819 for(i=0;i<vf->links;i++)
820 acc+=ov_time_total(vf,i);
823 return((float)(vf->pcmlengths[i])/vf->vi[i].rate);
827 /* seek to an offset relative to the *compressed* data. This also
828 scans packets to update the PCM cursor. It will cross a logical
829 bitstream boundary, but only if it can't get any packets out of the
830 tail of the bitstream we seek to (so no surprises).
832 returns zero on success, nonzero on failure */
834 int ov_raw_seek(OggVorbis_File *vf,long pos){
835 ogg_stream_state work_os;
837 if(vf->ready_state<OPENED)return(OV_EINVAL);
839 return(OV_ENOSEEK); /* don't dump machine if we can't seek */
841 if(pos<0 || pos>vf->offsets[vf->links])return(OV_EINVAL);
843 /* clear out decoding machine state */
847 _seek_helper(vf,pos);
849 /* we need to make sure the pcm_offset is set, but we don't want to
850 advance the raw cursor past good packets just to get to the first
851 with a granulepos. That's not equivalent behavior to beginning
852 decoding as immediately after the seek position as possible.
854 So, a hack. We use two stream states; a local scratch state and
855 a the shared vf->os stream state. We use the local state to
856 scan, and the shared state as a buffer for later decode.
858 Unfortuantely, on the last page we still advance to last packet
859 because the granulepos on the last page is not necessarily on a
860 packet boundary, and we need to make sure the granpos is
872 memset(&work_os,0,sizeof(work_os));/* so that it's safe to clear
873 it later even if we don't
877 if(vf->ready_state==STREAMSET){
878 /* snarf/scan a packet if we can */
879 int result=ogg_stream_packetout(&work_os,&op);
883 if(vf->vi[vf->current_link].codec_setup)
884 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
886 ogg_stream_packetout(&vf->os,NULL);
888 if(lastblock)accblock+=(lastblock+thisblock)>>2;
890 if(op.granulepos!=-1){
891 int i,link=vf->current_link;
892 ogg_int64_t granulepos=op.granulepos;
895 granulepos+=vf->pcmlengths[i];
896 vf->pcm_offset=granulepos-accblock;
905 if(_get_next_page(vf,&og,-1)<0){
906 vf->pcm_offset=ov_pcm_total(vf,-1);
910 /* huh? Bogus stream with packets but no granulepos */
915 /* has our decoding just traversed a bitstream boundary? */
916 if(vf->ready_state==STREAMSET)
917 if(vf->current_serialno!=ogg_page_serialno(&og)){
918 _decode_clear(vf); /* clear out stream state */
919 ogg_stream_clear(&work_os);
922 if(vf->ready_state<STREAMSET){
925 vf->current_serialno=ogg_page_serialno(&og);
926 for(link=0;link<vf->links;link++)
927 if(vf->serialnos[link]==vf->current_serialno)break;
928 if(link==vf->links)goto seek_error; /* sign of a bogus stream.
930 machine uninitialized */
931 vf->current_link=link;
933 ogg_stream_init(&vf->os,vf->current_serialno);
934 ogg_stream_reset(&vf->os);
935 ogg_stream_init(&work_os,vf->current_serialno);
936 ogg_stream_reset(&work_os);
937 vf->ready_state=STREAMSET;
941 ogg_stream_pagein(&vf->os,&og);
942 ogg_stream_pagein(&work_os,&og);
943 eosflag=ogg_page_eos(&og);
947 ogg_stream_clear(&work_os);
951 /* dump the machine so we're in a known state */
953 ogg_stream_clear(&work_os);
958 /* Page granularity seek (faster than sample granularity because we
959 don't do the last bit of decode to find a specific sample).
961 Seek to the last [granule marked] page preceeding the specified pos
962 location, such that decoding past the returned point will quickly
963 arrive at the requested position. */
964 int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
967 ogg_int64_t total=ov_pcm_total(vf,-1);
969 if(vf->ready_state<OPENED)return(OV_EINVAL);
970 if(!vf->seekable)return(OV_ENOSEEK);
971 if(pos<0 || pos>total)return(OV_EINVAL);
973 /* which bitstream section does this pcm offset occur in? */
974 for(link=vf->links-1;link>=0;link--){
975 total-=vf->pcmlengths[link];
979 /* search within the logical bitstream for the page with the highest
980 pcm_pos preceeding (or equal to) pos. There is a danger here;
981 missing pages or incorrect frame number information in the
982 bitstream could make our task impossible. Account for that (it
983 would be an error condition) */
985 /* new search algorithm by HB (Nicholas Vinen) */
987 ogg_int64_t target=pos-total;
988 long end=vf->offsets[link+1];
989 long begin=vf->offsets[link];
990 ogg_int64_t endtime = vf->pcmlengths[link];
991 ogg_int64_t begintime = 0;
998 if(end-begin<CHUNKSIZE){
1001 /* take a (pretty decent) guess. */
1003 (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
1007 _seek_helper(vf,bisect);
1010 ret=_get_next_page(vf,&og,end-bisect);
1011 if(ret==OV_EREAD) goto seek_error;
1014 end=begin; /* found it */
1016 if(bisect==0)goto seek_error;
1018 if(bisect<=begin)bisect=begin+1;
1019 _seek_helper(vf,bisect);
1022 ogg_int64_t granulepos=ogg_page_granulepos(&og);
1023 if(granulepos<target){
1024 best=ret; /* raw offset of packet with granulepos */
1025 begin=vf->offset; /* raw offset of next page */
1026 begintime=granulepos;
1028 if(target-begin>44100)break;
1029 bisect=begin; /* *not* begin + 1 */
1032 end=begin; /* found it */
1034 if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
1036 bisect-=CHUNKSIZE; /* an endless loop otherwise. */
1037 if(bisect<=begin)bisect=begin+1;
1038 _seek_helper(vf,bisect);
1050 /* found our page. seek to it, update pcm offset. Easier case than
1051 raw_seek, don't keep packets preceeding granulepos. */
1055 /* clear out decoding machine state */
1058 _seek_helper(vf,best);
1060 if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* shouldn't happen */
1061 vf->current_serialno=ogg_page_serialno(&og);
1062 vf->current_link=link;
1064 ogg_stream_init(&vf->os,vf->current_serialno);
1065 ogg_stream_reset(&vf->os);
1066 vf->ready_state=STREAMSET;
1067 ogg_stream_pagein(&vf->os,&og);
1069 /* pull out all but last packet; the one with granulepos */
1071 ret=ogg_stream_packetpeek(&vf->os,&op);
1073 /* !!! the packet finishing this page originated on a
1074 preceeding page. Keep fetching previous pages until we
1075 get one with a granulepos or without the 'continued' flag
1076 set. Then just use raw_seek for simplicity. */
1078 ret=_get_prev_page(vf,&og);
1079 if(ret<0)goto seek_error;
1080 if(ogg_page_granulepos(&og)>-1 ||
1081 !ogg_page_continued(&og)){
1082 return ov_raw_seek(vf,ret);
1087 if(ret<0)goto seek_error;
1088 if(op.granulepos!=-1 && !op.e_o_s){
1089 vf->pcm_offset=op.granulepos+total;
1092 ret=ogg_stream_packetout(&vf->os,NULL);
1098 if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1105 /* dump machine so we're in a known state */
1111 /* seek to a sample offset relative to the decompressed pcm stream
1112 returns zero on success, nonzero on failure */
1114 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1115 int thisblock,lastblock=0,blockacc=0;
1116 int ret=ov_pcm_seek_page(vf,pos);
1117 if(ret<0)return(ret);
1119 /* discard leading packets we don't need for the lapping of the
1120 position we want; don't decode them */
1126 int ret=ogg_stream_packetpeek(&vf->os,&op);
1128 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1131 ((lastblock+thisblock)>>2)+
1132 (thisblock>>1)+vf->pcm_offset>pos)break;
1134 ogg_stream_packetout(&vf->os,NULL);
1135 /* end of logical stream case is hard, especially with exact
1136 length positioning. */
1138 if(op.granulepos>-1){
1140 /* always believe the stream markers */
1141 vf->pcm_offset=op.granulepos;
1142 for(i=0;i<vf->current_link;i++)
1143 vf->pcm_offset+=vf->pcmlengths[i];
1146 if(lastblock)blockacc+=(lastblock+thisblock)>>2;
1148 lastblock=thisblock;
1150 if(ret<0 && ret!=OV_HOLE)break;
1152 /* suck in a new page */
1153 if(_get_next_page(vf,&og,-1)<0)break;
1154 if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf);
1156 if(vf->ready_state<STREAMSET){
1159 vf->current_serialno=ogg_page_serialno(&og);
1160 for(link=0;link<vf->links;link++)
1161 if(vf->serialnos[link]==vf->current_serialno)break;
1162 if(link==vf->links)return(OV_EBADLINK);
1163 vf->current_link=link;
1165 ogg_stream_init(&vf->os,vf->current_serialno);
1166 ogg_stream_reset(&vf->os);
1167 vf->ready_state=STREAMSET;
1170 ogg_stream_pagein(&vf->os,&og);
1174 if(lastblock)vf->pcm_offset+=blockacc;
1177 /* discard samples until we reach the desired position. Crossing a
1178 logical bitstream boundary with abandon is OK. */
1179 _make_decode_ready(vf);
1180 while(vf->pcm_offset<pos){
1182 long target=pos-vf->pcm_offset;
1183 long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1185 if(samples>target)samples=target;
1186 vorbis_synthesis_read(&vf->vd,samples);
1187 vf->pcm_offset+=samples;
1190 if(_process_packet(vf,1)<=0)
1191 vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1196 /* seek to a playback time relative to the decompressed pcm stream
1197 returns zero on success, nonzero on failure */
1198 int ov_time_seek(OggVorbis_File *vf,double seconds){
1199 /* translate time to PCM position and call ov_pcm_seek */
1202 ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1203 double time_total=ov_time_total(vf,-1);
1205 if(vf->ready_state<OPENED)return(OV_EINVAL);
1206 if(!vf->seekable)return(OV_ENOSEEK);
1207 if(seconds<0 || seconds>time_total)return(OV_EINVAL);
1209 /* which bitstream section does this time offset occur in? */
1210 for(link=vf->links-1;link>=0;link--){
1211 pcm_total-=vf->pcmlengths[link];
1212 time_total-=ov_time_total(vf,link);
1213 if(seconds>=time_total)break;
1216 /* enough information to convert time offset to pcm offset */
1218 ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1219 return(ov_pcm_seek(vf,target));
1223 /* page-granularity version of ov_time_seek
1224 returns zero on success, nonzero on failure */
1225 int ov_time_seek_page(OggVorbis_File *vf,double seconds){
1226 /* translate time to PCM position and call ov_pcm_seek */
1229 ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1230 double time_total=ov_time_total(vf,-1);
1232 if(vf->ready_state<OPENED)return(OV_EINVAL);
1233 if(!vf->seekable)return(OV_ENOSEEK);
1234 if(seconds<0 || seconds>time_total)return(OV_EINVAL);
1236 /* which bitstream section does this time offset occur in? */
1237 for(link=vf->links-1;link>=0;link--){
1238 pcm_total-=vf->pcmlengths[link];
1239 time_total-=ov_time_total(vf,link);
1240 if(seconds>=time_total)break;
1243 /* enough information to convert time offset to pcm offset */
1245 ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1246 return(ov_pcm_seek_page(vf,target));
1250 /* tell the current stream offset cursor. Note that seek followed by
1251 tell will likely not give the set offset due to caching */
1252 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1253 if(vf->ready_state<OPENED)return(OV_EINVAL);
1257 /* return PCM offset (sample) of next PCM sample to be read */
1258 ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1259 if(vf->ready_state<OPENED)return(OV_EINVAL);
1260 return(vf->pcm_offset);
1263 /* return time offset (seconds) of next PCM sample to be read */
1264 double ov_time_tell(OggVorbis_File *vf){
1265 /* translate time to PCM position and call ov_pcm_seek */
1268 ogg_int64_t pcm_total=0;
1269 double time_total=0.f;
1271 if(vf->ready_state<OPENED)return(OV_EINVAL);
1273 pcm_total=ov_pcm_total(vf,-1);
1274 time_total=ov_time_total(vf,-1);
1276 /* which bitstream section does this time offset occur in? */
1277 for(link=vf->links-1;link>=0;link--){
1278 pcm_total-=vf->pcmlengths[link];
1279 time_total-=ov_time_total(vf,link);
1280 if(vf->pcm_offset>=pcm_total)break;
1284 return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1287 /* link: -1) return the vorbis_info struct for the bitstream section
1288 currently being decoded
1289 0-n) to request information for a specific bitstream section
1291 In the case of a non-seekable bitstream, any call returns the
1292 current bitstream. NULL in the case that the machine is not
1295 vorbis_info *ov_info(OggVorbis_File *vf,int link){
1298 if(vf->ready_state>=STREAMSET)
1299 return vf->vi+vf->current_link;
1312 /* grr, strong typing, grr, no templates/inheritence, grr */
1313 vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1316 if(vf->ready_state>=STREAMSET)
1317 return vf->vc+vf->current_link;
1330 int host_is_big_endian() {
1331 ogg_int32_t pattern = 0xfeedface; /* deadbeef */
1332 unsigned char *bytewise = (unsigned char *)&pattern;
1333 if (bytewise[0] == 0xfe) return 1;
1337 /* up to this point, everything could more or less hide the multiple
1338 logical bitstream nature of chaining from the toplevel application
1339 if the toplevel application didn't particularly care. However, at
1340 the point that we actually read audio back, the multiple-section
1341 nature must surface: Multiple bitstream sections do not necessarily
1342 have to have the same number of channels or sampling rate.
1344 ov_read returns the sequential logical bitstream number currently
1345 being decoded along with the PCM data in order that the toplevel
1346 application can take action on channel/sample rate changes. This
1347 number will be incremented even for streamed (non-seekable) streams
1348 (for seekable streams, it represents the actual logical bitstream
1349 index within the physical bitstream. Note that the accessor
1350 functions above are aware of this dichotomy).
1352 input values: buffer) a buffer to hold packed PCM data for return
1353 length) the byte length requested to be placed into buffer
1354 bigendianp) should the data be packed LSB first (0) or
1356 word) word size for output. currently 1 (byte) or
1359 return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1361 n) number of bytes of PCM actually returned. The
1362 below works on a packet-by-packet basis, so the
1363 return length is not related to the 'length' passed
1364 in, just guaranteed to fit.
1366 *section) set to the logical bitstream number */
1368 long ov_read(OggVorbis_File *vf,char *buffer,int length,
1369 int bigendianp,int word,int sgned,int *bitstream){
1371 int host_endian = host_is_big_endian();
1373 if(vf->ready_state<OPENED)return(OV_EINVAL);
1374 if(vf->ready_state==OPENED)return(OV_EOF); /* stream is always
1377 open)... unless there
1378 was no page at the end
1383 if(vf->ready_state>=STREAMSET){
1385 long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1387 /* yay! proceed to pack data into the byte buffer */
1389 long channels=ov_info(vf,-1)->channels;
1390 long bytespersample=word * channels;
1391 vorbis_fpu_control fpu;
1392 if(samples>length/bytespersample)samples=length/bytespersample;
1394 /* a tight loop to pack each size */
1398 int off=(sgned?0:128);
1399 vorbis_fpu_setround(&fpu);
1400 for(j=0;j<samples;j++)
1401 for(i=0;i<channels;i++){
1402 val=vorbis_ftoi(pcm[i][j]*128.f);
1404 else if(val<-128)val=-128;
1407 vorbis_fpu_restore(fpu);
1409 int off=(sgned?0:32768);
1411 if(host_endian==bigendianp){
1414 vorbis_fpu_setround(&fpu);
1415 for(i=0;i<channels;i++) { /* It's faster in this order */
1417 short *dest=((short *)buffer)+i;
1418 for(j=0;j<samples;j++) {
1419 val=vorbis_ftoi(src[j]*32768.f);
1420 if(val>32767)val=32767;
1421 else if(val<-32768)val=-32768;
1426 vorbis_fpu_restore(fpu);
1430 vorbis_fpu_setround(&fpu);
1431 for(i=0;i<channels;i++) {
1433 short *dest=((short *)buffer)+i;
1434 for(j=0;j<samples;j++) {
1435 val=vorbis_ftoi(src[j]*32768.f);
1436 if(val>32767)val=32767;
1437 else if(val<-32768)val=-32768;
1442 vorbis_fpu_restore(fpu);
1445 }else if(bigendianp){
1447 vorbis_fpu_setround(&fpu);
1448 for(j=0;j<samples;j++)
1449 for(i=0;i<channels;i++){
1450 val=vorbis_ftoi(pcm[i][j]*32768.f);
1451 if(val>32767)val=32767;
1452 else if(val<-32768)val=-32768;
1455 *buffer++=(val&0xff);
1457 vorbis_fpu_restore(fpu);
1461 vorbis_fpu_setround(&fpu);
1462 for(j=0;j<samples;j++)
1463 for(i=0;i<channels;i++){
1464 val=vorbis_ftoi(pcm[i][j]*32768.f);
1465 if(val>32767)val=32767;
1466 else if(val<-32768)val=-32768;
1468 *buffer++=(val&0xff);
1471 vorbis_fpu_restore(fpu);
1477 vorbis_synthesis_read(&vf->vd,samples);
1478 vf->pcm_offset+=samples;
1479 if(bitstream)*bitstream=vf->current_link;
1480 return(samples*bytespersample);
1484 /* suck in another packet */
1485 switch(_process_packet(vf,1)){
1491 return(OV_EBADLINK);