1 /********************************************************************
2 * *
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
7 * *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015 *
9 * by the Xiph.Org Foundation http://www.xiph.org/ *
10 * *
11 ********************************************************************
12
13 function: stdio-based convenience library for opening/seeking/decoding
14 last mod: $Id: vorbisfile.c 19457 2015-03-03 00:15:29Z giles $
15
16 ********************************************************************/
17
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <errno.h>
21 #include <string.h>
22 #include <math.h>
23
24 #include "vorbis/codec.h"
25
26 /* we don't need or want the static callback symbols here */
27 #define OV_EXCLUDE_STATIC_CALLBACKS
28 #include "vorbis/vorbisfile.h"
29
30 #include "os.h"
31 #include "misc.h"
32
33 /* A 'chained bitstream' is a Vorbis bitstream that contains more than
34 one logical bitstream arranged end to end (the only form of Ogg
35 multiplexing allowed in a Vorbis bitstream; grouping [parallel
36 multiplexing] is not allowed in Vorbis) */
37
38 /* A Vorbis file can be played beginning to end (streamed) without
39 worrying ahead of time about chaining (see decoder_example.c). If
40 we have the whole file, however, and want random access
41 (seeking/scrubbing) or desire to know the total length/time of a
42 file, we need to account for the possibility of chaining. */
43
44 /* We can handle things a number of ways; we can determine the entire
45 bitstream structure right off the bat, or find pieces on demand.
46 This example determines and caches structure for the entire
47 bitstream, but builds a virtual decoder on the fly when moving
48 between links in the chain. */
49
50 /* There are also different ways to implement seeking. Enough
51 information exists in an Ogg bitstream to seek to
52 sample-granularity positions in the output. Or, one can seek by
53 picking some portion of the stream roughly in the desired area if
54 we only want coarse navigation through the stream. */
55
56 /*************************************************************************
57 * Many, many internal helpers. The intention is not to be confusing;
58 * rampant duplication and monolithic function implementation would be
59 * harder to understand anyway. The high level functions are last. Begin
60 * grokking near the end of the file */
61
62 /* read a little more data from the file/pipe into the ogg_sync framer
63 */
64 #define CHUNKSIZE 65536 /* greater-than-page-size granularity seeking */
65 #define READSIZE 2048 /* a smaller read size is needed for low-rate streaming. */
66
_get_data(OggVorbis_File * vf)67 static long _get_data(OggVorbis_File *vf){
68 errno=0;
69 if(!(vf->callbacks.read_func))return(-1);
70 if(vf->datasource){
71 char *buffer=ogg_sync_buffer(&vf->oy,READSIZE);
72 long bytes=(vf->callbacks.read_func)(buffer,1,READSIZE,vf->datasource);
73 if(bytes>0)ogg_sync_wrote(&vf->oy,bytes);
74 if(bytes==0 && errno)return(-1);
75 return(bytes);
76 }else
77 return(0);
78 }
79
80 /* save a tiny smidge of verbosity to make the code more readable */
_seek_helper(OggVorbis_File * vf,ogg_int64_t offset)81 static int _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){
82 if(vf->datasource){
83 /* only seek if the file position isn't already there */
84 if(vf->offset != offset){
85 if(!(vf->callbacks.seek_func)||
86 (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET) == -1)
87 return OV_EREAD;
88 vf->offset=offset;
89 ogg_sync_reset(&vf->oy);
90 }
91 }else{
92 /* shouldn't happen unless someone writes a broken callback */
93 return OV_EFAULT;
94 }
95 return 0;
96 }
97
98 /* The read/seek functions track absolute position within the stream */
99
100 /* from the head of the stream, get the next page. boundary specifies
101 if the function is allowed to fetch more data from the stream (and
102 how much) or only use internally buffered data.
103
104 boundary: -1) unbounded search
105 0) read no additional data; use cached only
106 n) search for a new page beginning for n bytes
107
108 return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD)
109 n) found a page at absolute offset n */
110
_get_next_page(OggVorbis_File * vf,ogg_page * og,ogg_int64_t boundary)111 static ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og,
112 ogg_int64_t boundary){
113 if(boundary>0)boundary+=vf->offset;
114 while(1){
115 long more;
116
117 if(boundary>0 && vf->offset>=boundary)return(OV_FALSE);
118 more=ogg_sync_pageseek(&vf->oy,og);
119
120 if(more<0){
121 /* skipped n bytes */
122 vf->offset-=more;
123 }else{
124 if(more==0){
125 /* send more paramedics */
126 if(!boundary)return(OV_FALSE);
127 {
128 long ret=_get_data(vf);
129 if(ret==0)return(OV_EOF);
130 if(ret<0)return(OV_EREAD);
131 }
132 }else{
133 /* got a page. Return the offset at the page beginning,
134 advance the internal offset past the page end */
135 ogg_int64_t ret=vf->offset;
136 vf->offset+=more;
137 return(ret);
138
139 }
140 }
141 }
142 }
143
144 /* find the latest page beginning before the passed in position. Much
145 dirtier than the above as Ogg doesn't have any backward search
146 linkage. no 'readp' as it will certainly have to read. */
147 /* returns offset or OV_EREAD, OV_FAULT */
_get_prev_page(OggVorbis_File * vf,ogg_int64_t begin,ogg_page * og)148 static ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_int64_t begin,ogg_page *og){
149 ogg_int64_t end = begin;
150 ogg_int64_t ret;
151 ogg_int64_t offset=-1;
152
153 while(offset==-1){
154 begin-=CHUNKSIZE;
155 if(begin<0)
156 begin=0;
157
158 ret=_seek_helper(vf,begin);
159 if(ret)return(ret);
160
161 while(vf->offset<end){
162 memset(og,0,sizeof(*og));
163 ret=_get_next_page(vf,og,end-vf->offset);
164 if(ret==OV_EREAD)return(OV_EREAD);
165 if(ret<0){
166 break;
167 }else{
168 offset=ret;
169 }
170 }
171 }
172
173 /* In a fully compliant, non-multiplexed stream, we'll still be
174 holding the last page. In multiplexed (or noncompliant streams),
175 we will probably have to re-read the last page we saw */
176 if(og->header_len==0){
177 ret=_seek_helper(vf,offset);
178 if(ret)return(ret);
179
180 ret=_get_next_page(vf,og,CHUNKSIZE);
181 if(ret<0)
182 /* this shouldn't be possible */
183 return(OV_EFAULT);
184 }
185
186 return(offset);
187 }
188
_add_serialno(ogg_page * og,long ** serialno_list,int * n)189 static void _add_serialno(ogg_page *og,long **serialno_list, int *n){
190 long s = ogg_page_serialno(og);
191 (*n)++;
192
193 if(*serialno_list){
194 *serialno_list = _ogg_realloc(*serialno_list, sizeof(**serialno_list)*(*n));
195 }else{
196 *serialno_list = _ogg_malloc(sizeof(**serialno_list));
197 }
198
199 (*serialno_list)[(*n)-1] = s;
200 }
201
202 /* returns nonzero if found */
_lookup_serialno(long s,long * serialno_list,int n)203 static int _lookup_serialno(long s, long *serialno_list, int n){
204 if(serialno_list){
205 while(n--){
206 if(*serialno_list == s) return 1;
207 serialno_list++;
208 }
209 }
210 return 0;
211 }
212
_lookup_page_serialno(ogg_page * og,long * serialno_list,int n)213 static int _lookup_page_serialno(ogg_page *og, long *serialno_list, int n){
214 long s = ogg_page_serialno(og);
215 return _lookup_serialno(s,serialno_list,n);
216 }
217
218 /* performs the same search as _get_prev_page, but prefers pages of
219 the specified serial number. If a page of the specified serialno is
220 spotted during the seek-back-and-read-forward, it will return the
221 info of last page of the matching serial number instead of the very
222 last page. If no page of the specified serialno is seen, it will
223 return the info of last page and alter *serialno. */
_get_prev_page_serial(OggVorbis_File * vf,ogg_int64_t begin,long * serial_list,int serial_n,int * serialno,ogg_int64_t * granpos)224 static ogg_int64_t _get_prev_page_serial(OggVorbis_File *vf, ogg_int64_t begin,
225 long *serial_list, int serial_n,
226 int *serialno, ogg_int64_t *granpos){
227 ogg_page og;
228 ogg_int64_t end=begin;
229 ogg_int64_t ret;
230
231 ogg_int64_t prefoffset=-1;
232 ogg_int64_t offset=-1;
233 ogg_int64_t ret_serialno=-1;
234 ogg_int64_t ret_gran=-1;
235
236 while(offset==-1){
237 begin-=CHUNKSIZE;
238 if(begin<0)
239 begin=0;
240
241 ret=_seek_helper(vf,begin);
242 if(ret)return(ret);
243
244 while(vf->offset<end){
245 ret=_get_next_page(vf,&og,end-vf->offset);
246 if(ret==OV_EREAD)return(OV_EREAD);
247 if(ret<0){
248 break;
249 }else{
250 ret_serialno=ogg_page_serialno(&og);
251 ret_gran=ogg_page_granulepos(&og);
252 offset=ret;
253
254 if(ret_serialno == *serialno){
255 prefoffset=ret;
256 *granpos=ret_gran;
257 }
258
259 if(!_lookup_serialno(ret_serialno,serial_list,serial_n)){
260 /* we fell off the end of the link, which means we seeked
261 back too far and shouldn't have been looking in that link
262 to begin with. If we found the preferred serial number,
263 forget that we saw it. */
264 prefoffset=-1;
265 }
266 }
267 }
268 }
269
270 /* we're not interested in the page... just the serialno and granpos. */
271 if(prefoffset>=0)return(prefoffset);
272
273 *serialno = ret_serialno;
274 *granpos = ret_gran;
275 return(offset);
276
277 }
278
279 /* uses the local ogg_stream storage in vf; this is important for
280 non-streaming input sources */
_fetch_headers(OggVorbis_File * vf,vorbis_info * vi,vorbis_comment * vc,long ** serialno_list,int * serialno_n,ogg_page * og_ptr)281 static int _fetch_headers(OggVorbis_File *vf,vorbis_info *vi,vorbis_comment *vc,
282 long **serialno_list, int *serialno_n,
283 ogg_page *og_ptr){
284 ogg_page og;
285 ogg_packet op;
286 int i,ret;
287 int allbos=0;
288
289 if(!og_ptr){
290 ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE);
291 if(llret==OV_EREAD)return(OV_EREAD);
292 if(llret<0)return(OV_ENOTVORBIS);
293 og_ptr=&og;
294 }
295
296 vorbis_info_init(vi);
297 vorbis_comment_init(vc);
298 vf->ready_state=OPENED;
299
300 /* extract the serialnos of all BOS pages + the first set of vorbis
301 headers we see in the link */
302
303 while(ogg_page_bos(og_ptr)){
304 if(serialno_list){
305 if(_lookup_page_serialno(og_ptr,*serialno_list,*serialno_n)){
306 /* a dupe serialnumber in an initial header packet set == invalid stream */
307 if(*serialno_list)_ogg_free(*serialno_list);
308 *serialno_list=0;
309 *serialno_n=0;
310 ret=OV_EBADHEADER;
311 goto bail_header;
312 }
313
314 _add_serialno(og_ptr,serialno_list,serialno_n);
315 }
316
317 if(vf->ready_state<STREAMSET){
318 /* we don't have a vorbis stream in this link yet, so begin
319 prospective stream setup. We need a stream to get packets */
320 ogg_stream_reset_serialno(&vf->os,ogg_page_serialno(og_ptr));
321 ogg_stream_pagein(&vf->os,og_ptr);
322
323 if(ogg_stream_packetout(&vf->os,&op) > 0 &&
324 vorbis_synthesis_idheader(&op)){
325 /* vorbis header; continue setup */
326 vf->ready_state=STREAMSET;
327 if((ret=vorbis_synthesis_headerin(vi,vc,&op))){
328 ret=OV_EBADHEADER;
329 goto bail_header;
330 }
331 }
332 }
333
334 /* get next page */
335 {
336 ogg_int64_t llret=_get_next_page(vf,og_ptr,CHUNKSIZE);
337 if(llret==OV_EREAD){
338 ret=OV_EREAD;
339 goto bail_header;
340 }
341 if(llret<0){
342 ret=OV_ENOTVORBIS;
343 goto bail_header;
344 }
345
346 /* if this page also belongs to our vorbis stream, submit it and break */
347 if(vf->ready_state==STREAMSET &&
348 vf->os.serialno == ogg_page_serialno(og_ptr)){
349 ogg_stream_pagein(&vf->os,og_ptr);
350 break;
351 }
352 }
353 }
354
355 if(vf->ready_state!=STREAMSET){
356 ret = OV_ENOTVORBIS;
357 goto bail_header;
358 }
359
360 while(1){
361
362 i=0;
363 while(i<2){ /* get a page loop */
364
365 while(i<2){ /* get a packet loop */
366
367 int result=ogg_stream_packetout(&vf->os,&op);
368 if(result==0)break;
369 if(result==-1){
370 ret=OV_EBADHEADER;
371 goto bail_header;
372 }
373
374 if((ret=vorbis_synthesis_headerin(vi,vc,&op)))
375 goto bail_header;
376
377 i++;
378 }
379
380 while(i<2){
381 if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){
382 ret=OV_EBADHEADER;
383 goto bail_header;
384 }
385
386 /* if this page belongs to the correct stream, go parse it */
387 if(vf->os.serialno == ogg_page_serialno(og_ptr)){
388 ogg_stream_pagein(&vf->os,og_ptr);
389 break;
390 }
391
392 /* if we never see the final vorbis headers before the link
393 ends, abort */
394 if(ogg_page_bos(og_ptr)){
395 if(allbos){
396 ret = OV_EBADHEADER;
397 goto bail_header;
398 }else
399 allbos=1;
400 }
401
402 /* otherwise, keep looking */
403 }
404 }
405
406 return 0;
407 }
408
409 bail_header:
410 vorbis_info_clear(vi);
411 vorbis_comment_clear(vc);
412 vf->ready_state=OPENED;
413
414 return ret;
415 }
416
417 /* Starting from current cursor position, get initial PCM offset of
418 next page. Consumes the page in the process without decoding
419 audio, however this is only called during stream parsing upon
420 seekable open. */
_initial_pcmoffset(OggVorbis_File * vf,vorbis_info * vi)421 static ogg_int64_t _initial_pcmoffset(OggVorbis_File *vf, vorbis_info *vi){
422 ogg_page og;
423 ogg_int64_t accumulated=0;
424 long lastblock=-1;
425 int result;
426 int serialno = vf->os.serialno;
427
428 while(1){
429 ogg_packet op;
430 if(_get_next_page(vf,&og,-1)<0)
431 break; /* should not be possible unless the file is truncated/mangled */
432
433 if(ogg_page_bos(&og)) break;
434 if(ogg_page_serialno(&og)!=serialno) continue;
435
436 /* count blocksizes of all frames in the page */
437 ogg_stream_pagein(&vf->os,&og);
438 while((result=ogg_stream_packetout(&vf->os,&op))){
439 if(result>0){ /* ignore holes */
440 long thisblock=vorbis_packet_blocksize(vi,&op);
441 if(thisblock>=0){
442 if(lastblock!=-1)
443 accumulated+=(lastblock+thisblock)>>2;
444 lastblock=thisblock;
445 }
446 }
447 }
448
449 if(ogg_page_granulepos(&og)!=-1){
450 /* pcm offset of last packet on the first audio page */
451 accumulated= ogg_page_granulepos(&og)-accumulated;
452 break;
453 }
454 }
455
456 /* less than zero? Either a corrupt file or a stream with samples
457 trimmed off the beginning, a normal occurrence; in both cases set
458 the offset to zero */
459 if(accumulated<0)accumulated=0;
460
461 return accumulated;
462 }
463
464 /* finds each bitstream link one at a time using a bisection search
465 (has to begin by knowing the offset of the lb's initial page).
466 Recurses for each link so it can alloc the link storage after
467 finding them all, then unroll and fill the cache at the same time */
_bisect_forward_serialno(OggVorbis_File * vf,ogg_int64_t begin,ogg_int64_t searched,ogg_int64_t end,ogg_int64_t endgran,int endserial,long * currentno_list,int currentnos,long m)468 static int _bisect_forward_serialno(OggVorbis_File *vf,
469 ogg_int64_t begin,
470 ogg_int64_t searched,
471 ogg_int64_t end,
472 ogg_int64_t endgran,
473 int endserial,
474 long *currentno_list,
475 int currentnos,
476 long m){
477 ogg_int64_t pcmoffset;
478 ogg_int64_t dataoffset=searched;
479 ogg_int64_t endsearched=end;
480 ogg_int64_t next=end;
481 ogg_int64_t searchgran=-1;
482 ogg_page og;
483 ogg_int64_t ret,last;
484 int serialno = vf->os.serialno;
485
486 /* invariants:
487 we have the headers and serialnos for the link beginning at 'begin'
488 we have the offset and granpos of the last page in the file (potentially
489 not a page we care about)
490 */
491
492 /* Is the last page in our list of current serialnumbers? */
493 if(_lookup_serialno(endserial,currentno_list,currentnos)){
494
495 /* last page is in the starting serialno list, so we've bisected
496 down to (or just started with) a single link. Now we need to
497 find the last vorbis page belonging to the first vorbis stream
498 for this link. */
499 searched = end;
500 while(endserial != serialno){
501 endserial = serialno;
502 searched=_get_prev_page_serial(vf,searched,currentno_list,currentnos,&endserial,&endgran);
503 }
504
505 vf->links=m+1;
506 if(vf->offsets)_ogg_free(vf->offsets);
507 if(vf->serialnos)_ogg_free(vf->serialnos);
508 if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
509
510 vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets));
511 vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
512 vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
513 vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos));
514 vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
515 vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
516
517 vf->offsets[m+1]=end;
518 vf->offsets[m]=begin;
519 vf->pcmlengths[m*2+1]=(endgran<0?0:endgran);
520
521 }else{
522
523 /* last page is not in the starting stream's serial number list,
524 so we have multiple links. Find where the stream that begins
525 our bisection ends. */
526
527 long *next_serialno_list=NULL;
528 int next_serialnos=0;
529 vorbis_info vi;
530 vorbis_comment vc;
531 int testserial = serialno+1;
532
533 /* the below guards against garbage seperating the last and
534 first pages of two links. */
535 while(searched<endsearched){
536 ogg_int64_t bisect;
537
538 if(endsearched-searched<CHUNKSIZE){
539 bisect=searched;
540 }else{
541 bisect=(searched+endsearched)/2;
542 }
543
544 ret=_seek_helper(vf,bisect);
545 if(ret)return(ret);
546
547 last=_get_next_page(vf,&og,-1);
548 if(last==OV_EREAD)return(OV_EREAD);
549 if(last<0 || !_lookup_page_serialno(&og,currentno_list,currentnos)){
550 endsearched=bisect;
551 if(last>=0)next=last;
552 }else{
553 searched=vf->offset;
554 }
555 }
556
557 /* Bisection point found */
558 /* for the time being, fetch end PCM offset the simple way */
559 searched = next;
560 while(testserial != serialno){
561 testserial = serialno;
562 searched = _get_prev_page_serial(vf,searched,currentno_list,currentnos,&testserial,&searchgran);
563 }
564
565 ret=_seek_helper(vf,next);
566 if(ret)return(ret);
567
568 ret=_fetch_headers(vf,&vi,&vc,&next_serialno_list,&next_serialnos,NULL);
569 if(ret)return(ret);
570 serialno = vf->os.serialno;
571 dataoffset = vf->offset;
572
573 /* this will consume a page, however the next bisection always
574 starts with a raw seek */
575 pcmoffset = _initial_pcmoffset(vf,&vi);
576
577 ret=_bisect_forward_serialno(vf,next,vf->offset,end,endgran,endserial,
578 next_serialno_list,next_serialnos,m+1);
579 if(ret)return(ret);
580
581 if(next_serialno_list)_ogg_free(next_serialno_list);
582
583 vf->offsets[m+1]=next;
584 vf->serialnos[m+1]=serialno;
585 vf->dataoffsets[m+1]=dataoffset;
586
587 vf->vi[m+1]=vi;
588 vf->vc[m+1]=vc;
589
590 vf->pcmlengths[m*2+1]=searchgran;
591 vf->pcmlengths[m*2+2]=pcmoffset;
592 vf->pcmlengths[m*2+3]-=pcmoffset;
593 if(vf->pcmlengths[m*2+3]<0)vf->pcmlengths[m*2+3]=0;
594 }
595 return(0);
596 }
597
_make_decode_ready(OggVorbis_File * vf)598 static int _make_decode_ready(OggVorbis_File *vf){
599 if(vf->ready_state>STREAMSET)return 0;
600 if(vf->ready_state<STREAMSET)return OV_EFAULT;
601 if(vf->seekable){
602 if(vorbis_synthesis_init(&vf->vd,vf->vi+vf->current_link))
603 return OV_EBADLINK;
604 }else{
605 if(vorbis_synthesis_init(&vf->vd,vf->vi))
606 return OV_EBADLINK;
607 }
608 vorbis_block_init(&vf->vd,&vf->vb);
609 vf->ready_state=INITSET;
610 vf->bittrack=0.f;
611 vf->samptrack=0.f;
612 return 0;
613 }
614
_open_seekable2(OggVorbis_File * vf)615 static int _open_seekable2(OggVorbis_File *vf){
616 ogg_int64_t dataoffset=vf->dataoffsets[0],end,endgran=-1;
617 int endserial=vf->os.serialno;
618 int serialno=vf->os.serialno;
619
620 /* we're partially open and have a first link header state in
621 storage in vf */
622
623 /* fetch initial PCM offset */
624 ogg_int64_t pcmoffset = _initial_pcmoffset(vf,vf->vi);
625
626 /* we can seek, so set out learning all about this file */
627 if(vf->callbacks.seek_func && vf->callbacks.tell_func){
628 (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END);
629 vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource);
630 }else{
631 vf->offset=vf->end=-1;
632 }
633
634 /* If seek_func is implemented, tell_func must also be implemented */
635 if(vf->end==-1) return(OV_EINVAL);
636
637 /* Get the offset of the last page of the physical bitstream, or, if
638 we're lucky the last vorbis page of this link as most OggVorbis
639 files will contain a single logical bitstream */
640 end=_get_prev_page_serial(vf,vf->end,vf->serialnos+2,vf->serialnos[1],&endserial,&endgran);
641 if(end<0)return(end);
642
643 /* now determine bitstream structure recursively */
644 if(_bisect_forward_serialno(vf,0,dataoffset,end,endgran,endserial,
645 vf->serialnos+2,vf->serialnos[1],0)<0)return(OV_EREAD);
646
647 vf->offsets[0]=0;
648 vf->serialnos[0]=serialno;
649 vf->dataoffsets[0]=dataoffset;
650 vf->pcmlengths[0]=pcmoffset;
651 vf->pcmlengths[1]-=pcmoffset;
652 if(vf->pcmlengths[1]<0)vf->pcmlengths[1]=0;
653
654 return(ov_raw_seek(vf,dataoffset));
655 }
656
657 /* clear out the current logical bitstream decoder */
_decode_clear(OggVorbis_File * vf)658 static void _decode_clear(OggVorbis_File *vf){
659 vorbis_dsp_clear(&vf->vd);
660 vorbis_block_clear(&vf->vb);
661 vf->ready_state=OPENED;
662 }
663
664 /* fetch and process a packet. Handles the case where we're at a
665 bitstream boundary and dumps the decoding machine. If the decoding
666 machine is unloaded, it loads it. It also keeps pcm_offset up to
667 date (seek and read both use this. seek uses a special hack with
668 readp).
669
670 return: <0) error, OV_HOLE (lost packet) or OV_EOF
671 0) need more data (only if readp==0)
672 1) got a packet
673 */
674
_fetch_and_process_packet(OggVorbis_File * vf,ogg_packet * op_in,int readp,int spanp)675 static int _fetch_and_process_packet(OggVorbis_File *vf,
676 ogg_packet *op_in,
677 int readp,
678 int spanp){
679 ogg_page og;
680
681 /* handle one packet. Try to fetch it from current stream state */
682 /* extract packets from page */
683 while(1){
684
685 if(vf->ready_state==STREAMSET){
686 int ret=_make_decode_ready(vf);
687 if(ret<0)return ret;
688 }
689
690 /* process a packet if we can. */
691
692 if(vf->ready_state==INITSET){
693 int hs=vorbis_synthesis_halfrate_p(vf->vi);
694
695 while(1) {
696 ogg_packet op;
697 ogg_packet *op_ptr=(op_in?op_in:&op);
698 int result=ogg_stream_packetout(&vf->os,op_ptr);
699 ogg_int64_t granulepos;
700
701 op_in=NULL;
702 if(result==-1)return(OV_HOLE); /* hole in the data. */
703 if(result>0){
704 /* got a packet. process it */
705 granulepos=op_ptr->granulepos;
706 if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy
707 header handling. The
708 header packets aren't
709 audio, so if/when we
710 submit them,
711 vorbis_synthesis will
712 reject them */
713
714 /* suck in the synthesis data and track bitrate */
715 {
716 int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
717 /* for proper use of libvorbis within libvorbisfile,
718 oldsamples will always be zero. */
719 if(oldsamples)return(OV_EFAULT);
720
721 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
722 vf->samptrack+=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs);
723 vf->bittrack+=op_ptr->bytes*8;
724 }
725
726 /* update the pcm offset. */
727 if(granulepos!=-1 && !op_ptr->e_o_s){
728 int link=(vf->seekable?vf->current_link:0);
729 int i,samples;
730
731 /* this packet has a pcm_offset on it (the last packet
732 completed on a page carries the offset) After processing
733 (above), we know the pcm position of the *last* sample
734 ready to be returned. Find the offset of the *first*
735
736 As an aside, this trick is inaccurate if we begin
737 reading anew right at the last page; the end-of-stream
738 granulepos declares the last frame in the stream, and the
739 last packet of the last page may be a partial frame.
740 So, we need a previous granulepos from an in-sequence page
741 to have a reference point. Thus the !op_ptr->e_o_s clause
742 above */
743
744 if(vf->seekable && link>0)
745 granulepos-=vf->pcmlengths[link*2];
746 if(granulepos<0)granulepos=0; /* actually, this
747 shouldn't be possible
748 here unless the stream
749 is very broken */
750
751 samples=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs);
752
753 granulepos-=samples;
754 for(i=0;i<link;i++)
755 granulepos+=vf->pcmlengths[i*2+1];
756 vf->pcm_offset=granulepos;
757 }
758 return(1);
759 }
760 }
761 else
762 break;
763 }
764 }
765
766 if(vf->ready_state>=OPENED){
767 ogg_int64_t ret;
768
769 while(1){
770 /* the loop is not strictly necessary, but there's no sense in
771 doing the extra checks of the larger loop for the common
772 case in a multiplexed bistream where the page is simply
773 part of a different logical bitstream; keep reading until
774 we get one with the correct serialno */
775
776 if(!readp)return(0);
777 if((ret=_get_next_page(vf,&og,-1))<0){
778 return(OV_EOF); /* eof. leave unitialized */
779 }
780
781 /* bitrate tracking; add the header's bytes here, the body bytes
782 are done by packet above */
783 vf->bittrack+=og.header_len*8;
784
785 if(vf->ready_state==INITSET){
786 if(vf->current_serialno!=ogg_page_serialno(&og)){
787
788 /* two possibilities:
789 1) our decoding just traversed a bitstream boundary
790 2) another stream is multiplexed into this logical section */
791
792 if(ogg_page_bos(&og)){
793 /* boundary case */
794 if(!spanp)
795 return(OV_EOF);
796
797 _decode_clear(vf);
798
799 if(!vf->seekable){
800 vorbis_info_clear(vf->vi);
801 vorbis_comment_clear(vf->vc);
802 }
803 break;
804
805 }else
806 continue; /* possibility #2 */
807 }
808 }
809
810 break;
811 }
812 }
813
814 /* Do we need to load a new machine before submitting the page? */
815 /* This is different in the seekable and non-seekable cases.
816
817 In the seekable case, we already have all the header
818 information loaded and cached; we just initialize the machine
819 with it and continue on our merry way.
820
821 In the non-seekable (streaming) case, we'll only be at a
822 boundary if we just left the previous logical bitstream and
823 we're now nominally at the header of the next bitstream
824 */
825
826 if(vf->ready_state!=INITSET){
827 int link;
828
829 if(vf->ready_state<STREAMSET){
830 if(vf->seekable){
831 long serialno = ogg_page_serialno(&og);
832
833 /* match the serialno to bitstream section. We use this rather than
834 offset positions to avoid problems near logical bitstream
835 boundaries */
836
837 for(link=0;link<vf->links;link++)
838 if(vf->serialnos[link]==serialno)break;
839
840 if(link==vf->links) continue; /* not the desired Vorbis
841 bitstream section; keep
842 trying */
843
844 vf->current_serialno=serialno;
845 vf->current_link=link;
846
847 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
848 vf->ready_state=STREAMSET;
849
850 }else{
851 /* we're streaming */
852 /* fetch the three header packets, build the info struct */
853
854 int ret=_fetch_headers(vf,vf->vi,vf->vc,NULL,NULL,&og);
855 if(ret)return(ret);
856 vf->current_serialno=vf->os.serialno;
857 vf->current_link++;
858 link=0;
859 }
860 }
861 }
862
863 /* the buffered page is the data we want, and we're ready for it;
864 add it to the stream state */
865 ogg_stream_pagein(&vf->os,&og);
866
867 }
868 }
869
870 /* if, eg, 64 bit stdio is configured by default, this will build with
871 fseek64 */
_fseek64_wrap(FILE * f,ogg_int64_t off,int whence)872 static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
873 if(f==NULL)return(-1);
874 return fseek(f,off,whence);
875 }
876
_ov_open1(void * f,OggVorbis_File * vf,const char * initial,long ibytes,ov_callbacks callbacks)877 static int _ov_open1(void *f,OggVorbis_File *vf,const char *initial,
878 long ibytes, ov_callbacks callbacks){
879 int offsettest=((f && callbacks.seek_func)?callbacks.seek_func(f,0,SEEK_CUR):-1);
880 long *serialno_list=NULL;
881 int serialno_list_size=0;
882 int ret;
883
884 memset(vf,0,sizeof(*vf));
885 vf->datasource=f;
886 vf->callbacks = callbacks;
887
888 /* init the framing state */
889 ogg_sync_init(&vf->oy);
890
891 /* perhaps some data was previously read into a buffer for testing
892 against other stream types. Allow initialization from this
893 previously read data (especially as we may be reading from a
894 non-seekable stream) */
895 if(initial){
896 char *buffer=ogg_sync_buffer(&vf->oy,ibytes);
897 memcpy(buffer,initial,ibytes);
898 ogg_sync_wrote(&vf->oy,ibytes);
899 }
900
901 /* can we seek? Stevens suggests the seek test was portable */
902 if(offsettest!=-1)vf->seekable=1;
903
904 /* No seeking yet; Set up a 'single' (current) logical bitstream
905 entry for partial open */
906 vf->links=1;
907 vf->vi=_ogg_calloc(vf->links,sizeof(*vf->vi));
908 vf->vc=_ogg_calloc(vf->links,sizeof(*vf->vc));
909 ogg_stream_init(&vf->os,-1); /* fill in the serialno later */
910
911 /* Fetch all BOS pages, store the vorbis header and all seen serial
912 numbers, load subsequent vorbis setup headers */
913 if((ret=_fetch_headers(vf,vf->vi,vf->vc,&serialno_list,&serialno_list_size,NULL))<0){
914 vf->datasource=NULL;
915 ov_clear(vf);
916 }else{
917 /* serial number list for first link needs to be held somewhere
918 for second stage of seekable stream open; this saves having to
919 seek/reread first link's serialnumber data then. */
920 vf->serialnos=_ogg_calloc(serialno_list_size+2,sizeof(*vf->serialnos));
921 vf->serialnos[0]=vf->current_serialno=vf->os.serialno;
922 vf->serialnos[1]=serialno_list_size;
923 memcpy(vf->serialnos+2,serialno_list,serialno_list_size*sizeof(*vf->serialnos));
924
925 vf->offsets=_ogg_calloc(1,sizeof(*vf->offsets));
926 vf->dataoffsets=_ogg_calloc(1,sizeof(*vf->dataoffsets));
927 vf->offsets[0]=0;
928 vf->dataoffsets[0]=vf->offset;
929
930 vf->ready_state=PARTOPEN;
931 }
932 if(serialno_list)_ogg_free(serialno_list);
933 return(ret);
934 }
935
_ov_open2(OggVorbis_File * vf)936 static int _ov_open2(OggVorbis_File *vf){
937 if(vf->ready_state != PARTOPEN) return OV_EINVAL;
938 vf->ready_state=OPENED;
939 if(vf->seekable){
940 int ret=_open_seekable2(vf);
941 if(ret){
942 vf->datasource=NULL;
943 ov_clear(vf);
944 }
945 return(ret);
946 }else
947 vf->ready_state=STREAMSET;
948
949 return 0;
950 }
951
952
953 /* clear out the OggVorbis_File struct */
ov_clear(OggVorbis_File * vf)954 int ov_clear(OggVorbis_File *vf){
955 if(vf){
956 vorbis_block_clear(&vf->vb);
957 vorbis_dsp_clear(&vf->vd);
958 ogg_stream_clear(&vf->os);
959
960 if(vf->vi && vf->links){
961 int i;
962 for(i=0;i<vf->links;i++){
963 vorbis_info_clear(vf->vi+i);
964 vorbis_comment_clear(vf->vc+i);
965 }
966 _ogg_free(vf->vi);
967 _ogg_free(vf->vc);
968 }
969 if(vf->dataoffsets)_ogg_free(vf->dataoffsets);
970 if(vf->pcmlengths)_ogg_free(vf->pcmlengths);
971 if(vf->serialnos)_ogg_free(vf->serialnos);
972 if(vf->offsets)_ogg_free(vf->offsets);
973 ogg_sync_clear(&vf->oy);
974 if(vf->datasource && vf->callbacks.close_func)
975 (vf->callbacks.close_func)(vf->datasource);
976 memset(vf,0,sizeof(*vf));
977 }
978 #ifdef DEBUG_LEAKS
979 _VDBG_dump();
980 #endif
981 return(0);
982 }
983
984 /* inspects the OggVorbis file and finds/documents all the logical
985 bitstreams contained in it. Tries to be tolerant of logical
986 bitstream sections that are truncated/woogie.
987
988 return: -1) error
989 0) OK
990 */
991
ov_open_callbacks(void * f,OggVorbis_File * vf,const char * initial,long ibytes,ov_callbacks callbacks)992 int ov_open_callbacks(void *f,OggVorbis_File *vf,
993 const char *initial,long ibytes,ov_callbacks callbacks){
994 int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
995 if(ret)return ret;
996 return _ov_open2(vf);
997 }
998
ov_open(FILE * f,OggVorbis_File * vf,const char * initial,long ibytes)999 int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes){
1000 ov_callbacks callbacks = {
1001 (size_t (*)(void *, size_t, size_t, void *)) fread,
1002 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
1003 (int (*)(void *)) fclose,
1004 (long (*)(void *)) ftell
1005 };
1006
1007 return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
1008 }
1009
ov_fopen(const char * path,OggVorbis_File * vf)1010 int ov_fopen(const char *path,OggVorbis_File *vf){
1011 int ret;
1012 FILE *f = fopen(path,"rb");
1013 if(!f) return -1;
1014
1015 ret = ov_open(f,vf,NULL,0);
1016 if(ret) fclose(f);
1017 return ret;
1018 }
1019
1020
1021 /* cheap hack for game usage where downsampling is desirable; there's
1022 no need for SRC as we can just do it cheaply in libvorbis. */
1023
ov_halfrate(OggVorbis_File * vf,int flag)1024 int ov_halfrate(OggVorbis_File *vf,int flag){
1025 int i;
1026 if(vf->vi==NULL)return OV_EINVAL;
1027 if(vf->ready_state>STREAMSET){
1028 /* clear out stream state; dumping the decode machine is needed to
1029 reinit the MDCT lookups. */
1030 vorbis_dsp_clear(&vf->vd);
1031 vorbis_block_clear(&vf->vb);
1032 vf->ready_state=STREAMSET;
1033 if(vf->pcm_offset>=0){
1034 ogg_int64_t pos=vf->pcm_offset;
1035 vf->pcm_offset=-1; /* make sure the pos is dumped if unseekable */
1036 ov_pcm_seek(vf,pos);
1037 }
1038 }
1039
1040 for(i=0;i<vf->links;i++){
1041 if(vorbis_synthesis_halfrate(vf->vi+i,flag)){
1042 if(flag) ov_halfrate(vf,0);
1043 return OV_EINVAL;
1044 }
1045 }
1046 return 0;
1047 }
1048
ov_halfrate_p(OggVorbis_File * vf)1049 int ov_halfrate_p(OggVorbis_File *vf){
1050 if(vf->vi==NULL)return OV_EINVAL;
1051 return vorbis_synthesis_halfrate_p(vf->vi);
1052 }
1053
1054 /* Only partially open the vorbis file; test for Vorbisness, and load
1055 the headers for the first chain. Do not seek (although test for
1056 seekability). Use ov_test_open to finish opening the file, else
1057 ov_clear to close/free it. Same return codes as open.
1058
1059 Note that vorbisfile does _not_ take ownership of the file if the
1060 call fails; the calling applicaiton is responsible for closing the file
1061 if this call returns an error. */
1062
ov_test_callbacks(void * f,OggVorbis_File * vf,const char * initial,long ibytes,ov_callbacks callbacks)1063 int ov_test_callbacks(void *f,OggVorbis_File *vf,
1064 const char *initial,long ibytes,ov_callbacks callbacks)
1065 {
1066 return _ov_open1(f,vf,initial,ibytes,callbacks);
1067 }
1068
ov_test(FILE * f,OggVorbis_File * vf,const char * initial,long ibytes)1069 int ov_test(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes){
1070 ov_callbacks callbacks = {
1071 (size_t (*)(void *, size_t, size_t, void *)) fread,
1072 (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap,
1073 (int (*)(void *)) fclose,
1074 (long (*)(void *)) ftell
1075 };
1076
1077 return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
1078 }
1079
ov_test_open(OggVorbis_File * vf)1080 int ov_test_open(OggVorbis_File *vf){
1081 if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
1082 return _ov_open2(vf);
1083 }
1084
1085 /* How many logical bitstreams in this physical bitstream? */
ov_streams(OggVorbis_File * vf)1086 long ov_streams(OggVorbis_File *vf){
1087 return vf->links;
1088 }
1089
1090 /* Is the FILE * associated with vf seekable? */
ov_seekable(OggVorbis_File * vf)1091 long ov_seekable(OggVorbis_File *vf){
1092 return vf->seekable;
1093 }
1094
1095 /* returns the bitrate for a given logical bitstream or the entire
1096 physical bitstream. If the file is open for random access, it will
1097 find the *actual* average bitrate. If the file is streaming, it
1098 returns the nominal bitrate (if set) else the average of the
1099 upper/lower bounds (if set) else -1 (unset).
1100
1101 If you want the actual bitrate field settings, get them from the
1102 vorbis_info structs */
1103
ov_bitrate(OggVorbis_File * vf,int i)1104 long ov_bitrate(OggVorbis_File *vf,int i){
1105 if(vf->ready_state<OPENED)return(OV_EINVAL);
1106 if(i>=vf->links)return(OV_EINVAL);
1107 if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
1108 if(i<0){
1109 ogg_int64_t bits=0;
1110 int i;
1111 float br;
1112 for(i=0;i<vf->links;i++)
1113 bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
1114 /* This once read: return(rint(bits/ov_time_total(vf,-1)));
1115 * gcc 3.x on x86 miscompiled this at optimisation level 2 and above,
1116 * so this is slightly transformed to make it work.
1117 */
1118 br = bits/ov_time_total(vf,-1);
1119 return(rint(br));
1120 }else{
1121 if(vf->seekable){
1122 /* return the actual bitrate */
1123 return(rint((vf->offsets[i+1]-vf->dataoffsets[i])*8/ov_time_total(vf,i)));
1124 }else{
1125 /* return nominal if set */
1126 if(vf->vi[i].bitrate_nominal>0){
1127 return vf->vi[i].bitrate_nominal;
1128 }else{
1129 if(vf->vi[i].bitrate_upper>0){
1130 if(vf->vi[i].bitrate_lower>0){
1131 return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
1132 }else{
1133 return vf->vi[i].bitrate_upper;
1134 }
1135 }
1136 return(OV_FALSE);
1137 }
1138 }
1139 }
1140 }
1141
1142 /* returns the actual bitrate since last call. returns -1 if no
1143 additional data to offer since last call (or at beginning of stream),
1144 EINVAL if stream is only partially open
1145 */
ov_bitrate_instant(OggVorbis_File * vf)1146 long ov_bitrate_instant(OggVorbis_File *vf){
1147 int link=(vf->seekable?vf->current_link:0);
1148 long ret;
1149 if(vf->ready_state<OPENED)return(OV_EINVAL);
1150 if(vf->samptrack==0)return(OV_FALSE);
1151 ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
1152 vf->bittrack=0.f;
1153 vf->samptrack=0.f;
1154 return(ret);
1155 }
1156
1157 /* Guess */
ov_serialnumber(OggVorbis_File * vf,int i)1158 long ov_serialnumber(OggVorbis_File *vf,int i){
1159 if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
1160 if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
1161 if(i<0){
1162 return(vf->current_serialno);
1163 }else{
1164 return(vf->serialnos[i]);
1165 }
1166 }
1167
1168 /* returns: total raw (compressed) length of content if i==-1
1169 raw (compressed) length of that logical bitstream for i==0 to n
1170 OV_EINVAL if the stream is not seekable (we can't know the length)
1171 or if stream is only partially open
1172 */
ov_raw_total(OggVorbis_File * vf,int i)1173 ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
1174 if(vf->ready_state<OPENED)return(OV_EINVAL);
1175 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1176 if(i<0){
1177 ogg_int64_t acc=0;
1178 int i;
1179 for(i=0;i<vf->links;i++)
1180 acc+=ov_raw_total(vf,i);
1181 return(acc);
1182 }else{
1183 return(vf->offsets[i+1]-vf->offsets[i]);
1184 }
1185 }
1186
1187 /* returns: total PCM length (samples) of content if i==-1 PCM length
1188 (samples) of that logical bitstream for i==0 to n
1189 OV_EINVAL if the stream is not seekable (we can't know the
1190 length) or only partially open
1191 */
ov_pcm_total(OggVorbis_File * vf,int i)1192 ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
1193 if(vf->ready_state<OPENED)return(OV_EINVAL);
1194 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1195 if(i<0){
1196 ogg_int64_t acc=0;
1197 int i;
1198 for(i=0;i<vf->links;i++)
1199 acc+=ov_pcm_total(vf,i);
1200 return(acc);
1201 }else{
1202 return(vf->pcmlengths[i*2+1]);
1203 }
1204 }
1205
1206 /* returns: total seconds of content if i==-1
1207 seconds in that logical bitstream for i==0 to n
1208 OV_EINVAL if the stream is not seekable (we can't know the
1209 length) or only partially open
1210 */
ov_time_total(OggVorbis_File * vf,int i)1211 double ov_time_total(OggVorbis_File *vf,int i){
1212 if(vf->ready_state<OPENED)return(OV_EINVAL);
1213 if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
1214 if(i<0){
1215 double acc=0;
1216 int i;
1217 for(i=0;i<vf->links;i++)
1218 acc+=ov_time_total(vf,i);
1219 return(acc);
1220 }else{
1221 return((double)(vf->pcmlengths[i*2+1])/vf->vi[i].rate);
1222 }
1223 }
1224
1225 /* seek to an offset relative to the *compressed* data. This also
1226 scans packets to update the PCM cursor. It will cross a logical
1227 bitstream boundary, but only if it can't get any packets out of the
1228 tail of the bitstream we seek to (so no surprises).
1229
1230 returns zero on success, nonzero on failure */
1231
ov_raw_seek(OggVorbis_File * vf,ogg_int64_t pos)1232 int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
1233 ogg_stream_state work_os;
1234 int ret;
1235
1236 if(vf->ready_state<OPENED)return(OV_EINVAL);
1237 if(!vf->seekable)
1238 return(OV_ENOSEEK); /* don't dump machine if we can't seek */
1239
1240 if(pos<0 || pos>vf->end)return(OV_EINVAL);
1241
1242 /* is the seek position outside our current link [if any]? */
1243 if(vf->ready_state>=STREAMSET){
1244 if(pos<vf->offsets[vf->current_link] || pos>=vf->offsets[vf->current_link+1])
1245 _decode_clear(vf); /* clear out stream state */
1246 }
1247
1248 /* don't yet clear out decoding machine (if it's initialized), in
1249 the case we're in the same link. Restart the decode lapping, and
1250 let _fetch_and_process_packet deal with a potential bitstream
1251 boundary */
1252 vf->pcm_offset=-1;
1253 ogg_stream_reset_serialno(&vf->os,
1254 vf->current_serialno); /* must set serialno */
1255 vorbis_synthesis_restart(&vf->vd);
1256
1257 ret=_seek_helper(vf,pos);
1258 if(ret)goto seek_error;
1259
1260 /* we need to make sure the pcm_offset is set, but we don't want to
1261 advance the raw cursor past good packets just to get to the first
1262 with a granulepos. That's not equivalent behavior to beginning
1263 decoding as immediately after the seek position as possible.
1264
1265 So, a hack. We use two stream states; a local scratch state and
1266 the shared vf->os stream state. We use the local state to
1267 scan, and the shared state as a buffer for later decode.
1268
1269 Unfortuantely, on the last page we still advance to last packet
1270 because the granulepos on the last page is not necessarily on a
1271 packet boundary, and we need to make sure the granpos is
1272 correct.
1273 */
1274
1275 {
1276 ogg_page og;
1277 ogg_packet op;
1278 int lastblock=0;
1279 int accblock=0;
1280 int thisblock=0;
1281 int lastflag=0;
1282 int firstflag=0;
1283 ogg_int64_t pagepos=-1;
1284
1285 ogg_stream_init(&work_os,vf->current_serialno); /* get the memory ready */
1286 ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE
1287 return from not necessarily
1288 starting from the beginning */
1289
1290 while(1){
1291 if(vf->ready_state>=STREAMSET){
1292 /* snarf/scan a packet if we can */
1293 int result=ogg_stream_packetout(&work_os,&op);
1294
1295 if(result>0){
1296
1297 if(vf->vi[vf->current_link].codec_setup){
1298 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1299 if(thisblock<0){
1300 ogg_stream_packetout(&vf->os,NULL);
1301 thisblock=0;
1302 }else{
1303
1304 /* We can't get a guaranteed correct pcm position out of the
1305 last page in a stream because it might have a 'short'
1306 granpos, which can only be detected in the presence of a
1307 preceding page. However, if the last page is also the first
1308 page, the granpos rules of a first page take precedence. Not
1309 only that, but for first==last, the EOS page must be treated
1310 as if its a normal first page for the stream to open/play. */
1311 if(lastflag && !firstflag)
1312 ogg_stream_packetout(&vf->os,NULL);
1313 else
1314 if(lastblock)accblock+=(lastblock+thisblock)>>2;
1315 }
1316
1317 if(op.granulepos!=-1){
1318 int i,link=vf->current_link;
1319 ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
1320 if(granulepos<0)granulepos=0;
1321
1322 for(i=0;i<link;i++)
1323 granulepos+=vf->pcmlengths[i*2+1];
1324 vf->pcm_offset=granulepos-accblock;
1325 if(vf->pcm_offset<0)vf->pcm_offset=0;
1326 break;
1327 }
1328 lastblock=thisblock;
1329 continue;
1330 }else
1331 ogg_stream_packetout(&vf->os,NULL);
1332 }
1333 }
1334
1335 if(!lastblock){
1336 pagepos=_get_next_page(vf,&og,-1);
1337 if(pagepos<0){
1338 vf->pcm_offset=ov_pcm_total(vf,-1);
1339 break;
1340 }
1341 }else{
1342 /* huh? Bogus stream with packets but no granulepos */
1343 vf->pcm_offset=-1;
1344 break;
1345 }
1346
1347 /* has our decoding just traversed a bitstream boundary? */
1348 if(vf->ready_state>=STREAMSET){
1349 if(vf->current_serialno!=ogg_page_serialno(&og)){
1350
1351 /* two possibilities:
1352 1) our decoding just traversed a bitstream boundary
1353 2) another stream is multiplexed into this logical section? */
1354
1355 if(ogg_page_bos(&og)){
1356 /* we traversed */
1357 _decode_clear(vf); /* clear out stream state */
1358 ogg_stream_clear(&work_os);
1359 } /* else, do nothing; next loop will scoop another page */
1360 }
1361 }
1362
1363 if(vf->ready_state<STREAMSET){
1364 int link;
1365 long serialno = ogg_page_serialno(&og);
1366
1367 for(link=0;link<vf->links;link++)
1368 if(vf->serialnos[link]==serialno)break;
1369
1370 if(link==vf->links) continue; /* not the desired Vorbis
1371 bitstream section; keep
1372 trying */
1373 vf->current_link=link;
1374 vf->current_serialno=serialno;
1375 ogg_stream_reset_serialno(&vf->os,serialno);
1376 ogg_stream_reset_serialno(&work_os,serialno);
1377 vf->ready_state=STREAMSET;
1378 firstflag=(pagepos<=vf->dataoffsets[link]);
1379 }
1380
1381 ogg_stream_pagein(&vf->os,&og);
1382 ogg_stream_pagein(&work_os,&og);
1383 lastflag=ogg_page_eos(&og);
1384
1385 }
1386 }
1387
1388 ogg_stream_clear(&work_os);
1389 vf->bittrack=0.f;
1390 vf->samptrack=0.f;
1391 return(0);
1392
1393 seek_error:
1394 /* dump the machine so we're in a known state */
1395 vf->pcm_offset=-1;
1396 ogg_stream_clear(&work_os);
1397 _decode_clear(vf);
1398 return OV_EBADLINK;
1399 }
1400
1401 /* Page granularity seek (faster than sample granularity because we
1402 don't do the last bit of decode to find a specific sample).
1403
1404 Seek to the last [granule marked] page preceding the specified pos
1405 location, such that decoding past the returned point will quickly
1406 arrive at the requested position. */
ov_pcm_seek_page(OggVorbis_File * vf,ogg_int64_t pos)1407 int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
1408 int link=-1;
1409 ogg_int64_t result=0;
1410 ogg_int64_t total=ov_pcm_total(vf,-1);
1411
1412 if(vf->ready_state<OPENED)return(OV_EINVAL);
1413 if(!vf->seekable)return(OV_ENOSEEK);
1414
1415 if(pos<0 || pos>total)return(OV_EINVAL);
1416
1417 /* which bitstream section does this pcm offset occur in? */
1418 for(link=vf->links-1;link>=0;link--){
1419 total-=vf->pcmlengths[link*2+1];
1420 if(pos>=total)break;
1421 }
1422
1423 /* Search within the logical bitstream for the page with the highest
1424 pcm_pos preceding pos. If we're looking for a position on the
1425 first page, bisection will halt without finding our position as
1426 it's before the first explicit granulepos fencepost. That case is
1427 handled separately below.
1428
1429 There is a danger here; missing pages or incorrect frame number
1430 information in the bitstream could make our task impossible.
1431 Account for that (it would be an error condition) */
1432
1433 /* new search algorithm originally by HB (Nicholas Vinen) */
1434
1435 {
1436 ogg_int64_t end=vf->offsets[link+1];
1437 ogg_int64_t begin=vf->dataoffsets[link];
1438 ogg_int64_t begintime = vf->pcmlengths[link*2];
1439 ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
1440 ogg_int64_t target=pos-total+begintime;
1441 ogg_int64_t best=-1;
1442 int got_page=0;
1443
1444 ogg_page og;
1445
1446 /* if we have only one page, there will be no bisection. Grab the page here */
1447 if(begin==end){
1448 result=_seek_helper(vf,begin);
1449 if(result) goto seek_error;
1450
1451 result=_get_next_page(vf,&og,1);
1452 if(result<0) goto seek_error;
1453
1454 got_page=1;
1455 }
1456
1457 /* bisection loop */
1458 while(begin<end){
1459 ogg_int64_t bisect;
1460
1461 if(end-begin<CHUNKSIZE){
1462 bisect=begin;
1463 }else{
1464 /* take a (pretty decent) guess. */
1465 bisect=begin +
1466 (ogg_int64_t)((double)(target-begintime)*(end-begin)/(endtime-begintime))
1467 - CHUNKSIZE;
1468 if(bisect<begin+CHUNKSIZE)
1469 bisect=begin;
1470 }
1471
1472 result=_seek_helper(vf,bisect);
1473 if(result) goto seek_error;
1474
1475 /* read loop within the bisection loop */
1476 while(begin<end){
1477 result=_get_next_page(vf,&og,end-vf->offset);
1478 if(result==OV_EREAD) goto seek_error;
1479 if(result<0){
1480 /* there is no next page! */
1481 if(bisect<=begin+1)
1482 /* No bisection left to perform. We've either found the
1483 best candidate already or failed. Exit loop. */
1484 end=begin;
1485 else{
1486 /* We tried to load a fraction of the last page; back up a
1487 bit and try to get the whole last page */
1488 if(bisect==0) goto seek_error;
1489 bisect-=CHUNKSIZE;
1490
1491 /* don't repeat/loop on a read we've already performed */
1492 if(bisect<=begin)bisect=begin+1;
1493
1494 /* seek and cntinue bisection */
1495 result=_seek_helper(vf,bisect);
1496 if(result) goto seek_error;
1497 }
1498 }else{
1499 ogg_int64_t granulepos;
1500 got_page=1;
1501
1502 /* got a page. analyze it */
1503 /* only consider pages from primary vorbis stream */
1504 if(ogg_page_serialno(&og)!=vf->serialnos[link])
1505 continue;
1506
1507 /* only consider pages with the granulepos set */
1508 granulepos=ogg_page_granulepos(&og);
1509 if(granulepos==-1)continue;
1510
1511 if(granulepos<target){
1512 /* this page is a successful candidate! Set state */
1513
1514 best=result; /* raw offset of packet with granulepos */
1515 begin=vf->offset; /* raw offset of next page */
1516 begintime=granulepos;
1517
1518 /* if we're before our target but within a short distance,
1519 don't bisect; read forward */
1520 if(target-begintime>44100)break;
1521
1522 bisect=begin; /* *not* begin + 1 as above */
1523 }else{
1524
1525 /* This is one of our pages, but the granpos is
1526 post-target; it is not a bisection return
1527 candidate. (The only way we'd use it is if it's the
1528 first page in the stream; we handle that case later
1529 outside the bisection) */
1530 if(bisect<=begin+1){
1531 /* No bisection left to perform. We've either found the
1532 best candidate already or failed. Exit loop. */
1533 end=begin;
1534 }else{
1535 if(end==vf->offset){
1536 /* bisection read to the end; use the known page
1537 boundary (result) to update bisection, back up a
1538 little bit, and try again */
1539 end=result;
1540 bisect-=CHUNKSIZE;
1541 if(bisect<=begin)bisect=begin+1;
1542 result=_seek_helper(vf,bisect);
1543 if(result) goto seek_error;
1544 }else{
1545 /* Normal bisection */
1546 end=bisect;
1547 endtime=granulepos;
1548 break;
1549 }
1550 }
1551 }
1552 }
1553 }
1554 }
1555
1556 /* Out of bisection: did it 'fail?' */
1557 if(best == -1){
1558
1559 /* Check the 'looking for data in first page' special case;
1560 bisection would 'fail' because our search target was before the
1561 first PCM granule position fencepost. */
1562
1563 if(got_page &&
1564 begin == vf->dataoffsets[link] &&
1565 ogg_page_serialno(&og)==vf->serialnos[link]){
1566
1567 /* Yes, this is the beginning-of-stream case. We already have
1568 our page, right at the beginning of PCM data. Set state
1569 and return. */
1570
1571 vf->pcm_offset=total;
1572
1573 if(link!=vf->current_link){
1574 /* Different link; dump entire decode machine */
1575 _decode_clear(vf);
1576
1577 vf->current_link=link;
1578 vf->current_serialno=vf->serialnos[link];
1579 vf->ready_state=STREAMSET;
1580
1581 }else{
1582 vorbis_synthesis_restart(&vf->vd);
1583 }
1584
1585 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
1586 ogg_stream_pagein(&vf->os,&og);
1587
1588 }else
1589 goto seek_error;
1590
1591 }else{
1592
1593 /* Bisection found our page. seek to it, update pcm offset. Easier case than
1594 raw_seek, don't keep packets preceding granulepos. */
1595
1596 ogg_page og;
1597 ogg_packet op;
1598
1599 /* seek */
1600 result=_seek_helper(vf,best);
1601 vf->pcm_offset=-1;
1602 if(result) goto seek_error;
1603 result=_get_next_page(vf,&og,-1);
1604 if(result<0) goto seek_error;
1605
1606 if(link!=vf->current_link){
1607 /* Different link; dump entire decode machine */
1608 _decode_clear(vf);
1609
1610 vf->current_link=link;
1611 vf->current_serialno=vf->serialnos[link];
1612 vf->ready_state=STREAMSET;
1613
1614 }else{
1615 vorbis_synthesis_restart(&vf->vd);
1616 }
1617
1618 ogg_stream_reset_serialno(&vf->os,vf->current_serialno);
1619 ogg_stream_pagein(&vf->os,&og);
1620
1621 /* pull out all but last packet; the one with granulepos */
1622 while(1){
1623 result=ogg_stream_packetpeek(&vf->os,&op);
1624 if(result==0){
1625 /* No packet returned; we exited the bisection with 'best'
1626 pointing to a page with a granule position, so the packet
1627 finishing this page ('best') originated on a preceding
1628 page. Keep fetching previous pages until we get one with
1629 a granulepos or without the 'continued' flag set. Then
1630 just use raw_seek for simplicity. */
1631 /* Do not rewind past the beginning of link data; if we do,
1632 it's either a bug or a broken stream */
1633 result=best;
1634 while(result>vf->dataoffsets[link]){
1635 result=_get_prev_page(vf,result,&og);
1636 if(result<0) goto seek_error;
1637 if(ogg_page_serialno(&og)==vf->current_serialno &&
1638 (ogg_page_granulepos(&og)>-1 ||
1639 !ogg_page_continued(&og))){
1640 return ov_raw_seek(vf,result);
1641 }
1642 }
1643 }
1644 if(result<0){
1645 result = OV_EBADPACKET;
1646 goto seek_error;
1647 }
1648 if(op.granulepos!=-1){
1649 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1650 if(vf->pcm_offset<0)vf->pcm_offset=0;
1651 vf->pcm_offset+=total;
1652 break;
1653 }else
1654 result=ogg_stream_packetout(&vf->os,NULL);
1655 }
1656 }
1657 }
1658
1659 /* verify result */
1660 if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
1661 result=OV_EFAULT;
1662 goto seek_error;
1663 }
1664 vf->bittrack=0.f;
1665 vf->samptrack=0.f;
1666 return(0);
1667
1668 seek_error:
1669 /* dump machine so we're in a known state */
1670 vf->pcm_offset=-1;
1671 _decode_clear(vf);
1672 return (int)result;
1673 }
1674
1675 /* seek to a sample offset relative to the decompressed pcm stream
1676 returns zero on success, nonzero on failure */
1677
ov_pcm_seek(OggVorbis_File * vf,ogg_int64_t pos)1678 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
1679 int thisblock,lastblock=0;
1680 int ret=ov_pcm_seek_page(vf,pos);
1681 if(ret<0)return(ret);
1682 if((ret=_make_decode_ready(vf)))return ret;
1683
1684 /* discard leading packets we don't need for the lapping of the
1685 position we want; don't decode them */
1686
1687 while(1){
1688 ogg_packet op;
1689 ogg_page og;
1690
1691 int ret=ogg_stream_packetpeek(&vf->os,&op);
1692 if(ret>0){
1693 thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
1694 if(thisblock<0){
1695 ogg_stream_packetout(&vf->os,NULL);
1696 continue; /* non audio packet */
1697 }
1698 if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
1699
1700 if(vf->pcm_offset+((thisblock+
1701 vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
1702
1703 /* remove the packet from packet queue and track its granulepos */
1704 ogg_stream_packetout(&vf->os,NULL);
1705 vorbis_synthesis_trackonly(&vf->vb,&op); /* set up a vb with
1706 only tracking, no
1707 pcm_decode */
1708 vorbis_synthesis_blockin(&vf->vd,&vf->vb);
1709
1710 /* end of logical stream case is hard, especially with exact
1711 length positioning. */
1712
1713 if(op.granulepos>-1){
1714 int i;
1715 /* always believe the stream markers */
1716 vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
1717 if(vf->pcm_offset<0)vf->pcm_offset=0;
1718 for(i=0;i<vf->current_link;i++)
1719 vf->pcm_offset+=vf->pcmlengths[i*2+1];
1720 }
1721
1722 lastblock=thisblock;
1723
1724 }else{
1725 if(ret<0 && ret!=OV_HOLE)break;
1726
1727 /* suck in a new page */
1728 if(_get_next_page(vf,&og,-1)<0)break;
1729 if(ogg_page_bos(&og))_decode_clear(vf);
1730
1731 if(vf->ready_state<STREAMSET){
1732 long serialno=ogg_page_serialno(&og);
1733 int link;
1734
1735 for(link=0;link<vf->links;link++)
1736 if(vf->serialnos[link]==serialno)break;
1737 if(link==vf->links) continue;
1738 vf->current_link=link;
1739
1740 vf->ready_state=STREAMSET;
1741 vf->current_serialno=ogg_page_serialno(&og);
1742 ogg_stream_reset_serialno(&vf->os,serialno);
1743 ret=_make_decode_ready(vf);
1744 if(ret)return ret;
1745 lastblock=0;
1746 }
1747
1748 ogg_stream_pagein(&vf->os,&og);
1749 }
1750 }
1751
1752 vf->bittrack=0.f;
1753 vf->samptrack=0.f;
1754 /* discard samples until we reach the desired position. Crossing a
1755 logical bitstream boundary with abandon is OK. */
1756 {
1757 /* note that halfrate could be set differently in each link, but
1758 vorbisfile encoforces all links are set or unset */
1759 int hs=vorbis_synthesis_halfrate_p(vf->vi);
1760 while(vf->pcm_offset<((pos>>hs)<<hs)){
1761 ogg_int64_t target=(pos-vf->pcm_offset)>>hs;
1762 long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
1763
1764 if(samples>target)samples=target;
1765 vorbis_synthesis_read(&vf->vd,samples);
1766 vf->pcm_offset+=samples<<hs;
1767
1768 if(samples<target)
1769 if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
1770 vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
1771 }
1772 }
1773 return 0;
1774 }
1775
1776 /* seek to a playback time relative to the decompressed pcm stream
1777 returns zero on success, nonzero on failure */
ov_time_seek(OggVorbis_File * vf,double seconds)1778 int ov_time_seek(OggVorbis_File *vf,double seconds){
1779 /* translate time to PCM position and call ov_pcm_seek */
1780
1781 int link=-1;
1782 ogg_int64_t pcm_total=0;
1783 double time_total=0.;
1784
1785 if(vf->ready_state<OPENED)return(OV_EINVAL);
1786 if(!vf->seekable)return(OV_ENOSEEK);
1787 if(seconds<0)return(OV_EINVAL);
1788
1789 /* which bitstream section does this time offset occur in? */
1790 for(link=0;link<vf->links;link++){
1791 double addsec = ov_time_total(vf,link);
1792 if(seconds<time_total+addsec)break;
1793 time_total+=addsec;
1794 pcm_total+=vf->pcmlengths[link*2+1];
1795 }
1796
1797 if(link==vf->links)return(OV_EINVAL);
1798
1799 /* enough information to convert time offset to pcm offset */
1800 {
1801 ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1802 return(ov_pcm_seek(vf,target));
1803 }
1804 }
1805
1806 /* page-granularity version of ov_time_seek
1807 returns zero on success, nonzero on failure */
ov_time_seek_page(OggVorbis_File * vf,double seconds)1808 int ov_time_seek_page(OggVorbis_File *vf,double seconds){
1809 /* translate time to PCM position and call ov_pcm_seek */
1810
1811 int link=-1;
1812 ogg_int64_t pcm_total=0;
1813 double time_total=0.;
1814
1815 if(vf->ready_state<OPENED)return(OV_EINVAL);
1816 if(!vf->seekable)return(OV_ENOSEEK);
1817 if(seconds<0)return(OV_EINVAL);
1818
1819 /* which bitstream section does this time offset occur in? */
1820 for(link=0;link<vf->links;link++){
1821 double addsec = ov_time_total(vf,link);
1822 if(seconds<time_total+addsec)break;
1823 time_total+=addsec;
1824 pcm_total+=vf->pcmlengths[link*2+1];
1825 }
1826
1827 if(link==vf->links)return(OV_EINVAL);
1828
1829 /* enough information to convert time offset to pcm offset */
1830 {
1831 ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
1832 return(ov_pcm_seek_page(vf,target));
1833 }
1834 }
1835
1836 /* tell the current stream offset cursor. Note that seek followed by
1837 tell will likely not give the set offset due to caching */
ov_raw_tell(OggVorbis_File * vf)1838 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
1839 if(vf->ready_state<OPENED)return(OV_EINVAL);
1840 return(vf->offset);
1841 }
1842
1843 /* return PCM offset (sample) of next PCM sample to be read */
ov_pcm_tell(OggVorbis_File * vf)1844 ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
1845 if(vf->ready_state<OPENED)return(OV_EINVAL);
1846 return(vf->pcm_offset);
1847 }
1848
1849 /* return time offset (seconds) of next PCM sample to be read */
ov_time_tell(OggVorbis_File * vf)1850 double ov_time_tell(OggVorbis_File *vf){
1851 int link=0;
1852 ogg_int64_t pcm_total=0;
1853 double time_total=0.f;
1854
1855 if(vf->ready_state<OPENED)return(OV_EINVAL);
1856 if(vf->seekable){
1857 pcm_total=ov_pcm_total(vf,-1);
1858 time_total=ov_time_total(vf,-1);
1859
1860 /* which bitstream section does this time offset occur in? */
1861 for(link=vf->links-1;link>=0;link--){
1862 pcm_total-=vf->pcmlengths[link*2+1];
1863 time_total-=ov_time_total(vf,link);
1864 if(vf->pcm_offset>=pcm_total)break;
1865 }
1866 }
1867
1868 return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);
1869 }
1870
1871 /* link: -1) return the vorbis_info struct for the bitstream section
1872 currently being decoded
1873 0-n) to request information for a specific bitstream section
1874
1875 In the case of a non-seekable bitstream, any call returns the
1876 current bitstream. NULL in the case that the machine is not
1877 initialized */
1878
ov_info(OggVorbis_File * vf,int link)1879 vorbis_info *ov_info(OggVorbis_File *vf,int link){
1880 if(vf->seekable){
1881 if(link<0)
1882 if(vf->ready_state>=STREAMSET)
1883 return vf->vi+vf->current_link;
1884 else
1885 return vf->vi;
1886 else
1887 if(link>=vf->links)
1888 return NULL;
1889 else
1890 return vf->vi+link;
1891 }else{
1892 return vf->vi;
1893 }
1894 }
1895
1896 /* grr, strong typing, grr, no templates/inheritence, grr */
ov_comment(OggVorbis_File * vf,int link)1897 vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
1898 if(vf->seekable){
1899 if(link<0)
1900 if(vf->ready_state>=STREAMSET)
1901 return vf->vc+vf->current_link;
1902 else
1903 return vf->vc;
1904 else
1905 if(link>=vf->links)
1906 return NULL;
1907 else
1908 return vf->vc+link;
1909 }else{
1910 return vf->vc;
1911 }
1912 }
1913
host_is_big_endian()1914 static int host_is_big_endian() {
1915 ogg_int32_t pattern = 0xfeedface; /* deadbeef */
1916 unsigned char *bytewise = (unsigned char *)&pattern;
1917 if (bytewise[0] == 0xfe) return 1;
1918 return 0;
1919 }
1920
1921 /* up to this point, everything could more or less hide the multiple
1922 logical bitstream nature of chaining from the toplevel application
1923 if the toplevel application didn't particularly care. However, at
1924 the point that we actually read audio back, the multiple-section
1925 nature must surface: Multiple bitstream sections do not necessarily
1926 have to have the same number of channels or sampling rate.
1927
1928 ov_read returns the sequential logical bitstream number currently
1929 being decoded along with the PCM data in order that the toplevel
1930 application can take action on channel/sample rate changes. This
1931 number will be incremented even for streamed (non-seekable) streams
1932 (for seekable streams, it represents the actual logical bitstream
1933 index within the physical bitstream. Note that the accessor
1934 functions above are aware of this dichotomy).
1935
1936 ov_read_filter is exactly the same as ov_read except that it processes
1937 the decoded audio data through a filter before packing it into the
1938 requested format. This gives greater accuracy than applying a filter
1939 after the audio has been converted into integral PCM.
1940
1941 input values: buffer) a buffer to hold packed PCM data for return
1942 length) the byte length requested to be placed into buffer
1943 bigendianp) should the data be packed LSB first (0) or
1944 MSB first (1)
1945 word) word size for output. currently 1 (byte) or
1946 2 (16 bit short)
1947
1948 return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
1949 0) EOF
1950 n) number of bytes of PCM actually returned. The
1951 below works on a packet-by-packet basis, so the
1952 return length is not related to the 'length' passed
1953 in, just guaranteed to fit.
1954
1955 *section) set to the logical bitstream number */
1956
ov_read_filter(OggVorbis_File * vf,char * buffer,int length,int bigendianp,int word,int sgned,int * bitstream,void (* filter)(float ** pcm,long channels,long samples,void * filter_param),void * filter_param)1957 long ov_read_filter(OggVorbis_File *vf,char *buffer,int length,
1958 int bigendianp,int word,int sgned,int *bitstream,
1959 void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param){
1960 int i,j;
1961 int host_endian = host_is_big_endian();
1962 int hs;
1963
1964 float **pcm;
1965 long samples;
1966
1967 if(vf->ready_state<OPENED)return(OV_EINVAL);
1968
1969 while(1){
1970 if(vf->ready_state==INITSET){
1971 samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
1972 if(samples)break;
1973 }
1974
1975 /* suck in another packet */
1976 {
1977 int ret=_fetch_and_process_packet(vf,NULL,1,1);
1978 if(ret==OV_EOF)
1979 return(0);
1980 if(ret<=0)
1981 return(ret);
1982 }
1983
1984 }
1985
1986 if(samples>0){
1987
1988 /* yay! proceed to pack data into the byte buffer */
1989
1990 long channels=ov_info(vf,-1)->channels;
1991 long bytespersample=word * channels;
1992 vorbis_fpu_control fpu;
1993 if(samples>length/bytespersample)samples=length/bytespersample;
1994
1995 if(samples <= 0)
1996 return OV_EINVAL;
1997
1998 /* Here. */
1999 if(filter)
2000 filter(pcm,channels,samples,filter_param);
2001
2002 /* a tight loop to pack each size */
2003 {
2004 int val;
2005 if(word==1){
2006 int off=(sgned?0:128);
2007 vorbis_fpu_setround(&fpu);
2008 for(j=0;j<samples;j++)
2009 for(i=0;i<channels;i++){
2010 val=vorbis_ftoi(pcm[i][j]*128.f);
2011 if(val>127)val=127;
2012 else if(val<-128)val=-128;
2013 *buffer++=val+off;
2014 }
2015 vorbis_fpu_restore(fpu);
2016 }else{
2017 int off=(sgned?0:32768);
2018
2019 if(host_endian==bigendianp){
2020 if(sgned){
2021
2022 vorbis_fpu_setround(&fpu);
2023 for(i=0;i<channels;i++) { /* It's faster in this order */
2024 float *src=pcm[i];
2025 short *dest=((short *)buffer)+i;
2026 for(j=0;j<samples;j++) {
2027 val=vorbis_ftoi(src[j]*32768.f);
2028 if(val>32767)val=32767;
2029 else if(val<-32768)val=-32768;
2030 *dest=val;
2031 dest+=channels;
2032 }
2033 }
2034 vorbis_fpu_restore(fpu);
2035
2036 }else{
2037
2038 vorbis_fpu_setround(&fpu);
2039 for(i=0;i<channels;i++) {
2040 float *src=pcm[i];
2041 short *dest=((short *)buffer)+i;
2042 for(j=0;j<samples;j++) {
2043 val=vorbis_ftoi(src[j]*32768.f);
2044 if(val>32767)val=32767;
2045 else if(val<-32768)val=-32768;
2046 *dest=val+off;
2047 dest+=channels;
2048 }
2049 }
2050 vorbis_fpu_restore(fpu);
2051
2052 }
2053 }else if(bigendianp){
2054
2055 vorbis_fpu_setround(&fpu);
2056 for(j=0;j<samples;j++)
2057 for(i=0;i<channels;i++){
2058 val=vorbis_ftoi(pcm[i][j]*32768.f);
2059 if(val>32767)val=32767;
2060 else if(val<-32768)val=-32768;
2061 val+=off;
2062 *buffer++=(val>>8);
2063 *buffer++=(val&0xff);
2064 }
2065 vorbis_fpu_restore(fpu);
2066
2067 }else{
2068 int val;
2069 vorbis_fpu_setround(&fpu);
2070 for(j=0;j<samples;j++)
2071 for(i=0;i<channels;i++){
2072 val=vorbis_ftoi(pcm[i][j]*32768.f);
2073 if(val>32767)val=32767;
2074 else if(val<-32768)val=-32768;
2075 val+=off;
2076 *buffer++=(val&0xff);
2077 *buffer++=(val>>8);
2078 }
2079 vorbis_fpu_restore(fpu);
2080
2081 }
2082 }
2083 }
2084
2085 vorbis_synthesis_read(&vf->vd,samples);
2086 hs=vorbis_synthesis_halfrate_p(vf->vi);
2087 vf->pcm_offset+=(samples<<hs);
2088 if(bitstream)*bitstream=vf->current_link;
2089 return(samples*bytespersample);
2090 }else{
2091 return(samples);
2092 }
2093 }
2094
ov_read(OggVorbis_File * vf,char * buffer,int length,int bigendianp,int word,int sgned,int * bitstream)2095 long ov_read(OggVorbis_File *vf,char *buffer,int length,
2096 int bigendianp,int word,int sgned,int *bitstream){
2097 return ov_read_filter(vf, buffer, length, bigendianp, word, sgned, bitstream, NULL, NULL);
2098 }
2099
2100 /* input values: pcm_channels) a float vector per channel of output
2101 length) the sample length being read by the app
2102
2103 return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
2104 0) EOF
2105 n) number of samples of PCM actually returned. The
2106 below works on a packet-by-packet basis, so the
2107 return length is not related to the 'length' passed
2108 in, just guaranteed to fit.
2109
2110 *section) set to the logical bitstream number */
2111
2112
2113
ov_read_float(OggVorbis_File * vf,float *** pcm_channels,int length,int * bitstream)2114 long ov_read_float(OggVorbis_File *vf,float ***pcm_channels,int length,
2115 int *bitstream){
2116
2117 if(vf->ready_state<OPENED)return(OV_EINVAL);
2118
2119 while(1){
2120 if(vf->ready_state==INITSET){
2121 float **pcm;
2122 long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
2123 if(samples){
2124 int hs=vorbis_synthesis_halfrate_p(vf->vi);
2125 if(pcm_channels)*pcm_channels=pcm;
2126 if(samples>length)samples=length;
2127 vorbis_synthesis_read(&vf->vd,samples);
2128 vf->pcm_offset+=samples<<hs;
2129 if(bitstream)*bitstream=vf->current_link;
2130 return samples;
2131
2132 }
2133 }
2134
2135 /* suck in another packet */
2136 {
2137 int ret=_fetch_and_process_packet(vf,NULL,1,1);
2138 if(ret==OV_EOF)return(0);
2139 if(ret<=0)return(ret);
2140 }
2141
2142 }
2143 }
2144
2145 extern const float *vorbis_window(vorbis_dsp_state *v,int W);
2146
_ov_splice(float ** pcm,float ** lappcm,int n1,int n2,int ch1,int ch2,const float * w1,const float * w2)2147 static void _ov_splice(float **pcm,float **lappcm,
2148 int n1, int n2,
2149 int ch1, int ch2,
2150 const float *w1, const float *w2){
2151 int i,j;
2152 const float *w=w1;
2153 int n=n1;
2154
2155 if(n1>n2){
2156 n=n2;
2157 w=w2;
2158 }
2159
2160 /* splice */
2161 for(j=0;j<ch1 && j<ch2;j++){
2162 float *s=lappcm[j];
2163 float *d=pcm[j];
2164
2165 for(i=0;i<n;i++){
2166 float wd=w[i]*w[i];
2167 float ws=1.-wd;
2168 d[i]=d[i]*wd + s[i]*ws;
2169 }
2170 }
2171 /* window from zero */
2172 for(;j<ch2;j++){
2173 float *d=pcm[j];
2174 for(i=0;i<n;i++){
2175 float wd=w[i]*w[i];
2176 d[i]=d[i]*wd;
2177 }
2178 }
2179
2180 }
2181
2182 /* make sure vf is INITSET */
_ov_initset(OggVorbis_File * vf)2183 static int _ov_initset(OggVorbis_File *vf){
2184 while(1){
2185 if(vf->ready_state==INITSET)break;
2186 /* suck in another packet */
2187 {
2188 int ret=_fetch_and_process_packet(vf,NULL,1,0);
2189 if(ret<0 && ret!=OV_HOLE)return(ret);
2190 }
2191 }
2192 return 0;
2193 }
2194
2195 /* make sure vf is INITSET and that we have a primed buffer; if
2196 we're crosslapping at a stream section boundary, this also makes
2197 sure we're sanity checking against the right stream information */
_ov_initprime(OggVorbis_File * vf)2198 static int _ov_initprime(OggVorbis_File *vf){
2199 vorbis_dsp_state *vd=&vf->vd;
2200 while(1){
2201 if(vf->ready_state==INITSET)
2202 if(vorbis_synthesis_pcmout(vd,NULL))break;
2203
2204 /* suck in another packet */
2205 {
2206 int ret=_fetch_and_process_packet(vf,NULL,1,0);
2207 if(ret<0 && ret!=OV_HOLE)return(ret);
2208 }
2209 }
2210 return 0;
2211 }
2212
2213 /* grab enough data for lapping from vf; this may be in the form of
2214 unreturned, already-decoded pcm, remaining PCM we will need to
2215 decode, or synthetic postextrapolation from last packets. */
_ov_getlap(OggVorbis_File * vf,vorbis_info * vi,vorbis_dsp_state * vd,float ** lappcm,int lapsize)2216 static void _ov_getlap(OggVorbis_File *vf,vorbis_info *vi,vorbis_dsp_state *vd,
2217 float **lappcm,int lapsize){
2218 int lapcount=0,i;
2219 float **pcm;
2220
2221 /* try first to decode the lapping data */
2222 while(lapcount<lapsize){
2223 int samples=vorbis_synthesis_pcmout(vd,&pcm);
2224 if(samples){
2225 if(samples>lapsize-lapcount)samples=lapsize-lapcount;
2226 for(i=0;i<vi->channels;i++)
2227 memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
2228 lapcount+=samples;
2229 vorbis_synthesis_read(vd,samples);
2230 }else{
2231 /* suck in another packet */
2232 int ret=_fetch_and_process_packet(vf,NULL,1,0); /* do *not* span */
2233 if(ret==OV_EOF)break;
2234 }
2235 }
2236 if(lapcount<lapsize){
2237 /* failed to get lapping data from normal decode; pry it from the
2238 postextrapolation buffering, or the second half of the MDCT
2239 from the last packet */
2240 int samples=vorbis_synthesis_lapout(&vf->vd,&pcm);
2241 if(samples==0){
2242 for(i=0;i<vi->channels;i++)
2243 memset(lappcm[i]+lapcount,0,sizeof(**pcm)*lapsize-lapcount);
2244 lapcount=lapsize;
2245 }else{
2246 if(samples>lapsize-lapcount)samples=lapsize-lapcount;
2247 for(i=0;i<vi->channels;i++)
2248 memcpy(lappcm[i]+lapcount,pcm[i],sizeof(**pcm)*samples);
2249 lapcount+=samples;
2250 }
2251 }
2252 }
2253
2254 /* this sets up crosslapping of a sample by using trailing data from
2255 sample 1 and lapping it into the windowing buffer of sample 2 */
ov_crosslap(OggVorbis_File * vf1,OggVorbis_File * vf2)2256 int ov_crosslap(OggVorbis_File *vf1, OggVorbis_File *vf2){
2257 vorbis_info *vi1,*vi2;
2258 float **lappcm;
2259 float **pcm;
2260 const float *w1,*w2;
2261 int n1,n2,i,ret,hs1,hs2;
2262
2263 if(vf1==vf2)return(0); /* degenerate case */
2264 if(vf1->ready_state<OPENED)return(OV_EINVAL);
2265 if(vf2->ready_state<OPENED)return(OV_EINVAL);
2266
2267 /* the relevant overlap buffers must be pre-checked and pre-primed
2268 before looking at settings in the event that priming would cross
2269 a bitstream boundary. So, do it now */
2270
2271 ret=_ov_initset(vf1);
2272 if(ret)return(ret);
2273 ret=_ov_initprime(vf2);
2274 if(ret)return(ret);
2275
2276 vi1=ov_info(vf1,-1);
2277 vi2=ov_info(vf2,-1);
2278 hs1=ov_halfrate_p(vf1);
2279 hs2=ov_halfrate_p(vf2);
2280
2281 lappcm=alloca(sizeof(*lappcm)*vi1->channels);
2282 n1=vorbis_info_blocksize(vi1,0)>>(1+hs1);
2283 n2=vorbis_info_blocksize(vi2,0)>>(1+hs2);
2284 w1=vorbis_window(&vf1->vd,0);
2285 w2=vorbis_window(&vf2->vd,0);
2286
2287 for(i=0;i<vi1->channels;i++)
2288 lappcm[i]=alloca(sizeof(**lappcm)*n1);
2289
2290 _ov_getlap(vf1,vi1,&vf1->vd,lappcm,n1);
2291
2292 /* have a lapping buffer from vf1; now to splice it into the lapping
2293 buffer of vf2 */
2294 /* consolidate and expose the buffer. */
2295 vorbis_synthesis_lapout(&vf2->vd,&pcm);
2296
2297 #if 0
2298 _analysis_output_always("pcmL",0,pcm[0],n1*2,0,0,0);
2299 _analysis_output_always("pcmR",0,pcm[1],n1*2,0,0,0);
2300 #endif
2301
2302 /* splice */
2303 _ov_splice(pcm,lappcm,n1,n2,vi1->channels,vi2->channels,w1,w2);
2304
2305 /* done */
2306 return(0);
2307 }
2308
_ov_64_seek_lap(OggVorbis_File * vf,ogg_int64_t pos,int (* localseek)(OggVorbis_File *,ogg_int64_t))2309 static int _ov_64_seek_lap(OggVorbis_File *vf,ogg_int64_t pos,
2310 int (*localseek)(OggVorbis_File *,ogg_int64_t)){
2311 vorbis_info *vi;
2312 float **lappcm;
2313 float **pcm;
2314 const float *w1,*w2;
2315 int n1,n2,ch1,ch2,hs;
2316 int i,ret;
2317
2318 if(vf->ready_state<OPENED)return(OV_EINVAL);
2319 ret=_ov_initset(vf);
2320 if(ret)return(ret);
2321 vi=ov_info(vf,-1);
2322 hs=ov_halfrate_p(vf);
2323
2324 ch1=vi->channels;
2325 n1=vorbis_info_blocksize(vi,0)>>(1+hs);
2326 w1=vorbis_window(&vf->vd,0); /* window arrays from libvorbis are
2327 persistent; even if the decode state
2328 from this link gets dumped, this
2329 window array continues to exist */
2330
2331 lappcm=alloca(sizeof(*lappcm)*ch1);
2332 for(i=0;i<ch1;i++)
2333 lappcm[i]=alloca(sizeof(**lappcm)*n1);
2334 _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
2335
2336 /* have lapping data; seek and prime the buffer */
2337 ret=localseek(vf,pos);
2338 if(ret)return ret;
2339 ret=_ov_initprime(vf);
2340 if(ret)return(ret);
2341
2342 /* Guard against cross-link changes; they're perfectly legal */
2343 vi=ov_info(vf,-1);
2344 ch2=vi->channels;
2345 n2=vorbis_info_blocksize(vi,0)>>(1+hs);
2346 w2=vorbis_window(&vf->vd,0);
2347
2348 /* consolidate and expose the buffer. */
2349 vorbis_synthesis_lapout(&vf->vd,&pcm);
2350
2351 /* splice */
2352 _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
2353
2354 /* done */
2355 return(0);
2356 }
2357
ov_raw_seek_lap(OggVorbis_File * vf,ogg_int64_t pos)2358 int ov_raw_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
2359 return _ov_64_seek_lap(vf,pos,ov_raw_seek);
2360 }
2361
ov_pcm_seek_lap(OggVorbis_File * vf,ogg_int64_t pos)2362 int ov_pcm_seek_lap(OggVorbis_File *vf,ogg_int64_t pos){
2363 return _ov_64_seek_lap(vf,pos,ov_pcm_seek);
2364 }
2365
ov_pcm_seek_page_lap(OggVorbis_File * vf,ogg_int64_t pos)2366 int ov_pcm_seek_page_lap(OggVorbis_File *vf,ogg_int64_t pos){
2367 return _ov_64_seek_lap(vf,pos,ov_pcm_seek_page);
2368 }
2369
_ov_d_seek_lap(OggVorbis_File * vf,double pos,int (* localseek)(OggVorbis_File *,double))2370 static int _ov_d_seek_lap(OggVorbis_File *vf,double pos,
2371 int (*localseek)(OggVorbis_File *,double)){
2372 vorbis_info *vi;
2373 float **lappcm;
2374 float **pcm;
2375 const float *w1,*w2;
2376 int n1,n2,ch1,ch2,hs;
2377 int i,ret;
2378
2379 if(vf->ready_state<OPENED)return(OV_EINVAL);
2380 ret=_ov_initset(vf);
2381 if(ret)return(ret);
2382 vi=ov_info(vf,-1);
2383 hs=ov_halfrate_p(vf);
2384
2385 ch1=vi->channels;
2386 n1=vorbis_info_blocksize(vi,0)>>(1+hs);
2387 w1=vorbis_window(&vf->vd,0); /* window arrays from libvorbis are
2388 persistent; even if the decode state
2389 from this link gets dumped, this
2390 window array continues to exist */
2391
2392 lappcm=alloca(sizeof(*lappcm)*ch1);
2393 for(i=0;i<ch1;i++)
2394 lappcm[i]=alloca(sizeof(**lappcm)*n1);
2395 _ov_getlap(vf,vi,&vf->vd,lappcm,n1);
2396
2397 /* have lapping data; seek and prime the buffer */
2398 ret=localseek(vf,pos);
2399 if(ret)return ret;
2400 ret=_ov_initprime(vf);
2401 if(ret)return(ret);
2402
2403 /* Guard against cross-link changes; they're perfectly legal */
2404 vi=ov_info(vf,-1);
2405 ch2=vi->channels;
2406 n2=vorbis_info_blocksize(vi,0)>>(1+hs);
2407 w2=vorbis_window(&vf->vd,0);
2408
2409 /* consolidate and expose the buffer. */
2410 vorbis_synthesis_lapout(&vf->vd,&pcm);
2411
2412 /* splice */
2413 _ov_splice(pcm,lappcm,n1,n2,ch1,ch2,w1,w2);
2414
2415 /* done */
2416 return(0);
2417 }
2418
ov_time_seek_lap(OggVorbis_File * vf,double pos)2419 int ov_time_seek_lap(OggVorbis_File *vf,double pos){
2420 return _ov_d_seek_lap(vf,pos,ov_time_seek);
2421 }
2422
ov_time_seek_page_lap(OggVorbis_File * vf,double pos)2423 int ov_time_seek_page_lap(OggVorbis_File *vf,double pos){
2424 return _ov_d_seek_lap(vf,pos,ov_time_seek_page);
2425 }
2426