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