Oops. Previous commit was of the wrong (not cleaned up) version. Sorry.
authorMike Smith <msmith@xiph.org>
Wed, 14 Feb 2001 13:24:29 +0000 (13:24 +0000)
committerMike Smith <msmith@xiph.org>
Wed, 14 Feb 2001 13:24:29 +0000 (13:24 +0000)
svn path=/trunk/vorbis/; revision=1277

lib/vorbisfile.c

index 766a4b8..72c05d5 100644 (file)
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.c,v 1.38 2001/02/14 13:12:15 msmith Exp $
+ last mod: $Id: vorbisfile.c,v 1.39 2001/02/14 13:24:29 msmith Exp $
 
  ********************************************************************/
 
@@ -847,42 +847,28 @@ int ov_raw_seek(OggVorbis_File *vf,long pos){
   return OV_EBADLINK;
 }
 
-int ov_raw_seek2(OggVorbis_File *vf,long pos, int offset, int link){
-  int flag=0;
-  if(!vf->seekable)return(OV_ENOSEEK); /* don't dump machine if we can't seek */
+int ov_raw_seek_fast(OggVorbis_File *vf, long pos, int offset, int link) {
+  int ret;
+  ogg_page og;
+  if(!vf->seekable)return(OV_ENOSEEK); /* Don't dump machine, this is ok. */
+
   if(pos<0 || pos>vf->offsets[vf->links])return(OV_EINVAL);
 
-  /* clear out decoding machine state */
+  /* Clear decode state */
   vf->pcm_offset=-1;
   _decode_clear(vf);
-//  ogg_stream_clear(&vf->os);
-//  vf->decode_ready=0;
 
-//  vf->bittrack=0.f;
-//  vf->samptrack=0.f;
-  
-  /* seek */
+  /* Do the seek */
   _seek_helper(vf,pos);
-
-  /* we need to make sure the pcm_offset is set.  We use the
-     _fetch_packet helper to process one packet with readp set, then
-     call it until it returns '0' with readp not set (the last packet
-     from a page has the 'granulepos' field set, and that's how the
-     helper updates the offset */
-
-  {
-    int ret;
-    ogg_page og;
-    ret=_get_next_page(vf,&og,vf->offsets[link+1]-vf->offset);
-    if( ret < 0 )
-      return ret;
-    vf->pcm_offset = offset;
-  }
+  ret = _get_next_page(vf,&og,vf->offsets[link+1]-vf->offset);
+  if(ret<0)
+    return ret;
+  vf->pcm_offset = offset;
 
   return 0;
-
 }
 
+
 /* Page granularity seek (faster than sample granularity because we
    don't do the last bit of decode to find a specific sample).
 
@@ -908,85 +894,88 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
      missing pages or incorrect frame number information in the
      bitstream could make our task impossible.  Account for that (it
      would be an error condition) */
+  /* Faster/more intelligent version from Nicholas Vinen */
 
-#if 1
-  // HB (Nicholas Vinen)
-  // I think this should be much faster.
   {
     ogg_int64_t target=pos-total;
     long end=vf->offsets[link+1];
     long begin=vf->offsets[link];
     ogg_int64_t endtime = vf->pcmlengths[link];
-    ogg_int64_t begintime = 0;
+    ogg_int64_t begintime=0;
     long best=begin;
-
     ogg_page og;
-    while(begin<end){
+
+    while(begin<end) {
       long bisect;
 
-      if(end-begin<CHUNKSIZE){
+      if(end-begin < CHUNKSIZE)
        bisect=begin;
-      }else{
-       //take a (pretty decent) guess.
-       bisect=begin + (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;
+      else {
+       /* Make an intelligent guess */
+       bisect=begin+(target-begintime)*(end-begin)/
+         (endtime-begintime) - CHUNKSIZE;
        if(bisect<=begin)
          bisect=begin+1;
       }
-    
-     TryAgain:
+
+      again:
       _seek_helper(vf,bisect);
-      ret=_get_next_page(vf,&og,end-bisect);
-      switch(ret){
-      case OV_FALSE: case OV_EOF:
-       if(bisect==begin+1)
-          goto found_it;
-       if(bisect==0)
+      ret=_get_next_page(vf,&og, end-bisect);
+      if(ret == OV_FALSE || ret==OV_EOF)
+      {
+        if(bisect==begin+1)
+         goto found;
+       if(bisect==0)
          goto seek_error;
-       bisect-=CHUNKSIZE;
+       bisect -= CHUNKSIZE;
        if(bisect<=begin)
          bisect=begin+1;
-       goto TryAgain;
-      case OV_EREAD:
-       goto seek_error;
-      default:
-       {
-         ogg_int64_t granulepos=ogg_page_granulepos(&og);
-         if(granulepos<target){
-           best=ret;  /* raw offset of packet with granulepos */ 
-           begin=vf->offset; /* raw offset of next packet */
-           begintime=granulepos;
-
-           if(target-begintime<2000) { //less than 1s before we hit the right page.
-             bisect=begin+1;
-             goto TryAgain;
-           }
-
-         }else{
-           if(bisect<=begin+1)
-             goto found_it;
-
-           if(end==vf->offset){
-             //we're pretty close - we'd be stuck in an endless loop otherwise...
-             bisect-=CHUNKSIZE;
-             goto TryAgain;    //sorry, I like gotos :)
-           }
-           end=vf->offset;
-           endtime=granulepos;
+       goto again;
+      }
+      else if(ret==OV_EREAD) goto seek_error;
+      else
+      {
+        ogg_int64_t granulepos=ogg_page_granulepos(&og);
+       if(granulepos<target){
+         best=ret; /* Raw offset of current page */
+         begin=vf->offset; /* Raw offset of next packet */
+         begintime=granulepos;
+
+         /* Assume that if we're within half a second of
+          * our target, it'll be faster to scan directly 
+          * forward. */
+         if(target-begintime<vf->vi->rate/2) {
+           bisect=begin+1;
+           goto again;
+         } 
+       }
+       else {
+         if(bisect<=begin+1)
+           goto found;
+         if(end==vf->offset){
+           /* near the end, try just back from here */
+           bisect-=CHUNKSIZE;
+           goto again;
          }
+         end=vf->offset;
+         endtime=granulepos;
        }
       }
     }
 
-    /* found our page. seek to it (call raw_seek). */
-   found_it:
-    if(link!=vf->current_link){
+    /* Found the relevent page. Seek to it */
+found:
+    if(link != vf->current_link){
       if((ret=ov_raw_seek(vf,best)))goto seek_error;
     } else {
-      if((ret=ov_raw_seek2(vf,best,begintime,link)))goto seek_error;
+      if((ret=ov_raw_seek_fast(vf,best,begintime,link)))goto seek_error;
     }
   }
 
-#else
+
+
+
+#if 0
   {
     ogg_int64_t target=pos-total;
     long end=vf->offsets[link+1];
@@ -1029,7 +1018,7 @@ int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){
     if((ret=ov_raw_seek(vf,best)))goto seek_error;
   }
 #endif
-
+  
   /* verify result */
   if(vf->pcm_offset>=pos || pos>ov_pcm_total(vf,-1)){
     ret=OV_EFAULT;
@@ -1057,8 +1046,6 @@ int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){
     float **pcm;
     long target=pos-vf->pcm_offset;
     long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
-    if( samples == 0 )
-       break;
 
     if(samples>target)samples=target;
     vorbis_synthesis_read(&vf->vd,samples);