1 /********************************************************************
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
5 * THE GNU LESSER/LIBRARY PUBLIC LICENSE, WHICH IS INCLUDED WITH *
6 * THIS SOURCE. 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.38 2001/02/14 13:12:15 msmith 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 4096
61 static long _get_data(OggVorbis_File *vf){
64 char *buffer=ogg_sync_buffer(&vf->oy,CHUNKSIZE);
65 long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource);
66 if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
67 if(bytes==0 && errno)return(-1);
73 /* save a tiny smidge of verbosity to make the code more readable */
74 static void _seek_helper(OggVorbis_File *vf,long offset){
76 (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET);
78 ogg_sync_reset(&vf->oy);
80 /* shouldn't happen unless someone writes a broken callback */
85 /* The read/seek functions track absolute position within the stream */
87 /* from the head of the stream, get the next page. boundary specifies
88 if the function is allowed to fetch more data from the stream (and
89 how much) or only use internally buffered data.
91 boundary: -1) unbounded search
92 0) read no additional data; use cached only
93 n) search for a new page beginning for n bytes
95 return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
96 n) found a page at absolute offset n */
98 static long _get_next_page(OggVorbis_File *vf,ogg_page *og,int boundary){
99 if(boundary>0)boundary+=vf->offset;
103 if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
104 more=ogg_sync_pageseek(&vf->oy,og);
107 /* skipped n bytes */
111 /* send more paramedics */
112 if(!boundary)return(OV_FALSE);
114 long ret=_get_data(vf);
115 if(ret==0)return(OV_EOF);
116 if(ret<0)return(OV_EREAD);
119 /* got a page. Return the offset at the page beginning,
120 advance the internal offset past the page end */
130 /* find the latest page beginning before the current stream cursor
131 position. Much dirtier than the above as Ogg doesn't have any
132 backward search linkage. no 'readp' as it will certainly have to
134 /* returns offset or OV_EREAD, OV_FAULT */
135 static long _get_prev_page(OggVorbis_File *vf,ogg_page *og){
136 long begin=vf->offset;
142 _seek_helper(vf,begin);
143 while(vf->offset<begin+CHUNKSIZE){
144 ret=_get_next_page(vf,og,begin+CHUNKSIZE-vf->offset);
145 if(ret==OV_EREAD)return(OV_EREAD);
154 /* we have the offset. Actually snork and hold the page now */
155 _seek_helper(vf,offset);
156 ret=_get_next_page(vf,og,CHUNKSIZE);
158 /* this shouldn't be possible */
164 /* finds each bitstream link one at a time using a bisection search
165 (has to begin by knowing the offset of the lb's initial page).
166 Recurses for each link so it can alloc the link storage after
167 finding them all, then unroll and fill the cache at the same time */
168 static int _bisect_forward_serialno(OggVorbis_File *vf,
174 long endsearched=end;
179 /* the below guards against garbage seperating the last and
180 first pages of two links. */
181 while(searched<endsearched){
184 if(endsearched-searched<CHUNKSIZE){
187 bisect=(searched+endsearched)/2;
190 _seek_helper(vf,bisect);
191 ret=_get_next_page(vf,&og,-1);
192 if(ret==OV_EREAD)return(OV_EREAD);
193 if(ret<0 || ogg_page_serialno(&og)!=currentno){
197 searched=ret+og.header_len+og.body_len;
201 _seek_helper(vf,next);
202 ret=_get_next_page(vf,&og,-1);
203 if(ret==OV_EREAD)return(OV_EREAD);
205 if(searched>=end || ret<0){
207 vf->offsets=_ogg_malloc((m+2)*sizeof(ogg_int64_t));
208 vf->offsets[m+1]=searched;
210 ret=_bisect_forward_serialno(vf,next,vf->offset,
211 end,ogg_page_serialno(&og),m+1);
212 if(ret==OV_EREAD)return(OV_EREAD);
215 vf->offsets[m]=begin;
219 /* uses the local ogg_stream storage in vf; this is important for
220 non-streaming input sources */
221 static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
222 long *serialno,ogg_page *og_ptr){
228 ret=_get_next_page(vf,&og,CHUNKSIZE);
229 if(ret==OV_EREAD)return(OV_EREAD);
230 if(ret<0)return OV_ENOTVORBIS;
234 if(serialno)*serialno=ogg_page_serialno(og_ptr);
235 ogg_stream_init(&vf->os,ogg_page_serialno(og_ptr));
237 /* extract the initial header from the first page and verify that the
238 Ogg bitstream is in fact Vorbis data */
240 vorbis_info_init(vi);
241 vorbis_comment_init(vc);
245 ogg_stream_pagein(&vf->os,og_ptr);
247 int result=ogg_stream_packetout(&vf->os,&op);
253 if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
259 if(_get_next_page(vf,og_ptr,1)<0){
267 vorbis_info_clear(vi);
268 vorbis_comment_clear(vc);
269 ogg_stream_clear(&vf->os);
273 /* last step of the OggVorbis_File initialization; get all the
274 vorbis_info structs and PCM positions. Only called by the seekable
275 initialization (local stream storage is hacked slightly; pay
276 attention to how that's done) */
278 /* this is void and does not propogate errors up because we want to be
279 able to open and use damaged bitstreams as well as we can. Just
280 watch out for missing information for links in the OggVorbis_File
282 static void _prefetch_all_headers(OggVorbis_File *vf,vorbis_info *first_i,
283 vorbis_comment *first_c,
288 vf->vi=_ogg_calloc(vf->links,sizeof(vorbis_info));
289 vf->vc=_ogg_calloc(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++){
295 if(first_i && first_c && i==0){
296 /* we already grabbed the initial header earlier. This just
297 saves the waste of grabbing it again */
298 memcpy(vf->vi+i,first_i,sizeof(vorbis_info));
299 memcpy(vf->vc+i,first_c,sizeof(vorbis_comment));
300 vf->dataoffsets[i]=dataoffset;
303 /* seek to the location of the initial header */
305 _seek_helper(vf,vf->offsets[i]);
306 if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){
307 vf->dataoffsets[i]=-1;
309 vf->dataoffsets[i]=vf->offset;
310 ogg_stream_clear(&vf->os);
314 /* get the serial number and PCM length of this link. To do this,
315 get the last page of the stream */
317 long end=vf->offsets[i+1];
318 _seek_helper(vf,end);
321 ret=_get_prev_page(vf,&og);
323 /* this should not be possible, actually */
324 vorbis_info_clear(vf->vi+i);
325 vorbis_comment_clear(vf->vc+i);
328 if(ogg_page_granulepos(&og)!=-1){
329 vf->serialnos[i]=ogg_page_serialno(&og);
330 vf->pcmlengths[i]=ogg_page_granulepos(&og);
338 static void _make_decode_ready(OggVorbis_File *vf){
339 if(vf->decode_ready)return;
341 vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link);
343 vorbis_synthesis_init(&vf->vd,vf->vi);
345 vorbis_block_init(&vf->vd,&vf->vb);
350 static int _open_seekable(OggVorbis_File *vf){
351 vorbis_info initial_i;
352 vorbis_comment initial_c;
358 /* is this even vorbis...? */
359 ret=_fetch_headers(vf,&initial_i,&initial_c,&serialno,NULL);
360 dataoffset=vf->offset;
361 ogg_stream_clear(&vf->os);
362 if(ret<0)return(ret);
364 /* we can seek, so set out learning all about this file */
366 (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
367 vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
369 /* We get the offset for the last page of the physical bitstream.
370 Most OggVorbis files will contain a single logical bitstream */
371 end=_get_prev_page(vf,&og);
373 ogg_stream_clear(&vf->os);
377 /* more than one logical bitstream? */
378 if(ogg_page_serialno(&og)!=serialno){
380 /* Chained bitstream. Bisect-search each logical bitstream
381 section. Do so based on serial number only */
382 if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0){
383 ogg_stream_clear(&vf->os);
389 /* Only one logical bitstream */
390 if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0)){
391 ogg_stream_clear(&vf->os);
397 _prefetch_all_headers(vf,&initial_i,&initial_c,dataoffset);
398 return(ov_raw_seek(vf,0));
402 static int _open_nonseekable(OggVorbis_File *vf){
404 /* we cannot seek. Set up a 'single' (current) logical bitstream entry */
406 vf->vi=_ogg_calloc(vf->links,sizeof(vorbis_info));
407 vf->vc=_ogg_calloc(vf->links,sizeof(vorbis_info));
409 /* Try to fetch the headers, maintaining all the storage */
410 if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0)
412 _make_decode_ready(vf);
417 /* clear out the current logical bitstream decoder */
418 static void _decode_clear(OggVorbis_File *vf){
419 ogg_stream_clear(&vf->os);
420 vorbis_dsp_clear(&vf->vd);
421 vorbis_block_clear(&vf->vb);
428 /* fetch and process a packet. Handles the case where we're at a
429 bitstream boundary and dumps the decoding machine. If the decoding
430 machine is unloaded, it loads it. It also keeps pcm_offset up to
431 date (seek and read both use this. seek uses a special hack with
434 return: <0) error, OV_HOLE (lost packet) or OV_EOF
435 0) need more data (only if readp==0)
439 static int _process_packet(OggVorbis_File *vf,int readp){
442 /* handle one packet. Try to fetch it from current stream state */
443 /* extract packets from page */
446 /* process a packet if we can. If the machine isn't loaded,
448 if(vf->decode_ready){
450 int result=ogg_stream_packetout(&vf->os,&op);
451 ogg_int64_t granulepos;
453 if(result==-1)return(OV_HOLE); /* hole in the data. */
455 /* got a packet. process it */
456 granulepos=op.granulepos;
457 if(!vorbis_synthesis(&vf->vb,&op)){ /* lazy check for lazy
459 header packets aren't
462 vorbis_synthesis will
465 /* suck in the synthesis data and track bitrate */
467 int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
468 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
469 vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
470 vf->bittrack+=op.bytes*8;
473 /* update the pcm offset. */
474 if(granulepos!=-1 && !op.e_o_s){
475 int link=(vf->seekable?vf->current_link:0);
478 /* this packet has a pcm_offset on it (the last packet
479 completed on a page carries the offset) After processing
480 (above), we know the pcm position of the *last* sample
481 ready to be returned. Find the offset of the *first*
483 As an aside, this trick is inaccurate if we begin
484 reading anew right at the last page; the end-of-stream
485 granulepos declares the last frame in the stream, and the
486 last packet of the last page may be a partial frame.
487 So, we need a previous granulepos from an in-sequence page
488 to have a reference point. Thus the !op.e_o_s clause
491 samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
495 granulepos+=vf->pcmlengths[i];
496 vf->pcm_offset=granulepos;
504 if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* eof. leave unitialized */
506 /* bitrate tracking; add the header's bytes here, the body bytes
507 are done by packet above */
508 vf->bittrack+=og.header_len*8;
510 /* has our decoding just traversed a bitstream boundary? */
511 if(vf->decode_ready){
512 if(vf->current_serialno!=ogg_page_serialno(&og)){
517 /* Do we need to load a new machine before submitting the page? */
518 /* This is different in the seekable and non-seekable cases.
520 In the seekable case, we already have all the header
521 information loaded and cached; we just initialize the machine
522 with it and continue on our merry way.
524 In the non-seekable (streaming) case, we'll only be at a
525 boundary if we just left the previous logical bitstream and
526 we're now nominally at the header of the next bitstream
529 if(!vf->decode_ready){
532 vf->current_serialno=ogg_page_serialno(&og);
534 /* match the serialno to bitstream section. We use this rather than
535 offset positions to avoid problems near logical bitstream
537 for(link=0;link<vf->links;link++)
538 if(vf->serialnos[link]==vf->current_serialno)break;
539 if(link==vf->links)return(OV_EBADLINK); /* sign of a bogus
544 vf->current_link=link;
546 ogg_stream_init(&vf->os,vf->current_serialno);
547 ogg_stream_reset(&vf->os);
550 /* we're streaming */
551 /* fetch the three header packets, build the info struct */
553 _fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og);
558 _make_decode_ready(vf);
560 ogg_stream_pagein(&vf->os,&og);
564 /**********************************************************************
565 * The helpers are over; it's all toplevel interface from here on out */
567 /* clear out the OggVorbis_File struct */
568 int ov_clear(OggVorbis_File *vf){
570 vorbis_block_clear(&vf->vb);
571 vorbis_dsp_clear(&vf->vd);
572 ogg_stream_clear(&vf->os);
574 if(vf->vi && vf->links){
576 for(i=0;i<vf->links;i++){
577 vorbis_info_clear(vf->vi+i);
578 vorbis_comment_clear(vf->vc+i);
583 if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
584 if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
585 if(vf->serialnos)_ogg_free(vf->serialnos);
586 if(vf->offsets)_ogg_free(vf->offsets);
587 ogg_sync_clear(&vf->oy);
588 if(vf->datasource)(vf->callbacks.close_func)(vf->datasource);
589 memset(vf,0,sizeof(OggVorbis_File));
597 static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
598 if(f==NULL)return(-1);
599 return fseek(f,(int)off,whence);
602 /* inspects the OggVorbis file and finds/documents all the logical
603 bitstreams contained in it. Tries to be tolerant of logical
604 bitstream sections that are truncated/woogie.
610 int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
611 ov_callbacks callbacks = {
612 (size_t (*)(void *, size_t, size_t, void *)) fread,
613 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
614 (int (*)(void *)) fclose,
615 (long (*)(void *)) ftell
618 return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
622 int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
623 ov_callbacks callbacks)
625 long offset=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
628 memset(vf,0,sizeof(OggVorbis_File));
630 vf->callbacks = callbacks;
632 /* init the framing state */
633 ogg_sync_init(&vf->oy);
635 /* perhaps some data was previously read into a buffer for testing
636 against other stream types. Allow initialization from this
637 previously read data (as we may be reading from a non-seekable
640 char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
641 memcpy(buffer,initial,ibytes);
642 ogg_sync_wrote(&vf->oy,ibytes);
645 /* can we seek? Stevens suggests the seek test was portable */
647 ret=_open_seekable(vf);
649 ret=_open_nonseekable(vf);
658 /* How many logical bitstreams in this physical bitstream? */
659 long ov_streams(OggVorbis_File *vf){
663 /* Is the FILE * associated with vf seekable? */
664 long ov_seekable(OggVorbis_File *vf){
668 /* returns the bitrate for a given logical bitstream or the entire
669 physical bitstream. If the file is open for random access, it will
670 find the *actual* average bitrate. If the file is streaming, it
671 returns the nominal bitrate (if set) else the average of the
672 upper/lower bounds (if set) else -1 (unset).
674 If you want the actual bitrate field settings, get them from the
675 vorbis_info structs */
677 long ov_bitrate(OggVorbis_File *vf,int i){
678 if(i>=vf->links)return(OV_EINVAL);
679 if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
683 for(i=0;i<vf->links;i++)
684 bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
685 return(rint(bits/ov_time_total(vf,-1)));
688 /* return the actual bitrate */
689 return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i)));
691 /* return nominal if set */
692 if(vf->vi[i].bitrate_nominal>0){
693 return vf->vi[i].bitrate_nominal;
695 if(vf->vi[i].bitrate_upper>0){
696 if(vf->vi[i].bitrate_lower>0){
697 return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
699 return vf->vi[i].bitrate_upper;
708 /* returns the actual bitrate since last call. returns -1 if no
709 additional data to offer since last call (or at beginning of stream) */
710 long ov_bitrate_instant(OggVorbis_File *vf){
711 int link=(vf->seekable?vf->current_link:0);
713 if(vf->samptrack==0)return(OV_FALSE);
714 ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
721 long ov_serialnumber(OggVorbis_File *vf,int i){
722 if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
723 if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
725 return(vf->current_serialno);
727 return(vf->serialnos[i]);
731 /* returns: total raw (compressed) length of content if i==-1
732 raw (compressed) length of that logical bitstream for i==0 to n
733 -1 if the stream is not seekable (we can't know the length)
735 ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
736 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
740 for(i=0;i<vf->links;i++)
741 acc+=ov_raw_total(vf,i);
744 return(vf->offsets[i+1]-vf->offsets[i]);
748 /* returns: total PCM length (samples) of content if i==-1
749 PCM length (samples) of that logical bitstream for i==0 to n
750 -1 if the stream is not seekable (we can't know the length)
752 ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
753 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
757 for(i=0;i<vf->links;i++)
758 acc+=ov_pcm_total(vf,i);
761 return(vf->pcmlengths[i]);
765 /* returns: total seconds of content if i==-1
766 seconds in that logical bitstream for i==0 to n
767 -1 if the stream is not seekable (we can't know the length)
769 double ov_time_total(OggVorbis_File *vf,int i){
770 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
774 for(i=0;i<vf->links;i++)
775 acc+=ov_time_total(vf,i);
778 return((float)(vf->pcmlengths[i])/vf->vi[i].rate);
782 /* seek to an offset relative to the *compressed* data. This also
783 immediately sucks in and decodes pages to update the PCM cursor. It
784 will cross a logical bitstream boundary, but only if it can't get
785 any packets out of the tail of the bitstream we seek to (so no
788 returns zero on success, nonzero on failure */
790 int ov_raw_seek(OggVorbis_File *vf,long pos){
792 if(!vf->seekable)return(OV_ENOSEEK); /* don't dump machine if we can't seek */
793 if(pos<0 || pos>vf->offsets[vf->links])return(OV_EINVAL);
795 /* clear out decoding machine state */
800 _seek_helper(vf,pos);
802 /* we need to make sure the pcm_offset is set. We use the
803 _fetch_packet helper to process one packet with readp set, then
804 call it until it returns '0' with readp not set (the last packet
805 from a page has the 'granulepos' field set, and that's how the
806 helper updates the offset */
809 switch(_process_packet(vf,1)){
811 /* oh, eof. There are no packets remaining. Set the pcm offset to
813 vf->pcm_offset=ov_pcm_total(vf,-1);
827 /* don't have to check each time through for the updated granule;
828 it's always the last complete packet on a page */
829 switch(_process_packet(vf,0)){
831 /* the offset is set unless it's a bogus bitstream with no
832 offset information but that's not our fault. We still run
833 gracefully, we're just missing the offset */
838 /* continue processing packets */
844 /* dump the machine so we're in a known state */
850 int ov_raw_seek2(OggVorbis_File *vf,long pos, int offset, int link){
852 if(!vf->seekable)return(OV_ENOSEEK); /* don't dump machine if we can't seek */
853 if(pos<0 || pos>vf->offsets[vf->links])return(OV_EINVAL);
855 /* clear out decoding machine state */
858 // ogg_stream_clear(&vf->os);
859 // vf->decode_ready=0;
862 // vf->samptrack=0.f;
865 _seek_helper(vf,pos);
867 /* we need to make sure the pcm_offset is set. We use the
868 _fetch_packet helper to process one packet with readp set, then
869 call it until it returns '0' with readp not set (the last packet
870 from a page has the 'granulepos' field set, and that's how the
871 helper updates the offset */
876 ret=_get_next_page(vf,&og,vf->offsets[link+1]-vf->offset);
879 vf->pcm_offset = offset;
886 /* Page granularity seek (faster than sample granularity because we
887 don't do the last bit of decode to find a specific sample).
889 Seek to the last [granule marked] page preceeding the specified pos
890 location, such that decoding past the returned point will quickly
891 arrive at the requested position. */
892 int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
895 ogg_int64_t total=ov_pcm_total(vf,-1);
897 if(!vf->seekable)return(OV_ENOSEEK);
898 if(pos<0 || pos>total)return(OV_EINVAL);
900 /* which bitstream section does this pcm offset occur in? */
901 for(link=vf->links-1;link>=0;link--){
902 total-=vf->pcmlengths[link];
906 /* search within the logical bitstream for the page with the highest
907 pcm_pos preceeding (or equal to) pos. There is a danger here;
908 missing pages or incorrect frame number information in the
909 bitstream could make our task impossible. Account for that (it
910 would be an error condition) */
913 // HB (Nicholas Vinen)
914 // I think this should be much faster.
916 ogg_int64_t target=pos-total;
917 long end=vf->offsets[link+1];
918 long begin=vf->offsets[link];
919 ogg_int64_t endtime = vf->pcmlengths[link];
920 ogg_int64_t begintime = 0;
927 if(end-begin<CHUNKSIZE){
930 //take a (pretty decent) guess.
931 bisect=begin + (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
937 _seek_helper(vf,bisect);
938 ret=_get_next_page(vf,&og,end-bisect);
940 case OV_FALSE: case OV_EOF:
953 ogg_int64_t granulepos=ogg_page_granulepos(&og);
954 if(granulepos<target){
955 best=ret; /* raw offset of packet with granulepos */
956 begin=vf->offset; /* raw offset of next packet */
957 begintime=granulepos;
959 if(target-begintime<2000) { //less than 1s before we hit the right page.
969 //we're pretty close - we'd be stuck in an endless loop otherwise...
971 goto TryAgain; //sorry, I like gotos :)
980 /* found our page. seek to it (call raw_seek). */
982 if(link!=vf->current_link){
983 if((ret=ov_raw_seek(vf,best)))goto seek_error;
985 if((ret=ov_raw_seek2(vf,best,begintime,link)))goto seek_error;
991 ogg_int64_t target=pos-total;
992 long end=vf->offsets[link+1];
993 long begin=vf->offsets[link];
1000 if(end-begin<CHUNKSIZE){
1003 bisect=(end+begin)/2;
1006 _seek_helper(vf,bisect);
1007 ret=_get_next_page(vf,&og,end-bisect);
1009 case OV_FALSE: case OV_EOF:
1016 ogg_int64_t granulepos=ogg_page_granulepos(&og);
1017 if(granulepos<target){
1018 best=ret; /* raw offset of packet with granulepos */
1019 begin=vf->offset; /* raw offset of next packet */
1027 /* found our page. seek to it (call raw_seek). */
1029 if((ret=ov_raw_seek(vf,best)))goto seek_error;
1034 if(vf->pcm_offset>=pos || pos>ov_pcm_total(vf,-1)){
1041 /* dump machine so we're in a known state */
1047 /* seek to a sample offset relative to the decompressed pcm stream
1048 returns zero on success, nonzero on failure */
1050 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1051 int ret=ov_pcm_seek_page(vf,pos);
1052 if(ret<0)return(ret);
1054 /* discard samples until we reach the desired position. Crossing a
1055 logical bitstream boundary with abandon is OK. */
1056 while(vf->pcm_offset<pos){
1058 long target=pos-vf->pcm_offset;
1059 long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1063 if(samples>target)samples=target;
1064 vorbis_synthesis_read(&vf->vd,samples);
1065 vf->pcm_offset+=samples;
1068 if(_process_packet(vf,1)==0)
1069 vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1074 /* seek to a playback time relative to the decompressed pcm stream
1075 returns zero on success, nonzero on failure */
1076 int ov_time_seek(OggVorbis_File *vf,double seconds){
1077 /* translate time to PCM position and call ov_pcm_seek */
1080 ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1081 double time_total=ov_time_total(vf,-1);
1083 if(!vf->seekable)return(OV_ENOSEEK);
1084 if(seconds<0 || seconds>time_total)return(OV_EINVAL);
1086 /* which bitstream section does this time offset occur in? */
1087 for(link=vf->links-1;link>=0;link--){
1088 pcm_total-=vf->pcmlengths[link];
1089 time_total-=ov_time_total(vf,link);
1090 if(seconds>=time_total)break;
1093 /* enough information to convert time offset to pcm offset */
1095 ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1096 return(ov_pcm_seek(vf,target));
1100 /* page-granularity version of ov_time_seek
1101 returns zero on success, nonzero on failure */
1102 int ov_time_seek_page(OggVorbis_File *vf,double seconds){
1103 /* translate time to PCM position and call ov_pcm_seek */
1106 ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1107 double time_total=ov_time_total(vf,-1);
1109 if(!vf->seekable)return(OV_ENOSEEK);
1110 if(seconds<0 || seconds>time_total)return(OV_EINVAL);
1112 /* which bitstream section does this time offset occur in? */
1113 for(link=vf->links-1;link>=0;link--){
1114 pcm_total-=vf->pcmlengths[link];
1115 time_total-=ov_time_total(vf,link);
1116 if(seconds>=time_total)break;
1119 /* enough information to convert time offset to pcm offset */
1121 ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1122 return(ov_pcm_seek_page(vf,target));
1126 /* tell the current stream offset cursor. Note that seek followed by
1127 tell will likely not give the set offset due to caching */
1128 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1132 /* return PCM offset (sample) of next PCM sample to be read */
1133 ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1134 return(vf->pcm_offset);
1137 /* return time offset (seconds) of next PCM sample to be read */
1138 double ov_time_tell(OggVorbis_File *vf){
1139 /* translate time to PCM position and call ov_pcm_seek */
1142 ogg_int64_t pcm_total=0;
1143 double time_total=0.f;
1146 pcm_total=ov_pcm_total(vf,-1);
1147 time_total=ov_time_total(vf,-1);
1149 /* which bitstream section does this time offset occur in? */
1150 for(link=vf->links-1;link>=0;link--){
1151 pcm_total-=vf->pcmlengths[link];
1152 time_total-=ov_time_total(vf,link);
1153 if(vf->pcm_offset>=pcm_total)break;
1157 return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1160 /* link: -1) return the vorbis_info struct for the bitstream section
1161 currently being decoded
1162 0-n) to request information for a specific bitstream section
1164 In the case of a non-seekable bitstream, any call returns the
1165 current bitstream. NULL in the case that the machine is not
1168 vorbis_info *ov_info(OggVorbis_File *vf,int link){
1171 if(vf->decode_ready)
1172 return vf->vi+vf->current_link;
1181 if(vf->decode_ready)
1188 /* grr, strong typing, grr, no templates/inheritence, grr */
1189 vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1192 if(vf->decode_ready)
1193 return vf->vc+vf->current_link;
1202 if(vf->decode_ready)
1209 int host_is_big_endian() {
1210 ogg_int32_t pattern = 0xfeedface; /* deadbeef */
1211 unsigned char *bytewise = (unsigned char *)&pattern;
1212 if (bytewise[0] == 0xfe) return 1;
1216 /* up to this point, everything could more or less hide the multiple
1217 logical bitstream nature of chaining from the toplevel application
1218 if the toplevel application didn't particularly care. However, at
1219 the point that we actually read audio back, the multiple-section
1220 nature must surface: Multiple bitstream sections do not necessarily
1221 have to have the same number of channels or sampling rate.
1223 ov_read returns the sequential logical bitstream number currently
1224 being decoded along with the PCM data in order that the toplevel
1225 application can take action on channel/sample rate changes. This
1226 number will be incremented even for streamed (non-seekable) streams
1227 (for seekable streams, it represents the actual logical bitstream
1228 index within the physical bitstream. Note that the accessor
1229 functions above are aware of this dichotomy).
1231 input values: buffer) a buffer to hold packed PCM data for return
1232 length) the byte length requested to be placed into buffer
1233 bigendianp) should the data be packed LSB first (0) or
1235 word) word size for output. currently 1 (byte) or
1238 return values: <0) error/hole in data (OV_HOLE)
1240 n) number of bytes of PCM actually returned. The
1241 below works on a packet-by-packet basis, so the
1242 return length is not related to the 'length' passed
1243 in, just guaranteed to fit.
1245 *section) set to the logical bitstream number */
1247 long ov_read(OggVorbis_File *vf,char *buffer,int length,
1248 int bigendianp,int word,int sgned,int *bitstream){
1250 int host_endian = host_is_big_endian();
1253 if(vf->decode_ready){
1255 long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1257 /* yay! proceed to pack data into the byte buffer */
1259 long channels=ov_info(vf,-1)->channels;
1260 long bytespersample=word * channels;
1261 vorbis_fpu_control fpu;
1262 if(samples>length/bytespersample)samples=length/bytespersample;
1264 /* a tight loop to pack each size */
1268 int off=(sgned?0:128);
1269 vorbis_fpu_setround(&fpu);
1270 for(j=0;j<samples;j++)
1271 for(i=0;i<channels;i++){
1272 val=vorbis_ftoi(pcm[i][j]*128.f);
1274 else if(val<-128)val=-128;
1277 vorbis_fpu_restore(fpu);
1279 int off=(sgned?0:32768);
1281 if(host_endian==bigendianp){
1284 vorbis_fpu_setround(&fpu);
1285 for(i=0;i<channels;i++) { /* It's faster in this order */
1287 short *dest=((short *)buffer)+i;
1288 for(j=0;j<samples;j++) {
1289 val=vorbis_ftoi(src[j]*32768.f);
1290 if(val>32767)val=32767;
1291 else if(val<-32768)val=-32768;
1296 vorbis_fpu_restore(fpu);
1300 vorbis_fpu_setround(&fpu);
1301 for(i=0;i<channels;i++) {
1303 short *dest=((short *)buffer)+i;
1304 for(j=0;j<samples;j++) {
1305 val=vorbis_ftoi(src[j]*32768.f);
1306 if(val>32767)val=32767;
1307 else if(val<-32768)val=-32768;
1312 vorbis_fpu_restore(fpu);
1315 }else if(bigendianp){
1317 vorbis_fpu_setround(&fpu);
1318 for(j=0;j<samples;j++)
1319 for(i=0;i<channels;i++){
1320 val=vorbis_ftoi(pcm[i][j]*32768.f);
1321 if(val>32767)val=32767;
1322 else if(val<-32768)val=-32768;
1325 *buffer++=(val&0xff);
1327 vorbis_fpu_restore(fpu);
1331 vorbis_fpu_setround(&fpu);
1332 for(j=0;j<samples;j++)
1333 for(i=0;i<channels;i++){
1334 val=vorbis_ftoi(pcm[i][j]*32768.f);
1335 if(val>32767)val=32767;
1336 else if(val<-32768)val=-32768;
1338 *buffer++=(val&0xff);
1341 vorbis_fpu_restore(fpu);
1347 vorbis_synthesis_read(&vf->vd,samples);
1348 vf->pcm_offset+=samples;
1349 if(bitstream)*bitstream=vf->current_link;
1350 return(samples*bytespersample);
1354 /* suck in another packet */
1355 switch(_process_packet(vf,1)){
1361 return(OV_EBADLINK);