summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/vorbis/tremor/vorbisfile.c
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/vorbis/tremor/vorbisfile.c') (more/less context) (show whitespace changes)
-rw-r--r--core/multimedia/opieplayer/vorbis/tremor/vorbisfile.c1592
1 files changed, 1592 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/vorbis/tremor/vorbisfile.c b/core/multimedia/opieplayer/vorbis/tremor/vorbisfile.c
new file mode 100644
index 0000000..7448b1e
--- a/dev/null
+++ b/core/multimedia/opieplayer/vorbis/tremor/vorbisfile.c
@@ -0,0 +1,1592 @@
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 ********************************************************************
13
14 function: stdio-based convenience library for opening/seeking/decoding
15 last mod: $Id$
16
17 ********************************************************************/
18
19#include <stdlib.h>
20#include <stdio.h>
21#include <errno.h>
22#include <string.h>
23#include <math.h>
24
25#include "ivorbiscodec.h"
26#include "ivorbisfile.h"
27
28#include "os.h"
29#include "misc.h"
30
31/* A 'chained bitstream' is a Vorbis bitstream that contains more than
32 one logical bitstream arranged end to end (the only form of Ogg
33 multiplexing allowed in a Vorbis bitstream; grouping [parallel
34 multiplexing] is not allowed in Vorbis) */
35
36/* A Vorbis file can be played beginning to end (streamed) without
37 worrying ahead of time about chaining (see decoder_example.c). If
38 we have the whole file, however, and want random access
39 (seeking/scrubbing) or desire to know the total length/time of a
40 file, we need to account for the possibility of chaining. */
41
42/* We can handle things a number of ways; we can determine the entire
43 bitstream structure right off the bat, or find pieces on demand.
44 This example determines and caches structure for the entire
45 bitstream, but builds a virtual decoder on the fly when moving
46 between links in the chain. */
47
48/* There are also different ways to implement seeking. Enough
49 information exists in an Ogg bitstream to seek to
50 sample-granularity positions in the output. Or, one can seek by
51 picking some portion of the stream roughly in the desired area if
52 we only want coarse navigation through the stream. */
53
54/*************************************************************************
55 * Many, many internal helpers. The intention is not to be confusing;
56 * rampant duplication and monolithic function implementation would be
57 * harder to understand anyway. The high level functions are last. Begin
58 * grokking near the end of the file */
59
60
61/* read a little more data from the file/pipe into the ogg_sync framer */
62static long _get_data(OggVorbis_File *vf){
63 errno=0;
64 if(vf->datasource){
65 char *buffer=ogg_sync_bufferin(vf->oy,CHUNKSIZE);
66 long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource);
67 if(bytes>0)ogg_sync_wrote(vf->oy,bytes);
68 if(bytes==0 && errno)return(-1);
69 return(bytes);
70 }else
71 return(0);
72}
73
74/* save a tiny smidge of verbosity to make the code more readable */
75static void _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
76 if(vf->datasource){
77 (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET);
78 vf->offset=offset;
79 ogg_sync_reset(vf->oy);
80 }else{
81 /* shouldn't happen unless someone writes a broken callback */
82 return;
83 }
84}
85
86/* The read/seek functions track absolute position within the stream */
87
88/* from the head of the stream, get the next page. boundary specifies
89 if the function is allowed to fetch more data from the stream (and
90 how much) or only use internally buffered data.
91
92 boundary: -1) unbounded search
93 0) read no additional data; use cached only
94 n) search for a new page beginning for n bytes
95
96 return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
97 n) found a page at absolute offset n
98
99 produces a refcounted page */
100
101static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
102 ogg_int64_t boundary){
103 if(boundary>0)boundary+=vf->offset;
104 while(1){
105 long more;
106
107 if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
108 more=ogg_sync_pageseek(vf->oy,og);
109
110 if(more<0){
111 /* skipped n bytes */
112 vf->offset-=more;
113 }else{
114 if(more==0){
115 /* send more paramedics */
116 if(!boundary)return(OV_FALSE);
117 {
118 long ret=_get_data(vf);
119 if(ret==0)return(OV_EOF);
120 if(ret<0)return(OV_EREAD);
121 }
122 }else{
123 /* got a page. Return the offset at the page beginning,
124 advance the internal offset past the page end */
125 ogg_int64_t ret=vf->offset;
126 vf->offset+=more;
127 return(ret);
128
129 }
130 }
131 }
132}
133
134/* find the latest page beginning before the current stream cursor
135 position. Much dirtier than the above as Ogg doesn't have any
136 backward search linkage. no 'readp' as it will certainly have to
137 read. */
138/* returns offset or OV_EREAD, OV_FAULT and produces a refcounted page */
139
140static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){
141 ogg_int64_t begin=vf->offset;
142 ogg_int64_t end=begin;
143 ogg_int64_t ret;
144 ogg_int64_t offset=-1;
145
146 while(offset==-1){
147 begin-=CHUNKSIZE;
148 if(begin<0)
149 begin=0;
150 _seek_helper(vf,begin);
151 while(vf->offset<end){
152 ret=_get_next_page(vf,og,end-vf->offset);
153 if(ret==OV_EREAD)return(OV_EREAD);
154 if(ret<0){
155 break;
156 }else{
157 offset=ret;
158 }
159 }
160 }
161
162 /* we have the offset. Actually snork and hold the page now */
163 _seek_helper(vf,offset);
164 ret=_get_next_page(vf,og,CHUNKSIZE);
165 if(ret<0)
166 /* this shouldn't be possible */
167 return(OV_EFAULT);
168
169 return(offset);
170}
171
172/* finds each bitstream link one at a time using a bisection search
173 (has to begin by knowing the offset of the lb's initial page).
174 Recurses for each link so it can alloc the link storage after
175 finding them all, then unroll and fill the cache at the same time */
176static int _bisect_forward_serialno(OggVorbis_File *vf,
177 ogg_int64_t begin,
178 ogg_int64_t searched,
179 ogg_int64_t end,
180 ogg_uint32_t currentno,
181 long m){
182 ogg_int64_t endsearched=end;
183 ogg_int64_t next=end;
184 ogg_page og={0,0,0,0};
185 ogg_int64_t ret;
186
187 /* the below guards against garbage seperating the last and
188 first pages of two links. */
189 while(searched<endsearched){
190 ogg_int64_t bisect;
191
192 if(endsearched-searched<CHUNKSIZE){
193 bisect=searched;
194 }else{
195 bisect=(searched+endsearched)/2;
196 }
197
198 _seek_helper(vf,bisect);
199 ret=_get_next_page(vf,&og,-1);
200 if(ret==OV_EREAD)return(OV_EREAD);
201 if(ret<0 || ogg_page_serialno(&og)!=currentno){
202 endsearched=bisect;
203 if(ret>=0)next=ret;
204 }else{
205 searched=ret+og.header_len+og.body_len;
206 }
207 ogg_page_release(&og);
208 }
209
210 _seek_helper(vf,next);
211 ret=_get_next_page(vf,&og,-1);
212 if(ret==OV_EREAD)return(OV_EREAD);
213
214 if(searched>=end || ret<0){
215 ogg_page_release(&og);
216 vf->links=m+1;
217 vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
218 vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
219 vf->offsets[m+1]=searched;
220 }else{
221 ret=_bisect_forward_serialno(vf,next,vf->offset,
222 end,ogg_page_serialno(&og),m+1);
223 ogg_page_release(&og);
224 if(ret==OV_EREAD)return(OV_EREAD);
225 }
226
227 vf->offsets[m]=begin;
228 vf->serialnos[m]=currentno;
229 return(0);
230}
231
232/* uses the local ogg_stream storage in vf; this is important for
233 non-streaming input sources */
234/* consumes the page that's passed in (if any) */
235
236static int _fetch_headers(OggVorbis_File *vf,
237 vorbis_info *vi,
238 vorbis_comment *vc,
239 ogg_uint32_t *serialno,
240 ogg_page *og_ptr){
241 ogg_page og={0,0,0,0};
242 ogg_packet op={0,0,0,0,0,0};
243 int i,ret;
244
245 if(!og_ptr){
246 ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
247 if(llret==OV_EREAD)return(OV_EREAD);
248 if(llret<0)return OV_ENOTVORBIS;
249 og_ptr=&og;
250 }
251
252 ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr));
253 if(serialno)*serialno=vf->os->serialno;
254 vf->ready_state=STREAMSET;
255
256 /* extract the initial header from the first page and verify that the
257 Ogg bitstream is in fact Vorbis data */
258
259 vorbis_info_init(vi);
260 vorbis_comment_init(vc);
261
262 i=0;
263 while(i<3){
264 ogg_stream_pagein(vf->os,og_ptr);
265 while(i<3){
266 int result=ogg_stream_packetout(vf->os,&op);
267 if(result==0)break;
268 if(result==-1){
269 ret=OV_EBADHEADER;
270 goto bail_header;
271 }
272 if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
273 goto bail_header;
274 }
275 i++;
276 }
277 if(i<3)
278 if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
279 ret=OV_EBADHEADER;
280 goto bail_header;
281 }
282 }
283
284 ogg_packet_release(&op);
285 ogg_page_release(&og);
286 return 0;
287
288 bail_header:
289 ogg_packet_release(&op);
290 ogg_page_release(&og);
291 vorbis_info_clear(vi);
292 vorbis_comment_clear(vc);
293 vf->ready_state=OPENED;
294
295 return ret;
296}
297
298/* last step of the OggVorbis_File initialization; get all the
299 vorbis_info structs and PCM positions. Only called by the seekable
300 initialization (local stream storage is hacked slightly; pay
301 attention to how that's done) */
302
303/* this is void and does not propogate errors up because we want to be
304 able to open and use damaged bitstreams as well as we can. Just
305 watch out for missing information for links in the OggVorbis_File
306 struct */
307static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){
308 ogg_page og={0,0,0,0};
309 int i;
310 ogg_int64_t ret;
311
312 vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
313 vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
314 vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
315 vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
316
317 for(i=0;i<vf->links;i++){
318 if(i==0){
319 /* we already grabbed the initial header earlier. Just set the offset */
320 vf->dataoffsets[i]=dataoffset;
321 _seek_helper(vf,dataoffset);
322
323 }else{
324
325 /* seek to the location of the initial header */
326
327 _seek_helper(vf,vf->offsets[i]);
328 if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){
329 vf->dataoffsets[i]=-1;
330 }else{
331 vf->dataoffsets[i]=vf->offset;
332 }
333 }
334
335 /* fetch beginning PCM offset */
336
337 if(vf->dataoffsets[i]!=-1){
338 ogg_int64_t accumulated=0,pos;
339 long lastblock=-1;
340 int result;
341
342 ogg_stream_reset_serialno(vf->os,vf->serialnos[i]);
343
344 while(1){
345 ogg_packet op={0,0,0,0,0,0};
346
347 ret=_get_next_page(vf,&og,-1);
348 if(ret<0)
349 /* this should not be possible unless the file is
350 truncated/mangled */
351 break;
352
353 if(ogg_page_serialno(&og)!=vf->serialnos[i])
354 break;
355
356 pos=ogg_page_granulepos(&og);
357
358 /* count blocksizes of all frames in the page */
359 ogg_stream_pagein(vf->os,&og);
360 while((result=ogg_stream_packetout(vf->os,&op))){
361 if(result>0){ /* ignore holes */
362 long thisblock=vorbis_packet_blocksize(vf->vi+i,&op);
363 if(lastblock!=-1)
364 accumulated+=(lastblock+thisblock)>>2;
365 lastblock=thisblock;
366 }
367 }
368 ogg_packet_release(&op);
369
370 if(pos!=-1){
371 /* pcm offset of last packet on the first audio page */
372 accumulated= pos-accumulated;
373 break;
374 }
375 }
376
377 /* less than zero? This is a stream with samples trimmed off
378 the beginning, a normal occurrence; set the offset to zero */
379 if(accumulated<0)accumulated=0;
380
381 vf->pcmlengths[i*2]=accumulated;
382 }
383
384 /* get the PCM length of this link. To do this,
385 get the last page of the stream */
386 {
387 ogg_int64_t end=vf->offsets[i+1];
388 _seek_helper(vf,end);
389
390 while(1){
391 ret=_get_prev_page(vf,&og);
392 if(ret<0){
393 /* this should not be possible */
394 vorbis_info_clear(vf->vi+i);
395 vorbis_comment_clear(vf->vc+i);
396 break;
397 }
398 if(ogg_page_granulepos(&og)!=-1){
399 vf->pcmlengths[i*2+1]=ogg_page_granulepos(&og)-vf->pcmlengths[i*2];
400 break;
401 }
402 vf->offset=ret;
403 }
404 }
405 }
406 ogg_page_release(&og);
407}
408
409static void _make_decode_ready(OggVorbis_File *vf){
410 if(vf->ready_state!=STREAMSET)return;
411 if(vf->seekable){
412 vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link);
413 }else{
414 vorbis_synthesis_init(&vf->vd,vf->vi);
415 }
416 vorbis_block_init(&vf->vd,&vf->vb);
417 vf->ready_state=INITSET;
418 vf->bittrack=0;
419 vf->samptrack=0;
420 return;
421}
422
423static int _open_seekable2(OggVorbis_File *vf){
424 ogg_uint32_t serialno=vf->current_serialno;
425 ogg_uint32_t tempserialno;
426 ogg_int64_t dataoffset=vf->offset, end;
427 ogg_page og={0,0,0,0};
428
429 /* we're partially open and have a first link header state in
430 storage in vf */
431 /* we can seek, so set out learning all about this file */
432 (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
433 vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
434
435 /* We get the offset for the last page of the physical bitstream.
436 Most OggVorbis files will contain a single logical bitstream */
437 end=_get_prev_page(vf,&og);
438 if(end<0)return(end);
439
440 /* more than one logical bitstream? */
441 tempserialno=ogg_page_serialno(&og);
442 ogg_page_release(&og);
443
444 if(tempserialno!=serialno){
445
446 /* Chained bitstream. Bisect-search each logical bitstream
447 section. Do so based on serial number only */
448 if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0)return(OV_EREAD);
449
450 }else{
451
452 /* Only one logical bitstream */
453 if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0))return(OV_EREAD);
454
455 }
456
457 /* the initial header memory is referenced by vf after; don't free it */
458 _prefetch_all_headers(vf,dataoffset);
459 return(ov_raw_seek(vf,0));
460}
461
462/* clear out the current logical bitstream decoder */
463static void _decode_clear(OggVorbis_File *vf){
464 vorbis_dsp_clear(&vf->vd);
465 vorbis_block_clear(&vf->vb);
466 vf->ready_state=OPENED;
467}
468
469/* fetch and process a packet. Handles the case where we're at a
470 bitstream boundary and dumps the decoding machine. If the decoding
471 machine is unloaded, it loads it. It also keeps pcm_offset up to
472 date (seek and read both use this. seek uses a special hack with
473 readp).
474
475 return: <0) error, OV_HOLE (lost packet) or OV_EOF
476 0) need more data (only if readp==0)
477 1) got a packet
478*/
479
480static int _fetch_and_process_packet(OggVorbis_File *vf,
481 int readp,
482 int spanp){
483 ogg_page og={0,0,0,0};
484 ogg_packet op={0,0,0,0,0,0};
485 int ret=0;
486
487 /* handle one packet. Try to fetch it from current stream state */
488 /* extract packets from page */
489 while(1){
490
491 /* process a packet if we can. If the machine isn't loaded,
492 neither is a page */
493 if(vf->ready_state==INITSET){
494 while(1) {
495 int result=ogg_stream_packetout(vf->os,&op);
496 ogg_int64_t granulepos;
497
498 if(result<0){
499 ret=OV_HOLE; /* hole in the data. */
500 goto cleanup;
501 }
502 if(result>0){
503 /* got a packet. process it */
504 granulepos=op.granulepos;
505 if(!vorbis_synthesis(&vf->vb,&op,1)){ /* lazy check for lazy
506 header handling. The
507 header packets aren't
508 audio, so if/when we
509 submit them,
510 vorbis_synthesis will
511 reject them */
512
513 /* suck in the synthesis data and track bitrate */
514 {
515 int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
516 /* for proper use of libvorbis within libvorbisfile,
517 oldsamples will always be zero. */
518 if(oldsamples){
519 ret=OV_EFAULT;
520 goto cleanup;
521 }
522
523 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
524 vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
525 vf->bittrack+=op.bytes*8;
526 }
527
528 /* update the pcm offset. */
529 if(granulepos!=-1 && !op.e_o_s){
530 int link=(vf->seekable?vf->current_link:0);
531 int i,samples;
532
533 /* this packet has a pcm_offset on it (the last packet
534 completed on a page carries the offset) After processing
535 (above), we know the pcm position of the *last* sample
536 ready to be returned. Find the offset of the *first*
537
538 As an aside, this trick is inaccurate if we begin
539 reading anew right at the last page; the end-of-stream
540 granulepos declares the last frame in the stream, and the
541 last packet of the last page may be a partial frame.
542 So, we need a previous granulepos from an in-sequence page
543 to have a reference point. Thus the !op.e_o_s clause
544 above */
545
546 if(vf->seekable && link>0)
547 granulepos-=vf->pcmlengths[link*2];
548 if(granulepos<0)granulepos=0; /* actually, this
549 shouldn't be possible
550 here unless the stream
551 is very broken */
552
553 samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
554
555 granulepos-=samples;
556 for(i=0;i<link;i++)
557 granulepos+=vf->pcmlengths[i*2+1];
558 vf->pcm_offset=granulepos;
559 }
560 ret=1;
561 goto cleanup;
562 }
563 }
564 else
565 break;
566 }
567 }
568
569 if(vf->ready_state>=OPENED){
570 int ret;
571 if(!readp){
572 ret=0;
573 goto cleanup;
574 }
575 if((ret=_get_next_page(vf,&og,-1))<0){
576 ret=OV_EOF; /* eof. leave unitialized */
577 goto cleanup;
578 }
579
580 /* bitrate tracking; add the header's bytes here, the body bytes
581 are done by packet above */
582 vf->bittrack+=og.header_len*8;
583
584 /* has our decoding just traversed a bitstream boundary? */
585 if(vf->ready_state==INITSET){
586 if(vf->current_serialno!=ogg_page_serialno(&og)){
587 if(!spanp){
588 ret=OV_EOF;
589 goto cleanup;
590 }
591
592 _decode_clear(vf);
593
594 if(!vf->seekable){
595 vorbis_info_clear(vf->vi);
596 vorbis_comment_clear(vf->vc);
597 }
598 }
599 }
600 }
601
602 /* Do we need to load a new machine before submitting the page? */
603 /* This is different in the seekable and non-seekable cases.
604
605 In the seekable case, we already have all the header
606 information loaded and cached; we just initialize the machine
607 with it and continue on our merry way.
608
609 In the non-seekable (streaming) case, we'll only be at a
610 boundary if we just left the previous logical bitstream and
611 we're now nominally at the header of the next bitstream
612 */
613
614 if(vf->ready_state!=INITSET){
615 int link;
616
617 if(vf->ready_state<STREAMSET){
618 if(vf->seekable){
619 vf->current_serialno=ogg_page_serialno(&og);
620
621 /* match the serialno to bitstream section. We use this rather than
622 offset positions to avoid problems near logical bitstream
623 boundaries */
624 for(link=0;link<vf->links;link++)
625 if(vf->serialnos[link]==vf->current_serialno)break;
626 if(link==vf->links){
627 ret=OV_EBADLINK; /* sign of a bogus stream. error out,
628 leave machine uninitialized */
629 goto cleanup;
630 }
631
632 vf->current_link=link;
633
634 ogg_stream_reset_serialno(vf->os,vf->current_serialno);
635 vf->ready_state=STREAMSET;
636
637 }else{
638 /* we're streaming */
639 /* fetch the three header packets, build the info struct */
640
641 int ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,&og);
642 if(ret) goto cleanup;
643 vf->current_link++;
644 link=0;
645 }
646 }
647
648 _make_decode_ready(vf);
649 }
650 ogg_stream_pagein(vf->os,&og);
651 }
652 cleanup:
653 ogg_packet_release(&op);
654 ogg_page_release(&og);
655 return ret;
656}
657
658/* if, eg, 64 bit stdio is configured by default, this will build with
659 fseek64 */
660static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
661 if(f==NULL)return(-1);
662 return fseek(f,off,whence);
663}
664
665static int _ov_open1(void *f,OggVorbis_File *vf,char *initial,
666 long ibytes, ov_callbacks callbacks){
667 int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1);
668 int ret;
669
670 memset(vf,0,sizeof(*vf));
671 vf->datasource=f;
672 vf->callbacks = callbacks;
673
674 /* init the framing state */
675 vf->oy=ogg_sync_create();
676
677 /* perhaps some data was previously read into a buffer for testing
678 against other stream types. Allow initialization from this
679 previously read data (as we may be reading from a non-seekable
680 stream) */
681 if(initial){
682 char *buffer=ogg_sync_bufferin(vf->oy,ibytes);
683 memcpy(buffer,initial,ibytes);
684 ogg_sync_wrote(vf->oy,ibytes);
685 }
686
687 /* can we seek? Stevens suggests the seek test was portable */
688 if(offsettest!=-1)vf->seekable=1;
689
690 /* No seeking yet; Set up a 'single' (current) logical bitstream
691 entry for partial open */
692 vf->links=1;
693 vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
694 vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
695 vf->os=ogg_stream_create(-1); /* fill in the serialno later */
696
697 /* Try to fetch the headers, maintaining all the storage */
698 if((ret=_fetch_headers(vf,vf->vi,vf->vc,&vf->current_serialno,NULL))<0){
699 vf->datasource=NULL;
700 ov_clear(vf);
701 }else if(vf->ready_state < PARTOPEN)
702 vf->ready_state=PARTOPEN;
703 return(ret);
704}
705
706static int _ov_open2(OggVorbis_File *vf){
707 if(vf->ready_state < OPENED)
708 vf->ready_state=OPENED;
709 if(vf->seekable){
710 int ret=_open_seekable2(vf);
711 if(ret){
712 vf->datasource=NULL;
713 ov_clear(vf);
714 }
715 return(ret);
716 }
717 return 0;
718}
719
720
721/* clear out the OggVorbis_File struct */
722int ov_clear(OggVorbis_File *vf){
723 if(vf){
724 vorbis_block_clear(&vf->vb);
725 vorbis_dsp_clear(&vf->vd);
726 ogg_stream_destroy(vf->os);
727
728 if(vf->vi && vf->links){
729 int i;
730 for(i=0;i<vf->links;i++){
731 vorbis_info_clear(vf->vi+i);
732 vorbis_comment_clear(vf->vc+i);
733 }
734 _ogg_free(vf->vi);
735 _ogg_free(vf->vc);
736 }
737 if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
738 if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
739 if(vf->serialnos)_ogg_free(vf->serialnos);
740 if(vf->offsets)_ogg_free(vf->offsets);
741 ogg_sync_destroy(vf->oy);
742
743 if(vf->datasource)(vf->callbacks.close_func)(vf->datasource);
744 memset(vf,0,sizeof(*vf));
745 }
746#ifdef DEBUG_LEAKS
747 _VDBG_dump();
748#endif
749 return(0);
750}
751
752/* inspects the OggVorbis file and finds/documents all the logical
753 bitstreams contained in it. Tries to be tolerant of logical
754 bitstream sections that are truncated/woogie.
755
756 return: -1) error
757 0) OK
758*/
759
760int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
761 ov_callbacks callbacks){
762 int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
763 if(ret)return ret;
764 return _ov_open2(vf);
765}
766
767int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
768 ov_callbacks callbacks = {
769 (size_t (*)(void *, size_t, size_t, void *)) fread,
770 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
771 (int (*)(void *)) fclose,
772 (long (*)(void *)) ftell
773 };
774
775 return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
776}
777
778/* Only partially open the vorbis file; test for Vorbisness, and load
779 the headers for the first chain. Do not seek (although test for
780 seekability). Use ov_test_open to finish opening the file, else
781 ov_clear to close/free it. Same return codes as open. */
782
783int ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
784 ov_callbacks callbacks)
785{
786 return _ov_open1(f,vf,initial,ibytes,callbacks);
787}
788
789int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
790 ov_callbacks callbacks = {
791 (size_t (*)(void *, size_t, size_t, void *)) fread,
792 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
793 (int (*)(void *)) fclose,
794 (long (*)(void *)) ftell
795 };
796
797 return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
798}
799
800int ov_test_open(OggVorbis_File *vf){
801 if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
802 return _ov_open2(vf);
803}
804
805/* How many logical bitstreams in this physical bitstream? */
806long ov_streams(OggVorbis_File *vf){
807 return vf->links;
808}
809
810/* Is the FILE * associated with vf seekable? */
811long ov_seekable(OggVorbis_File *vf){
812 return vf->seekable;
813}
814
815/* returns the bitrate for a given logical bitstream or the entire
816 physical bitstream. If the file is open for random access, it will
817 find the *actual* average bitrate. If the file is streaming, it
818 returns the nominal bitrate (if set) else the average of the
819 upper/lower bounds (if set) else -1 (unset).
820
821 If you want the actual bitrate field settings, get them from the
822 vorbis_info structs */
823
824long ov_bitrate(OggVorbis_File *vf,int i){
825 if(vf->ready_state<OPENED)return(OV_EINVAL);
826 if(i>=vf->links)return(OV_EINVAL);
827 if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
828 if(i<0){
829 ogg_int64_t bits=0;
830 int i;
831 for(i=0;i<vf->links;i++)
832 bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
833 /* This once read: return(rint(bits/ov_time_total(vf,-1)));
834 * gcc 3.x on x86 miscompiled this at optimisation level 2 and above,
835 * so this is slightly transformed to make it work.
836 */
837 return(bits*1000/ov_time_total(vf,-1));
838 }else{
839 if(vf->seekable){
840 /* return the actual bitrate */
841 return((vf->offsets[i+1]-vf->dataoffsets[i])*8000/ov_time_total(vf,i));
842 }else{
843 /* return nominal if set */
844 if(vf->vi[i].bitrate_nominal>0){
845 return vf->vi[i].bitrate_nominal;
846 }else{
847 if(vf->vi[i].bitrate_upper>0){
848 if(vf->vi[i].bitrate_lower>0){
849 return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
850 }else{
851 return vf->vi[i].bitrate_upper;
852 }
853 }
854 return(OV_FALSE);
855 }
856 }
857 }
858}
859
860/* returns the actual bitrate since last call. returns -1 if no
861 additional data to offer since last call (or at beginning of stream),
862 EINVAL if stream is only partially open
863*/
864long ov_bitrate_instant(OggVorbis_File *vf){
865 int link=(vf->seekable?vf->current_link:0);
866 long ret;
867 if(vf->ready_state<OPENED)return(OV_EINVAL);
868 if(vf->samptrack==0)return(OV_FALSE);
869 ret=vf->bittrack/vf->samptrack*vf->vi[link].rate;
870 vf->bittrack=0;
871 vf->samptrack=0;
872 return(ret);
873}
874
875/* Guess */
876long ov_serialnumber(OggVorbis_File *vf,int i){
877 if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
878 if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
879 if(i<0){
880 return(vf->current_serialno);
881 }else{
882 return(vf->serialnos[i]);
883 }
884}
885
886/* returns: total raw (compressed) length of content if i==-1
887 raw (compressed) length of that logical bitstream for i==0 to n
888 OV_EINVAL if the stream is not seekable (we can't know the length)
889 or if stream is only partially open
890*/
891ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
892 if(vf->ready_state<OPENED)return(OV_EINVAL);
893 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
894 if(i<0){
895 ogg_int64_t acc=0;
896 int i;
897 for(i=0;i<vf->links;i++)
898 acc+=ov_raw_total(vf,i);
899 return(acc);
900 }else{
901 return(vf->offsets[i+1]-vf->offsets[i]);
902 }
903}
904
905/* returns: total PCM length (samples) of content if i==-1 PCM length
906 (samples) of that logical bitstream for i==0 to n
907 OV_EINVAL if the stream is not seekable (we can't know the
908 length) or only partially open
909*/
910ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
911 if(vf->ready_state<OPENED)return(OV_EINVAL);
912 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
913 if(i<0){
914 ogg_int64_t acc=0;
915 int i;
916 for(i=0;i<vf->links;i++)
917 acc+=ov_pcm_total(vf,i);
918 return(acc);
919 }else{
920 return(vf->pcmlengths[i*2+1]);
921 }
922}
923
924/* returns: total milliseconds of content if i==-1
925 milliseconds in that logical bitstream for i==0 to n
926 OV_EINVAL if the stream is not seekable (we can't know the
927 length) or only partially open
928*/
929ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){
930 if(vf->ready_state<OPENED)return(OV_EINVAL);
931 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
932 if(i<0){
933 ogg_int64_t acc=0;
934 int i;
935 for(i=0;i<vf->links;i++)
936 acc+=ov_time_total(vf,i);
937 return(acc);
938 }else{
939 return(((ogg_int64_t)vf->pcmlengths[i*2+1])*1000/vf->vi[i].rate);
940 }
941}
942
943/* seek to an offset relative to the *compressed* data. This also
944 scans packets to update the PCM cursor. It will cross a logical
945 bitstream boundary, but only if it can't get any packets out of the
946 tail of the bitstream we seek to (so no surprises).
947
948 returns zero on success, nonzero on failure */
949
950int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
951 ogg_stream_state *work_os=NULL;
952 ogg_page og={0,0,0,0};
953 ogg_packet op={0,0,0,0,0,0};
954
955 if(vf->ready_state<OPENED)return(OV_EINVAL);
956 if(!vf->seekable)
957 return(OV_ENOSEEK); /* don't dump machine if we can't seek */
958
959 if(pos<0 || pos>vf->end)return(OV_EINVAL);
960
961 /* don't yet clear out decoding machine (if it's initialized), in
962 the case we're in the same link. Restart the decode lapping, and
963 let _fetch_and_process_packet deal with a potential bitstream
964 boundary */
965 vf->pcm_offset=-1;
966 ogg_stream_reset_serialno(vf->os,
967 vf->current_serialno); /* must set serialno */
968 vorbis_synthesis_restart(&vf->vd);
969
970 _seek_helper(vf,pos);
971
972 /* we need to make sure the pcm_offset is set, but we don't want to
973 advance the raw cursor past good packets just to get to the first
974 with a granulepos. That's not equivalent behavior to beginning
975 decoding as immediately after the seek position as possible.
976
977 So, a hack. We use two stream states; a local scratch state and
978 the shared vf->os stream state. We use the local state to
979 scan, and the shared state as a buffer for later decode.
980
981 Unfortuantely, on the last page we still advance to last packet
982 because the granulepos on the last page is not necessarily on a
983 packet boundary, and we need to make sure the granpos is
984 correct.
985 */
986
987 {
988 int lastblock=0;
989 int accblock=0;
990 int thisblock;
991 int eosflag;
992
993 work_os=ogg_stream_create(vf->current_serialno); /* get the memory ready */
994 while(1){
995 if(vf->ready_state>=STREAMSET){
996 /* snarf/scan a packet if we can */
997 int result=ogg_stream_packetout(work_os,&op);
998
999 if(result>0){
1000
1001 if(vf->vi[vf->current_link].codec_setup){
1002 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1003 if(thisblock<0){
1004 ogg_stream_packetout(vf->os,NULL);
1005 thisblock=0;
1006 }else{
1007
1008 if(eosflag)
1009 ogg_stream_packetout(vf->os,NULL);
1010 else
1011 if(lastblock)accblock+=(lastblock+thisblock)>>2;
1012 }
1013
1014 if(op.granulepos!=-1){
1015 int i,link=vf->current_link;
1016 ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
1017 if(granulepos<0)granulepos=0;
1018
1019 for(i=0;i<link;i++)
1020 granulepos+=vf->pcmlengths[i*2+1];
1021 vf->pcm_offset=granulepos-accblock;
1022 break;
1023 }
1024 lastblock=thisblock;
1025 continue;
1026 }else
1027 ogg_stream_packetout(vf->os,NULL);
1028 }
1029 }
1030
1031 if(!lastblock){
1032 if(_get_next_page(vf,&og,-1)<0){
1033 vf->pcm_offset=ov_pcm_total(vf,-1);
1034 break;
1035 }
1036 }else{
1037 /* huh? Bogus stream with packets but no granulepos */
1038 vf->pcm_offset=-1;
1039 break;
1040 }
1041
1042 /* has our decoding just traversed a bitstream boundary? */
1043 if(vf->ready_state>=STREAMSET)
1044 if(vf->current_serialno!=ogg_page_serialno(&og)){
1045 _decode_clear(vf); /* clear out stream state */
1046 ogg_stream_destroy(work_os);
1047 }
1048
1049 if(vf->ready_state<STREAMSET){
1050 int link;
1051
1052 vf->current_serialno=ogg_page_serialno(&og);
1053 for(link=0;link<vf->links;link++)
1054 if(vf->serialnos[link]==vf->current_serialno)break;
1055 if(link==vf->links)
1056 goto seek_error; /* sign of a bogus stream. error out,
1057 leave machine uninitialized */
1058
1059 vf->current_link=link;
1060
1061 ogg_stream_reset_serialno(vf->os,vf->current_serialno);
1062 ogg_stream_reset_serialno(work_os,vf->current_serialno);
1063 vf->ready_state=STREAMSET;
1064
1065 }
1066
1067 {
1068 ogg_page dup;
1069 ogg_page_dup(&dup,&og);
1070 eosflag=ogg_page_eos(&og);
1071 ogg_stream_pagein(vf->os,&og);
1072 ogg_stream_pagein(work_os,&dup);
1073 }
1074 }
1075 }
1076
1077 ogg_packet_release(&op);
1078 ogg_page_release(&og);
1079 ogg_stream_destroy(work_os);
1080 vf->bittrack=0;
1081 vf->samptrack=0;
1082 return(0);
1083
1084 seek_error:
1085 ogg_packet_release(&op);
1086 ogg_page_release(&og);
1087
1088 /* dump the machine so we're in a known state */
1089 vf->pcm_offset=-1;
1090 ogg_stream_destroy(work_os);
1091 _decode_clear(vf);
1092 return OV_EBADLINK;
1093}
1094
1095/* Page granularity seek (faster than sample granularity because we
1096 don't do the last bit of decode to find a specific sample).
1097
1098 Seek to the last [granule marked] page preceeding the specified pos
1099 location, such that decoding past the returned point will quickly
1100 arrive at the requested position. */
1101int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1102 int link=-1;
1103 ogg_int64_t result=0;
1104 ogg_int64_t total=ov_pcm_total(vf,-1);
1105 ogg_page og={0,0,0,0};
1106 ogg_packet op={0,0,0,0,0,0};
1107
1108 if(vf->ready_state<OPENED)return(OV_EINVAL);
1109 if(!vf->seekable)return(OV_ENOSEEK);
1110 if(pos<0 || pos>total)return(OV_EINVAL);
1111
1112 /* which bitstream section does this pcm offset occur in? */
1113 for(link=vf->links-1;link>=0;link--){
1114 total-=vf->pcmlengths[link*2+1];
1115 if(pos>=total)break;
1116 }
1117
1118 /* search within the logical bitstream for the page with the highest
1119 pcm_pos preceeding (or equal to) pos. There is a danger here;
1120 missing pages or incorrect frame number information in the
1121 bitstream could make our task impossible. Account for that (it
1122 would be an error condition) */
1123
1124 /* new search algorithm by HB (Nicholas Vinen) */
1125 {
1126 ogg_int64_t end=vf->offsets[link+1];
1127 ogg_int64_t begin=vf->offsets[link];
1128 ogg_int64_t begintime = vf->pcmlengths[link*2];
1129 ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
1130 ogg_int64_t target=pos-total+begintime;
1131 ogg_int64_t best=begin;
1132
1133 while(begin<end){
1134 ogg_int64_t bisect;
1135
1136 if(end-begin<CHUNKSIZE){
1137 bisect=begin;
1138 }else{
1139 /* take a (pretty decent) guess. */
1140 bisect=begin +
1141 (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
1142 if(bisect<=begin)
1143 bisect=begin+1;
1144 }
1145
1146 _seek_helper(vf,bisect);
1147
1148 while(begin<end){
1149 result=_get_next_page(vf,&og,end-vf->offset);
1150 if(result==OV_EREAD) goto seek_error;
1151 if(result<0){
1152 if(bisect<=begin+1)
1153 end=begin; /* found it */
1154 else{
1155 if(bisect==0) goto seek_error;
1156 bisect-=CHUNKSIZE;
1157 if(bisect<=begin)bisect=begin+1;
1158 _seek_helper(vf,bisect);
1159 }
1160 }else{
1161 ogg_int64_t granulepos=ogg_page_granulepos(&og);
1162 if(granulepos==-1)continue;
1163 if(granulepos<target){
1164 best=result; /* raw offset of packet with granulepos */
1165 begin=vf->offset; /* raw offset of next page */
1166 begintime=granulepos;
1167
1168 if(target-begintime>44100)break;
1169 bisect=begin; /* *not* begin + 1 */
1170 }else{
1171 if(bisect<=begin+1)
1172 end=begin; /* found it */
1173 else{
1174 if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
1175 end=result;
1176 bisect-=CHUNKSIZE; /* an endless loop otherwise. */
1177 if(bisect<=begin)bisect=begin+1;
1178 _seek_helper(vf,bisect);
1179 }else{
1180 end=result;
1181 endtime=granulepos;
1182 break;
1183 }
1184 }
1185 }
1186 }
1187 }
1188 }
1189
1190 /* found our page. seek to it, update pcm offset. Easier case than
1191 raw_seek, don't keep packets preceeding granulepos. */
1192 {
1193
1194 /* seek */
1195 _seek_helper(vf,best);
1196 vf->pcm_offset=-1;
1197
1198 if(_get_next_page(vf,&og,-1)<0){
1199 ogg_page_release(&og);
1200 return(OV_EOF); /* shouldn't happen */
1201 }
1202
1203 if(link!=vf->current_link){
1204 /* Different link; dump entire decode machine */
1205 _decode_clear(vf);
1206
1207 vf->current_link=link;
1208 vf->current_serialno=ogg_page_serialno(&og);
1209 vf->ready_state=STREAMSET;
1210
1211 }else{
1212 vorbis_synthesis_restart(&vf->vd);
1213 }
1214
1215 ogg_stream_reset_serialno(vf->os,vf->current_serialno);
1216 ogg_stream_pagein(vf->os,&og);
1217
1218 /* pull out all but last packet; the one with granulepos */
1219 while(1){
1220 result=ogg_stream_packetpeek(vf->os,&op);
1221 if(result==0){
1222 /* !!! the packet finishing this page originated on a
1223 preceeding page. Keep fetching previous pages until we
1224 get one with a granulepos or without the 'continued' flag
1225 set. Then just use raw_seek for simplicity. */
1226
1227 _seek_helper(vf,best);
1228
1229 while(1){
1230 result=_get_prev_page(vf,&og);
1231 if(result<0) goto seek_error;
1232 if(ogg_page_granulepos(&og)>-1 ||
1233 !ogg_page_continued(&og)){
1234 return ov_raw_seek(vf,result);
1235 }
1236 vf->offset=result;
1237 }
1238 }
1239 if(result<0){
1240 result = OV_EBADPACKET;
1241 goto seek_error;
1242 }
1243 if(op.granulepos!=-1){
1244 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1245 if(vf->pcm_offset<0)vf->pcm_offset=0;
1246 vf->pcm_offset+=total;
1247 break;
1248 }else
1249 result=ogg_stream_packetout(vf->os,NULL);
1250 }
1251 }
1252 }
1253
1254 /* verify result */
1255 if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1256 result=OV_EFAULT;
1257 goto seek_error;
1258 }
1259 vf->bittrack=0;
1260 vf->samptrack=0;
1261
1262 ogg_page_release(&og);
1263 ogg_packet_release(&op);
1264 return(0);
1265
1266 seek_error:
1267
1268 ogg_page_release(&og);
1269 ogg_packet_release(&op);
1270
1271 /* dump machine so we're in a known state */
1272 vf->pcm_offset=-1;
1273 _decode_clear(vf);
1274 return (int)result;
1275}
1276
1277/* seek to a sample offset relative to the decompressed pcm stream
1278 returns zero on success, nonzero on failure */
1279
1280int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1281 ogg_packet op={0,0,0,0,0,0};
1282 ogg_page og={0,0,0,0};
1283 int thisblock,lastblock=0;
1284 int ret=ov_pcm_seek_page(vf,pos);
1285 if(ret<0)return(ret);
1286 _make_decode_ready(vf);
1287
1288 /* discard leading packets we don't need for the lapping of the
1289 position we want; don't decode them */
1290
1291 while(1){
1292
1293 int ret=ogg_stream_packetpeek(vf->os,&op);
1294 if(ret>0){
1295 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1296 if(thisblock<0){
1297 ogg_stream_packetout(vf->os,NULL);
1298 continue; /* non audio packet */
1299 }
1300 if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1301
1302 if(vf->pcm_offset+((thisblock+
1303 vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
1304
1305 /* remove the packet from packet queue and track its granulepos */
1306 ogg_stream_packetout(vf->os,NULL);
1307 vorbis_synthesis(&vf->vb,&op,0); /* set up a vb with
1308 only tracking, no
1309 pcm_decode */
1310 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
1311
1312 /* end of logical stream case is hard, especially with exact
1313 length positioning. */
1314
1315 if(op.granulepos>-1){
1316 int i;
1317 /* always believe the stream markers */
1318 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1319 if(vf->pcm_offset<0)vf->pcm_offset=0;
1320 for(i=0;i<vf->current_link;i++)
1321 vf->pcm_offset+=vf->pcmlengths[i*2+1];
1322 }
1323
1324 lastblock=thisblock;
1325
1326 }else{
1327 if(ret<0 && ret!=OV_HOLE)break;
1328
1329 /* suck in a new page */
1330 if(_get_next_page(vf,&og,-1)<0)break;
1331 if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf);
1332
1333 if(vf->ready_state<STREAMSET){
1334 int link;
1335
1336 vf->current_serialno=ogg_page_serialno(&og);
1337 for(link=0;link<vf->links;link++)
1338 if(vf->serialnos[link]==vf->current_serialno)break;
1339 if(link==vf->links){
1340 ogg_page_release(&og);
1341 ogg_packet_release(&op);
1342 return(OV_EBADLINK);
1343 }
1344 vf->current_link=link;
1345
1346 ogg_stream_reset_serialno(vf->os,vf->current_serialno);
1347 vf->ready_state=STREAMSET;
1348 _make_decode_ready(vf);
1349 lastblock=0;
1350 }
1351
1352 ogg_stream_pagein(vf->os,&og);
1353 }
1354 }
1355
1356 vf->bittrack=0;
1357 vf->samptrack=0;
1358 /* discard samples until we reach the desired position. Crossing a
1359 logical bitstream boundary with abandon is OK. */
1360 while(vf->pcm_offset<pos){
1361 ogg_int64_t target=pos-vf->pcm_offset;
1362 long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
1363
1364 if(samples>target)samples=target;
1365 vorbis_synthesis_read(&vf->vd,samples);
1366 vf->pcm_offset+=samples;
1367
1368 if(samples<target)
1369 if(_fetch_and_process_packet(vf,1,1)<=0)
1370 vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1371 }
1372
1373 ogg_page_release(&og);
1374 ogg_packet_release(&op);
1375 return 0;
1376}
1377
1378/* seek to a playback time relative to the decompressed pcm stream
1379 returns zero on success, nonzero on failure */
1380int ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){
1381 /* translate time to PCM position and call ov_pcm_seek */
1382
1383 int link=-1;
1384 ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1385 ogg_int64_t time_total=ov_time_total(vf,-1);
1386
1387 if(vf->ready_state<OPENED)return(OV_EINVAL);
1388 if(!vf->seekable)return(OV_ENOSEEK);
1389 if(milliseconds<0 || milliseconds>time_total)return(OV_EINVAL);
1390
1391 /* which bitstream section does this time offset occur in? */
1392 for(link=vf->links-1;link>=0;link--){
1393 pcm_total-=vf->pcmlengths[link*2+1];
1394 time_total-=ov_time_total(vf,link);
1395 if(milliseconds>=time_total)break;
1396 }
1397
1398 /* enough information to convert time offset to pcm offset */
1399 {
1400 ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000;
1401 return(ov_pcm_seek(vf,target));
1402 }
1403}
1404
1405/* page-granularity version of ov_time_seek
1406 returns zero on success, nonzero on failure */
1407int ov_time_seek_page(OggVorbis_File *vf,ogg_int64_t milliseconds){
1408 /* translate time to PCM position and call ov_pcm_seek */
1409
1410 int link=-1;
1411 ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
1412 ogg_int64_t time_total=ov_time_total(vf,-1);
1413
1414 if(vf->ready_state<OPENED)return(OV_EINVAL);
1415 if(!vf->seekable)return(OV_ENOSEEK);
1416 if(milliseconds<0 || milliseconds>time_total)return(OV_EINVAL);
1417
1418 /* which bitstream section does this time offset occur in? */
1419 for(link=vf->links-1;link>=0;link--){
1420 pcm_total-=vf->pcmlengths[link*2+1];
1421 time_total-=ov_time_total(vf,link);
1422 if(milliseconds>=time_total)break;
1423 }
1424
1425 /* enough information to convert time offset to pcm offset */
1426 {
1427 ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000;
1428 return(ov_pcm_seek_page(vf,target));
1429 }
1430}
1431
1432/* tell the current stream offset cursor. Note that seek followed by
1433 tell will likely not give the set offset due to caching */
1434ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1435 if(vf->ready_state<OPENED)return(OV_EINVAL);
1436 return(vf->offset);
1437}
1438
1439/* return PCM offset (sample) of next PCM sample to be read */
1440ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1441 if(vf->ready_state<OPENED)return(OV_EINVAL);
1442 return(vf->pcm_offset);
1443}
1444
1445/* return time offset (milliseconds) of next PCM sample to be read */
1446ogg_int64_t ov_time_tell(OggVorbis_File *vf){
1447 int link=0;
1448 ogg_int64_t pcm_total=0;
1449 ogg_int64_t time_total=0;
1450
1451 if(vf->ready_state<OPENED)return(OV_EINVAL);
1452 if(vf->seekable){
1453 pcm_total=ov_pcm_total(vf,-1);
1454 time_total=ov_time_total(vf,-1);
1455
1456 /* which bitstream section does this time offset occur in? */
1457 for(link=vf->links-1;link>=0;link--){
1458 pcm_total-=vf->pcmlengths[link*2+1];
1459 time_total-=ov_time_total(vf,link);
1460 if(vf->pcm_offset>=pcm_total)break;
1461 }
1462 }
1463
1464 return(time_total+(1000*vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1465}
1466
1467/* link: -1) return the vorbis_info struct for the bitstream section
1468 currently being decoded
1469 0-n) to request information for a specific bitstream section
1470
1471 In the case of a non-seekable bitstream, any call returns the
1472 current bitstream. NULL in the case that the machine is not
1473 initialized */
1474
1475vorbis_info *ov_info(OggVorbis_File *vf,int link){
1476 if(vf->seekable){
1477 if(link<0)
1478 if(vf->ready_state>=STREAMSET)
1479 return vf->vi+vf->current_link;
1480 else
1481 return vf->vi;
1482 else
1483 if(link>=vf->links)
1484 return NULL;
1485 else
1486 return vf->vi+link;
1487 }else{
1488 return vf->vi;
1489 }
1490}
1491
1492/* grr, strong typing, grr, no templates/inheritence, grr */
1493vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1494 if(vf->seekable){
1495 if(link<0)
1496 if(vf->ready_state>=STREAMSET)
1497 return vf->vc+vf->current_link;
1498 else
1499 return vf->vc;
1500 else
1501 if(link>=vf->links)
1502 return NULL;
1503 else
1504 return vf->vc+link;
1505 }else{
1506 return vf->vc;
1507 }
1508}
1509
1510/* up to this point, everything could more or less hide the multiple
1511 logical bitstream nature of chaining from the toplevel application
1512 if the toplevel application didn't particularly care. However, at
1513 the point that we actually read audio back, the multiple-section
1514 nature must surface: Multiple bitstream sections do not necessarily
1515 have to have the same number of channels or sampling rate.
1516
1517 ov_read returns the sequential logical bitstream number currently
1518 being decoded along with the PCM data in order that the toplevel
1519 application can take action on channel/sample rate changes. This
1520 number will be incremented even for streamed (non-seekable) streams
1521 (for seekable streams, it represents the actual logical bitstream
1522 index within the physical bitstream. Note that the accessor
1523 functions above are aware of this dichotomy).
1524
1525 input values: buffer) a buffer to hold packed PCM data for return
1526 length) the byte length requested to be placed into buffer
1527
1528 return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1529 0) EOF
1530 n) number of bytes of PCM actually returned. The
1531 below works on a packet-by-packet basis, so the
1532 return length is not related to the 'length' passed
1533 in, just guaranteed to fit.
1534
1535 *section) set to the logical bitstream number */
1536
1537long ov_read(OggVorbis_File *vf,char *buffer,int bytes_req,int *bitstream){
1538 int i,j;
1539
1540 ogg_int32_t **pcm;
1541 long samples;
1542
1543 if(vf->ready_state<OPENED)return(OV_EINVAL);
1544
1545 while(1){
1546 if(vf->ready_state==INITSET){
1547 samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1548 if(samples)break;
1549 }
1550
1551 /* suck in another packet */
1552 {
1553 int ret=_fetch_and_process_packet(vf,1,1);
1554 if(ret==OV_EOF)
1555 return(0);
1556 if(ret<=0)
1557 return(ret);
1558 }
1559
1560 }
1561
1562 if(samples>0){
1563
1564 /* yay! proceed to pack data into the byte buffer */
1565
1566 long channels=ov_info(vf,-1)->channels;
1567
1568 if(channels==1){
1569 if(samples>(bytes_req/2))
1570 samples=bytes_req/2;
1571 }else{
1572 if(samples>(bytes_req/4))
1573 samples=bytes_req/4;
1574 }
1575
1576 for(i=0;i<channels;i++) { /* It's faster in this order */
1577 ogg_int32_t *src=pcm[i];
1578 short *dest=((short *)buffer)+i;
1579 for(j=0;j<samples;j++) {
1580 *dest=CLIP_TO_15(src[j]>>9);
1581 dest+=channels;
1582 }
1583 }
1584
1585 vorbis_synthesis_read(&vf->vd,samples);
1586 vf->pcm_offset+=samples;
1587 if(bitstream)*bitstream=vf->current_link;
1588 return(samples*2*channels);
1589 }else{
1590 return(samples);
1591 }
1592}