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