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