Made API consistent wrt in64_t internal types and return values
authorMonty <xiphmont@xiph.org>
Wed, 14 Jun 2000 10:13:35 +0000 (10:13 +0000)
committerMonty <xiphmont@xiph.org>
Wed, 14 Jun 2000 10:13:35 +0000 (10:13 +0000)
fixed end of stream padding bug in libvorbis/vorbisfile

Monty

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

examples/chaining_example.c
examples/decoder_example.c
include/vorbis/codec.h
include/vorbis/vorbisfile.h
lib/block.c
lib/vorbisfile.c

index 632eaee..445c9a3 100644 (file)
@@ -12,7 +12,7 @@
  ********************************************************************
 
  function: illustrate simple use of chained bitstream and vorbisfile.a
- last mod: $Id: chaining_example.c,v 1.4 2000/03/10 13:21:18 xiphmont Exp $
+ last mod: $Id: chaining_example.c,v 1.5 2000/06/14 10:13:35 xiphmont Exp $
 
  ********************************************************************/
 
@@ -48,7 +48,7 @@ int main(){
     printf("\t\t%ldHz %d channels bitrate %ldkbps serial number=%ld\n",
           vi->rate,vi->channels,ov_bitrate(&ov,i)/1000,
           ov_serialnumber(&ov,i));
-    printf("\t\tcompressed length: %ld bytes ",ov_raw_total(&ov,i));
+    printf("\t\tcompressed length: %ld bytes ",(long)(ov_raw_total(&ov,i)));
     printf(" play time: %lds\n",(long)ov_time_total(&ov,i));
   }
 
index 8e6abf2..4180b40 100644 (file)
@@ -12,7 +12,7 @@
  ********************************************************************
 
  function: simple example decoder
- last mod: $Id: decoder_example.c,v 1.7 2000/05/12 08:38:20 msmith Exp $
+ last mod: $Id: decoder_example.c,v 1.8 2000/06/14 10:13:35 xiphmont Exp $
 
  ********************************************************************/
 
@@ -201,6 +201,7 @@ int main(int argc, char **argv){
                                         this point */
          while(1){
            result=ogg_stream_packetout(&os,&op);
+
            if(result==0)break; /* need more data */
            if(result==-1){ /* missing or corrupt data at this page position */
              /* no reason to complain; already complained above */
@@ -245,7 +246,7 @@ int main(int argc, char **argv){
                }
                
                if(clipflag)
-                 fprintf(stderr,"Clipping in frame %ld\n",vd.sequence);
+                 fprintf(stderr,"Clipping in frame %ld\n",(long)(vd.sequence));
                
                
                fwrite(convbuffer,2*vi.channels,bout,stdout);
index b150632..c2b12f1 100644 (file)
@@ -12,7 +12,7 @@
  ********************************************************************
 
  function: libvorbis codec headers
- last mod: $Id: codec.h,v 1.16 2000/06/14 01:38:27 xiphmont Exp $
+ last mod: $Id: codec.h,v 1.17 2000/06/14 10:13:35 xiphmont Exp $
 
  ********************************************************************/
 
@@ -191,8 +191,8 @@ typedef struct {
   int     b_o_s;          /* set after we've written the initial page
                             of a logical bitstream */
   long     serialno;
-  long     pageno;
-  long     packetno;      /* sequence number for decode; the framing
+  int      pageno;
+  int64_t  packetno;      /* sequence number for decode; the framing
                              knows where there's a hole in the data,
                              but we need coupling so that the codec
                              (which is in a seperate abstraction
@@ -211,7 +211,7 @@ typedef struct {
   long  e_o_s;
 
   int64_t  frameno;
-  long    packetno;       /* sequence number for decode; the framing
+  int64_t  packetno;       /* sequence number for decode; the framing
                              knows where there's a hole in the data,
                              but we need coupling so that the codec
                              (which is in a seperate abstraction
@@ -255,8 +255,8 @@ typedef struct vorbis_dsp_state{
   long nW;
   long centerW;
 
-  long frameno;
-  long sequence;
+  int64_t frameno;
+  int64_t sequence;
 
   int64_t glue_bits;
   int64_t time_bits;
@@ -303,8 +303,8 @@ typedef struct vorbis_block{
   int   mode;
 
   int eofflag;
-  int frameno;
-  int sequence;
+  int64_t frameno;
+  int64_t sequence;
   vorbis_dsp_state *vd; /* For read-only access of configuration */
 
   /* local storage to avoid remallocing; it's up to the mapping to
index b83ca8d..06c3724 100644 (file)
@@ -12,7 +12,7 @@
  ********************************************************************
 
  function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.h,v 1.4 2000/04/23 15:34:12 msmith Exp $
+ last mod: $Id: vorbisfile.h,v 1.5 2000/06/14 10:13:35 xiphmont Exp $
 
  ********************************************************************/
 
@@ -39,7 +39,7 @@ extern "C"
  */
 typedef struct {
   size_t (*read_func)  (void *ptr, size_t size, size_t nmemb, void *datasource);
-  int    (*seek_func)  (void *datasource, long offset, int whence);
+  int    (*seek_func)  (void *datasource, int64_t offset, int whence);
   int    (*close_func) (void *datasource);
   long   (*tell_func)  (void *datasource);
 } ov_callbacks;
@@ -48,15 +48,15 @@ typedef struct {
 typedef struct {
   void             *datasource; /* Pointer to a FILE *, etc. */
   int              seekable;
-  long             offset;
-  long             end;
+  int64_t          offset;
+  int64_t          end;
   ogg_sync_state   oy; 
 
   /* If the FILE handle isn't seekable (eg, a pipe), only the current
      stream appears */
   int              links;
-  long             *offsets;
-  long             *dataoffsets;
+  int64_t          *offsets;
+  int64_t          *dataoffsets;
   long             *serialnos;
   int64_t          *pcmlengths;
   vorbis_info      *vi;
@@ -87,7 +87,7 @@ extern long ov_streams(OggVorbis_File *vf);
 extern long ov_seekable(OggVorbis_File *vf);
 extern long ov_serialnumber(OggVorbis_File *vf,int i);
 
-extern long ov_raw_total(OggVorbis_File *vf,int i);
+extern int64_t ov_raw_total(OggVorbis_File *vf,int i);
 extern int64_t ov_pcm_total(OggVorbis_File *vf,int i);
 extern double ov_time_total(OggVorbis_File *vf,int i);
 
@@ -95,7 +95,7 @@ extern int ov_raw_seek(OggVorbis_File *vf,long pos);
 extern int ov_pcm_seek(OggVorbis_File *vf,int64_t pos);
 extern int ov_time_seek(OggVorbis_File *vf,double pos);
 
-extern long ov_raw_tell(OggVorbis_File *vf);
+extern int64_t ov_raw_tell(OggVorbis_File *vf);
 extern int64_t ov_pcm_tell(OggVorbis_File *vf);
 extern double ov_time_tell(OggVorbis_File *vf);
 
index f7ba7fb..546793b 100644 (file)
@@ -12,7 +12,7 @@
  ********************************************************************
 
  function: PCM data vector blocking, windowing and dis/reassembly
- last mod: $Id: block.c,v 1.30 2000/05/08 20:49:48 xiphmont Exp $
+ last mod: $Id: block.c,v 1.31 2000/06/14 10:13:35 xiphmont Exp $
 
  Handle windowing, overlap-add, etc of the PCM vectors.  This is made
  more amusing by Vorbis' current two allowed block sizes.
@@ -508,6 +508,7 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
     if(v->centerW>=v->eofflag){
       v->eofflag=-1;
       vb->eofflag=1;
+      return(1);
     }
   }
 
@@ -517,6 +518,8 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
     int movementW=centerNext-new_centerNext;
     int movementM=movementW/vi->envelopesa;
 
+
+
     /* the multipliers and pcm stay synced up because the blocksize
        must be multiples of samples_per_envelope_step (minimum
        multiple is 2) */
@@ -536,10 +539,17 @@ int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
     v->centerW=new_centerNext;
 
     v->sequence++;
-    v->frameno+=movementW;
 
-    if(v->eofflag)
+    if(v->eofflag){
       v->eofflag-=movementW;
+      /* do not add padding to end of stream! */
+      if(v->centerW>=v->eofflag){
+       v->frameno+=v->eofflag;
+      }else{
+       v->frameno+=movementW;
+      }
+    }else
+      v->frameno+=movementW;
   }
 
   /* done */
@@ -552,6 +562,9 @@ int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
   /* Adjust centerW to allow an easier mechanism for determining output */
   v->pcm_returned=v->centerW;
   v->centerW-= vi->blocksizes[v->W]/4+vi->blocksizes[v->lW]/4;
+  v->frameno=-1;
+  v->sequence=-1;
+
   return(0);
 }
 
@@ -592,6 +605,10 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
   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->frameno=-1; /* out of sequence;
+                                                     lose count */
+
   v->sequence=vb->sequence;
 
   {
@@ -636,6 +653,31 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
        pcm[i]=vb->pcm[j][i];
     }
 
+    /* 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->frameno.
+       
+       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->frameno==-1)
+      v->frameno=vb->frameno;
+    else{
+      v->frameno+=(centerW-v->centerW);
+      if(vb->frameno!=-1 && v->frameno!=vb->frameno){
+       if(v->frameno>vb->frameno && vb->eofflag){
+         /* partial last frame.  Strip the padding off */
+         centerW-=(v->frameno-vb->frameno);
+       }/* else{ Shouldn't happen *unless* the bitstream is out of
+            spec.  Either way, believe the bitstream } */
+       v->frameno=vb->frameno;
+      }
+    }
+
     /* Update, cleanup */
 
     v->centerW=centerW;
@@ -643,6 +685,7 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
 
     if(vb->eofflag)v->eofflag=1;
   }
+
   return(0);
 }
 
index 5bd3a9b..09e6cfc 100644 (file)
@@ -12,7 +12,7 @@
  ********************************************************************
 
  function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.c,v 1.23 2000/05/16 11:38:36 msmith Exp $
+ last mod: $Id: vorbisfile.c,v 1.24 2000/06/14 10:13:35 xiphmont Exp $
 
  ********************************************************************/
 
@@ -189,7 +189,7 @@ static void _bisect_forward_serialno(OggVorbis_File *vf,
   
   if(searched>=end || ret==-1){
     vf->links=m+1;
-    vf->offsets=malloc((m+2)*sizeof(long));
+    vf->offsets=malloc((m+2)*sizeof(int64_t));
     vf->offsets[m+1]=searched;
   }else{
     _bisect_forward_serialno(vf,next,vf->offset,
@@ -265,7 +265,7 @@ static void _prefetch_all_headers(OggVorbis_File *vf,vorbis_info *first_i,
   
   vf->vi=calloc(vf->links,sizeof(vorbis_info));
   vf->vc=calloc(vf->links,sizeof(vorbis_info));
-  vf->dataoffsets=malloc(vf->links*sizeof(long));
+  vf->dataoffsets=malloc(vf->links*sizeof(int64_t));
   vf->pcmlengths=malloc(vf->links*sizeof(int64_t));
   vf->serialnos=malloc(vf->links*sizeof(long));
   
@@ -428,7 +428,7 @@ static int _process_packet(OggVorbis_File *vf,int readp){
          vorbis_synthesis_blockin(&vf->vd,&vf->vb);
          
          /* update the pcm offset. */
-         if(frameno!=-1){
+         if(frameno!=-1 && !op.e_o_s){
            int link=(vf->seekable?vf->current_link:0);
            double **dummy;
            int i,samples;
@@ -436,7 +436,15 @@ static int _process_packet(OggVorbis_File *vf,int readp){
            /* this packet has a pcm_offset on it (the last packet
               completed on a page carries the offset) After processing
               (above), we know the pcm position of the *last* sample
-              ready to be returned. Find the offset of the *first* */
+              ready to be returned. Find the offset of the *first*
+
+              As an aside, this trick is inaccurate if we begin
+              reading anew right at the last page; the end-of-stream
+              frameno 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 frameno from an in-sequence page
+              to have a reference point.  Thus the !op.e_o_s clause
+              above */
            
            samples=vorbis_synthesis_pcmout(&vf->vd,&dummy);
            
@@ -538,6 +546,10 @@ int ov_clear(OggVorbis_File *vf){
   return(0);
 }
 
+static int _fseek64_wrap(FILE *f,int64_t off,int whence){
+  return fseek(f,(int)off,whence);
+}
+
 /* inspects the OggVorbis file and finds/documents all the logical
    bitstreams contained in it.  Tries to be tolerant of logical
    bitstream sections that are truncated/woogie. 
@@ -549,7 +561,7 @@ int ov_clear(OggVorbis_File *vf){
 int ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){
   ov_callbacks callbacks = {
     (size_t (*)(void *, size_t, size_t, void *))  fread,
-    (int (*)(void *, long, int))                  fseek,
+    (int (*)(void *, int64_t, int))              _fseek64_wrap,
     (int (*)(void *))                             fclose,
     (long (*)(void *))                            ftell
   };
@@ -659,7 +671,7 @@ long ov_serialnumber(OggVorbis_File *vf,int i){
             raw (compressed) length of that logical bitstream for i==0 to n
            -1 if the stream is not seekable (we can't know the length)
 */
-long ov_raw_total(OggVorbis_File *vf,int i){
+int64_t ov_raw_total(OggVorbis_File *vf,int i){
   if(!vf->seekable || i>=vf->links)return(-1);
   if(i<0){
     long acc=0;
@@ -887,7 +899,7 @@ int ov_time_seek(OggVorbis_File *vf,double seconds){
 
 /* tell the current stream offset cursor.  Note that seek followed by
    tell will likely not give the set offset due to caching */
-long ov_raw_tell(OggVorbis_File *vf){
+int64_t ov_raw_tell(OggVorbis_File *vf){
   return(vf->offset);
 }