misc/libtremor/vorbisfile.c
changeset 6415 af2047bb4f70
parent 6414 8474b7fa84d6
parent 6350 41b0a9955c47
child 6416 850b8dd3e6df
equal deleted inserted replaced
6414:8474b7fa84d6 6415:af2047bb4f70
     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)(vf->datasource);
       
   743     memset(vf,0,sizeof(*vf));
       
   744   }
       
   745 #ifdef DEBUG_LEAKS
       
   746   _VDBG_dump();
       
   747 #endif
       
   748   return(0);
       
   749 }
       
   750 
       
   751 /* inspects the OggVorbis file and finds/documents all the logical
       
   752    bitstreams contained in it.  Tries to be tolerant of logical
       
   753    bitstream sections that are truncated/woogie. 
       
   754 
       
   755    return: -1) error
       
   756             0) OK
       
   757 */
       
   758 
       
   759 int ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
       
   760     ov_callbacks callbacks){
       
   761   int ret=_ov_open1(f,vf,initial,ibytes,callbacks);
       
   762   if(ret)return ret;
       
   763   return _ov_open2(vf);
       
   764 }
       
   765 
       
   766 int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
       
   767   ov_callbacks callbacks = {
       
   768     (size_t (*)(void *, size_t, size_t, void *))  fread,
       
   769     (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
       
   770     (int (*)(void *))                             fclose,
       
   771     (long (*)(void *))                            ftell
       
   772   };
       
   773 
       
   774   return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks);
       
   775 }
       
   776   
       
   777 /* Only partially open the vorbis file; test for Vorbisness, and load
       
   778    the headers for the first chain.  Do not seek (although test for
       
   779    seekability).  Use ov_test_open to finish opening the file, else
       
   780    ov_clear to close/free it. Same return codes as open. */
       
   781 
       
   782 int ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes,
       
   783     ov_callbacks callbacks)
       
   784 {
       
   785   return _ov_open1(f,vf,initial,ibytes,callbacks);
       
   786 }
       
   787 
       
   788 int ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
       
   789   ov_callbacks callbacks = {
       
   790     (size_t (*)(void *, size_t, size_t, void *))  fread,
       
   791     (int (*)(void *, ogg_int64_t, int))              _fseek64_wrap,
       
   792     (int (*)(void *))                             fclose,
       
   793     (long (*)(void *))                            ftell
       
   794   };
       
   795 
       
   796   return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks);
       
   797 }
       
   798   
       
   799 int ov_test_open(OggVorbis_File *vf){
       
   800   if(vf->ready_state!=PARTOPEN)return(OV_EINVAL);
       
   801   return _ov_open2(vf);
       
   802 }
       
   803 
       
   804 /* How many logical bitstreams in this physical bitstream? */
       
   805 long ov_streams(OggVorbis_File *vf){
       
   806   return vf->links;
       
   807 }
       
   808 
       
   809 /* Is the FILE * associated with vf seekable? */
       
   810 long ov_seekable(OggVorbis_File *vf){
       
   811   return vf->seekable;
       
   812 }
       
   813 
       
   814 /* returns the bitrate for a given logical bitstream or the entire
       
   815    physical bitstream.  If the file is open for random access, it will
       
   816    find the *actual* average bitrate.  If the file is streaming, it
       
   817    returns the nominal bitrate (if set) else the average of the
       
   818    upper/lower bounds (if set) else -1 (unset).
       
   819 
       
   820    If you want the actual bitrate field settings, get them from the
       
   821    vorbis_info structs */
       
   822 
       
   823 long ov_bitrate(OggVorbis_File *vf,int i){
       
   824   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
   825   if(i>=vf->links)return(OV_EINVAL);
       
   826   if(!vf->seekable && i!=0)return(ov_bitrate(vf,0));
       
   827   if(i<0){
       
   828     ogg_int64_t bits=0;
       
   829     int i;
       
   830     for(i=0;i<vf->links;i++)
       
   831       bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8;
       
   832     /* This once read: return(rint(bits/ov_time_total(vf,-1)));
       
   833      * gcc 3.x on x86 miscompiled this at optimisation level 2 and above,
       
   834      * so this is slightly transformed to make it work.
       
   835      */
       
   836     return(bits*1000/ov_time_total(vf,-1));
       
   837   }else{
       
   838     if(vf->seekable){
       
   839       /* return the actual bitrate */
       
   840       return((vf->offsets[i+1]-vf->dataoffsets[i])*8000/ov_time_total(vf,i));
       
   841     }else{
       
   842       /* return nominal if set */
       
   843       if(vf->vi[i].bitrate_nominal>0){
       
   844 	return vf->vi[i].bitrate_nominal;
       
   845       }else{
       
   846 	if(vf->vi[i].bitrate_upper>0){
       
   847 	  if(vf->vi[i].bitrate_lower>0){
       
   848 	    return (vf->vi[i].bitrate_upper+vf->vi[i].bitrate_lower)/2;
       
   849 	  }else{
       
   850 	    return vf->vi[i].bitrate_upper;
       
   851 	  }
       
   852 	}
       
   853 	return(OV_FALSE);
       
   854       }
       
   855     }
       
   856   }
       
   857 }
       
   858 
       
   859 /* returns the actual bitrate since last call.  returns -1 if no
       
   860    additional data to offer since last call (or at beginning of stream),
       
   861    EINVAL if stream is only partially open 
       
   862 */
       
   863 long ov_bitrate_instant(OggVorbis_File *vf){
       
   864   int link=(vf->seekable?vf->current_link:0);
       
   865   long ret;
       
   866   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
   867   if(vf->samptrack==0)return(OV_FALSE);
       
   868   ret=vf->bittrack/vf->samptrack*vf->vi[link].rate;
       
   869   vf->bittrack=0;
       
   870   vf->samptrack=0;
       
   871   return(ret);
       
   872 }
       
   873 
       
   874 /* Guess */
       
   875 long ov_serialnumber(OggVorbis_File *vf,int i){
       
   876   if(i>=vf->links)return(ov_serialnumber(vf,vf->links-1));
       
   877   if(!vf->seekable && i>=0)return(ov_serialnumber(vf,-1));
       
   878   if(i<0){
       
   879     return(vf->current_serialno);
       
   880   }else{
       
   881     return(vf->serialnos[i]);
       
   882   }
       
   883 }
       
   884 
       
   885 /* returns: total raw (compressed) length of content if i==-1
       
   886             raw (compressed) length of that logical bitstream for i==0 to n
       
   887 	    OV_EINVAL if the stream is not seekable (we can't know the length)
       
   888 	    or if stream is only partially open
       
   889 */
       
   890 ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){
       
   891   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
   892   if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
       
   893   if(i<0){
       
   894     ogg_int64_t acc=0;
       
   895     int i;
       
   896     for(i=0;i<vf->links;i++)
       
   897       acc+=ov_raw_total(vf,i);
       
   898     return(acc);
       
   899   }else{
       
   900     return(vf->offsets[i+1]-vf->offsets[i]);
       
   901   }
       
   902 }
       
   903 
       
   904 /* returns: total PCM length (samples) of content if i==-1 PCM length
       
   905 	    (samples) of that logical bitstream for i==0 to n
       
   906 	    OV_EINVAL if the stream is not seekable (we can't know the
       
   907 	    length) or only partially open 
       
   908 */
       
   909 ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){
       
   910   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
   911   if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
       
   912   if(i<0){
       
   913     ogg_int64_t acc=0;
       
   914     int i;
       
   915     for(i=0;i<vf->links;i++)
       
   916       acc+=ov_pcm_total(vf,i);
       
   917     return(acc);
       
   918   }else{
       
   919     return(vf->pcmlengths[i*2+1]);
       
   920   }
       
   921 }
       
   922 
       
   923 /* returns: total milliseconds of content if i==-1
       
   924             milliseconds in that logical bitstream for i==0 to n
       
   925 	    OV_EINVAL if the stream is not seekable (we can't know the
       
   926 	    length) or only partially open 
       
   927 */
       
   928 ogg_int64_t ov_time_total(OggVorbis_File *vf,int i){
       
   929   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
   930   if(!vf->seekable || i>=vf->links)return(OV_EINVAL);
       
   931   if(i<0){
       
   932     ogg_int64_t acc=0;
       
   933     int i;
       
   934     for(i=0;i<vf->links;i++)
       
   935       acc+=ov_time_total(vf,i);
       
   936     return(acc);
       
   937   }else{
       
   938     return(((ogg_int64_t)vf->pcmlengths[i*2+1])*1000/vf->vi[i].rate);
       
   939   }
       
   940 }
       
   941 
       
   942 /* seek to an offset relative to the *compressed* data. This also
       
   943    scans packets to update the PCM cursor. It will cross a logical
       
   944    bitstream boundary, but only if it can't get any packets out of the
       
   945    tail of the bitstream we seek to (so no surprises).
       
   946 
       
   947    returns zero on success, nonzero on failure */
       
   948 
       
   949 int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){
       
   950   ogg_stream_state *work_os=NULL;
       
   951   ogg_page og={0,0,0,0};
       
   952   ogg_packet op={0,0,0,0,0,0};
       
   953   
       
   954   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
   955   if(!vf->seekable)
       
   956     return(OV_ENOSEEK); /* don't dump machine if we can't seek */
       
   957 
       
   958   if(pos<0 || pos>vf->end)return(OV_EINVAL);
       
   959 
       
   960   /* don't yet clear out decoding machine (if it's initialized), in
       
   961      the case we're in the same link.  Restart the decode lapping, and
       
   962      let _fetch_and_process_packet deal with a potential bitstream
       
   963      boundary */
       
   964   vf->pcm_offset=-1;
       
   965   ogg_stream_reset_serialno(vf->os,
       
   966 			    vf->current_serialno); /* must set serialno */
       
   967   vorbis_synthesis_restart(&vf->vd);
       
   968     
       
   969   _seek_helper(vf,pos);
       
   970 
       
   971   /* we need to make sure the pcm_offset is set, but we don't want to
       
   972      advance the raw cursor past good packets just to get to the first
       
   973      with a granulepos.  That's not equivalent behavior to beginning
       
   974      decoding as immediately after the seek position as possible.
       
   975 
       
   976      So, a hack.  We use two stream states; a local scratch state and
       
   977      the shared vf->os stream state.  We use the local state to
       
   978      scan, and the shared state as a buffer for later decode. 
       
   979 
       
   980      Unfortuantely, on the last page we still advance to last packet
       
   981      because the granulepos on the last page is not necessarily on a
       
   982      packet boundary, and we need to make sure the granpos is
       
   983      correct. 
       
   984   */
       
   985 
       
   986   {
       
   987     int lastblock=0;
       
   988     int accblock=0;
       
   989     int thisblock;
       
   990     int eosflag=0;
       
   991 
       
   992     work_os=ogg_stream_create(vf->current_serialno); /* get the memory ready */
       
   993     while(1){
       
   994       if(vf->ready_state>=STREAMSET){
       
   995 	/* snarf/scan a packet if we can */
       
   996 	int result=ogg_stream_packetout(work_os,&op);
       
   997       
       
   998 	if(result>0){
       
   999 
       
  1000 	  if(vf->vi[vf->current_link].codec_setup){
       
  1001 	    thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
       
  1002 	    if(thisblock<0){
       
  1003 	      ogg_stream_packetout(vf->os,NULL);
       
  1004 	      thisblock=0;
       
  1005 	    }else{
       
  1006 	      
       
  1007 	      if(eosflag)
       
  1008 		ogg_stream_packetout(vf->os,NULL);
       
  1009 	      else
       
  1010 		if(lastblock)accblock+=(lastblock+thisblock)>>2;
       
  1011 	    }	    
       
  1012 
       
  1013 	    if(op.granulepos!=-1){
       
  1014 	      int i,link=vf->current_link;
       
  1015 	      ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];
       
  1016 	      if(granulepos<0)granulepos=0;
       
  1017 	      
       
  1018 	      for(i=0;i<link;i++)
       
  1019 		granulepos+=vf->pcmlengths[i*2+1];
       
  1020 	      vf->pcm_offset=granulepos-accblock;
       
  1021 	      break;
       
  1022 	    }
       
  1023 	    lastblock=thisblock;
       
  1024 	    continue;
       
  1025 	  }else
       
  1026 	    ogg_stream_packetout(vf->os,NULL);
       
  1027 	}
       
  1028       }
       
  1029       
       
  1030       if(!lastblock){
       
  1031 	if(_get_next_page(vf,&og,-1)<0){
       
  1032 	  vf->pcm_offset=ov_pcm_total(vf,-1);
       
  1033 	  break;
       
  1034 	}
       
  1035       }else{
       
  1036 	/* huh?  Bogus stream with packets but no granulepos */
       
  1037 	vf->pcm_offset=-1;
       
  1038 	break;
       
  1039       }
       
  1040       
       
  1041       /* has our decoding just traversed a bitstream boundary? */
       
  1042       if(vf->ready_state>=STREAMSET)
       
  1043 	if(vf->current_serialno!=ogg_page_serialno(&og)){
       
  1044 	  _decode_clear(vf); /* clear out stream state */
       
  1045 	  ogg_stream_destroy(work_os);
       
  1046 	}
       
  1047 
       
  1048       if(vf->ready_state<STREAMSET){
       
  1049 	int link;
       
  1050 	
       
  1051 	vf->current_serialno=ogg_page_serialno(&og);
       
  1052 	for(link=0;link<vf->links;link++)
       
  1053 	  if(vf->serialnos[link]==vf->current_serialno)break;
       
  1054 	if(link==vf->links)
       
  1055 	  goto seek_error; /* sign of a bogus stream.  error out,
       
  1056 			      leave machine uninitialized */
       
  1057  
       
  1058 	vf->current_link=link;
       
  1059 	
       
  1060 	ogg_stream_reset_serialno(vf->os,vf->current_serialno);
       
  1061 	ogg_stream_reset_serialno(work_os,vf->current_serialno); 
       
  1062 	vf->ready_state=STREAMSET;
       
  1063 	
       
  1064       }
       
  1065     
       
  1066       {
       
  1067 	ogg_page dup;
       
  1068 	ogg_page_dup(&dup,&og);
       
  1069 	eosflag=ogg_page_eos(&og);
       
  1070 	ogg_stream_pagein(vf->os,&og);
       
  1071 	ogg_stream_pagein(work_os,&dup);
       
  1072       }
       
  1073     }
       
  1074   }
       
  1075 
       
  1076   ogg_packet_release(&op);
       
  1077   ogg_page_release(&og);
       
  1078   ogg_stream_destroy(work_os);
       
  1079   vf->bittrack=0;
       
  1080   vf->samptrack=0;
       
  1081   return(0);
       
  1082 
       
  1083  seek_error:
       
  1084   ogg_packet_release(&op);
       
  1085   ogg_page_release(&og);
       
  1086 
       
  1087   /* dump the machine so we're in a known state */
       
  1088   vf->pcm_offset=-1;
       
  1089   ogg_stream_destroy(work_os);
       
  1090   _decode_clear(vf);
       
  1091   return OV_EBADLINK;
       
  1092 }
       
  1093 
       
  1094 /* Page granularity seek (faster than sample granularity because we
       
  1095    don't do the last bit of decode to find a specific sample).
       
  1096 
       
  1097    Seek to the last [granule marked] page preceeding the specified pos
       
  1098    location, such that decoding past the returned point will quickly
       
  1099    arrive at the requested position. */
       
  1100 int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
       
  1101   int link=-1;
       
  1102   ogg_int64_t result=0;
       
  1103   ogg_int64_t total=ov_pcm_total(vf,-1);
       
  1104   ogg_page og={0,0,0,0};
       
  1105   ogg_packet op={0,0,0,0,0,0};
       
  1106 
       
  1107   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
  1108   if(!vf->seekable)return(OV_ENOSEEK);
       
  1109   if(pos<0 || pos>total)return(OV_EINVAL);
       
  1110  
       
  1111   /* which bitstream section does this pcm offset occur in? */
       
  1112   for(link=vf->links-1;link>=0;link--){
       
  1113     total-=vf->pcmlengths[link*2+1];
       
  1114     if(pos>=total)break;
       
  1115   }
       
  1116 
       
  1117   /* search within the logical bitstream for the page with the highest
       
  1118      pcm_pos preceeding (or equal to) pos.  There is a danger here;
       
  1119      missing pages or incorrect frame number information in the
       
  1120      bitstream could make our task impossible.  Account for that (it
       
  1121      would be an error condition) */
       
  1122 
       
  1123   /* new search algorithm by HB (Nicholas Vinen) */
       
  1124   {
       
  1125     ogg_int64_t end=vf->offsets[link+1];
       
  1126     ogg_int64_t begin=vf->offsets[link];
       
  1127     ogg_int64_t begintime = vf->pcmlengths[link*2];
       
  1128     ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;
       
  1129     ogg_int64_t target=pos-total+begintime;
       
  1130     ogg_int64_t best=begin;
       
  1131     
       
  1132     while(begin<end){
       
  1133       ogg_int64_t bisect;
       
  1134       
       
  1135       if(end-begin<CHUNKSIZE){
       
  1136 	bisect=begin;
       
  1137       }else{
       
  1138 	/* take a (pretty decent) guess. */
       
  1139 	bisect=begin + 
       
  1140 	  (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
       
  1141 	if(bisect<=begin)
       
  1142 	  bisect=begin+1;
       
  1143       }
       
  1144       
       
  1145       _seek_helper(vf,bisect);
       
  1146     
       
  1147       while(begin<end){
       
  1148 	result=_get_next_page(vf,&og,end-vf->offset);
       
  1149 	if(result==OV_EREAD) goto seek_error;
       
  1150 	if(result<0){
       
  1151 	  if(bisect<=begin+1)
       
  1152 	    end=begin; /* found it */
       
  1153 	  else{
       
  1154 	    if(bisect==0) goto seek_error;
       
  1155 	    bisect-=CHUNKSIZE;
       
  1156 	    if(bisect<=begin)bisect=begin+1;
       
  1157 	    _seek_helper(vf,bisect);
       
  1158 	  }
       
  1159 	}else{
       
  1160 	  ogg_int64_t granulepos=ogg_page_granulepos(&og);
       
  1161 	  if(granulepos==-1)continue;
       
  1162 	  if(granulepos<target){
       
  1163 	    best=result;  /* raw offset of packet with granulepos */ 
       
  1164 	    begin=vf->offset; /* raw offset of next page */
       
  1165 	    begintime=granulepos;
       
  1166 	    
       
  1167 	    if(target-begintime>44100)break;
       
  1168 	    bisect=begin; /* *not* begin + 1 */
       
  1169 	  }else{
       
  1170 	    if(bisect<=begin+1)
       
  1171 	      end=begin;  /* found it */
       
  1172 	    else{
       
  1173 	      if(end==vf->offset){ /* we're pretty close - we'd be stuck in */
       
  1174 		end=result;
       
  1175 		bisect-=CHUNKSIZE; /* an endless loop otherwise. */
       
  1176 		if(bisect<=begin)bisect=begin+1;
       
  1177 		_seek_helper(vf,bisect);
       
  1178 	      }else{
       
  1179 		end=result;
       
  1180 		endtime=granulepos;
       
  1181 		break;
       
  1182 	      }
       
  1183 	    }
       
  1184 	  }
       
  1185 	}
       
  1186       }
       
  1187     }
       
  1188 
       
  1189     /* found our page. seek to it, update pcm offset. Easier case than
       
  1190        raw_seek, don't keep packets preceeding granulepos. */
       
  1191     {
       
  1192       
       
  1193       /* seek */
       
  1194       _seek_helper(vf,best);
       
  1195       vf->pcm_offset=-1;
       
  1196       
       
  1197       if(_get_next_page(vf,&og,-1)<0){
       
  1198 	ogg_page_release(&og);
       
  1199 	return(OV_EOF); /* shouldn't happen */
       
  1200       }
       
  1201 
       
  1202       if(link!=vf->current_link){
       
  1203 	/* Different link; dump entire decode machine */
       
  1204 	_decode_clear(vf);  
       
  1205 	
       
  1206 	vf->current_link=link;
       
  1207 	vf->current_serialno=ogg_page_serialno(&og);
       
  1208 	vf->ready_state=STREAMSET;
       
  1209 	
       
  1210       }else{
       
  1211 	vorbis_synthesis_restart(&vf->vd);
       
  1212       }
       
  1213 
       
  1214       ogg_stream_reset_serialno(vf->os,vf->current_serialno);
       
  1215       ogg_stream_pagein(vf->os,&og);
       
  1216 
       
  1217       /* pull out all but last packet; the one with granulepos */
       
  1218       while(1){
       
  1219 	result=ogg_stream_packetpeek(vf->os,&op);
       
  1220 	if(result==0){
       
  1221 	  /* !!! the packet finishing this page originated on a
       
  1222              preceeding page. Keep fetching previous pages until we
       
  1223              get one with a granulepos or without the 'continued' flag
       
  1224              set.  Then just use raw_seek for simplicity. */
       
  1225 	  
       
  1226 	  _seek_helper(vf,best);
       
  1227 	  
       
  1228 	  while(1){
       
  1229 	    result=_get_prev_page(vf,&og);
       
  1230 	    if(result<0) goto seek_error;
       
  1231 	    if(ogg_page_granulepos(&og)>-1 ||
       
  1232 	       !ogg_page_continued(&og)){
       
  1233 	      return ov_raw_seek(vf,result);
       
  1234 	    }
       
  1235 	    vf->offset=result;
       
  1236 	  }
       
  1237 	}
       
  1238 	if(result<0){
       
  1239 	  result = OV_EBADPACKET; 
       
  1240 	  goto seek_error;
       
  1241 	}
       
  1242 	if(op.granulepos!=-1){
       
  1243 	  vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
       
  1244 	  if(vf->pcm_offset<0)vf->pcm_offset=0;
       
  1245 	  vf->pcm_offset+=total;
       
  1246 	  break;
       
  1247 	}else
       
  1248 	  result=ogg_stream_packetout(vf->os,NULL);
       
  1249       }
       
  1250     }
       
  1251   }
       
  1252   
       
  1253   /* verify result */
       
  1254   if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){
       
  1255     result=OV_EFAULT;
       
  1256     goto seek_error;
       
  1257   }
       
  1258   vf->bittrack=0;
       
  1259   vf->samptrack=0;
       
  1260 
       
  1261   ogg_page_release(&og);
       
  1262   ogg_packet_release(&op);
       
  1263   return(0);
       
  1264   
       
  1265  seek_error:
       
  1266 
       
  1267   ogg_page_release(&og);
       
  1268   ogg_packet_release(&op);
       
  1269 
       
  1270   /* dump machine so we're in a known state */
       
  1271   vf->pcm_offset=-1;
       
  1272   _decode_clear(vf);
       
  1273   return (int)result;
       
  1274 }
       
  1275 
       
  1276 /* seek to a sample offset relative to the decompressed pcm stream 
       
  1277    returns zero on success, nonzero on failure */
       
  1278 
       
  1279 int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
       
  1280   ogg_packet op={0,0,0,0,0,0};
       
  1281   ogg_page og={0,0,0,0};
       
  1282   int thisblock,lastblock=0;
       
  1283   int ret=ov_pcm_seek_page(vf,pos);
       
  1284   if(ret<0)return(ret);
       
  1285   _make_decode_ready(vf);
       
  1286 
       
  1287   /* discard leading packets we don't need for the lapping of the
       
  1288      position we want; don't decode them */
       
  1289 
       
  1290   while(1){
       
  1291 
       
  1292     int ret=ogg_stream_packetpeek(vf->os,&op);
       
  1293     if(ret>0){
       
  1294       thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
       
  1295       if(thisblock<0){
       
  1296 	ogg_stream_packetout(vf->os,NULL);
       
  1297 	continue; /* non audio packet */
       
  1298       }
       
  1299       if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
       
  1300       
       
  1301       if(vf->pcm_offset+((thisblock+
       
  1302 			  vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
       
  1303       
       
  1304       /* remove the packet from packet queue and track its granulepos */
       
  1305       ogg_stream_packetout(vf->os,NULL);
       
  1306       vorbis_synthesis(&vf->vb,&op,0);  /* set up a vb with
       
  1307 					   only tracking, no
       
  1308 					   pcm_decode */
       
  1309       vorbis_synthesis_blockin(&vf->vd,&vf->vb); 
       
  1310       
       
  1311       /* end of logical stream case is hard, especially with exact
       
  1312 	 length positioning. */
       
  1313       
       
  1314       if(op.granulepos>-1){
       
  1315 	int i;
       
  1316 	/* always believe the stream markers */
       
  1317 	vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];
       
  1318 	if(vf->pcm_offset<0)vf->pcm_offset=0;
       
  1319 	for(i=0;i<vf->current_link;i++)
       
  1320 	  vf->pcm_offset+=vf->pcmlengths[i*2+1];
       
  1321       }
       
  1322 	
       
  1323       lastblock=thisblock;
       
  1324       
       
  1325     }else{
       
  1326       if(ret<0 && ret!=OV_HOLE)break;
       
  1327       
       
  1328       /* suck in a new page */
       
  1329       if(_get_next_page(vf,&og,-1)<0)break;
       
  1330       if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf);
       
  1331       
       
  1332       if(vf->ready_state<STREAMSET){
       
  1333 	int link;
       
  1334 	
       
  1335 	vf->current_serialno=ogg_page_serialno(&og);
       
  1336 	for(link=0;link<vf->links;link++)
       
  1337 	  if(vf->serialnos[link]==vf->current_serialno)break;
       
  1338 	if(link==vf->links){
       
  1339 	  ogg_page_release(&og);
       
  1340 	  ogg_packet_release(&op);
       
  1341 	  return(OV_EBADLINK);
       
  1342 	}
       
  1343 	vf->current_link=link;
       
  1344 	
       
  1345 	ogg_stream_reset_serialno(vf->os,vf->current_serialno); 
       
  1346 	vf->ready_state=STREAMSET;      
       
  1347 	_make_decode_ready(vf);
       
  1348 	lastblock=0;
       
  1349       }
       
  1350 
       
  1351       ogg_stream_pagein(vf->os,&og);
       
  1352     }
       
  1353   }
       
  1354 
       
  1355   vf->bittrack=0;
       
  1356   vf->samptrack=0;
       
  1357   /* discard samples until we reach the desired position. Crossing a
       
  1358      logical bitstream boundary with abandon is OK. */
       
  1359   while(vf->pcm_offset<pos){
       
  1360     ogg_int64_t target=pos-vf->pcm_offset;
       
  1361     long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
       
  1362 
       
  1363     if(samples>target)samples=target;
       
  1364     vorbis_synthesis_read(&vf->vd,samples);
       
  1365     vf->pcm_offset+=samples;
       
  1366     
       
  1367     if(samples<target)
       
  1368       if(_fetch_and_process_packet(vf,1,1)<=0)
       
  1369 	vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
       
  1370   }
       
  1371 
       
  1372   ogg_page_release(&og);
       
  1373   ogg_packet_release(&op);
       
  1374   return 0;
       
  1375 }
       
  1376 
       
  1377 /* seek to a playback time relative to the decompressed pcm stream 
       
  1378    returns zero on success, nonzero on failure */
       
  1379 int ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){
       
  1380   /* translate time to PCM position and call ov_pcm_seek */
       
  1381 
       
  1382   int link=-1;
       
  1383   ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
       
  1384   ogg_int64_t time_total=ov_time_total(vf,-1);
       
  1385 
       
  1386   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
  1387   if(!vf->seekable)return(OV_ENOSEEK);
       
  1388   if(milliseconds<0 || milliseconds>time_total)return(OV_EINVAL);
       
  1389   
       
  1390   /* which bitstream section does this time offset occur in? */
       
  1391   for(link=vf->links-1;link>=0;link--){
       
  1392     pcm_total-=vf->pcmlengths[link*2+1];
       
  1393     time_total-=ov_time_total(vf,link);
       
  1394     if(milliseconds>=time_total)break;
       
  1395   }
       
  1396 
       
  1397   /* enough information to convert time offset to pcm offset */
       
  1398   {
       
  1399     ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000;
       
  1400     return(ov_pcm_seek(vf,target));
       
  1401   }
       
  1402 }
       
  1403 
       
  1404 /* page-granularity version of ov_time_seek 
       
  1405    returns zero on success, nonzero on failure */
       
  1406 int ov_time_seek_page(OggVorbis_File *vf,ogg_int64_t milliseconds){
       
  1407   /* translate time to PCM position and call ov_pcm_seek */
       
  1408 
       
  1409   int link=-1;
       
  1410   ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
       
  1411   ogg_int64_t time_total=ov_time_total(vf,-1);
       
  1412 
       
  1413   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
  1414   if(!vf->seekable)return(OV_ENOSEEK);
       
  1415   if(milliseconds<0 || milliseconds>time_total)return(OV_EINVAL);
       
  1416   
       
  1417   /* which bitstream section does this time offset occur in? */
       
  1418   for(link=vf->links-1;link>=0;link--){
       
  1419     pcm_total-=vf->pcmlengths[link*2+1];
       
  1420     time_total-=ov_time_total(vf,link);
       
  1421     if(milliseconds>=time_total)break;
       
  1422   }
       
  1423 
       
  1424   /* enough information to convert time offset to pcm offset */
       
  1425   {
       
  1426     ogg_int64_t target=pcm_total+(milliseconds-time_total)*vf->vi[link].rate/1000;
       
  1427     return(ov_pcm_seek_page(vf,target));
       
  1428   }
       
  1429 }
       
  1430 
       
  1431 /* tell the current stream offset cursor.  Note that seek followed by
       
  1432    tell will likely not give the set offset due to caching */
       
  1433 ogg_int64_t ov_raw_tell(OggVorbis_File *vf){
       
  1434   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
  1435   return(vf->offset);
       
  1436 }
       
  1437 
       
  1438 /* return PCM offset (sample) of next PCM sample to be read */
       
  1439 ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){
       
  1440   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
  1441   return(vf->pcm_offset);
       
  1442 }
       
  1443 
       
  1444 /* return time offset (milliseconds) of next PCM sample to be read */
       
  1445 ogg_int64_t ov_time_tell(OggVorbis_File *vf){
       
  1446   int link=0;
       
  1447   ogg_int64_t pcm_total=0;
       
  1448   ogg_int64_t time_total=0;
       
  1449   
       
  1450   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
  1451   if(vf->seekable){
       
  1452     pcm_total=ov_pcm_total(vf,-1);
       
  1453     time_total=ov_time_total(vf,-1);
       
  1454   
       
  1455     /* which bitstream section does this time offset occur in? */
       
  1456     for(link=vf->links-1;link>=0;link--){
       
  1457       pcm_total-=vf->pcmlengths[link*2+1];
       
  1458       time_total-=ov_time_total(vf,link);
       
  1459       if(vf->pcm_offset>=pcm_total)break;
       
  1460     }
       
  1461   }
       
  1462 
       
  1463   return(time_total+(1000*vf->pcm_offset-pcm_total)/vf->vi[link].rate);
       
  1464 }
       
  1465 
       
  1466 /*  link:   -1) return the vorbis_info struct for the bitstream section
       
  1467                 currently being decoded
       
  1468            0-n) to request information for a specific bitstream section
       
  1469     
       
  1470     In the case of a non-seekable bitstream, any call returns the
       
  1471     current bitstream.  NULL in the case that the machine is not
       
  1472     initialized */
       
  1473 
       
  1474 vorbis_info *ov_info(OggVorbis_File *vf,int link){
       
  1475   if(vf->seekable){
       
  1476     if(link<0)
       
  1477       if(vf->ready_state>=STREAMSET)
       
  1478 	return vf->vi+vf->current_link;
       
  1479       else
       
  1480       return vf->vi;
       
  1481     else
       
  1482       if(link>=vf->links)
       
  1483 	return NULL;
       
  1484       else
       
  1485 	return vf->vi+link;
       
  1486   }else{
       
  1487     return vf->vi;
       
  1488   }
       
  1489 }
       
  1490 
       
  1491 /* grr, strong typing, grr, no templates/inheritence, grr */
       
  1492 vorbis_comment *ov_comment(OggVorbis_File *vf,int link){
       
  1493   if(vf->seekable){
       
  1494     if(link<0)
       
  1495       if(vf->ready_state>=STREAMSET)
       
  1496 	return vf->vc+vf->current_link;
       
  1497       else
       
  1498 	return vf->vc;
       
  1499     else
       
  1500       if(link>=vf->links)
       
  1501 	return NULL;
       
  1502       else
       
  1503 	return vf->vc+link;
       
  1504   }else{
       
  1505     return vf->vc;
       
  1506   }
       
  1507 }
       
  1508 
       
  1509 /* up to this point, everything could more or less hide the multiple
       
  1510    logical bitstream nature of chaining from the toplevel application
       
  1511    if the toplevel application didn't particularly care.  However, at
       
  1512    the point that we actually read audio back, the multiple-section
       
  1513    nature must surface: Multiple bitstream sections do not necessarily
       
  1514    have to have the same number of channels or sampling rate.
       
  1515 
       
  1516    ov_read returns the sequential logical bitstream number currently
       
  1517    being decoded along with the PCM data in order that the toplevel
       
  1518    application can take action on channel/sample rate changes.  This
       
  1519    number will be incremented even for streamed (non-seekable) streams
       
  1520    (for seekable streams, it represents the actual logical bitstream
       
  1521    index within the physical bitstream.  Note that the accessor
       
  1522    functions above are aware of this dichotomy).
       
  1523 
       
  1524    input values: buffer) a buffer to hold packed PCM data for return
       
  1525 		 length) the byte length requested to be placed into buffer
       
  1526 
       
  1527    return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL)
       
  1528                    0) EOF
       
  1529 		   n) number of bytes of PCM actually returned.  The
       
  1530 		   below works on a packet-by-packet basis, so the
       
  1531 		   return length is not related to the 'length' passed
       
  1532 		   in, just guaranteed to fit.
       
  1533 
       
  1534 	    *section) set to the logical bitstream number */
       
  1535 
       
  1536 long ov_read(OggVorbis_File *vf,char *buffer,int bytes_req,int *bitstream){
       
  1537   int i,j;
       
  1538 
       
  1539   ogg_int32_t **pcm;
       
  1540   long samples;
       
  1541 
       
  1542   if(vf->ready_state<OPENED)return(OV_EINVAL);
       
  1543 
       
  1544   while(1){
       
  1545     if(vf->ready_state==INITSET){
       
  1546       samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
       
  1547       if(samples)break;
       
  1548     }
       
  1549 
       
  1550     /* suck in another packet */
       
  1551     {
       
  1552       int ret=_fetch_and_process_packet(vf,1,1);
       
  1553       if(ret==OV_EOF)
       
  1554 	return(0);
       
  1555       if(ret<=0)
       
  1556 	return(ret);
       
  1557     }
       
  1558 
       
  1559   }
       
  1560 
       
  1561   if(samples>0){
       
  1562   
       
  1563     /* yay! proceed to pack data into the byte buffer */
       
  1564     
       
  1565     long channels=ov_info(vf,-1)->channels;
       
  1566 
       
  1567     if(samples>(bytes_req/(2*channels)))
       
  1568       samples=bytes_req/(2*channels);      
       
  1569     
       
  1570     for(i=0;i<channels;i++) { /* It's faster in this order */
       
  1571       ogg_int32_t *src=pcm[i];
       
  1572       short *dest=((short *)buffer)+i;
       
  1573       for(j=0;j<samples;j++) {
       
  1574         *dest=CLIP_TO_15(src[j]>>9);
       
  1575         dest+=channels;
       
  1576       }
       
  1577     }
       
  1578     
       
  1579     vorbis_synthesis_read(&vf->vd,samples);
       
  1580     vf->pcm_offset+=samples;
       
  1581     if(bitstream)*bitstream=vf->current_link;
       
  1582     return(samples*2*channels);
       
  1583   }else{
       
  1584     return(samples);
       
  1585   }
       
  1586 }