[xiph-cvs] cvs commit: vorbis/lib block.c mapping0.c synthesis.c vorbisfile.c

Monty xiphmont at xiph.org
Wed Feb 27 20:12:50 PST 2002



xiphmont    02/02/27 20:12:49

  Modified:    examples encoder_example.c seeking_example.c
               include/vorbis codec.h
               lib      block.c mapping0.c synthesis.c vorbisfile.c
  Log:
  Single link files seeking fixes:
  
  fix pcm exact seeking at very beginning (a rejected packet was being
  interpreted as a negative pcm offset) and very end of files (short
  final frames require processing from previous page's granulepos to get
  length of final frame correct)

Revision  Changes    Path
1.37      +2 -2      vorbis/examples/encoder_example.c

Index: encoder_example.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/examples/encoder_example.c,v
retrieving revision 1.36
retrieving revision 1.37
diff -u -r1.36 -r1.37
--- encoder_example.c	2002/01/23 16:04:55	1.36
+++ encoder_example.c	2002/02/28 04:12:47	1.37
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: simple example encoder
- last mod: $Id: encoder_example.c,v 1.36 2002/01/23 16:04:55 segher Exp $
+ last mod: $Id: encoder_example.c,v 1.37 2002/02/28 04:12:47 xiphmont Exp $
 
  ********************************************************************/
 
@@ -97,7 +97,7 @@
   /* (quality mode .4: 44kHz stereo coupled, roughly 128kbps VBR) */
   vorbis_info_init(&vi);
 
-  vorbis_encode_init_vbr(&vi,2,44100,.1); /* max compression */
+  vorbis_encode_init_vbr(&vi,2,44100,.4); /* max compression */
 
   /* add a comment */
   vorbis_comment_init(&vc);

<p><p>1.13      +15 -4     vorbis/examples/seeking_example.c

Index: seeking_example.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/examples/seeking_example.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -r1.12 -r1.13
--- seeking_example.c	2001/12/20 01:00:24	1.12
+++ seeking_example.c	2002/02/28 04:12:47	1.13
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: illustrate seeking, and test it too
- last mod: $Id: seeking_example.c,v 1.12 2001/12/20 01:00:24 segher Exp $
+ last mod: $Id: seeking_example.c,v 1.13 2002/02/28 04:12:47 xiphmont Exp $
 
  ********************************************************************/
 
@@ -54,6 +54,16 @@
   for(j=0;j<bread;j++){
     if(buffer[j]!=bigassbuffer[j+pos*2]){
       printf("data position after seek doesn't match pcm position\n");
+
+      {
+	FILE *f=fopen("a.m","w");
+	for(j=0;j<bread;j++)fprintf(f,"%d\n",(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]);
+	fclose(f);
+      }
+
       exit(1);
     }
   }
@@ -94,7 +104,6 @@
     
     /* because we want to do sample-level verification that the seek
        does what it claimed, decode the entire file into memory */
-    printf("loading....\n");
     fflush(stdout);
     pcmlength=ov_pcm_total(&ov,-1);
     bigassbuffer=malloc(pcmlength*2); /* w00t */
@@ -107,6 +116,8 @@
       }else{
         pcmlength=i/2;
       }
+      fprintf(stderr,"\rloading.... [%ld left]              ",
+	      (long)(pcmlength*2-i));
     }
     
     /* Exercise all the real seeking cases; ov_raw_seek,
@@ -114,7 +125,7 @@
        on pcm_seek */
     {
       ogg_int64_t length=ov.end;
-      printf("testing raw seeking to random places in %ld bytes....\n",
+      printf("\rtesting raw seeking to random places in %ld bytes....\n",
              (long)length);
     
       for(i=0;i<1000;i++){
@@ -172,7 +183,7 @@
           exit(1);
         }
         if(ov_pcm_tell(&ov)!=val){
-	  printf("Decalred position didn't perfectly match request: %ld != %ld\n",
+	  printf("Declared position didn't perfectly match request: %ld != %ld\n",
                  (long)val,(long)ov_pcm_tell(&ov));
           exit(1);
         }

<p><p>1.40      +2 -1      vorbis/include/vorbis/codec.h

Index: codec.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis/include/vorbis/codec.h,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- codec.h	2001/12/12 09:45:23	1.39
+++ codec.h	2002/02/28 04:12:47	1.40
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: libvorbis codec headers
- last mod: $Id: codec.h,v 1.39 2001/12/12 09:45:23 xiphmont Exp $
+ last mod: $Id: codec.h,v 1.40 2002/02/28 04:12:47 xiphmont Exp $
 
  ********************************************************************/
 
@@ -201,6 +201,7 @@
 
 extern int      vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi);
 extern int      vorbis_synthesis(vorbis_block *vb,ogg_packet *op);
+extern int      vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op);
 extern int      vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb);
 extern int      vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm);
 extern int      vorbis_synthesis_read(vorbis_dsp_state *v,int samples);

<p><p>1.59      +62 -62    vorbis/lib/block.c

Index: block.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/block.c,v
retrieving revision 1.58
retrieving revision 1.59
diff -u -r1.58 -r1.59
--- block.c	2002/01/22 11:59:00	1.58
+++ block.c	2002/02/28 04:12:48	1.59
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: PCM data vector blocking, windowing and dis/reassembly
- last mod: $Id: block.c,v 1.58 2002/01/22 11:59:00 xiphmont Exp $
+ last mod: $Id: block.c,v 1.59 2002/02/28 04:12:48 xiphmont Exp $
 
  Handle windowing, overlap-add, etc of the PCM vectors.  This is made
  more amusing by Vorbis' current two allowed block sizes.
@@ -620,23 +620,19 @@
   codec_setup_info *ci=vi->codec_setup;
   int i,j;
 
+  if(!vb)return(OV_EINVAL);
   if(v->pcm_current>v->pcm_returned  && v->pcm_returned!=-1)return(OV_EINVAL);
-
+    
   v->lW=v->W;
   v->W=vb->W;
   v->nW=-1;
-
-  v->glue_bits+=vb->glue_bits;
-  v->time_bits+=vb->time_bits;
-  v->floor_bits+=vb->floor_bits;
-  v->res_bits+=vb->res_bits;
-
+  
   if(v->sequence+1 != vb->sequence)v->granulepos=-1; /* out of sequence;
-                                                     lose count */
-
+							lose count */
   v->sequence=vb->sequence;
   
-  {
+  if(vb->pcm){  /* not pcm to process if vorbis_synthesis_trackonly 
+		   was called on block */
     int n=ci->blocksizes[v->W]/2;
     int n0=ci->blocksizes[0]/2;
     int n1=ci->blocksizes[1]/2;
@@ -644,12 +640,17 @@
     int thisCenter;
     int prevCenter;
     
+    v->glue_bits+=vb->glue_bits;
+    v->time_bits+=vb->time_bits;
+    v->floor_bits+=vb->floor_bits;
+    v->res_bits+=vb->res_bits;
+    
     if(v->centerW){
       thisCenter=n1;
       prevCenter=0;
     }else{
-      thisCenter=0;
-      prevCenter=n1;
+	thisCenter=0;
+	prevCenter=n1;
     }
     
     /* v->pcm is now used like a two-stage double buffer.  We don't want
@@ -709,7 +710,7 @@
     /* deal with initial packet state; we do this using the explicit
        pcm_returned==-1 flag otherwise we're sensitive to first block
        being short or long */
-
+    
     if(v->pcm_returned==-1){
       v->pcm_returned=thisCenter;
       v->pcm_current=thisCenter;
@@ -719,57 +720,56 @@
         ci->blocksizes[v->lW]/4+
         ci->blocksizes[v->W]/4;
     }
+    
+  }
 
-    /* track the frame number... This is for convenience, but also
-       making sure our last packet doesn't end with added padding.  If
-       the last packet is partial, the number of samples we'll have to
-       return will be past the vb->granulepos.
-       
-       This is not foolproof!  It will be confused if we begin
-       decoding at the last page after a seek or hole.  In that case,
-       we don't have a starting point to judge where the last frame
-       is.  For this reason, vorbisfile will always try to make sure
-       it reads the last two marked pages in proper sequence */
-
-    if(v->granulepos==-1)
-      if(vb->granulepos==-1){
-	v->granulepos=0;
-      }else{
-	v->granulepos=vb->granulepos;
-      }
-    else{
-      v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
-      if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
-
-	if(v->granulepos>vb->granulepos){
-	  long extra=v->granulepos-vb->granulepos;
-
-	  if(vb->eofflag){
-	    /* partial last frame.  Strip the extra samples off */
-	    v->pcm_current-=extra;
-	  }else if(vb->sequence == 1){
-	    /* ^^^ argh, this can be 1 from seeking! */
-
-
-	    /* partial first frame.  Discard extra leading samples */
-	    v->pcm_returned+=extra;
-	    if(v->pcm_returned>v->pcm_current)
-	      v->pcm_returned=v->pcm_current;
-	    
-	  }
+  /* track the frame number... This is for convenience, but also
+     making sure our last packet doesn't end with added padding.  If
+     the last packet is partial, the number of samples we'll have to
+     return will be past the vb->granulepos.
+     
+     This is not foolproof!  It will be confused if we begin
+     decoding at the last page after a seek or hole.  In that case,
+     we don't have a starting point to judge where the last frame
+     is.  For this reason, vorbisfile will always try to make sure
+     it reads the last two marked pages in proper sequence */
+  
+  if(v->granulepos==-1){
+    if(vb->granulepos!=-1){ /* only set if we have a position to set to */
+      v->granulepos=vb->granulepos;
+    }
+  }else{
+    v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
+    if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
+      
+      if(v->granulepos>vb->granulepos){
+	long extra=v->granulepos-vb->granulepos;
+	
+	if(vb->eofflag){
+	  /* partial last frame.  Strip the extra samples off */
+	  v->pcm_current-=extra;
+	}else if(vb->sequence == 1){
+	  /* ^^^ argh, this can be 1 from seeking! */
           
-	}/* else{ Shouldn't happen *unless* the bitstream is out of
-	    spec.  Either way, believe the bitstream } */
-	v->granulepos=vb->granulepos;
-      }
+	  
+	  /* partial first frame.  Discard extra leading samples */
+	  v->pcm_returned+=extra;
+	  if(v->pcm_returned>v->pcm_current)
+	    v->pcm_returned=v->pcm_current;
+	  
+	} /* else {Shouldn't happen *unless* the bitstream is out of
+	     spec.  Either way, believe the bitstream } */
+      } /* else {Shouldn't happen *unless* the bitstream is out of
+	   spec.  Either way, believe the bitstream } */
+      v->granulepos=vb->granulepos;
     }
-    
-    /* Update, cleanup */
-    
-    if(vb->eofflag)v->eofflag=1;
   }
   
+  /* Update, cleanup */
+  
+  if(vb->eofflag)v->eofflag=1;
   return(0);
+  
 }
 
 /* pcm==NULL indicates we just want the pending samples, no more */
@@ -787,9 +787,9 @@
   return(0);
 }
 
-int vorbis_synthesis_read(vorbis_dsp_state *v,int bytes){
-  if(bytes && v->pcm_returned+bytes>v->pcm_current)return(OV_EINVAL);
-  v->pcm_returned+=bytes;
+int vorbis_synthesis_read(vorbis_dsp_state *v,int n){
+  if(n && v->pcm_returned+n>v->pcm_current)return(OV_EINVAL);
+  v->pcm_returned+=n;
   return(0);
 }
 

<p><p>1.45      +3 -2      vorbis/lib/mapping0.c

Index: mapping0.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/mapping0.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -r1.44 -r1.45
--- mapping0.c	2002/01/22 11:59:00	1.44
+++ mapping0.c	2002/02/28 04:12:48	1.45
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: channel mapping 0 implementation
- last mod: $Id: mapping0.c,v 1.44 2002/01/22 11:59:00 xiphmont Exp $
+ last mod: $Id: mapping0.c,v 1.45 2002/02/28 04:12:48 xiphmont Exp $
 
  ********************************************************************/
 
@@ -681,7 +681,7 @@
         pcm[j]=0.f;
 
   }
-	    
+
   /* all done! */
   return(0);
 }
@@ -697,3 +697,4 @@
   &mapping0_forward,
   &mapping0_inverse
 };
+

<p><p>1.26      +48 -1     vorbis/lib/synthesis.c

Index: synthesis.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/synthesis.c,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- synthesis.c	2001/12/20 01:00:30	1.25
+++ synthesis.c	2002/02/28 04:12:48	1.26
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: single-block PCM synthesis
- last mod: $Id: synthesis.c,v 1.25 2001/12/20 01:00:30 segher Exp $
+ last mod: $Id: synthesis.c,v 1.26 2002/02/28 04:12:48 xiphmont Exp $
 
  ********************************************************************/
 
@@ -71,6 +71,53 @@
   type=ci->map_type[ci->mode_param[mode]->mapping];
 
   return(_mapping_P[type]->inverse(vb,b->mode[mode]));
+}
+
+/* used to track pcm position without actually performing decode.
+   Useful for sequential 'fast forward' */
+int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){
+  vorbis_dsp_state     *vd=vb->vd;
+  backend_lookup_state *b=vd->backend_state;
+  vorbis_info          *vi=vd->vi;
+  codec_setup_info     *ci=vi->codec_setup;
+  oggpack_buffer       *opb=&vb->opb;
+  int                   mode;
+ 
+  /* first things first.  Make sure decode is ready */
+  _vorbis_block_ripcord(vb);
+  oggpack_readinit(opb,op->packet,op->bytes);
+
+  /* Check the packet type */
+  if(oggpack_read(opb,1)!=0){
+    /* Oops.  This is not an audio data packet */
+    return(OV_ENOTAUDIO);
+  }
+
+  /* read our mode and pre/post windowsize */
+  mode=oggpack_read(opb,b->modebits);
+  if(mode==-1)return(OV_EBADPACKET);
+  
+  vb->mode=mode;
+  vb->W=ci->mode_param[mode]->blockflag;
+  if(vb->W){
+    vb->lW=oggpack_read(opb,1);
+    vb->nW=oggpack_read(opb,1);
+    if(vb->nW==-1)   return(OV_EBADPACKET);
+  }else{
+    vb->lW=0;
+    vb->nW=0;
+  }
+  
+  /* more setup */
+  vb->granulepos=op->granulepos;
+  vb->sequence=op->packetno-3; /* first block is third packet */
+  vb->eofflag=op->e_o_s;
+
+  /* no pcm */
+  vb->pcmend=0;
+  vb->pcm=NULL;
+
+  return(0);
 }
 
 long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){

<p><p>1.56      +40 -25    vorbis/lib/vorbisfile.c

Index: vorbisfile.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/vorbisfile.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -r1.55 -r1.56
--- vorbisfile.c	2002/01/22 08:06:08	1.55
+++ vorbisfile.c	2002/02/28 04:12:48	1.56
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.c,v 1.55 2002/01/22 08:06:08 xiphmont Exp $
+ last mod: $Id: vorbisfile.c,v 1.56 2002/02/28 04:12:48 xiphmont Exp $
 
  ********************************************************************/
 
@@ -416,7 +416,9 @@
             1) got a packet 
 */
 
-static int _process_packet(OggVorbis_File *vf,int readp){
+static int _fetch_and_process_packet(OggVorbis_File *vf,
+				     ogg_packet *op_in,
+				     int readp){
   ogg_page og;
 
   /* handle one packet.  Try to fetch it from current stream state */
@@ -428,31 +430,37 @@
     if(vf->ready_state==INITSET){
       while(1) {
               ogg_packet op;
-	int result=ogg_stream_packetout(&vf->os,&op);
+      	ogg_packet *op_ptr=(op_in?op_in:&op);
+	int result=ogg_stream_packetout(&vf->os,op_ptr);
         ogg_int64_t granulepos;
 
+	op_in=NULL;
         if(result==-1)return(OV_HOLE); /* hole in the data. */
         if(result>0){
           /* got a packet.  process it */
-	  granulepos=op.granulepos;
-	  if(!vorbis_synthesis(&vf->vb,&op)){ /* lazy check for lazy
-                                                 header handling.  The
-                                                 header packets aren't
-                                                 audio, so if/when we
-                                                 submit them,
-                                                 vorbis_synthesis will
-                                                 reject them */
+	  granulepos=op_ptr->granulepos;
+	  if(!vorbis_synthesis(&vf->vb,op_ptr)){ /* lazy check for lazy
+						    header handling.  The
+						    header packets aren't
+						    audio, so if/when we
+						    submit them,
+						    vorbis_synthesis will
+						    reject them */
 
             /* suck in the synthesis data and track bitrate */
             {
               int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
+	      /* for proper use of libvorbis within libvorbisfile,
+                 oldsamples will always be zero. */
+	      if(oldsamples)return(OV_EFAULT);
+	      
               vorbis_synthesis_blockin(&vf->vd,&vf->vb);
               vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
-	      vf->bittrack+=op.bytes*8;
+	      vf->bittrack+=op_ptr->bytes*8;
             }
           
             /* update the pcm offset. */
-	    if(granulepos!=-1 && !op.e_o_s){
+	    if(granulepos!=-1 && !op_ptr->e_o_s){
               int link=(vf->seekable?vf->current_link:0);
               int i,samples;
             
@@ -466,7 +474,7 @@
                  granulepos declares the last frame in the stream, and the
                  last packet of the last page may be a partial frame.
                  So, we need a previous granulepos from an in-sequence page
-	         to have a reference point.  Thus the !op.e_o_s clause
+	         to have a reference point.  Thus the !op_ptr->e_o_s clause
                  above */
             
               samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
@@ -1125,6 +1133,7 @@
   int thisblock,lastblock=0;
   int ret=ov_pcm_seek_page(vf,pos);
   if(ret<0)return(ret);
+  _make_decode_ready(vf);
 
   /* discard leading packets we don't need for the lapping of the
      position we want; don't decode them */
@@ -1136,17 +1145,22 @@
     int ret=ogg_stream_packetpeek(&vf->os,&op);
     if(ret>0){
       thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);
+      if(thisblock<0)thisblock=0; /* non audio packet */
       if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;
-
+      
       if(vf->pcm_offset+((thisblock+
                           vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;
-
+      
+      /* remove the packet from packet queue and track its granulepos */
       ogg_stream_packetout(&vf->os,NULL);
+      vorbis_synthesis_trackonly(&vf->vb,&op);  /* set up a vb with
+                                                   only tracking, no
+                                                   pcm_decode */
+      vorbis_synthesis_blockin(&vf->vd,&vf->vb); 
       
-
       /* end of logical stream case is hard, especially with exact
-         length positioning. */
-
+	 length positioning. */
+      
       if(op.granulepos>-1){
         int i;
         /* always believe the stream markers */
@@ -1154,9 +1168,9 @@
         for(i=0;i<vf->current_link;i++)
           vf->pcm_offset+=vf->pcmlengths[i];
       }
-
+	
       lastblock=thisblock;
-
+      
     }else{
       if(ret<0 && ret!=OV_HOLE)break;
       
@@ -1176,15 +1190,16 @@
         ogg_stream_init(&vf->os,vf->current_serialno);
         ogg_stream_reset(&vf->os); 
         vf->ready_state=STREAMSET;      
+	_make_decode_ready(vf);
         lastblock=0;
       }
+
       ogg_stream_pagein(&vf->os,&og);
     }
   }
 
   /* discard samples until we reach the desired position. Crossing a
      logical bitstream boundary with abandon is OK. */
-  _make_decode_ready(vf);
   while(vf->pcm_offset<pos){
     float **pcm;
     long target=pos-vf->pcm_offset;
@@ -1195,7 +1210,7 @@
     vf->pcm_offset+=samples;
     
     if(samples<target)
-      if(_process_packet(vf,1)<=0)
+      if(_fetch_and_process_packet(vf,NULL,1)<=0)
         vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */
   }
   return 0;
@@ -1393,7 +1408,7 @@
 
     /* suck in another packet */
     {
-      int ret=_process_packet(vf,1);
+      int ret=_fetch_and_process_packet(vf,NULL,1);
       if(ret==OV_EOF)return(0);
       if(ret<=0)return(ret);
     }
@@ -1419,7 +1434,7 @@
 
     /* suck in another packet */
     {
-      int ret=_process_packet(vf,1);
+      int ret=_fetch_and_process_packet(vf,NULL,1);
       if(ret==OV_EOF)return(0);
       if(ret<=0)return(ret);
     }

<p><p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list