Recognizes if input is ogg or not.
[xiph.git] / Tremor / vorbisfile.c
blob0c48f1fff2c57d8187c76b3514d76f95a944e79e
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: vorbisfile.c,v 1.6 2003/03/30 23:40:56 xiphmont Exp $
17 ********************************************************************/
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <math.h>
25 #include "ivorbiscodec.h"
26 #include "ivorbisfile.h"
28 #include "misc.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 coarse 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 */
60 /* read a little more data from the file/pipe into the ogg_sync framer */
61 static long _get_data(OggVorbis_File *vf){
62 errno=0;
63 if(vf->datasource){
64 unsigned char *buffer=ogg_sync_bufferin(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);
68 return(bytes);
69 }else
70 return(0);
73 /* save a tiny smidge of verbosity to make the code more readable */
74 static void _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
75 if(vf->datasource){
76 (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET);
77 vf->offset=offset;
78 ogg_sync_reset(vf->oy);
79 }else{
80 /* shouldn't happen unless someone writes a broken callback */
81 return;
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 produces a refcounted page */
100 static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
101 ogg_int64_t boundary){
102 if(boundary>0)boundary+=vf->offset;
103 while(1){
104 long more;
106 if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
107 more=ogg_sync_pageseek(vf->oy,og);
109 if(more<0){
110 /* skipped n bytes */
111 vf->offset-=more;
112 }else{
113 if(more==0){
114 /* send more paramedics */
115 if(!boundary)return(OV_FALSE);
117 long ret=_get_data(vf);
118 if(ret==0)return(OV_EOF);
119 if(ret<0)return(OV_EREAD);
121 }else{
122 /* got a page. Return the offset at the page beginning,
123 advance the internal offset past the page end */
124 ogg_int64_t ret=vf->offset;
125 vf->offset+=more;
126 return(ret);
133 /* find the latest page beginning before the current stream cursor
134 position. Much dirtier than the above as Ogg doesn't have any
135 backward search linkage. no 'readp' as it will certainly have to
136 read. */
137 /* returns offset or OV_EREAD, OV_FAULT and produces a refcounted page */
139 static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
140 ogg_int64_t begin=vf->offset;
141 ogg_int64_t end=begin;
142 ogg_int64_t ret;
143 ogg_int64_t offset=-1;
145 while(offset==-1){
146 begin-=CHUNKSIZE;
147 if(begin<0)
148 begin=0;
149 _seek_helper(vf,begin);
150 while(vf->offset<end){
151 ret=_get_next_page(vf,og,end-vf->offset);
152 if(ret==OV_EREAD)return(OV_EREAD);
153 if(ret<0){
154 break;
155 }else{
156 offset=ret;
161 /* we have the offset. Actually snork and hold the page now */
162 _seek_helper(vf,offset);
163 ret=_get_next_page(vf,og,CHUNKSIZE);
164 if(ret<0)
165 /* this shouldn't be possible */
166 return(OV_EFAULT);
168 return(offset);
171 /* finds each bitstream link one at a time using a bisection search
172 (has to begin by knowing the offset of the lb's initial page).
173 Recurses for each link so it can alloc the link storage after
174 finding them all, then unroll and fill the cache at the same time */
175 static int _bisect_forward_serialno(OggVorbis_File *vf,
176 ogg_int64_t begin,
177 ogg_int64_t searched,
178 ogg_int64_t end,
179 ogg_uint32_t currentno,
180 long m){
181 ogg_int64_t endsearched=end;
182 ogg_int64_t next=end;
183 ogg_page og={0,0,0,0};
184 ogg_int64_t ret;
186 /* the below guards against garbage seperating the last and
187 first pages of two links. */
188 while(searched<endsearched){
189 ogg_int64_t bisect;
191 if(endsearched-searched<CHUNKSIZE){
192 bisect=searched;
193 }else{
194 bisect=(searched+endsearched)/2;
197 _seek_helper(vf,bisect);
198 ret=_get_next_page(vf,&og,-1);
199 if(ret==OV_EREAD)return(OV_EREAD);
200 if(ret<0 || ogg_page_serialno(&og)!=currentno){
201 endsearched=bisect;
202 if(ret>=0)next=ret;
203 }else{
204 searched=ret+og.header_len+og.body_len;
206 ogg_page_release(&og);
209 _seek_helper(vf,next);
210 ret=_get_next_page(vf,&og,-1);
211 if(ret==OV_EREAD)return(OV_EREAD);
213 if(searched>=end || ret<0){
214 ogg_page_release(&og);
215 vf->links=m+1;
216 vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
217 vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
218 vf->offsets[m+1]=searched;
219 }else{
220 ret=_bisect_forward_serialno(vf,next,vf->offset,
221 end,ogg_page_serialno(&og),m+1);
222 ogg_page_release(&og);
223 if(ret==OV_EREAD)return(OV_EREAD);
226 vf->offsets[m]=begin;
227 vf->serialnos[m]=currentno;
228 return(0);
231 /* uses the local ogg_stream storage in vf; this is important for
232 non-streaming input sources */
233 /* consumes the page that's passed in (if any) */
235 static int _fetch_headers(OggVorbis_File *vf,
236 vorbis_info *vi,
237 vorbis_comment *vc,
238 ogg_uint32_t *serialno,
239 ogg_page *og_ptr){
240 ogg_page og={0,0,0,0};
241 ogg_packet op={0,0,0,0,0,0};
242 int i,ret;
244 if(!og_ptr){
245 ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
246 if(llret==OV_EREAD)return(OV_EREAD);
247 if(llret<0)return OV_ENOTVORBIS;
248 og_ptr=&og;
251 ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr));
252 if(serialno)*serialno=vf->os->serialno;
253 vf->ready_state=STREAMSET;
255 /* extract the initial header from the first page and verify that the
256 Ogg bitstream is in fact Vorbis data */
258 vorbis_info_init(vi);
259 vorbis_comment_init(vc);
261 i=0;
262 while(i<3){
263 ogg_stream_pagein(vf->os,og_ptr);
264 while(i<3){
265 int result=ogg_stream_packetout(vf->os,&op);
266 if(result==0)break;
267 if(result==-1){
268 ret=OV_EBADHEADER;
269 goto bail_header;
271 if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
272 goto bail_header;
274 i++;
276 if(i<3)
277 if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
278 ret=OV_EBADHEADER;
279 goto bail_header;
283 ogg_packet_release(&op);
284 ogg_page_release(&og);
285 return 0;
287 bail_header:
288 ogg_packet_release(&op);
289 ogg_page_release(&og);
290 vorbis_info_clear(vi);
291 vorbis_comment_clear(vc);
292 vf->ready_state=OPENED;
294 return ret;
297 /* last step of the OggVorbis_File initialization; get all the
298 vorbis_info structs and PCM positions. Only called by the seekable
299 initialization (local stream storage is hacked slightly; pay
300 attention to how that's done) */
302 /* this is void and does not propogate errors up because we want to be
303 able to open and use damaged bitstreams as well as we can. Just
304 watch out for missing information for links in the OggVorbis_File
305 struct */
306 static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){
307 ogg_page og={0,0,0,0};
308 int i;
309 ogg_int64_t ret;
311 vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
312 vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
313 vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
314 vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
316 for(i=0;i<vf->links;i++){
317 if(i==0){
318 /* we already grabbed the initial header earlier. Just set the offset */
319 vf->dataoffsets[i]=dataoffset;
320 _seek_helper(vf,dataoffset);
322 }else{
324 /* seek to the location of the initial header */
326 _seek_helper(vf,vf->offsets[i]);
327 if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){
328 vf->dataoffsets[i]=-1;
329 }else{
330 vf->dataoffsets[i]=vf->offset;
334 /* fetch beginning PCM offset */
336 if(vf->dataoffsets[i]!=-1){
337 ogg_int64_t accumulated=0,pos;
338 long lastblock=-1;
339 int result;
341 ogg_stream_reset_serialno(vf->os,vf->serialnos[i]);
343 while(1){
344 ogg_packet op={0,0,0,0,0,0};
346 ret=_get_next_page(vf,&og,-1);
347 if(ret<0)
348 /* this should not be possible unless the file is
349 truncated/mangled */
350 break;
352 if(ogg_page_serialno(&og)!=vf->serialnos[i])
353 break;
355 pos=ogg_page_granulepos(&og);
357 /* count blocksizes of all frames in the page */
358 ogg_stream_pagein(vf->os,&og);
359 while((result=ogg_stream_packetout(vf->os,&op))){
360 if(result>0){ /* ignore holes */
361 long thisblock=vorbis_packet_blocksize(vf->vi+i,&op);
362 if(lastblock!=-1)
363 accumulated+=(lastblock+thisblock)>>2;
364 lastblock=thisblock;
367 ogg_packet_release(&op);
369 if(pos!=-1){
370 /* pcm offset of last packet on the first audio page */
371 accumulated= pos-accumulated;
372 break;
376 /* less than zero? This is a stream with samples trimmed off
377 the beginning, a normal occurrence; set the offset to zero */
378 if(accumulated<0)accumulated=0;
380 vf->pcmlengths[i*2]=accumulated;
383 /* get the PCM length of this link. To do this,
384 get the last page of the stream */
386 ogg_int64_t end=vf->offsets[i+1];
387 _seek_helper(vf,end);
389 while(1){
390 ret=_get_prev_page(vf,&og);
391 if(ret<0){
392 /* this should not be possible */
393 vorbis_info_clear(vf->vi+i);
394 vorbis_comment_clear(vf->vc+i);
395 break;
397 if(ogg_page_granulepos(&og)!=-1){
398 vf->pcmlengths[i*2+1]=ogg_page_granulepos(&og)-vf->pcmlengths[i*2];
399 break;
401 vf->offset=ret;
405 ogg_page_release(&og);
408 static void _make_decode_ready(OggVorbis_File *vf){
409 if(vf->ready_state!=STREAMSET)return;
410 if(vf->seekable){
411 vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link);
412 }else{
413 vorbis_synthesis_init(&vf->vd,vf->vi);
415 vorbis_block_init(&vf->vd,&vf->vb);
416 vf->ready_state=INITSET;
417 vf->bittrack=0;
418 vf->samptrack=0;
419 return;
422 static int _open_seekable2(OggVorbis_File *vf){
423 ogg_uint32_t serialno=vf->current_serialno;
424 ogg_uint32_t tempserialno;
425 ogg_int64_t dataoffset=vf->offset, end;
426 ogg_page og={0,0,0,0};
428 /* we're partially open and have a first link header state in
429 storage in vf */
430 /* we can seek, so set out learning all about this file */
431 (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
432 vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
434 /* We get the offset for the last page of the physical bitstream.
435 Most OggVorbis files will contain a single logical bitstream */
436 end=_get_prev_page(vf,&og);
437 if(end<0)return(end);
439 /* more than one logical bitstream? */
440 tempserialno=ogg_page_serialno(&og);
441 ogg_page_release(&og);
443 if(tempserialno!=serialno){
445 /* Chained bitstream. Bisect-search each logical bitstream
446 section. Do so based on serial number only */
447 if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0)return(OV_EREAD);
449 }else{
451 /* Only one logical bitstream */
452 if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0))return(OV_EREAD);
456 /* the initial header memory is referenced by vf after; don't free it */
457 _prefetch_all_headers(vf,dataoffset);
458 return(ov_raw_seek(vf,0));
461 /* clear out the current logical bitstream decoder */
462 static void _decode_clear(OggVorbis_File *vf){
463 vorbis_dsp_clear(&vf->vd);
464 vorbis_block_clear(&vf->vb);
465 vf->ready_state=OPENED;
468 /* fetch and process a packet. Handles the case where we're at a
469 bitstream boundary and dumps the decoding machine. If the decoding
470 machine is unloaded, it loads it. It also keeps pcm_offset up to
471 date (seek and read both use this. seek uses a special hack with
472 readp).
474 return: <0) error, OV_HOLE (lost packet) or OV_EOF
475 0) need more data (only if readp==0)
476 1) got a packet
479 static int _fetch_and_process_packet(OggVorbis_File *vf,
480 int readp,
481 int spanp){
482 ogg_page og={0,0,0,0};
483 ogg_packet op={0,0,0,0,0,0};
484 int ret=0;
486 /* handle one packet. Try to fetch it from current stream state */
487 /* extract packets from page */
488 while(1){
490 /* process a packet if we can. If the machine isn't loaded,
491 neither is a page */
492 if(vf->ready_state==INITSET){
493 while(1) {
494 int result=ogg_stream_packetout(vf->os,&op);
495 ogg_int64_t granulepos;
497 if(result<0){
498 ret=OV_HOLE; /* hole in the data. */
499 goto cleanup;
501 if(result>0){
502 /* got a packet. process it */
503 granulepos=op.granulepos;
504 if(!vorbis_synthesis(&vf->vb,&op,1)){ /* lazy check for lazy
505 header handling. The
506 header packets aren't
507 audio, so if/when we
508 submit them,
509 vorbis_synthesis will
510 reject them */
512 /* suck in the synthesis data and track bitrate */
514 int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
515 /* for proper use of libvorbis within libvorbisfile,
516 oldsamples will always be zero. */
517 if(oldsamples){
518 ret=OV_EFAULT;
519 goto cleanup;
522 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
523 vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
524 vf->bittrack+=op.bytes*8;
527 /* update the pcm offset. */
528 if(granulepos!=-1 && !op.e_o_s){
529 int link=(vf->seekable?vf->current_link:0);
530 int i,samples;
532 /* this packet has a pcm_offset on it (the last packet
533 completed on a page carries the offset) After processing
534 (above), we know the pcm position of the *last* sample
535 ready to be returned. Find the offset of the *first*
537 As an aside, this trick is inaccurate if we begin
538 reading anew right at the last page; the end-of-stream
539 granulepos declares the last frame in the stream, and the
540 last packet of the last page may be a partial frame.
541 So, we need a previous granulepos from an in-sequence page
542 to have a reference point. Thus the !op.e_o_s clause
543 above */
545 if(vf->seekable && link>0)
546 granulepos-=vf->pcmlengths[link*2];
547 if(granulepos<0)granulepos=0; /* actually, this
548 shouldn't be possible
549 here unless the stream
550 is very broken */
552 samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
554 granulepos-=samples;
555 for(i=0;i<link;i++)
556 granulepos+=vf->pcmlengths[i*2+1];
557 vf->pcm_offset=granulepos;
559 ret=1;
560 goto cleanup;
563 else
564 break;
568 if(vf->ready_state>=OPENED){
569 int ret;
570 if(!readp){
571 ret=0;
572 goto cleanup;
574 if((ret=_get_next_page(vf,&og,-1))<0){
575 ret=OV_EOF; /* eof. leave unitialized */
576 goto cleanup;
579 /* bitrate tracking; add the header's bytes here, the body bytes
580 are done by packet above */
581 vf->bittrack+=og.header_len*8;
583 /* has our decoding just traversed a bitstream boundary? */
584 if(vf->ready_state==INITSET){
585 if(vf->current_serialno!=ogg_page_serialno(&og)){
586 if(!spanp){
587 ret=OV_EOF;
588 goto cleanup;
591 _decode_clear(vf);
593 if(!vf->seekable){
594 vorbis_info_clear(vf->vi);
595 vorbis_comment_clear(vf->vc);
601 /* Do we need to load a new machine before submitting the page? */
602 /* This is different in the seekable and non-seekable cases.
604 In the seekable case, we already have all the header
605 information loaded and cached; we just initialize the machine
606 with it and continue on our merry way.
608 In the non-seekable (streaming) case, we'll only be at a
609 boundary if we just left the previous logical bitstream and
610 we're now nominally at the header of the next bitstream
613 if(vf->ready_state!=INITSET){
614 int link;
616 if(vf->ready_state<STREAMSET){
617 if(vf->seekable){
618 vf->current_serialno=ogg_page_serialno(&og);
620 /* match the serialno to bitstream section. We use this rather than
621 offset positions to avoid problems near logical bitstream
622 boundaries */
623 for(link=0;link<vf->links;link++)
624 if(vf->serialnos[link]==vf->current_serialno)break;
625 if(link==vf->links){
626 ret=OV_EBADLINK; /* sign of a bogus stream. error out,
627 leave machine uninitialized */
628 goto cleanup;
631 vf->current_link=link;
633 ogg_stream_reset_serialno(vf->os,vf->current_serialno);
634 vf->ready_state=STREAMSET;
636 }else{
637 /* we're streaming */
638 /* fetch the three header packets, build the info struct */
640 int ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og);
641 if(ret) goto cleanup;
642 vf->current_link++;
643 link=0;
647 _make_decode_ready(vf);
649 ogg_stream_pagein(vf->os,&og);
651 cleanup:
652 ogg_packet_release(&op);
653 ogg_page_release(&og);
654 return ret;
657 /* if, eg, 64 bit stdio is configured by default, this will build with
658 fseek64 */
659 static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
660 if(f==NULL)return(-1);
661 return fseek(f,off,whence);
664 static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
665 long ibytes, ov_callbacks callbacks){
666 int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
667 int ret;
669 memset(vf,0,sizeof(*vf));
670 vf->datasource=f;
671 vf->callbacks = callbacks;
673 /* init the framing state */
674 vf->oy=ogg_sync_create();
676 /* perhaps some data was previously read into a buffer for testing
677 against other stream types. Allow initialization from this
678 previously read data (as we may be reading from a non-seekable
679 stream) */
680 if(initial){
681 unsigned char *buffer=ogg_sync_bufferin(vf->oy,ibytes);
682 memcpy(buffer,initial,ibytes);
683 ogg_sync_wrote(vf->oy,ibytes);
686 /* can we seek? Stevens suggests the seek test was portable */
687 if(offsettest!=-1)vf->seekable=1;
689 /* No seeking yet; Set up a 'single' (current) logical bitstream
690 entry for partial open */
691 vf->links=1;
692 vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
693 vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
694 vf->os=ogg_stream_create(-1); /* fill in the serialno later */
696 /* Try to fetch the headers, maintaining all the storage */
697 if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0){
698 vf->datasource=NULL;
699 ov_clear(vf);
700 }else if(vf->ready_state < PARTOPEN)
701 vf->ready_state=PARTOPEN;
702 return(ret);
705 static int _ov_open2(OggVorbis_File *vf){
706 if(vf->ready_state < OPENED)
707 vf->ready_state=OPENED;
708 if(vf->seekable){
709 int ret=_open_seekable2(vf);
710 if(ret){
711 vf->datasource=NULL;
712 ov_clear(vf);
714 return(ret);
716 return 0;
720 /* clear out the OggVorbis_File struct */
721 int ov_clear(OggVorbis_File *vf){
722 if(vf){
723 vorbis_block_clear(&vf->vb);
724 vorbis_dsp_clear(&vf->vd);
725 ogg_stream_destroy(vf->os);
727 if(vf->vi && vf->links){
728 int i;
729 for(i=0;i<vf->links;i++){
730 vorbis_info_clear(vf->vi+i);
731 vorbis_comment_clear(vf->vc+i);
733 _ogg_free(vf->vi);
734 _ogg_free(vf->vc);
736 if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
737 if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
738 if(vf->serialnos)_ogg_free(vf->serialnos);
739 if(vf->offsets)_ogg_free(vf->offsets);
740 ogg_sync_destroy(vf->oy);
742 if(vf->datasource)(vf->callbacks.close_func)(vf->datasource);
743 memset(vf,0,sizeof(*vf));
745 #ifdef DEBUG_LEAKS
746 _VDBG_dump();
747 #endif
748 return(0);
751 /* inspects the OggVorbis file and finds/documents all the logical
752 bitstreams contained in it. Tries to be tolerant of logical
753 bitstream sections that are truncated/woogie.
755 return: -1) error
756 0) OK
759 int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
760 ov_callbacks callbacks){
761 int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
762 if(ret)return ret;
763 return _ov_open2(vf);
766 int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
767 ov_callbacks callbacks = {
768 (size_t (*)(void *, size_t, size_t, void *)) fread,
769 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
770 (int (*)(void *)) fclose,
771 (long (*)(void *)) ftell
774 return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
777 /* Only partially open the vorbis file; test for Vorbisness, and load
778 the headers for the first chain. Do not seek (although test for
779 seekability). Use ov_test_open to finish opening the file, else
780 ov_clear to close/free it. Same return codes as open. */
782 int ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
783 ov_callbacks callbacks)
785 return _ov_open1(f,vf,initial,ibytes,callbacks);
788 int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
789 ov_callbacks callbacks = {
790 (size_t (*)(void *, size_t, size_t, void *)) fread,
791 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
792 (int (*)(void *)) fclose,
793 (long (*)(void *)) ftell
796 return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
799 int ov_test_open(OggVorbis_File *vf){
800 if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
801 return _ov_open2(vf);
804 /* How many logical bitstreams in this physical bitstream? */
805 long ov_streams(OggVorbis_File *vf){
806 return vf->links;
809 /* Is the FILE * associated with vf seekable? */
810 long ov_seekable(OggVorbis_File *vf){
811 return vf->seekable;
814 /* returns the bitrate for a given logical bitstream or the entire
815 physical bitstream. If the file is open for random access, it will
816 find the *actual* average bitrate. If the file is streaming, it
817 returns the nominal bitrate (if set) else the average of the
818 upper/lower bounds (if set) else -1 (unset).
820 If you want the actual bitrate field settings, get them from the
821 vorbis_info structs */
823 long ov_bitrate(OggVorbis_File *vf,int i){
824 if(vf->ready_state<OPENED)return(OV_EINVAL);
825 if(i>=vf->links)return(OV_EINVAL);
826 if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
827 if(i<0){
828 ogg_int64_t bits=0;
829 int i;
830 for(i=0;i<vf->links;i++)
831 bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
832 /* This once read: return(rint(bits/ov_time_total(vf,-1)));
833 * gcc 3.x on x86 miscompiled this at optimisation level 2 and above,
834 * so this is slightly transformed to make it work.
836 return(bits*1000/ov_time_total(vf,-1));
837 }else{
838 if(vf->seekable){
839 /* return the actual bitrate */
840 return((vf->offsets[i+1]-vf->dataoffsets[i])*8000/ov_time_total(vf,i));
841 }else{
842 /* return nominal if set */
843 if(vf->vi[i].bitrate_nominal>0){
844 return vf->vi[i].bitrate_nominal;
845 }else{
846 if(vf->vi[i].bitrate_upper>0){
847 if(vf->vi[i].bitrate_lower>0){
848 return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
849 }else{
850 return vf->vi[i].bitrate_upper;
853 return(OV_FALSE);
859 /* returns the actual bitrate since last call. returns -1 if no
860 additional data to offer since last call (or at beginning of stream),
861 EINVAL if stream is only partially open
863 long ov_bitrate_instant(OggVorbis_File *vf){
864 int link=(vf->seekable?vf->current_link:0);
865 long ret;
866 if(vf->ready_state<OPENED)return(OV_EINVAL);
867 if(vf->samptrack==0)return(OV_FALSE);
868 ret=vf->bittrack/vf->samptrack*vf->vi[link].rate;
869 vf->bittrack=0;
870 vf->samptrack=0;
871 return(ret);
874 /* Guess */
875 long ov_serialnumber(OggVorbis_File *vf,int i){
876 if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
877 if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
878 if(i<0){
879 return(vf->current_serialno);
880 }else{
881 return(vf->serialnos[i]);
885 /* returns: total raw (compressed) length of content if i==-1
886 raw (compressed) length of that logical bitstream for i==0 to n
887 OV_EINVAL if the stream is not seekable (we can't know the length)
888 or if stream is only partially open
890 ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
891 if(vf->ready_state<OPENED)return(OV_EINVAL);
892 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
893 if(i<0){
894 ogg_int64_t acc=0;
895 int i;
896 for(i=0;i<vf->links;i++)
897 acc+=ov_raw_total(vf,i);
898 return(acc);
899 }else{
900 return(vf->offsets[i+1]-vf->offsets[i]);
904 /* returns: total PCM length (samples) of content if i==-1 PCM length
905 (samples) of that logical bitstream for i==0 to n
906 OV_EINVAL if the stream is not seekable (we can't know the
907 length) or only partially open
909 ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
910 if(vf->ready_state<OPENED)return(OV_EINVAL);
911 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
912 if(i<0){
913 ogg_int64_t acc=0;
914 int i;
915 for(i=0;i<vf->links;i++)
916 acc+=ov_pcm_total(vf,i);
917 return(acc);
918 }else{
919 return(vf->pcmlengths[i*2+1]);
923 /* returns: total milliseconds of content if i==-1
924 milliseconds in that logical bitstream for i==0 to n
925 OV_EINVAL if the stream is not seekable (we can't know the
926 length) or only partially open
928 ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){
929 if(vf->ready_state<OPENED)return(OV_EINVAL);
930 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
931 if(i<0){
932 ogg_int64_t acc=0;
933 int i;
934 for(i=0;i<vf->links;i++)
935 acc+=ov_time_total(vf,i);
936 return(acc);
937 }else{
938 return(((ogg_int64_t)vf->pcmlengths[i*2+1])*1000/vf->vi[i].rate);
942 /* seek to an offset relative to the *compressed* data. This also
943 scans packets to update the PCM cursor. It will cross a logical
944 bitstream boundary, but only if it can't get any packets out of the
945 tail of the bitstream we seek to (so no surprises).
947 returns zero on success, nonzero on failure */
949 int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
950 ogg_stream_state *work_os=NULL;
951 ogg_page og={0,0,0,0};
952 ogg_packet op={0,0,0,0,0,0};
954 if(vf->ready_state<OPENED)return(OV_EINVAL);
955 if(!vf->seekable)
956 return(OV_ENOSEEK); /* don't dump machine if we can't seek */
958 if(pos<0 || pos>vf->end)return(OV_EINVAL);
960 /* don't yet clear out decoding machine (if it's initialized), in
961 the case we're in the same link. Restart the decode lapping, and
962 let _fetch_and_process_packet deal with a potential bitstream
963 boundary */
964 vf->pcm_offset=-1;
965 ogg_stream_reset_serialno(vf->os,
966 vf->current_serialno); /* must set serialno */
967 vorbis_synthesis_restart(&vf->vd);
969 _seek_helper(vf,pos);
971 /* we need to make sure the pcm_offset is set, but we don't want to
972 advance the raw cursor past good packets just to get to the first
973 with a granulepos. That's not equivalent behavior to beginning
974 decoding as immediately after the seek position as possible.
976 So, a hack. We use two stream states; a local scratch state and
977 the shared vf->os stream state. We use the local state to
978 scan, and the shared state as a buffer for later decode.
980 Unfortuantely, on the last page we still advance to last packet
981 because the granulepos on the last page is not necessarily on a
982 packet boundary, and we need to make sure the granpos is
983 correct.
987 int lastblock=0;
988 int accblock=0;
989 int thisblock;
990 int eosflag=0;
992 work_os=ogg_stream_create(vf->current_serialno); /* get the memory ready */
993 while(1){
994 if(vf->ready_state>=STREAMSET){
995 /* snarf/scan a packet if we can */
996 int result=ogg_stream_packetout(work_os,&op);
998 if(result>0){
1000 if(vf->vi[vf->current_link].codec_setup){
1001 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1002 if(thisblock<0){
1003 ogg_stream_packetout(vf->os,NULL);
1004 thisblock=0;
1005 }else{
1007 if(eosflag)
1008 ogg_stream_packetout(vf->os,NULL);
1009 else
1010 if(lastblock)accblock+=(lastblock+thisblock)>>2;
1013 if(op.granulepos!=-1){
1014 int i,link=vf->current_link;
1015 ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
1016 if(granulepos<0)granulepos=0;
1018 for(i=0;i<link;i++)
1019 granulepos+=vf->pcmlengths[i*2+1];
1020 vf->pcm_offset=granulepos-accblock;
1021 break;
1023 lastblock=thisblock;
1024 continue;
1025 }else
1026 ogg_stream_packetout(vf->os,NULL);
1030 if(!lastblock){
1031 if(_get_next_page(vf,&og,-1)<0){
1032 vf->pcm_offset=ov_pcm_total(vf,-1);
1033 break;
1035 }else{
1036 /* huh? Bogus stream with packets but no granulepos */
1037 vf->pcm_offset=-1;
1038 break;
1041 /* has our decoding just traversed a bitstream boundary? */
1042 if(vf->ready_state>=STREAMSET)
1043 if(vf->current_serialno!=ogg_page_serialno(&og)){
1044 _decode_clear(vf); /* clear out stream state */
1045 ogg_stream_destroy(work_os);
1048 if(vf->ready_state<STREAMSET){
1049 int link;
1051 vf->current_serialno=ogg_page_serialno(&og);
1052 for(link=0;link<vf->links;link++)
1053 if(vf->serialnos[link]==vf->current_serialno)break;
1054 if(link==vf->links)
1055 goto seek_error; /* sign of a bogus stream. error out,
1056 leave machine uninitialized */
1058 vf->current_link=link;
1060 ogg_stream_reset_serialno(vf->os,vf->current_serialno);
1061 ogg_stream_reset_serialno(work_os,vf->current_serialno);
1062 vf->ready_state=STREAMSET;
1067 ogg_page dup;
1068 ogg_page_dup(&dup,&og);
1069 eosflag=ogg_page_eos(&og);
1070 ogg_stream_pagein(vf->os,&og);
1071 ogg_stream_pagein(work_os,&dup);
1076 ogg_packet_release(&op);
1077 ogg_page_release(&og);
1078 ogg_stream_destroy(work_os);
1079 vf->bittrack=0;
1080 vf->samptrack=0;
1081 return(0);
1083 seek_error:
1084 ogg_packet_release(&op);
1085 ogg_page_release(&og);
1087 /* dump the machine so we're in a known state */
1088 vf->pcm_offset=-1;
1089 ogg_stream_destroy(work_os);
1090 _decode_clear(vf);
1091 return OV_EBADLINK;
1094 /* Page granularity seek (faster than sample granularity because we
1095 don't do the last bit of decode to find a specific sample).
1097 Seek to the last [granule marked] page preceeding the specified pos
1098 location, such that decoding past the returned point will quickly
1099 arrive at the requested position. */
1100 int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1101 int link=-1;
1102 ogg_int64_t result=0;
1103 ogg_int64_t total=ov_pcm_total(vf,-1);
1104 ogg_page og={0,0,0,0};
1105 ogg_packet op={0,0,0,0,0,0};
1107 if(vf->ready_state<OPENED)return(OV_EINVAL);
1108 if(!vf->seekable)return(OV_ENOSEEK);
1109 if(pos<0 || pos>total)return(OV_EINVAL);
1111 /* which bitstream section does this pcm offset occur in? */
1112 for(link=vf->links-1;link>=0;link--){
1113 total-=vf->pcmlengths[link*2+1];
1114 if(pos>=total)break;
1117 /* search within the logical bitstream for the page with the highest
1118 pcm_pos preceeding (or equal to) pos. There is a danger here;
1119 missing pages or incorrect frame number information in the
1120 bitstream could make our task impossible. Account for that (it
1121 would be an error condition) */
1123 /* new search algorithm by HB (Nicholas Vinen) */
1125 ogg_int64_t end=vf->offsets[link+1];
1126 ogg_int64_t begin=vf->offsets[link];
1127 ogg_int64_t begintime = vf->pcmlengths[link*2];
1128 ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
1129 ogg_int64_t target=pos-total+begintime;
1130 ogg_int64_t best=begin;
1132 while(begin<end){
1133 ogg_int64_t bisect;
1135 if(end-begin<CHUNKSIZE){
1136 bisect=begin;
1137 }else{
1138 /* take a (pretty decent) guess. */
1139 bisect=begin +
1140 (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
1141 if(bisect<=begin)
1142 bisect=begin+1;
1145 _seek_helper(vf,bisect);
1147 while(begin<end){
1148 result=_get_next_page(vf,&og,end-vf->offset);
1149 if(result==OV_EREAD) goto seek_error;
1150 if(result<0){
1151 if(bisect<=begin+1)
1152 end=begin; /* found it */
1153 else{
1154 if(bisect==0) goto seek_error;
1155 bisect-=CHUNKSIZE;
1156 if(bisect<=begin)bisect=begin+1;
1157 _seek_helper(vf,bisect);
1159 }else{
1160 ogg_int64_t granulepos=ogg_page_granulepos(&og);
1161 if(granulepos==-1)continue;
1162 if(granulepos<target){
1163 best=result; /* raw offset of packet with granulepos */
1164 begin=vf->offset; /* raw offset of next page */
1165 begintime=granulepos;
1167 if(target-begintime>44100)break;
1168 bisect=begin; /* *not* begin + 1 */
1169 }else{
1170 if(bisect<=begin+1)
1171 end=begin; /* found it */
1172 else{
1173 if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
1174 end=result;
1175 bisect-=CHUNKSIZE; /* an endless loop otherwise. */
1176 if(bisect<=begin)bisect=begin+1;
1177 _seek_helper(vf,bisect);
1178 }else{
1179 end=result;
1180 endtime=granulepos;
1181 break;
1189 /* found our page. seek to it, update pcm offset. Easier case than
1190 raw_seek, don't keep packets preceeding granulepos. */
1193 /* seek */
1194 _seek_helper(vf,best);
1195 vf->pcm_offset=-1;
1197 if(_get_next_page(vf,&og,-1)<0){
1198 ogg_page_release(&og);
1199 return(OV_EOF); /* shouldn't happen */
1202 if(link!=vf->current_link){
1203 /* Different link; dump entire decode machine */
1204 _decode_clear(vf);
1206 vf->current_link=link;
1207 vf->current_serialno=ogg_page_serialno(&og);
1208 vf->ready_state=STREAMSET;
1210 }else{
1211 vorbis_synthesis_restart(&vf->vd);
1214 ogg_stream_reset_serialno(vf->os,vf->current_serialno);
1215 ogg_stream_pagein(vf->os,&og);
1217 /* pull out all but last packet; the one with granulepos */
1218 while(1){
1219 result=ogg_stream_packetpeek(vf->os,&op);
1220 if(result==0){
1221 /* !!! the packet finishing this page originated on a
1222 preceeding page. Keep fetching previous pages until we
1223 get one with a granulepos or without the 'continued' flag
1224 set. Then just use raw_seek for simplicity. */
1226 _seek_helper(vf,best);
1228 while(1){
1229 result=_get_prev_page(vf,&og);
1230 if(result<0) goto seek_error;
1231 if(ogg_page_granulepos(&og)>-1 ||
1232 !ogg_page_continued(&og)){
1233 return ov_raw_seek(vf,result);
1235 vf->offset=result;
1238 if(result<0){
1239 result = OV_EBADPACKET;
1240 goto seek_error;
1242 if(op.granulepos!=-1){
1243 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1244 if(vf->pcm_offset<0)vf->pcm_offset=0;
1245 vf->pcm_offset+=total;
1246 break;
1247 }else
1248 result=ogg_stream_packetout(vf->os,NULL);
1253 /* verify result */
1254 if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1255 result=OV_EFAULT;
1256 goto seek_error;
1258 vf->bittrack=0;
1259 vf->samptrack=0;
1261 ogg_page_release(&og);
1262 ogg_packet_release(&op);
1263 return(0);
1265 seek_error:
1267 ogg_page_release(&og);
1268 ogg_packet_release(&op);
1270 /* dump machine so we're in a known state */
1271 vf->pcm_offset=-1;
1272 _decode_clear(vf);
1273 return (int)result;
1276 /* seek to a sample offset relative to the decompressed pcm stream
1277 returns zero on success, nonzero on failure */
1279 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1280 ogg_packet op={0,0,0,0,0,0};
1281 ogg_page og={0,0,0,0};
1282 int thisblock,lastblock=0;
1283 int ret=ov_pcm_seek_page(vf,pos);
1284 if(ret<0)return(ret);
1285 _make_decode_ready(vf);
1287 /* discard leading packets we don't need for the lapping of the
1288 position we want; don't decode them */
1290 while(1){
1292 int ret=ogg_stream_packetpeek(vf->os,&op);
1293 if(ret>0){
1294 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1295 if(thisblock<0){
1296 ogg_stream_packetout(vf->os,NULL);
1297 continue; /* non audio packet */
1299 if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1301 if(vf->pcm_offset+((thisblock+
1302 vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
1304 /* remove the packet from packet queue and track its granulepos */
1305 ogg_stream_packetout(vf->os,NULL);
1306 vorbis_synthesis(&vf->vb,&op,0); /* set up a vb with
1307 only tracking, no
1308 pcm_decode */
1309 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
1311 /* end of logical stream case is hard, especially with exact
1312 length positioning. */
1314 if(op.granulepos>-1){
1315 int i;
1316 /* always believe the stream markers */
1317 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1318 if(vf->pcm_offset<0)vf->pcm_offset=0;
1319 for(i=0;i<vf->current_link;i++)
1320 vf->pcm_offset+=vf->pcmlengths[i*2+1];
1323 lastblock=thisblock;
1325 }else{
1326 if(ret<0 && ret!=OV_HOLE)break;
1328 /* suck in a new page */
1329 if(_get_next_page(vf,&og,-1)<0)break;
1330 if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf);
1332 if(vf->ready_state<STREAMSET){
1333 int link;
1335 vf->current_serialno=ogg_page_serialno(&og);
1336 for(link=0;link<vf->links;link++)
1337 if(vf->serialnos[link]==vf->current_serialno)break;
1338 if(link==vf->links){
1339 ogg_page_release(&og);
1340 ogg_packet_release(&op);
1341 return(OV_EBADLINK);
1343 vf->current_link=link;
1345 ogg_stream_reset_serialno(vf->os,vf->current_serialno);
1346 vf->ready_state=STREAMSET;
1347 _make_decode_ready(vf);
1348 lastblock=0;
1351 ogg_stream_pagein(vf->os,&og);
1355 vf->bittrack=0;
1356 vf->samptrack=0;
1357 /* discard samples until we reach the desired position. Crossing a
1358 logical bitstream boundary with abandon is OK. */
1359 while(vf->pcm_offset<pos){
1360 ogg_int64_t target=pos-vf->pcm_offset;
1361 long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
1363 if(samples>target)samples=target;
1364 vorbis_synthesis_read(&vf->vd,samples);
1365 vf->pcm_offset+=samples;
1367 if(samples<target)
1368 if(_fetch_and_process_packet(vf,1,1)<=0)
1369 vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1372 ogg_page_release(&og);
1373 ogg_packet_release(&op);
1374 return 0;
1377 /* seek to a playback time relative to the decompressed pcm stream
1378 returns zero on success, nonzero on failure */
1379 int ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){
1380 /* translate time to PCM position and call ov_pcm_seek */
1382 int link=-1;
1383 ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1384 ogg_int64_t time_total=ov_time_total(vf,-1);
1386 if(vf->ready_state<OPENED)return(OV_EINVAL);
1387 if(!vf->seekable)return(OV_ENOSEEK);
1388 if(milliseconds<0 || milliseconds>time_total)return(OV_EINVAL);
1390 /* which bitstream section does this time offset occur in? */
1391 for(link=vf->links-1;link>=0;link--){
1392 pcm_total-=vf->pcmlengths[link*2+1];
1393 time_total-=ov_time_total(vf,link);
1394 if(milliseconds>=time_total)break;
1397 /* enough information to convert time offset to pcm offset */
1399 ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000;
1400 return(ov_pcm_seek(vf,target));
1404 /* page-granularity version of ov_time_seek
1405 returns zero on success, nonzero on failure */
1406 int ov_time_seek_page(OggVorbis_File *vf,ogg_int64_t milliseconds){
1407 /* translate time to PCM position and call ov_pcm_seek */
1409 int link=-1;
1410 ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1411 ogg_int64_t time_total=ov_time_total(vf,-1);
1413 if(vf->ready_state<OPENED)return(OV_EINVAL);
1414 if(!vf->seekable)return(OV_ENOSEEK);
1415 if(milliseconds<0 || milliseconds>time_total)return(OV_EINVAL);
1417 /* which bitstream section does this time offset occur in? */
1418 for(link=vf->links-1;link>=0;link--){
1419 pcm_total-=vf->pcmlengths[link*2+1];
1420 time_total-=ov_time_total(vf,link);
1421 if(milliseconds>=time_total)break;
1424 /* enough information to convert time offset to pcm offset */
1426 ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000;
1427 return(ov_pcm_seek_page(vf,target));
1431 /* tell the current stream offset cursor. Note that seek followed by
1432 tell will likely not give the set offset due to caching */
1433 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1434 if(vf->ready_state<OPENED)return(OV_EINVAL);
1435 return(vf->offset);
1438 /* return PCM offset (sample) of next PCM sample to be read */
1439 ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1440 if(vf->ready_state<OPENED)return(OV_EINVAL);
1441 return(vf->pcm_offset);
1444 /* return time offset (milliseconds) of next PCM sample to be read */
1445 ogg_int64_t ov_time_tell(OggVorbis_File *vf){
1446 int link=0;
1447 ogg_int64_t pcm_total=0;
1448 ogg_int64_t time_total=0;
1450 if(vf->ready_state<OPENED)return(OV_EINVAL);
1451 if(vf->seekable){
1452 pcm_total=ov_pcm_total(vf,-1);
1453 time_total=ov_time_total(vf,-1);
1455 /* which bitstream section does this time offset occur in? */
1456 for(link=vf->links-1;link>=0;link--){
1457 pcm_total-=vf->pcmlengths[link*2+1];
1458 time_total-=ov_time_total(vf,link);
1459 if(vf->pcm_offset>=pcm_total)break;
1463 return(time_total+(1000*vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1466 /* link: -1) return the vorbis_info struct for the bitstream section
1467 currently being decoded
1468 0-n) to request information for a specific bitstream section
1470 In the case of a non-seekable bitstream, any call returns the
1471 current bitstream. NULL in the case that the machine is not
1472 initialized */
1474 vorbis_info *ov_info(OggVorbis_File *vf,int link){
1475 if(vf->seekable){
1476 if(link<0)
1477 if(vf->ready_state>=STREAMSET)
1478 return vf->vi+vf->current_link;
1479 else
1480 return vf->vi;
1481 else
1482 if(link>=vf->links)
1483 return NULL;
1484 else
1485 return vf->vi+link;
1486 }else{
1487 return vf->vi;
1491 /* grr, strong typing, grr, no templates/inheritence, grr */
1492 vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1493 if(vf->seekable){
1494 if(link<0)
1495 if(vf->ready_state>=STREAMSET)
1496 return vf->vc+vf->current_link;
1497 else
1498 return vf->vc;
1499 else
1500 if(link>=vf->links)
1501 return NULL;
1502 else
1503 return vf->vc+link;
1504 }else{
1505 return vf->vc;
1509 /* up to this point, everything could more or less hide the multiple
1510 logical bitstream nature of chaining from the toplevel application
1511 if the toplevel application didn't particularly care. However, at
1512 the point that we actually read audio back, the multiple-section
1513 nature must surface: Multiple bitstream sections do not necessarily
1514 have to have the same number of channels or sampling rate.
1516 ov_read returns the sequential logical bitstream number currently
1517 being decoded along with the PCM data in order that the toplevel
1518 application can take action on channel/sample rate changes. This
1519 number will be incremented even for streamed (non-seekable) streams
1520 (for seekable streams, it represents the actual logical bitstream
1521 index within the physical bitstream. Note that the accessor
1522 functions above are aware of this dichotomy).
1524 input values: buffer) a buffer to hold packed PCM data for return
1525 length) the byte length requested to be placed into buffer
1527 return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1528 0) EOF
1529 n) number of bytes of PCM actually returned. The
1530 below works on a packet-by-packet basis, so the
1531 return length is not related to the 'length' passed
1532 in, just guaranteed to fit.
1534 *section) set to the logical bitstream number */
1536 long ov_read(OggVorbis_File *vf,char *buffer,int bytes_req,int *bitstream){
1537 int i,j;
1539 ogg_int32_t **pcm;
1540 long samples;
1542 if(vf->ready_state<OPENED)return(OV_EINVAL);
1544 while(1){
1545 if(vf->ready_state==INITSET){
1546 samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1547 if(samples)break;
1550 /* suck in another packet */
1552 int ret=_fetch_and_process_packet(vf,1,1);
1553 if(ret==OV_EOF)
1554 return(0);
1555 if(ret<=0)
1556 return(ret);
1561 if(samples>0){
1563 /* yay! proceed to pack data into the byte buffer */
1565 long channels=ov_info(vf,-1)->channels;
1567 if(samples>(bytes_req/(2*channels)))
1568 samples=bytes_req/(2*channels);
1570 for(i=0;i<channels;i++) { /* It's faster in this order */
1571 ogg_int32_t *src=pcm[i];
1572 short *dest=((short *)buffer)+i;
1573 for(j=0;j<samples;j++) {
1574 *dest=CLIP_TO_15(src[j]>>9);
1575 dest+=channels;
1579 vorbis_synthesis_read(&vf->vd,samples);
1580 vf->pcm_offset+=samples;
1581 if(bitstream)*bitstream=vf->current_link;
1582 return(samples*2*channels);
1583 }else{
1584 return(samples);