[xiph-commits] r17560 - in trunk/vorbis: examples lib

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Sat Oct 23 03:29:11 PDT 2010


Author: xiphmont
Date: 2010-10-23 03:29:11 -0700 (Sat, 23 Oct 2010)
New Revision: 17560

Modified:
   trunk/vorbis/examples/seeking_example.c
   trunk/vorbis/lib/vorbisfile.c
Log:
While reviewing a patch to port Tremor r17541, noticed that the 
half-rate decode code in Vorbisfile was never completed past the 
original 'quick and dirty' feature request.  Specifically, it made no 
attempt to keep the pcm offset tracking consistent in seeks.

Complete this code, and add a testing mode to seeking_example.c to 
torture test seeking in halfrate mode.  Also remove requirement that 
halfrate mode only work with seekable files.



Modified: trunk/vorbis/examples/seeking_example.c
===================================================================
--- trunk/vorbis/examples/seeking_example.c	2010-10-22 10:28:49 UTC (rev 17559)
+++ trunk/vorbis/examples/seeking_example.c	2010-10-23 10:29:11 UTC (rev 17560)
@@ -29,11 +29,13 @@
              ogg_int64_t val,ogg_int64_t pcmval,double timeval,
              ogg_int64_t pcmlength,
              char *bigassbuffer){
+  off_t i;
   int j;
   long bread;
   char buffer[4096];
   int dummy;
   ogg_int64_t pos;
+  int hs = ov_halfrate_p(ov);
 
   /* verify the raw position, the pcm position and position decode */
   if(val!=-1 && ov_raw_tell(ov)<val){
@@ -58,15 +60,24 @@
   }
   bread=ov_read(ov,buffer,4096,1,1,1,&dummy);
   for(j=0;j<bread;j++){
-    if(buffer[j]!=bigassbuffer[j+pos*2]){
-      fprintf(stderr,"data position after seek doesn't match pcm position\n");
+    if(buffer[j]!=bigassbuffer[j+((pos>>hs)*2)]){
+      fprintf(stderr,"data after seek doesn't match declared pcm position %lld\n",pos);
 
+      for(i=0;i<(pcmlength>>hs)*2-bread;i++){
+        for(j=0;j<bread;j++)
+          if(buffer[j] != bigassbuffer[i+j])break;
+        if(j==bread){
+          fprintf(stderr,"data after seek appears to match position %lld\n",(i/2)<<hs);
+        }
+      }
       {
         FILE *f=fopen("a.m","w");
-        for(j=0;j<bread;j++)fprintf(f,"%d\n",(int)buffer[j]);
+        for(j=0;j<bread;j++)fprintf(f,"%d %d\n",j,(int)buffer[j]);
         fclose(f);
         f=fopen("b.m","w");
-        for(j=0;j<bread;j++)fprintf(f,"%d\n",(int)bigassbuffer[j+pos*2]);
+        for(j=-4096;j<bread+4096;j++)
+          if(j+((pos*2)>>hs)>=0 && (j+((pos*2)>>hs))<(pcmlength>>hs)*2)
+             fprintf(f,"%d %d\n",j,(int)bigassbuffer[j+((pos*2)>>hs)]);
         fclose(f);
       }
 
@@ -82,6 +93,7 @@
   double timelength;
   char *bigassbuffer;
   int dummy;
+  int hs=0;
 
 #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
   _setmode( _fileno( stdin ), _O_BINARY );
@@ -94,6 +106,14 @@
     exit(1);
   }
 
+#if 0 /*enable this code to test seeking with halfrate decode */
+  if(ov_halfrate(&ov,1)){
+    fprintf(stderr,"Sorry; unable to set half-rate decode.\n\n");
+    exit(1);
+  }else
+    hs=1;
+#endif
+
   if(ov_seekable(&ov)){
 
     /* to simplify our own lives, we want to assume the whole file is
@@ -112,10 +132,10 @@
        does what it claimed, decode the entire file into memory */
     pcmlength=ov_pcm_total(&ov,-1);
     timelength=ov_time_total(&ov,-1);
-    bigassbuffer=malloc(pcmlength*2); /* w00t */
+    bigassbuffer=malloc((pcmlength>>hs)*2); /* w00t */
     i=0;
-    while(i<pcmlength*2){
-      int ret=ov_read(&ov,bigassbuffer+i,pcmlength*2-i,1,1,1,&dummy);
+    while(i<(pcmlength>>hs)*2){
+      int ret=ov_read(&ov,bigassbuffer+i,((pcmlength>>hs)*2)-i,1,1,1,&dummy);
       if(ret<0){
         fprintf(stderr,"Error reading file.\n");
         exit(1);
@@ -123,10 +143,10 @@
       if(ret){
         i+=ret;
       }else{
-        pcmlength=i/2;
+        pcmlength=(i/2)<<hs;
       }
       fprintf(stderr,"\rloading.... [%ld left]              ",
-              (long)(pcmlength*2-i));
+              (long)((pcmlength>>hs)*2-i));
     }
     
     {
@@ -166,7 +186,7 @@
 
       }
     }
-    
+
     fprintf(stderr,"\r");
     {
       fprintf(stderr,"testing pcm exact seeking to random places in %ld samples....\n",
@@ -180,7 +200,7 @@
           fprintf(stderr,"seek failed: %d\n",ret);
           exit(1);
         }
-        if(ov_pcm_tell(&ov)!=val){
+        if(ov_pcm_tell(&ov)!=((val>>hs)<<hs)){
           fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n",
                  (long)val,(long)ov_pcm_tell(&ov));
           exit(1);

Modified: trunk/vorbis/lib/vorbisfile.c
===================================================================
--- trunk/vorbis/lib/vorbisfile.c	2010-10-22 10:28:49 UTC (rev 17559)
+++ trunk/vorbis/lib/vorbisfile.c	2010-10-23 10:29:11 UTC (rev 17560)
@@ -689,6 +689,8 @@
     /* process a packet if we can. */
 
     if(vf->ready_state==INITSET){
+      int hs=vorbis_synthesis_halfrate_p(vf->vi);
+
       while(1) {
               ogg_packet op;
               ogg_packet *op_ptr=(op_in?op_in:&op);
@@ -716,7 +718,7 @@
               if(oldsamples)return(OV_EFAULT);
 
               vorbis_synthesis_blockin(&vf->vd,&vf->vb);
-              vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
+              vf->samptrack+=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs);
               vf->bittrack+=op_ptr->bytes*8;
             }
 
@@ -745,7 +747,7 @@
                                                here unless the stream
                                                is very broken */
 
-              samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
+              samples=(vorbis_synthesis_pcmout(&vf->vd,NULL)<<hs);
 
               granulepos-=samples;
               for(i=0;i<link;i++)
@@ -1022,17 +1024,22 @@
 int ov_halfrate(OggVorbis_File *vf,int flag){
   int i;
   if(vf->vi==NULL)return OV_EINVAL;
-  if(!vf->seekable)return OV_EINVAL;
-  if(vf->ready_state>=STREAMSET)
-    _decode_clear(vf); /* clear out stream state; later on libvorbis
-                          will be able to swap this on the fly, but
-                          for now dumping the decode machine is needed
-                          to reinit the MDCT lookups.  1.1 libvorbis
-                          is planned to be able to switch on the fly */
+  if(vf->ready_state>STREAMSET){
+    /* clear out stream state; dumping the decode machine is needed to
+       reinit the MDCT lookups. */
+    vorbis_dsp_clear(&vf->vd);
+    vorbis_block_clear(&vf->vb);
+    vf->ready_state=STREAMSET;
+    if(vf->pcm_offset>=0){
+      ogg_int64_t pos=vf->pcm_offset;
+      vf->pcm_offset=-1; /* make sure the pos is dumped if unseekable */
+      ov_pcm_seek(vf,pos);
+    }
+  }
 
   for(i=0;i<vf->links;i++){
     if(vorbis_synthesis_halfrate(vf->vi+i,flag)){
-      ov_halfrate(vf,0);
+      if(flag) ov_halfrate(vf,0);
       return OV_EINVAL;
     }
   }
@@ -1657,17 +1664,22 @@
   vf->samptrack=0.f;
   /* discard samples until we reach the desired position. Crossing a
      logical bitstream boundary with abandon is OK. */
-  while(vf->pcm_offset<pos){
-    ogg_int64_t target=pos-vf->pcm_offset;
-    long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
+  {
+    /* note that halfrate could be set differently in each link, but
+       vorbisfile encoforces all links are set or unset */
+    int hs=vorbis_synthesis_halfrate_p(vf->vi);
+    while(vf->pcm_offset<((pos>>hs)<<hs)){
+      ogg_int64_t target=(pos-vf->pcm_offset)>>hs;
+      long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
 
-    if(samples>target)samples=target;
-    vorbis_synthesis_read(&vf->vd,samples);
-    vf->pcm_offset+=samples;
+      if(samples>target)samples=target;
+      vorbis_synthesis_read(&vf->vd,samples);
+      vf->pcm_offset+=samples<<hs;
 
-    if(samples<target)
-      if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
-        vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
+      if(samples<target)
+        if(_fetch_and_process_packet(vf,NULL,1,1)<=0)
+          vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
+    }
   }
   return 0;
 }
@@ -1858,6 +1870,7 @@
                     void (*filter)(float **pcm,long channels,long samples,void *filter_param),void *filter_param){
   int i,j;
   int host_endian = host_is_big_endian();
+  int hs;
 
   float **pcm;
   long samples;
@@ -1981,7 +1994,8 @@
     }
 
     vorbis_synthesis_read(&vf->vd,samples);
-    vf->pcm_offset+=samples;
+    hs=vorbis_synthesis_halfrate_p(vf->vi);
+    vf->pcm_offset+=(samples<<hs);
     if(bitstream)*bitstream=vf->current_link;
     return(samples*bytespersample);
   }else{
@@ -2018,10 +2032,11 @@
       float **pcm;
       long samples=vorbis_synthesis_pcmout(&vf->vd,&pcm);
       if(samples){
+        int hs=vorbis_synthesis_halfrate_p(vf->vi);
         if(pcm_channels)*pcm_channels=pcm;
         if(samples>length)samples=length;
         vorbis_synthesis_read(&vf->vd,samples);
-        vf->pcm_offset+=samples;
+        vf->pcm_offset+=samples<<hs;
         if(bitstream)*bitstream=vf->current_link;
         return samples;
 



More information about the commits mailing list