Fix for bug 577; used a different approach than the submitted patch
authorMonty <xiphmont@xiph.org>
Fri, 29 Jun 2007 05:14:41 +0000 (05:14 +0000)
committerMonty <xiphmont@xiph.org>
Fri, 29 Jun 2007 05:14:41 +0000 (05:14 +0000)
(rather than fudging an out of bound result after computation, do it
the right way to begin with)

Add test for fix to seeking_example.

svn path=/trunk/vorbis/; revision=13198

examples/seeking_example.c
lib/vorbisfile.c

index 32fc1e9..ca465dd 100644 (file)
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: illustrate seeking, and test it too
- last mod: $Id: seeking_example.c,v 1.15 2002/07/11 06:40:47 xiphmont Exp $
+ last mod: $Id$
 
  ********************************************************************/
 
 # include <fcntl.h>
 #endif
 
-void _verify(OggVorbis_File *ov,ogg_int64_t pos,
-            ogg_int64_t val,ogg_int64_t pcmval,
+void _verify(OggVorbis_File *ov,
+            ogg_int64_t val,ogg_int64_t pcmval,double timeval,
             ogg_int64_t pcmlength,
             char *bigassbuffer){
   int j;
   long bread;
   char buffer[4096];
   int dummy;
+  ogg_int64_t pos;
 
   /* verify the raw position, the pcm position and position decode */
   if(val!=-1 && ov_raw_tell(ov)<val){
@@ -45,6 +46,11 @@ void _verify(OggVorbis_File *ov,ogg_int64_t pos,
           (long)pcmval,(long)ov_pcm_tell(ov));
     exit(1);
   }
+  if(timeval!=-1 && ov_time_tell(ov)>timeval){
+    printf("time position out of tolerance: requested %f, got %f\n",
+          timeval,ov_time_tell(ov));
+    exit(1);
+  }
   pos=ov_pcm_tell(ov);
   if(pos<0 || pos>pcmlength){
     printf("pcm position out of bounds: got %ld\n",(long)pos);
@@ -73,6 +79,7 @@ int main(){
   OggVorbis_File ov;
   int i,ret;
   ogg_int64_t pcmlength;
+  double timelength;
   char *bigassbuffer;
   int dummy;
 
@@ -106,6 +113,7 @@ int main(){
        does what it claimed, decode the entire file into memory */
     fflush(stdout);
     pcmlength=ov_pcm_total(&ov,-1);
+    timelength=ov_time_total(&ov,-1);
     bigassbuffer=malloc(pcmlength*2); /* w00t */
     i=0;
     while(i<pcmlength*2){
@@ -120,9 +128,6 @@ int main(){
              (long)(pcmlength*2-i));
     }
     
-    /* Exercise all the real seeking cases; ov_raw_seek,
-       ov_pcm_seek_page and ov_pcm_seek.  time seek is just a wrapper
-       on pcm_seek */
     {
       ogg_int64_t length=ov.end;
       printf("\rtesting raw seeking to random places in %ld bytes....\n",
@@ -130,7 +135,6 @@ int main(){
     
       for(i=0;i<1000;i++){
        ogg_int64_t val=(double)rand()/RAND_MAX*length;
-       ogg_int64_t pos;
        printf("\r\t%d [raw position %ld]...     ",i,(long)val);
        fflush(stdout);
        ret=ov_raw_seek(&ov,val);
@@ -139,7 +143,7 @@ int main(){
          exit(1);
        }
 
-       _verify(&ov,pos,val,-1,pcmlength,bigassbuffer);
+       _verify(&ov,val,-1,-1.,pcmlength,bigassbuffer);
 
       }
     }
@@ -151,7 +155,6 @@ int main(){
     
       for(i=0;i<1000;i++){
        ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength;
-       ogg_int64_t pos;
        printf("\r\t%d [pcm position %ld]...     ",i,(long)val);
        fflush(stdout);
        ret=ov_pcm_seek_page(&ov,val);
@@ -160,20 +163,18 @@ int main(){
          exit(1);
        }
 
-       _verify(&ov,pos,-1,val,pcmlength,bigassbuffer);
+       _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);
 
       }
     }
     
     printf("\r");
     {
-      ogg_int64_t length=ov.end;
       printf("testing pcm exact seeking to random places in %ld samples....\n",
             (long)pcmlength);
     
       for(i=0;i<1000;i++){
        ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength;
-       ogg_int64_t pos;
        printf("\r\t%d [pcm position %ld]...     ",i,(long)val);
        fflush(stdout);
        ret=ov_pcm_seek(&ov,val);
@@ -187,7 +188,52 @@ int main(){
          exit(1);
        }
 
-       _verify(&ov,pos,-1,val,pcmlength,bigassbuffer);
+       _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);
+
+      }
+    }
+
+    printf("\r");
+    {
+      printf("testing time page seeking to random places in %f seconds....\n",
+            timelength);
+    
+      for(i=0;i<1000;i++){
+       double val=(double)rand()/RAND_MAX*timelength;
+       printf("\r\t%d [time position %f]...     ",i,val);
+       fflush(stdout);
+       ret=ov_time_seek_page(&ov,val);
+       if(ret<0){
+         printf("seek failed: %d\n",ret);
+         exit(1);
+       }
+
+       _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);
+
+      }
+    }
+
+    printf("\r");
+    {
+      printf("testing time exact seeking to random places in %f seconds....\n",
+            timelength);
+    
+      for(i=0;i<1000;i++){
+       double val=(double)rand()/RAND_MAX*timelength;
+       printf("\r\t%d [time position %f]...     ",i,val);
+       fflush(stdout);
+       ret=ov_time_seek(&ov,val);
+       if(ret<0){
+         printf("seek failed: %d\n",ret);
+         exit(1);
+       }
+       if(ov_time_tell(&ov)<val-1 || ov_time_tell(&ov)>val+1){
+         printf("Declared position didn't perfectly match request: %f != %f\n",
+                val,ov_time_tell(&ov));
+         exit(1);
+       }
+
+       _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);
 
       }
     }
index 3949210..4c192ee 100644 (file)
@@ -1360,20 +1360,23 @@ int ov_time_seek(OggVorbis_File *vf,double seconds){
   /* translate time to PCM position and call ov_pcm_seek */
 
   int link=-1;
-  ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
-  double time_total=ov_time_total(vf,-1);
+  ogg_int64_t pcm_total=0;
+  double time_total=0.;
 
   if(vf->ready_state<OPENED)return(OV_EINVAL);
   if(!vf->seekable)return(OV_ENOSEEK);
-  if(seconds<0 || seconds>time_total)return(OV_EINVAL);
+  if(seconds<0)return(OV_EINVAL);
   
   /* which bitstream section does this time offset occur in? */
-  for(link=vf->links-1;link>=0;link--){
-    pcm_total-=vf->pcmlengths[link*2+1];
-    time_total-=ov_time_total(vf,link);
-    if(seconds>=time_total)break;
+  for(link=0;link<vf->links;link++){
+    double addsec = ov_time_total(vf,link);
+    if(seconds<time_total+addsec)break;
+    time_total+=addsec;
+    pcm_total+=vf->pcmlengths[link*2+1];
   }
 
+  if(link==vf->links)return(OV_EINVAL);
+
   /* enough information to convert time offset to pcm offset */
   {
     ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;
@@ -1387,20 +1390,23 @@ int ov_time_seek_page(OggVorbis_File *vf,double seconds){
   /* translate time to PCM position and call ov_pcm_seek */
 
   int link=-1;
-  ogg_int64_t pcm_total=ov_pcm_total(vf,-1);
-  double time_total=ov_time_total(vf,-1);
+  ogg_int64_t pcm_total=0;
+  double time_total=0.;
 
   if(vf->ready_state<OPENED)return(OV_EINVAL);
   if(!vf->seekable)return(OV_ENOSEEK);
-  if(seconds<0 || seconds>time_total)return(OV_EINVAL);
+  if(seconds<0)return(OV_EINVAL);
   
   /* which bitstream section does this time offset occur in? */
-  for(link=vf->links-1;link>=0;link--){
-    pcm_total-=vf->pcmlengths[link*2+1];
-    time_total-=ov_time_total(vf,link);
-    if(seconds>=time_total)break;
+  for(link=0;link<vf->links;link++){
+    double addsec = ov_time_total(vf,link);
+    if(seconds<time_total+addsec)break;
+    time_total+=addsec;
+    pcm_total+=vf->pcmlengths[link*2+1];
   }
 
+  if(link==vf->links)return(OV_EINVAL);
+
   /* enough information to convert time offset to pcm offset */
   {
     ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;