Fixed a link-crossing bug in libvorbis (total time was reset to -1
authorMonty <xiphmont@xiph.org>
Thu, 15 Jun 2000 12:17:03 +0000 (12:17 +0000)
committerMonty <xiphmont@xiph.org>
Thu, 15 Jun 2000 12:17:03 +0000 (12:17 +0000)
at the link boundary until the next packet with a frame number arrived)

Implemented instantaneous bitrate capability in libvorbis; added
ov_bitrate_instant() to interface

Added instantaneous bitrate display to xmms

Monty

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

include/vorbis/vorbisfile.h
lib/block.c
lib/vorbisfile.c
todo.txt

index 06c3724..983c1ba 100644 (file)
@@ -12,7 +12,7 @@
  ********************************************************************
 
  function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.h,v 1.5 2000/06/14 10:13:35 xiphmont Exp $
+ last mod: $Id: vorbisfile.h,v 1.6 2000/06/15 12:17:03 xiphmont Exp $
 
  ********************************************************************/
 
@@ -68,6 +68,9 @@ typedef struct {
   long             current_serialno;
   int              current_link;
 
+  double           bittrack;
+  double           samptrack;
+
   ogg_stream_state os; /* take physical pages, weld into a logical
                           stream of packets */
   vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
@@ -83,6 +86,7 @@ extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf,
                char *initial, long ibytes, ov_callbacks callbacks);
 
 extern long ov_bitrate(OggVorbis_File *vf,int i);
+extern long ov_bitrate_instant(OggVorbis_File *vf);
 extern long ov_streams(OggVorbis_File *vf);
 extern long ov_seekable(OggVorbis_File *vf);
 extern long ov_serialnumber(OggVorbis_File *vf,int i);
index 546793b..ba74458 100644 (file)
@@ -12,7 +12,7 @@
  ********************************************************************
 
  function: PCM data vector blocking, windowing and dis/reassembly
- last mod: $Id: block.c,v 1.31 2000/06/14 10:13:35 xiphmont Exp $
+ last mod: $Id: block.c,v 1.32 2000/06/15 12:17:03 xiphmont Exp $
 
  Handle windowing, overlap-add, etc of the PCM vectors.  This is made
  more amusing by Vorbis' current two allowed block sizes.
@@ -689,13 +689,16 @@ int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
   return(0);
 }
 
+/* pcm==NULL indicates we just want the pending samples, no more */
 int vorbis_synthesis_pcmout(vorbis_dsp_state *v,double ***pcm){
   vorbis_info *vi=v->vi;
   if(v->pcm_returned<v->centerW){
-    int i;
-    for(i=0;i<vi->channels;i++)
-      v->pcmret[i]=v->pcm[i]+v->pcm_returned;
-    *pcm=v->pcmret;
+    if(pcm){
+      int i;
+      for(i=0;i<vi->channels;i++)
+       v->pcmret[i]=v->pcm[i]+v->pcm_returned;
+      *pcm=v->pcmret;
+    }
     return(v->centerW-v->pcm_returned);
   }
   return(0);
index 09e6cfc..82836f7 100644 (file)
@@ -12,7 +12,7 @@
  ********************************************************************
 
  function: stdio-based convenience library for opening/seeking/decoding
- last mod: $Id: vorbisfile.c,v 1.24 2000/06/14 10:13:35 xiphmont Exp $
+ last mod: $Id: vorbisfile.c,v 1.25 2000/06/15 12:17:03 xiphmont Exp $
 
  ********************************************************************/
 
@@ -385,8 +385,10 @@ static void _decode_clear(OggVorbis_File *vf){
   ogg_stream_clear(&vf->os);
   vorbis_dsp_clear(&vf->vd);
   vorbis_block_clear(&vf->vb);
-  vf->pcm_offset=-1;
   vf->decode_ready=0;
+
+  vf->bittrack=0.;
+  vf->samptrack=0.;
 }
 
 /* fetch and process a packet.  Handles the case where we're at a
@@ -425,12 +427,18 @@ static int _process_packet(OggVorbis_File *vf,int readp){
                                                submit them,
                                                vorbis_synthesis will
                                                reject them */
-         vorbis_synthesis_blockin(&vf->vd,&vf->vb);
+
+         /* suck in the synthesis data and track bitrate */
+         {
+           int oldsamples=vorbis_synthesis_pcmout(&vf->vd,NULL);
+           vorbis_synthesis_blockin(&vf->vd,&vf->vb);
+           vf->samptrack+=vorbis_synthesis_pcmout(&vf->vd,NULL)-oldsamples;
+           vf->bittrack+=op.bytes*8;
+         }
          
          /* update the pcm offset. */
          if(frameno!=-1 && !op.e_o_s){
            int link=(vf->seekable?vf->current_link:0);
-           double **dummy;
            int i,samples;
            
            /* this packet has a pcm_offset on it (the last packet
@@ -446,7 +454,7 @@ static int _process_packet(OggVorbis_File *vf,int readp){
               to have a reference point.  Thus the !op.e_o_s clause
               above */
            
-           samples=vorbis_synthesis_pcmout(&vf->vd,&dummy);
+           samples=vorbis_synthesis_pcmout(&vf->vd,NULL);
            
            frameno-=samples;
            for(i=0;i<link;i++)
@@ -461,6 +469,10 @@ static int _process_packet(OggVorbis_File *vf,int readp){
     if(!readp)return(0);
     if(_get_next_page(vf,&og,-1)<0)return(0); /* eof. leave unitialized */
 
+    /* bitrate tracking; add the header's bytes here, the body bytes
+       are done by packet above */
+    vf->bittrack+=og.header_len*8;
+
     /* has our decoding just traversed a bitstream boundary? */
     if(vf->decode_ready){
       if(vf->current_serialno!=ogg_page_serialno(&og)){
@@ -656,6 +668,18 @@ long ov_bitrate(OggVorbis_File *vf,int i){
   }
 }
 
+/* returns the actual bitrate since last call.  returns -1 if no
+   additional data to offer since last call (or at beginning of stream) */
+long ov_bitrate_instant(OggVorbis_File *vf){
+  int link=(vf->seekable?vf->current_link:0);
+  long ret;
+  if(vf->samptrack==0)return(-1);
+  ret=vf->bittrack/vf->samptrack*vf->vi[link].rate+.5;
+  vf->bittrack=0.;
+  vf->samptrack=0.;
+  return(ret);
+}
+
 /* Guess */
 long ov_serialnumber(OggVorbis_File *vf,int i){
   if(i>=vf->links)return(-1);
@@ -732,6 +756,7 @@ int ov_raw_seek(OggVorbis_File *vf,long pos){
   if(pos<0 || pos>vf->offsets[vf->links])goto seek_error;
 
   /* clear out decoding machine state */
+  vf->pcm_offset=-1;
   _decode_clear(vf);
 
   /* seek */
@@ -775,6 +800,7 @@ int ov_raw_seek(OggVorbis_File *vf,long pos){
   
  seek_error:
   /* dump the machine so we're in a known state */
+  vf->pcm_offset=-1;
   _decode_clear(vf);
   return -1;
 }
@@ -862,6 +888,7 @@ int ov_pcm_seek(OggVorbis_File *vf,int64_t pos){
   
  seek_error:
   /* dump machine so we're in a known state */
+  vf->pcm_offset=-1;
   _decode_clear(vf);
   return -1;
 }
@@ -893,6 +920,7 @@ int ov_time_seek(OggVorbis_File *vf,double seconds){
 
  seek_error:
   /* dump machine so we're in a known state */
+  vf->pcm_offset=-1;
   _decode_clear(vf);
   return -1;
 }
@@ -924,7 +952,7 @@ double ov_time_tell(OggVorbis_File *vf){
     for(link=vf->links-1;link>=0;link--){
       pcm_total-=vf->pcmlengths[link];
       time_total-=ov_time_total(vf,link);
-      if(vf->pcm_offset>pcm_total)break;
+      if(vf->pcm_offset>=pcm_total)break;
     }
   }
 
index bb90db9..dccd1d0 100644 (file)
--- a/todo.txt
+++ b/todo.txt
@@ -2,10 +2,6 @@ Development hit list for 1.0:
 
 libvorbis:
 
-Implement correct truncated packet handling; this is mostly a case of
-'intiialize vectors and check return values' in res0.c:inverse (but
-not entirely)
-
 Meaningful error code returns
 
 Option for brute-forcing vq search on maptype 2 (helps on undertrained