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