[xiph-cvs] cvs commit: vorbis/lib analysis.c backends.h bitrate.c bitrate.h block.c codec_internal.h floor1.c highlevel.h info.c mapping0.c res0.c vorbisenc.c

Monty xiphmont at xiph.org
Tue Dec 30 03:02:23 PST 2003



xiphmont    03/12/30 06:02:23

  Modified:    include/vorbis vorbisenc.h
               lib      analysis.c backends.h bitrate.c bitrate.h block.c
                        codec_internal.h floor1.c highlevel.h info.c
                        mapping0.c res0.c vorbisenc.c
  Log:
  Replace time-windowed bitrate management setup with a one-pass
  'greedy' bit reservoir system.
  
  Advantages:
  
  no additional encoder latency
  more predictable buffering
  lower memory usage
  
  These changes introduce two new vorbis_encode_ctls to get to the new
  functionality.  The old ectl calls are still supported for
  compatability and binary library compatability is not broken (but
  libvorbis/file/enc need to be upgraded as a set).
  
  ...now going to update oggenc.
  
  Monty

Revision  Changes    Path
1.11      +27 -8     vorbis/include/vorbis/vorbisenc.h

Index: vorbisenc.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis/include/vorbis/vorbisenc.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- vorbisenc.h	1 Jul 2002 11:20:10 -0000	1.10
+++ vorbisenc.h	30 Dec 2003 11:02:21 -0000	1.11
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: vorbis encode-engine setup
- last mod: $Id: vorbisenc.h,v 1.10 2002/07/01 11:20:10 xiphmont Exp $
+ last mod: $Id: vorbisenc.h,v 1.11 2003/12/30 11:02:21 xiphmont Exp $
 
  ********************************************************************/
 
@@ -59,18 +59,12 @@
 
 extern int vorbis_encode_ctl(vorbis_info *vi,int number,void *arg);
 
+  /* deprecated rate management supported only for compatability */
 #define OV_ECTL_RATEMANAGE_GET       0x10
-
 #define OV_ECTL_RATEMANAGE_SET       0x11
 #define OV_ECTL_RATEMANAGE_AVG       0x12
 #define OV_ECTL_RATEMANAGE_HARD      0x13
 
-#define OV_ECTL_LOWPASS_GET          0x20
-#define OV_ECTL_LOWPASS_SET          0x21
-
-#define OV_ECTL_IBLOCK_GET           0x30
-#define OV_ECTL_IBLOCK_SET           0x31
-
 struct ovectl_ratemanage_arg {
   int    management_active;
 
@@ -84,6 +78,31 @@
   double bitrate_av_window_center;
 };
 
+
+  /* new rate setup */
+#define OV_ECTL_RATEMANAGE2_GET      0x14
+#define OV_ECTL_RATEMANAGE2_SET      0x15
+
+struct ovectl_ratemanage2_arg {
+  int    management_active;
+
+  long   bitrate_limit_min_kbps;
+  long   bitrate_limit_max_kbps;
+  long   bitrate_limit_reservoir_bits;
+  double bitrate_limit_reservoir_bias;
+
+  long   bitrate_average_kbps;
+  double bitrate_average_damping;
+};
+
+
+
+#define OV_ECTL_LOWPASS_GET          0x20
+#define OV_ECTL_LOWPASS_SET          0x21
+
+#define OV_ECTL_IBLOCK_GET           0x30
+#define OV_ECTL_IBLOCK_SET           0x31
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

<p><p>1.56      +5 -3      vorbis/lib/analysis.c

Index: analysis.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/analysis.c,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -r1.55 -r1.56
--- analysis.c	11 Jul 2002 06:40:48 -0000	1.55
+++ analysis.c	30 Dec 2003 11:02:22 -0000	1.56
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: single-block PCM analysis mode dispatch
- last mod: $Id: analysis.c,v 1.55 2002/07/11 06:40:48 xiphmont Exp $
+ last mod: $Id: analysis.c,v 1.56 2003/12/30 11:02:22 xiphmont Exp $
 
  ********************************************************************/
 
@@ -30,7 +30,8 @@
 
 /* decides between modes, dispatches to the appropriate mapping. */
 int vorbis_analysis(vorbis_block *vb, ogg_packet *op){
-  int                   ret;
+  int ret,i;
+  vorbis_block_internal *vbi=vb->internal;
 
   vb->glue_bits=0;
   vb->time_bits=0;
@@ -38,7 +39,8 @@
   vb->res_bits=0;
 
   /* first things first.  Make sure encode is ready */
-  oggpack_reset(&vb->opb);
+  for(i=0;i<PACKETBLOBS;i++)
+    oggpack_reset(vbi->packetblob[i]);
   
   /* we only have one mapping type (0), and we let the mapping code
      itself figure out what soft mode to use.  This allows easier

<p><p>1.15      +3 -2      vorbis/lib/backends.h

Index: backends.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/backends.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -r1.14 -r1.15
--- backends.h	11 Jul 2002 06:40:48 -0000	1.14
+++ backends.h	30 Dec 2003 11:02:22 -0000	1.15
@@ -12,7 +12,7 @@
 
  function: libvorbis backend and mapping structures; needed for 
            static mode headers
- last mod: $Id: backends.h,v 1.14 2002/07/11 06:40:48 xiphmont Exp $
+ last mod: $Id: backends.h,v 1.15 2003/12/30 11:02:22 xiphmont Exp $
 
  ********************************************************************/
 
@@ -94,7 +94,8 @@
   void (*free_look)    (vorbis_look_residue *);
   long **(*class)      (struct vorbis_block *,vorbis_look_residue *,
                         float **,int *,int);
-  int  (*forward)      (struct vorbis_block *,vorbis_look_residue *,
+  int  (*forward)      (oggpack_buffer *,struct vorbis_block *,
+			vorbis_look_residue *,
                         float **,float **,int *,int,long **);
   int  (*inverse)      (struct vorbis_block *,vorbis_look_residue *,
                         float **,int *,int);

<p><p>1.22      +151 -445  vorbis/lib/bitrate.c

Index: bitrate.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/bitrate.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -r1.21 -r1.22
--- bitrate.c	11 Oct 2002 11:14:41 -0000	1.21
+++ bitrate.c	30 Dec 2003 11:02:22 -0000	1.22
@@ -11,11 +11,10 @@
  ********************************************************************
 
  function: bitrate tracking and management
- last mod: $Id: bitrate.c,v 1.21 2002/10/11 11:14:41 xiphmont Exp $
+ last mod: $Id: bitrate.c,v 1.22 2003/12/30 11:02:22 xiphmont Exp $
 
  ********************************************************************/
 
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <math.h>
@@ -26,146 +25,32 @@
 #include "misc.h"
 #include "bitrate.h"
 
-
-static long BINBYTES(bitrate_manager_state *bm,long pos,long bin){
-  int bins=bm->queue_bins;
-  return(bm->queue_binned[pos*bins+bin]);
-}
-
-#define LIMITBYTES(pos,bin) (bm->minmax_binstack[(pos)*bins*2+((bin)+bins)])
-
-static long LACING_ADJUST(long bytes){
-  int addto=bytes/255+1;
-  return(bytes+addto);
-}
-
-static int floater_interpolate(bitrate_manager_state *bm,vorbis_info *vi,
-				  double desired_rate){
-  int bin=rint(bm->avgfloat);
-  double lobitrate,hibitrate;
-
-
-  lobitrate=(double)(bm->avg_binacc[bin]*8)/bm->avg_sampleacc*vi->rate;
-  while(lobitrate>desired_rate && bin>0){
-    bin--;
-    lobitrate=(double)(bm->avg_binacc[bin]*8)/bm->avg_sampleacc*vi->rate;
-  }
-
-  if(bin+1<bm->queue_bins){
-    hibitrate=(double)(bm->avg_binacc[bin+1]*8)/bm->avg_sampleacc*vi->rate;
-    if(fabs(hibitrate-desired_rate) < fabs(lobitrate-desired_rate))bin++;
-  }
-  return(bin);
-}
-
-/* try out a new limit */
-static long limit_sum(bitrate_manager_state *bm,int limit){
-  int i=bm->minmax_stackptr;
-  long acc=bm->minmax_acctotal;
-  long bins=bm->queue_bins;
-  
-  acc-=LIMITBYTES(i,0);
-  acc+=LIMITBYTES(i,limit);
-
-  while(i-->0){
-    if(bm->minmax_limitstack[i]<=limit)break;
-    acc-=LIMITBYTES(i,bm->minmax_limitstack[i]);
-    acc+=LIMITBYTES(i,limit);
-  }
-  return(acc);
-}
-
 /* compute bitrate tracking setup, allocate circular packet size queue */
 void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){
-  int i;
   codec_setup_info *ci=vi->codec_setup;
   bitrate_manager_info *bi=&ci->bi;
-  long maxlatency;
 
   memset(bm,0,sizeof(*bm));
   
-  if(bi){
-    
-    bm->avg_sampledesired=bi->queue_avg_time*vi->rate;
-    bm->avg_centerdesired=bi->queue_avg_time*vi->rate*bi->queue_avg_center;
-    bm->minmax_sampledesired=bi->queue_minmax_time*vi->rate;
-    
-    /* first find the max possible needed queue size */
-    maxlatency=max(bm->avg_sampledesired-bm->avg_centerdesired,
-		   bm->minmax_sampledesired)+bm->avg_centerdesired;
+  if(bi && (bi->reservoir_bits>0)){
+    long ratesamples=vi->rate;
+    int  halfsamples=ci->blocksizes[0]>>1;
+
+    bm->short_per_long=ci->blocksizes[1]/ci->blocksizes[0];
+    bm->managed=1;
+
+    bm->avg_bitsper= rint(1.*bi->avg_rate*halfsamples/ratesamples);
+    bm->min_bitsper= rint(1.*bi->min_rate*halfsamples/ratesamples);
+    bm->max_bitsper= rint(1.*bi->max_rate*halfsamples/ratesamples);
     
-    if(maxlatency>0 &&
-       (bi->queue_avgmin>0 || bi->queue_avgmax>0 || bi->queue_hardmax>0 ||
-	bi->queue_hardmin>0)){
-      long maxpackets=maxlatency/(ci->blocksizes[0]>>1)+3;
-      long bins=PACKETBLOBS;
-      
-      bm->queue_size=maxpackets;
-      bm->queue_bins=bins;
-      bm->queue_binned=_ogg_calloc(maxpackets,bins*sizeof(*bm->queue_binned));
-      bm->queue_actual=_ogg_calloc(maxpackets,sizeof(*bm->queue_actual));
-      
-      if((bi->queue_avgmin>0 || bi->queue_avgmax>0) &&
-	 bi->queue_avg_time>0){
-	
-	bm->avg_binacc=_ogg_calloc(bins,sizeof(*bm->avg_binacc));
-	bm->avgfloat=PACKETBLOBS/2;
-	
-      }else{
-	bm->avg_tail= -1;
-      }
-      
-      if((bi->queue_hardmin>0 || bi->queue_hardmax>0) &&
-	 bi->queue_minmax_time>0){
-	
-	bm->minmax_binstack=_ogg_calloc((bins*2+1)*bins*2,
-					sizeof(*bm->minmax_binstack));
-	bm->minmax_posstack=_ogg_calloc((bins*2+1),
-				      sizeof(*bm->minmax_posstack));
-	bm->minmax_limitstack=_ogg_calloc((bins*2+1),
-					  sizeof(*bm->minmax_limitstack));
-      }else{
-	bm->minmax_tail= -1;
-      }
-      
-      /* space for the packet queueing */
-      bm->packetbuffers=_ogg_calloc(maxpackets,sizeof(*bm->packetbuffers));
-      bm->packets=_ogg_calloc(maxpackets,sizeof(*bm->packets));
-      for(i=0;i<maxpackets;i++)
-	oggpack_writeinit(bm->packetbuffers+i);
-      
-    }else{
-      bm->packetbuffers=_ogg_calloc(1,sizeof(*bm->packetbuffers));
-      bm->packets=_ogg_calloc(1,sizeof(*bm->packets));
-      oggpack_writeinit(bm->packetbuffers);
+    bm->avgfloat=PACKETBLOBS/2;    
 
-    }      
-  }
+  }    
 }
 
 void vorbis_bitrate_clear(bitrate_manager_state *bm){
-  int i;
-  if(bm){
-    if(bm->queue_binned)_ogg_free(bm->queue_binned);
-    if(bm->queue_actual)_ogg_free(bm->queue_actual);
-    if(bm->avg_binacc)_ogg_free(bm->avg_binacc);
-    if(bm->minmax_binstack)_ogg_free(bm->minmax_binstack);
-    if(bm->minmax_posstack)_ogg_free(bm->minmax_posstack);
-    if(bm->minmax_limitstack)_ogg_free(bm->minmax_limitstack);
-
-    if(bm->packetbuffers){
-      if(bm->queue_size==0){
-	oggpack_writeclear(bm->packetbuffers);
-      }else{
-	for(i=0;i<bm->queue_size;i++)
-	  oggpack_writeclear(bm->packetbuffers+i);	
-      }
-      _ogg_free(bm->packetbuffers);
-    }
-    if(bm->packets)_ogg_free(bm->packets);
-    
-    memset(bm,0,sizeof(*bm));
-  }
+  memset(bm,0,sizeof(*bm));
+  return;
 }
 
 int vorbis_bitrate_managed(vorbis_block *vb){
@@ -173,13 +58,12 @@
   private_state         *b=vd->backend_state; 
   bitrate_manager_state *bm=&b->bms;
 
-  if(bm->queue_binned)return(1);
+  if(bm && bm->managed)return(1);
   return(0);
 }
 
 /* finish taking in the block we just processed */
 int vorbis_bitrate_addblock(vorbis_block *vb){
-  int i; 
   vorbis_block_internal *vbi=vb->internal;
   vorbis_dsp_state      *vd=vb->vd;
   private_state         *b=vd->backend_state; 
@@ -187,345 +71,167 @@
   vorbis_info           *vi=vd->vi;
   codec_setup_info      *ci=vi->codec_setup;
   bitrate_manager_info  *bi=&ci->bi;
-  int                    eofflag=vb->eofflag;
-  int                    head=bm->queue_head;
-  int                    next_head=head+1;
-  int                    bins=bm->queue_bins;
-  int                    minmax_head,new_minmax_head;
-  
-  ogg_uint32_t           *head_ptr;
-  oggpack_buffer          temp;
 
-  if(!bm->queue_binned){
-    oggpack_buffer temp;
+  int  choice=rint(bm->avgfloat);
+  long this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
+  long min_target_bits=(vb->W?bm->min_bitsper*bm->short_per_long:bm->min_bitsper);
+  long max_target_bits=(vb->W?bm->max_bitsper*bm->short_per_long:bm->max_bitsper);
+  int  samples=ci->blocksizes[vb->W]>>1;
+  long desired_fill=bi->reservoir_bits*bi->reservoir_bias;
+  if(!bm->managed){
     /* not a bitrate managed stream, but for API simplicity, we'll
        buffer one packet to keep the code path clean */
     
-    if(bm->queue_head)return(-1); /* one has been submitted without
-                                     being claimed */
-    bm->queue_head++;
-
-    bm->packets[0].packet=oggpack_get_buffer(&vb->opb);
-    bm->packets[0].bytes=oggpack_bytes(&vb->opb);
-    bm->packets[0].b_o_s=0;
-    bm->packets[0].e_o_s=vb->eofflag;
-    bm->packets[0].granulepos=vb->granulepos;
-    bm->packets[0].packetno=vb->sequence; /* for sake of completeness */
-
-    memcpy(&temp,bm->packetbuffers,sizeof(vb->opb));
-    memcpy(bm->packetbuffers,&vb->opb,sizeof(vb->opb));
-    memcpy(&vb->opb,&temp,sizeof(vb->opb));
-
+    if(bm->vb)return(-1); /* one has been submitted without
+			     being claimed */
+    bm->vb=vb;
     return(0);
   }
 
-  /* add encoded packet to head */
-  if(next_head>=bm->queue_size)next_head=0;
-  head_ptr=bm->queue_binned+bins*head;
-
-  /* is there room to add a block? In proper use of the API, this will
-     never come up... but guard it anyway */
-  if(next_head==bm->avg_tail || next_head==bm->minmax_tail)return(-1);
-
-  /* add the block to the toplevel queue */
-  bm->queue_head=next_head;
-  bm->queue_actual[head]=(vb->W?0x80000000UL:0);
-
-  /* buffer packet fields */
-  bm->packets[head].packet=oggpack_get_buffer(&vb->opb);
-  bm->packets[head].bytes=oggpack_bytes(&vb->opb);
-  bm->packets[head].b_o_s=0;
-  bm->packets[head].e_o_s=vb->eofflag;
-  bm->packets[head].granulepos=vb->granulepos;
-  bm->packets[head].packetno=vb->sequence; /* for sake of completeness */
-
-  /* swap packet buffers */
-  memcpy(&temp,bm->packetbuffers+head,sizeof(vb->opb));
-  memcpy(bm->packetbuffers+head,&vb->opb,sizeof(vb->opb));
-  memcpy(&vb->opb,&temp,sizeof(vb->opb));
-
-  /* save markers */
-  head_ptr[0]=vbi->packetblob_markers[0];
-  for(i=1;i<PACKETBLOBS;i++){
-    head_ptr[i]=vbi->packetblob_markers[i]-vbi->packetblob_markers[i-1];
+  bm->vb=vb;
+  
+  /* look ahead for avg floater */
+  if(bm->avg_bitsper>0){
+    double slew=0.;
+    long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper);
+    double slewlimit= 15./bi->slew_damp;
+
+    /* choosing a new floater:
+       if we're over target, we slew down
+       if we're under target, we slew up
+
+       choose slew as follows: look through packetblobs of this frame
+       and set slew as the first in the appropriate direction that
+       gives us the slew we want.  This may mean no slew if delta is
+       already favorable.
+
+       Then limit slew to slew max */
+
+    if(bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){
+      while(choice>0 && this_bits>avg_target_bits &&
+	    bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){
+	choice--;
+	this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
+      }
+    }else if(bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){
+      while(choice+1<PACKETBLOBS && this_bits<avg_target_bits &&
+	    bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){
+	choice++;
+	this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
+      }
+    }
+
+    slew=rint(choice-bm->avgfloat)/samples*vi->rate;
+    if(slew<-slewlimit)slew=-slewlimit;
+    if(slew>slewlimit)slew=slewlimit;
+    choice=rint(bm->avgfloat+= slew/vi->rate*samples);
+    this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
   }
 
-  if(bm->avg_binacc)
-    new_minmax_head=minmax_head=bm->avg_center;
-  else
-    new_minmax_head=minmax_head=head;
-
-  /* the average tracking queue is updated first; its results (if it's
-     in use) are taken into account by the min/max limiter (if min/max
-     is in use) */
-  if(bm->avg_binacc){
-    unsigned long desired_center=bm->avg_centerdesired;
-    if(eofflag)desired_center=0;
-
-    /* update the avg head */
-    for(i=0;i<bins;i++)
-      bm->avg_binacc[i]+=LACING_ADJUST(head_ptr[i]);
-    bm->avg_sampleacc+=ci->blocksizes[vb->W]>>1;
-    bm->avg_centeracc+=ci->blocksizes[vb->W]>>1;
-
-    if(bm->avg_sampleacc>bm->avg_sampledesired || eofflag){
-
-      /* update the avg center */
-      if(bm->avg_centeracc>desired_center){
-	/* choose the new average floater */
-	int samples=ci->blocksizes[vb->W]>>1;
-	double upper=floater_interpolate(bm,vi,bi->queue_avgmax);
-	double lower=floater_interpolate(bm,vi,bi->queue_avgmin);
-	double new=PACKETBLOBS/2.,slew;
-	int bin;
-	
-	if(upper<new)new=upper;
-	if(lower>new)new=lower;
-	
-	slew=(new-bm->avgfloat)/samples*vi->rate;
-	
-	if(slew<bi->avgfloat_downslew_max)
-	  new=bm->avgfloat+bi->avgfloat_downslew_max/vi->rate*samples;
-	if(slew>bi->avgfloat_upslew_max)
-	  new=bm->avgfloat+bi->avgfloat_upslew_max/vi->rate*samples;
-	
-	bm->avgfloat=new;
-	/* apply the average floater to new blocks */
-	bin=rint(bm->avgfloat);
-
-	/*fprintf(stderr,"%d ",bin);*/
-	
-	while(bm->avg_centeracc>desired_center){
-	  samples=ci->blocksizes[bm->queue_actual[bm->avg_center]&
-				0x80000000UL?1:0]>>1;
-	  
-	  bm->queue_actual[bm->avg_center]|=bin;
-	  
-	  bm->avg_centeracc-=samples;
-	  bm->avg_center++;
-	  if(bm->avg_center>=bm->queue_size)bm->avg_center=0;
-	}
-	new_minmax_head=bm->avg_center;
-	
-      }
-      
-      /* update the avg tail if needed */
-      while(bm->avg_sampleacc>bm->avg_sampledesired){
-	int samples=
-	  ci->blocksizes[bm->queue_actual[bm->avg_tail]&0x80000000UL?1:0]>>1;
-	for(i=0;i<bm->queue_bins;i++)
-	  bm->avg_binacc[i]-=LACING_ADJUST(bm->queue_binned[bins*bm->avg_tail+i]);
-	bm->avg_sampleacc-=samples;
-	bm->avg_tail++;
-	if(bm->avg_tail>=bm->queue_size)bm->avg_tail=0;
+
+
+  /* enforce min(if used) on the current floater (if used) */
+  if(bm->min_bitsper>0){
+    /* do we need to force the bitrate up? */
+    if(this_bits<min_target_bits){
+      while(bm->minmax_reservoir-(min_target_bits-this_bits)<0){
+	choice++;
+	if(choice>=PACKETBLOBS)break;
+	this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
       }
-      
-      
     }
-  }else{
-    /* if we're not using an average tracker, the 'float' is nailed to
-       the avgfloat_initial value.  It needs to be set for the min/max
-       to deal properly */
-    long bin=PACKETBLOBS/2;
-    bm->queue_actual[head]|=bin;
-    new_minmax_head=next_head;
-  }	
+  }
   
-  /* update the min/max queues and enforce limits */
-  if(bm->minmax_binstack){
-    unsigned long sampledesired=eofflag?0:bm->minmax_sampledesired;
-    
-    /* add to stack recent */
-    while(minmax_head!=new_minmax_head){
-      unsigned int i;
-      int samples=ci->blocksizes[bm->queue_actual[minmax_head]&
-				0x80000000UL?1:0]>>1;
-      int actual=bm->queue_actual[minmax_head]&0x7fffffffUL;
-
-      for(i=0;i<(unsigned int)bins;i++){
-	bm->minmax_binstack[bm->minmax_stackptr*bins*2+bins+i]+=
-	  LACING_ADJUST(BINBYTES(bm,minmax_head,
-				actual>i?actual:i));
-	
-	bm->minmax_binstack[bm->minmax_stackptr*bins*2+i]+=
-	  LACING_ADJUST(BINBYTES(bm,minmax_head,
-				actual<i?actual:i));
+  /* enforce max (if used) on the current floater (if used) */
+  if(bm->max_bitsper>0){
+    /* do we need to force the bitrate down? */
+    if(this_bits>max_target_bits){
+      while(bm->minmax_reservoir+(this_bits-max_target_bits)>bi->reservoir_bits){
+	choice--;
+	if(choice<0)break;
+	this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
       }
-      
-      bm->minmax_posstack[bm->minmax_stackptr]=minmax_head; /* not one
-							       past
-							       like
-							       typical */
-      bm->minmax_limitstack[bm->minmax_stackptr]=0;
-      bm->minmax_sampleacc+=samples;
-      bm->minmax_acctotal+=
-	LACING_ADJUST(BINBYTES(bm,minmax_head,actual));
-      
-      minmax_head++;
-      if(minmax_head>=bm->queue_size)minmax_head=0;
+    }
+  }
 
+  /* Choice of packetblobs now made based on floater, and min/max
+     requirements. Now boundary check extreme choices */
 
+  if(choice>=PACKETBLOBS){
+    /* choosing a larger packetblob is insufficient to prop up bitrate.
+       pad this frame out with zeroes */
+    long minsize=(min_target_bits-bm->minmax_reservoir+7)/8;
+    bm->choice=choice=PACKETBLOBS-1;
+
+    minsize-=oggpack_bytes(vbi->packetblob[choice]);
+
+    while(minsize--)oggpack_write(vbi->packetblob[choice],0,8);
+    this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
+
+  }else if(choice<0){
+    /* choosing a smaller packetblob is insufficient to trim bitrate.
+       frame will need to be truncated */
+    long maxsize=(max_target_bits+(bi->reservoir_bits-bm->minmax_reservoir))/8;
+    bm->choice=choice=0;
+
+    if(oggpack_bytes(vbi->packetblob[choice])>maxsize){
+
+      oggpack_writetrunc(vbi->packetblob[choice],maxsize*8);
+      this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
     }
-    
-    /* check limits, enforce changes */
-    if(bm->minmax_sampleacc>sampledesired){
-      double bitrate=(double)(bm->minmax_acctotal*8)/
-	bm->minmax_sampleacc*vi->rate;
-      int limit=0;
-      
-      if((bi->queue_hardmax>0 && bitrate>bi->queue_hardmax) || 
-	 (bi->queue_hardmin>0 && bitrate<bi->queue_hardmin)){
-	int newstack;
-	int stackctr;
-	long bitsum=bm->minmax_acctotal*8;
-
-	bitrate=(double)bitsum/bm->minmax_sampleacc*vi->rate;
-
-	/* we're off rate.  Iteratively try out new hard floater
-           limits until we find one that brings us inside.  Here's
-           where we see the whole point of the limit stacks.  */
-	if(bi->queue_hardmax>0 && bitrate>bi->queue_hardmax){
-	  for(limit=-1;limit>-bins+1;limit--){
-	    long bitsum=limit_sum(bm,limit)*8;
-	    bitrate=(double)bitsum/bm->minmax_sampleacc*vi->rate;
-	    if(bitrate<=bi->queue_hardmax)break;
-	  }
-	}else if(bitrate<bi->queue_hardmin){
-	  for(limit=1;limit<bins-1;limit++){
-	    long bitsum=limit_sum(bm,limit)*8;
-	    bitrate=(double)bitsum/bm->minmax_sampleacc*vi->rate;
-	    if(bitrate>=bi->queue_hardmin)break;
-	  }
-	  if(bitrate>bi->queue_hardmax)limit--;
-	}
-
-	/* trace the limit backward, stop when we see a lower limit */
-	newstack=bm->minmax_stackptr-1;
-	while(newstack>=0){
-	  if(bm->minmax_limitstack[newstack]<limit)break;
-	  newstack--;
-	}
-	
-	/* update bit counter with new limit and replace any stack
-           limits that have been replaced by our new lower limit */
-	stackctr=bm->minmax_stackptr;
-	while(stackctr>newstack){
-	  bm->minmax_acctotal-=
-	    LIMITBYTES(stackctr,bm->minmax_limitstack[stackctr]);
-	  bm->minmax_acctotal+=LIMITBYTES(stackctr,limit);
-	  
-	  if(stackctr<bm->minmax_stackptr)
-	    for(i=0;i<bins*2;i++)
-	      bm->minmax_binstack[stackctr*bins*2+i]+=
-		bm->minmax_binstack[(stackctr+1)*bins*2+i];
-
-	  stackctr--;
-	}
-	stackctr++;
-	bm->minmax_posstack[stackctr]=bm->minmax_posstack[bm->minmax_stackptr];
-	bm->minmax_limitstack[stackctr]=limit;
-
-	/* set up new blank stack entry */
-	stackctr++;
-	bm->minmax_stackptr=stackctr;
-	memset(&bm->minmax_binstack[stackctr*bins*2],
-	       0,
-	       sizeof(*bm->minmax_binstack)*bins*2);
-	bm->minmax_limitstack[stackctr]=0;
-	bm->minmax_posstack[stackctr]=-1;
-	
-      }
-    }
-    
-    /* remove from tail */
-    while(bm->minmax_sampleacc>sampledesired){
-      int samples=
-	ci->blocksizes[bm->queue_actual[bm->minmax_tail]&0x80000000UL?1:0]>>1;
-      int actual=bm->queue_actual[bm->minmax_tail]&0x7fffffffUL;
-
-      for(i=0;i<bins;i++){
-	bm->minmax_binstack[bins+i]-= /* always comes off the stack bottom */
-	  LACING_ADJUST(BINBYTES(bm,bm->minmax_tail,
-				actual>i?
-				actual:i));
-	bm->minmax_binstack[i]-= 
-	  LACING_ADJUST(BINBYTES(bm,bm->minmax_tail,
-				actual<i?
-				actual:i));
-      }
+  }else
+    bm->choice=choice;
 
-      if(bm->minmax_limitstack[0]>actual)
-	actual=bm->minmax_limitstack[0];
-      if(bins+bm->minmax_limitstack[0]<actual)
-	actual=bins+bm->minmax_limitstack[0];
-      
-      bm->minmax_acctotal-=LACING_ADJUST(BINBYTES(bm,bm->minmax_tail,actual));
-      bm->minmax_sampleacc-=samples;
-
-      /* revise queue_actual to reflect the limit */
-      bm->queue_actual[bm->minmax_tail]&=0x80000000UL;
-      bm->queue_actual[bm->minmax_tail]|=actual;
-      
-      if(bm->minmax_tail==bm->minmax_posstack[0]){
-	/* the stack becomes a FIFO; the first data has fallen off */
-	memmove(bm->minmax_binstack,bm->minmax_binstack+bins*2,
-		sizeof(*bm->minmax_binstack)*bins*2*bm->minmax_stackptr);
-	memmove(bm->minmax_posstack,bm->minmax_posstack+1,
-		sizeof(*bm->minmax_posstack)*bm->minmax_stackptr);
-	memmove(bm->minmax_limitstack,bm->minmax_limitstack+1,
-		sizeof(*bm->minmax_limitstack)*bm->minmax_stackptr);
-	bm->minmax_stackptr--;
-      }
-      
-      bm->minmax_tail++;
-      if(bm->minmax_tail>=bm->queue_size)bm->minmax_tail=0;
+  /* now we have the final packet and the final packet size.  Update statistics */
+  /* min and max reservoir */
+  if(bm->min_bitsper>0 || bm->max_bitsper>0){
 
+    if(max_target_bits>0 && this_bits>max_target_bits){
+      bm->minmax_reservoir+=(this_bits-max_target_bits);
+    }else if(min_target_bits>0 && this_bits<min_target_bits){
+      bm->minmax_reservoir+=(this_bits-min_target_bits);
+    }else{
+      /* inbetween; we want to take reservoir toward but not past desired_fill */
+      if(bm->minmax_reservoir>desired_fill){
+	bm->minmax_reservoir+=(this_bits-max_target_bits);
+	if(bm->minmax_reservoir<desired_fill)bm->minmax_reservoir=desired_fill;
+      }else{
+	bm->minmax_reservoir+=(this_bits-min_target_bits);
+	if(bm->minmax_reservoir>desired_fill)bm->minmax_reservoir=desired_fill;
+      }
     }
-    
-    
-    bm->last_to_flush=bm->minmax_tail;
-  }else{
-    bm->last_to_flush=bm->avg_center;
   }
-  if(eofflag)
-    bm->last_to_flush=bm->queue_head;
+
+  /* avg reservoir */
+  if(bm->avg_bitsper>0){
+    long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper);    
+    bm->avg_reservoir+=this_bits-avg_target_bits;
+  }
+
   return(0);
 }
 
 int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,ogg_packet *op){
   private_state         *b=vd->backend_state;
   bitrate_manager_state *bm=&b->bms;
-
-  if(bm->queue_size==0){
-    if(bm->queue_head==0)return(0);
-
-    memcpy(op,bm->packets,sizeof(*op));
-    bm->queue_head=0;
-
-  }else{
-
-    if(bm->next_to_flush==bm->last_to_flush)return(0);
-
-    {
-      long bin=bm->queue_actual[bm->next_to_flush]&0x7fffffff,i;
-      long bins=bm->queue_bins;
-      ogg_uint32_t *markers=bm->queue_binned+bins*bm->next_to_flush;
-      long bytes=markers[bin];
-
-      memcpy(op,bm->packets+bm->next_to_flush,sizeof(*op));
-
-      /* we have [PACKETBLOBS] possible packets all squished together in
-	 the buffer, in sequence.  count in to number [bin] */
-      for(i=0;i<bin;i++)
-	op->packet+=markers[i];
-      op->bytes=bytes;
-	
-    }
-
-    bm->next_to_flush++;
-    if(bm->next_to_flush>=bm->queue_size)bm->next_to_flush=0;
-
+  vorbis_block          *vb=bm->vb;
+  int                    choice=PACKETBLOBS/2;
+  if(!vb)return 0;
+
+  if(op){
+    vorbis_block_internal *vbi=vb->internal;
+    
+    if(vorbis_bitrate_managed(vb))
+      choice=bm->choice;
+    
+    op->packet=oggpack_get_buffer(vbi->packetblob[choice]);
+    op->bytes=oggpack_bytes(vbi->packetblob[choice]);
+    op->b_o_s=0;
+    op->e_o_s=vb->eofflag;
+    op->granulepos=vb->granulepos;
+    op->packetno=vb->sequence; /* for sake of completeness */
   }
-
+  
+  bm->vb=0;
   return(1);
 }

<p><p>1.8       +18 -43    vorbis/lib/bitrate.h

Index: bitrate.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/bitrate.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- bitrate.h	11 Jul 2002 06:40:48 -0000	1.7
+++ bitrate.h	30 Dec 2003 11:02:22 -0000	1.8
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: bitrate tracking and management
- last mod: $Id: bitrate.h,v 1.7 2002/07/11 06:40:48 xiphmont Exp $
+ last mod: $Id: bitrate.h,v 1.8 2003/12/30 11:02:22 xiphmont Exp $
 
  ********************************************************************/
 
@@ -24,54 +24,29 @@
 
 /* encode side bitrate tracking */
 typedef struct bitrate_manager_state {
-  ogg_uint32_t  *queue_binned;
-  ogg_uint32_t  *queue_actual;
-  int            queue_size;
-
-  int            queue_head;
-  int            queue_bins;
-
-  long          *avg_binacc;
-  int            avg_center;
-  int            avg_tail;
-  ogg_uint32_t   avg_centeracc;
-  ogg_uint32_t   avg_sampleacc;
-  ogg_uint32_t   avg_sampledesired;
-  ogg_uint32_t   avg_centerdesired;
-
-  long          *minmax_binstack;
-  long          *minmax_posstack;
-  long          *minmax_limitstack;
-  long           minmax_stackptr;
-
-  long           minmax_acctotal;
-  int            minmax_tail;
-  ogg_uint32_t   minmax_sampleacc;
-  ogg_uint32_t   minmax_sampledesired;
-
-  int            next_to_flush;
-  int            last_to_flush;
-  
-  double         avgfloat;
+  int            managed;
+
+  long           avg_reservoir;
+  long           minmax_reservoir;
+  long           avg_bitsper;
+  long           min_bitsper;
+  long           max_bitsper;
 
-  /* unfortunately, we need to hold queued packet data somewhere */
-  oggpack_buffer *packetbuffers;
-  ogg_packet     *packets;
+  long           short_per_long;
+  double         avgfloat;
 
+  vorbis_block  *vb;
+  int            choice;
 } bitrate_manager_state;
 
 typedef struct bitrate_manager_info{
-  /* detailed bitrate management setup */
-  double queue_avg_time;
-  double queue_avg_center;
-  double queue_minmax_time;
-  double queue_hardmin;
-  double queue_hardmax;
-  double queue_avgmin;
-  double queue_avgmax;
+  long           avg_rate;
+  long           min_rate;
+  long           max_rate;
+  long           reservoir_bits;
+  double         reservoir_bias;
 
-  double avgfloat_downslew_max;
-  double avgfloat_upslew_max;
+  double         slew_damp;
 
 } bitrate_manager_info;
 

<p><p>1.76      +22 -8     vorbis/lib/block.c

Index: block.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/block.c,v
retrieving revision 1.75
retrieving revision 1.76
diff -u -r1.75 -r1.76
--- block.c	2 Sep 2003 04:39:26 -0000	1.75
+++ block.c	30 Dec 2003 11:02:22 -0000	1.76
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: PCM data vector blocking, windowing and dis/reassembly
- last mod: $Id: block.c,v 1.75 2003/09/02 04:39:26 xiphmont Exp $
+ last mod: $Id: block.c,v 1.76 2003/12/30 11:02:22 xiphmont Exp $
 
  Handle windowing, overlap-add, etc of the PCM vectors.  This is made
  more amusing by Vorbis' current two allowed block sizes.
@@ -86,6 +86,7 @@
 #endif
 
 int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
+  int i;
   memset(vb,0,sizeof(*vb));
   vb->vd=v;
   vb->localalloc=0;
@@ -93,8 +94,17 @@
   if(v->analysisp){
     vorbis_block_internal *vbi=
       vb->internal=_ogg_calloc(1,sizeof(vorbis_block_internal));
-    oggpack_writeinit(&vb->opb);
     vbi->ampmax=-9999;
+
+    for(i=0;i<PACKETBLOBS;i++){
+      if(i==PACKETBLOBS/2){
+	vbi->packetblob[i]=&vb->opb;
+      }else{
+	vbi->packetblob[i]=
+	  _ogg_calloc(1,sizeof(oggpack_buffer));
+      }
+      oggpack_writeinit(vbi->packetblob[i]);
+    }    
   }
   
   return(0);
@@ -147,15 +157,19 @@
 }
 
 int vorbis_block_clear(vorbis_block *vb){
-  if(vb->vd)
-    if(vb->vd->analysisp)
-      oggpack_writeclear(&vb->opb);
+  int i;
+  vorbis_block_internal *vbi=vb->internal;
+
   _vorbis_block_ripcord(vb);
   if(vb->localstore)_ogg_free(vb->localstore);
 
-  if(vb->internal)
-    _ogg_free(vb->internal);
-
+  if(vbi){
+    for(i=0;i<PACKETBLOBS;i++){
+      oggpack_writeclear(vbi->packetblob[i]);
+      if(i!=PACKETBLOBS/2)_ogg_free(vbi->packetblob[i]);
+    }
+    _ogg_free(vbi);
+  }
   memset(vb,0,sizeof(*vb));
   return(0);
 }

<p><p>1.18      +5 -2      vorbis/lib/codec_internal.h

Index: codec_internal.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/codec_internal.h,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- codec_internal.h	18 Aug 2003 05:34:01 -0000	1.17
+++ codec_internal.h	30 Dec 2003 11:02:22 -0000	1.18
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: libvorbis codec headers
- last mod: $Id: codec_internal.h,v 1.17 2003/08/18 05:34:01 xiphmont Exp $
+ last mod: $Id: codec_internal.h,v 1.18 2003/12/30 11:02:22 xiphmont Exp $
 
  ********************************************************************/
 
@@ -33,7 +33,10 @@
   float  ampmax;
   int    blocktype;
 
-  ogg_uint32_t   packetblob_markers[PACKETBLOBS];
+  oggpack_buffer *packetblob[PACKETBLOBS]; /* initialized, must be freed; 
+					      blob [PACKETBLOBS/2] points to
+					      the oggpack_buffer in the 
+					      main vorbis_block */
 } vorbis_block_internal;
 
 typedef void vorbis_look_floor;

<p><p>1.27      +9 -8      vorbis/lib/floor1.c

Index: floor1.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/floor1.c,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -r1.26 -r1.27
--- floor1.c	15 Feb 2003 07:10:07 -0000	1.26
+++ floor1.c	30 Dec 2003 11:02:22 -0000	1.27
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: floor backend 1 implementation
- last mod: $Id: floor1.c,v 1.26 2003/02/15 07:10:07 xiphmont Exp $
+ last mod: $Id: floor1.c,v 1.27 2003/12/30 11:02:22 xiphmont Exp $
 
  ********************************************************************/
 
@@ -757,7 +757,8 @@
 }
 
 
-int floor1_encode(vorbis_block *vb,vorbis_look_floor1 *look,
+int floor1_encode(oggpack_buffer *opb,vorbis_block *vb,
+		  vorbis_look_floor1 *look,
                   int *post,int *ilogmask){
 
   long i,j;
@@ -840,13 +841,13 @@
     
     /* we have everything we need. pack it out */
     /* mark nontrivial floor */
-    oggpack_write(&vb->opb,1,1);
+    oggpack_write(opb,1,1);
       
     /* beginning/end post */
     look->frames++;
     look->postbits+=ilog(look->quant_q-1)*2;
-    oggpack_write(&vb->opb,out[0],ilog(look->quant_q-1));
-    oggpack_write(&vb->opb,out[1],ilog(look->quant_q-1));
+    oggpack_write(opb,out[0],ilog(look->quant_q-1));
+    oggpack_write(opb,out[1],ilog(look->quant_q-1));
       
       
     /* partition by partition */
@@ -884,7 +885,7 @@
         }
         /* write it */
         look->phrasebits+=
-	  vorbis_book_encode(books+info->class_book[class],cval,&vb->opb);
+	  vorbis_book_encode(books+info->class_book[class],cval,opb);
         
 #ifdef TRAIN_FLOOR1
         {
@@ -906,7 +907,7 @@
           /* hack to allow training with 'bad' books */
           if(out[j+k]<(books+book)->entries)
             look->postbits+=vorbis_book_encode(books+book,
-					       out[j+k],&vb->opb);
+					       out[j+k],opb);
           /*else
             fprintf(stderr,"+!");*/
           
@@ -951,7 +952,7 @@
       return(1);
     }
   }else{
-    oggpack_write(&vb->opb,0,1);
+    oggpack_write(opb,0,1);
     memset(ilogmask,0,vb->pcmend/2*sizeof(*ilogmask));
     seq++;
     return(0);

<p><p>1.5       +5 -6      vorbis/lib/highlevel.h

Index: highlevel.h
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/highlevel.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- highlevel.h	1 Jul 2002 11:20:11 -0000	1.4
+++ highlevel.h	30 Dec 2003 11:02:22 -0000	1.5
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: highlevel encoder setup struct seperated out for vorbisenc clarity
- last mod: $Id: highlevel.h,v 1.4 2002/07/01 11:20:11 xiphmont Exp $
+ last mod: $Id: highlevel.h,v 1.5 2003/12/30 11:02:22 xiphmont Exp $
 
  ********************************************************************/
 
@@ -33,12 +33,11 @@
 
   int    managed;
   long   bitrate_min;
-  long   bitrate_av_lo;
-  long   bitrate_av_hi;
+  long   bitrate_av;
+  double bitrate_av_damp;
   long   bitrate_max;
-  double bitrate_limit_window;
-  double bitrate_av_window;
-  double bitrate_av_window_center;
+  long   bitrate_reservoir;
+  double bitrate_reservoir_bias;
   
   int impulse_block_p;
   int noise_normalize_p;

<p><p>1.63      +2 -2      vorbis/lib/info.c

Index: info.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/info.c,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -r1.62 -r1.63
--- info.c	10 Sep 2003 01:10:18 -0000	1.62
+++ info.c	30 Dec 2003 11:02:22 -0000	1.63
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: maintain the info structure, info <-> header packets
- last mod: $Id: info.c,v 1.62 2003/09/10 01:10:18 xiphmont Exp $
+ last mod: $Id: info.c,v 1.63 2003/12/30 11:02:22 xiphmont Exp $
 
  ********************************************************************/
 
@@ -416,7 +416,7 @@
 }
 
 static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
-  char temp[]="Xiph.Org libVorbis I 20030909";
+  char temp[]="Xiph.Org libVorbis I 20031230";
   int bytes = strlen(temp);
 
   /* preamble */  

<p><p>1.61      +11 -12    vorbis/lib/mapping0.c

Index: mapping0.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/mapping0.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -r1.60 -r1.61
--- mapping0.c	1 Sep 2003 23:05:49 -0000	1.60
+++ mapping0.c	30 Dec 2003 11:02:22 -0000	1.61
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: channel mapping 0 implementation
- last mod: $Id: mapping0.c,v 1.60 2003/09/01 23:05:49 xiphmont Exp $
+ last mod: $Id: mapping0.c,v 1.61 2003/12/30 11:02:22 xiphmont Exp $
 
  ********************************************************************/
 
@@ -235,7 +235,8 @@
 extern int *floor1_interpolate_fit(vorbis_block *vb,vorbis_look_floor *look,
                                    int *A,int *B,
                                    int del);
-extern int floor1_encode(vorbis_block *vb,vorbis_look_floor *look,
+extern int floor1_encode(oggpack_buffer *opb,vorbis_block *vb,
+			 vorbis_look_floor *look,
                          int *post,int *ilogmask);
 
 
@@ -536,16 +537,17 @@
     for(k=(vorbis_bitrate_managed(vb)?0:PACKETBLOBS/2);
         k<=(vorbis_bitrate_managed(vb)?PACKETBLOBS-1:PACKETBLOBS/2);
         k++){
+      oggpack_buffer *opb=vbi->packetblob[k];
 
       /* start out our new packet blob with packet type and mode */
       /* Encode the packet type */
-      oggpack_write(&vb->opb,0,1);
+      oggpack_write(opb,0,1);
       /* Encode the modenumber */
       /* Encode frame mode, pre,post windowsize, then dispatch */
-      oggpack_write(&vb->opb,modenumber,b->modebits);
+      oggpack_write(opb,modenumber,b->modebits);
       if(vb->W){
-	oggpack_write(&vb->opb,vb->lW,1);
-	oggpack_write(&vb->opb,vb->nW,1);
+	oggpack_write(opb,vb->lW,1);
+	oggpack_write(opb,vb->nW,1);
       }
 
       /* encode floor, compute masking curve, sep out residue */
@@ -556,7 +558,7 @@
         int   *ilogmask=ilogmaskch[i]=
           _vorbis_block_alloc(vb,n/2*sizeof(**gmdct));
       
-	nonzero[i]=floor1_encode(vb,b->flr[info->floorsubmap[submap]],
+	nonzero[i]=floor1_encode(opb,vb,b->flr[info->floorsubmap[submap]],
                                  floor_posts[i][k],
                                  ilogmask);
 #if 0
@@ -629,14 +631,11 @@
           class(vb,b->residue[resnum],couple_bundle,zerobundle,ch_in_bundle);
         
         _residue_P[ci->residue_type[resnum]]->
-	  forward(vb,b->residue[resnum],
+	  forward(opb,vb,b->residue[resnum],
                   couple_bundle,NULL,zerobundle,ch_in_bundle,classifications);
       }
       
-      /* ok, done encoding.  Mark this protopacket and prepare next. */
-      oggpack_writealign(&vb->opb);
-      vbi->packetblob_markers[k]=oggpack_bytes(&vb->opb);
-      
+      /* ok, done encoding.  Next protopacket. */
     }
     
   }

<p><p>1.50      +10 -8     vorbis/lib/res0.c

Index: res0.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/res0.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- res0.c	18 Jan 2003 08:28:37 -0000	1.49
+++ res0.c	30 Dec 2003 11:02:22 -0000	1.50
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: residue backend 0, 1 and 2 implementation
- last mod: $Id: res0.c,v 1.49 2003/01/18 08:28:37 xiphmont Exp $
+ last mod: $Id: res0.c,v 1.50 2003/12/30 11:02:22 xiphmont Exp $
 
  ********************************************************************/
 
@@ -487,7 +487,8 @@
   return(partword);
 }
 
-static int _01forward(vorbis_block *vb,vorbis_look_residue *vl,
+static int _01forward(oggpack_buffer *opb,
+		      vorbis_block *vb,vorbis_look_residue *vl,
                       float **in,int ch,
                       long **partword,
                       int (*encode)(oggpack_buffer *,float *,int,
@@ -540,7 +541,7 @@
 
           /* training hack */
           if(val<look->phrasebook->entries)
-	    look->phrasebits+=vorbis_book_encode(look->phrasebook,val,&vb->opb);
+	    look->phrasebits+=vorbis_book_encode(look->phrasebook,val,opb);
 #if 0 /*def TRAIN_RES*/
           else
             fprintf(stderr,"!");
@@ -575,7 +576,7 @@
               }
 #endif
               
-	      ret=encode(&vb->opb,in[j]+offset,samples_per_partition,
+	      ret=encode(opb,in[j]+offset,samples_per_partition,
                          statebook,accumulator);
 
               look->postbits+=ret;
@@ -719,7 +720,7 @@
     return(0);
 }
 
-int res1_forward(vorbis_block *vb,vorbis_look_residue *vl,
+int res1_forward(oggpack_buffer *opb,vorbis_block *vb,vorbis_look_residue *vl,
                  float **in,float **out,int *nonzero,int ch,
                  long **partword){
   int i,j,used=0,n=vb->pcmend/2;
@@ -732,7 +733,7 @@
     }
 
   if(used){
-    int ret=_01forward(vb,vl,in,used,partword,_encodepart);
+    int ret=_01forward(opb,vb,vl,in,used,partword,_encodepart);
     if(out){
       used=0;
       for(i=0;i<ch;i++)
@@ -786,7 +787,8 @@
 /* res2 is slightly more different; all the channels are interleaved
    into a single vector and encoded. */
 
-int res2_forward(vorbis_block *vb,vorbis_look_residue *vl,
+int res2_forward(oggpack_buffer *opb,
+		 vorbis_block *vb,vorbis_look_residue *vl,
                  float **in,float **out,int *nonzero,int ch,
                  long **partword){
   long i,j,k,n=vb->pcmend/2,used=0;
@@ -803,7 +805,7 @@
   }
   
   if(used){
-    int ret=_01forward(vb,vl,&work,1,partword,_encodepart);
+    int ret=_01forward(opb,vb,vl,&work,1,partword,_encodepart);
     /* update the sofar vector */
     if(out){
       for(i=0;i<ch;i++){

<p><p>1.48      +95 -51    vorbis/lib/vorbisenc.c

Index: vorbisenc.c
===================================================================
RCS file: /usr/local/cvsroot/vorbis/lib/vorbisenc.c,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -r1.47 -r1.48
--- vorbisenc.c	11 Jul 2002 06:40:50 -0000	1.47
+++ vorbisenc.c	30 Dec 2003 11:02:22 -0000	1.48
@@ -11,7 +11,7 @@
  ********************************************************************
 
  function: simple programmatic interface for encoder mode setup
- last mod: $Id: vorbisenc.c,v 1.47 2002/07/11 06:40:50 xiphmont Exp $
+ last mod: $Id: vorbisenc.c,v 1.48 2003/12/30 11:02:22 xiphmont Exp $
 
  ********************************************************************/
 
@@ -832,18 +832,19 @@
   vi->bitrate_nominal=setting_to_approx_bitrate(vi);
   vi->bitrate_lower=hi->bitrate_min;
   vi->bitrate_upper=hi->bitrate_max;
-  vi->bitrate_window=hi->bitrate_limit_window;
+  vi->bitrate_window=(double)hi->bitrate_reservoir/vi->rate;
 
   if(hi->managed){
-    ci->bi.queue_avg_time=hi->bitrate_av_window;
-    ci->bi.queue_avg_center=hi->bitrate_av_window_center;
-    ci->bi.queue_minmax_time=hi->bitrate_limit_window;
-    ci->bi.queue_hardmin=hi->bitrate_min;
-    ci->bi.queue_hardmax=hi->bitrate_max;
-    ci->bi.queue_avgmin=hi->bitrate_av_lo;
-    ci->bi.queue_avgmax=hi->bitrate_av_hi;
-    ci->bi.avgfloat_downslew_max=-999999.f;
-    ci->bi.avgfloat_upslew_max=999999.f;
+    ci->bi.avg_rate=hi->bitrate_av;
+    ci->bi.min_rate=hi->bitrate_min;
+    ci->bi.max_rate=hi->bitrate_max;
+
+    ci->bi.reservoir_bits=hi->bitrate_reservoir;
+    ci->bi.reservoir_bias=
+      hi->bitrate_reservoir_bias;
+    
+    ci->bi.slew_damp=hi->bitrate_av_damp;
+
   }
 
   return(0);
@@ -966,15 +967,13 @@
   }
 
   /* initialize management with sane defaults */
-      /* initialize management with sane defaults */
   hi->managed=1;
-  hi->bitrate_av_window=4.;
-  hi->bitrate_av_window_center=.5;
-  hi->bitrate_limit_window=2.;
   hi->bitrate_min=min_bitrate;
   hi->bitrate_max=max_bitrate;
-  hi->bitrate_av_lo=tnominal;
-  hi->bitrate_av_hi=tnominal;
+  hi->bitrate_av=tnominal;
+  hi->bitrate_av_damp=.75f; /* full range in no less than 3/4 second */
+  hi->bitrate_reservoir=tnominal;
+  hi->bitrate_reservoir_bias=.2; /* bias toward hoarding bits */
 
   return(ret);
 
@@ -1010,8 +1009,10 @@
     int setp=(number&0xf); /* a read request has a low nibble of 0 */
 
     if(setp && hi->set_in_stone)return(OV_EINVAL);
-
+    
     switch(number){
+      
+    /* now deprecated *****************/
     case OV_ECTL_RATEMANAGE_GET:
       {
         
@@ -1019,17 +1020,18 @@
           (struct ovectl_ratemanage_arg *)arg;
         
         ai->management_active=hi->managed;
-	ai->bitrate_av_window=hi->bitrate_av_window;
-	ai->bitrate_av_window_center=hi->bitrate_av_window_center;
-	ai->bitrate_hard_window=hi->bitrate_limit_window;
+	ai->bitrate_hard_window=ai->bitrate_av_window=
+	  (double)hi->bitrate_reservoir/vi->rate;
+	ai->bitrate_av_window_center=1.;
         ai->bitrate_hard_min=hi->bitrate_min;
         ai->bitrate_hard_max=hi->bitrate_max;
-	ai->bitrate_av_lo=hi->bitrate_av_lo;
-	ai->bitrate_av_hi=hi->bitrate_av_hi;
+	ai->bitrate_av_lo=hi->bitrate_av;
+	ai->bitrate_av_hi=hi->bitrate_av;
         
       }
       return(0);
     
+    /* now deprecated *****************/
     case OV_ECTL_RATEMANAGE_SET:
       {
         struct ovectl_ratemanage_arg *ai=
@@ -1044,33 +1046,19 @@
       }
       return 0;
 
+    /* now deprecated *****************/
     case OV_ECTL_RATEMANAGE_AVG:
       {
         struct ovectl_ratemanage_arg *ai=
           (struct ovectl_ratemanage_arg *)arg;
         if(ai==NULL){
-	  hi->bitrate_av_lo=0;
-	  hi->bitrate_av_hi=0;
-	  hi->bitrate_av_window=0;
+	  hi->bitrate_av=0;
         }else{
-	  hi->bitrate_av_window=ai->bitrate_av_window;
-	  hi->bitrate_av_window_center=ai->bitrate_av_window_center;
-	  hi->bitrate_av_lo=ai->bitrate_av_lo;
-	  hi->bitrate_av_hi=ai->bitrate_av_hi;
+	  hi->bitrate_av=(ai->bitrate_av_lo+ai->bitrate_av_hi)*.5;
         }
-
-	if(hi->bitrate_av_window<.25)hi->bitrate_av_window=.25;
-	if(hi->bitrate_av_window>10.)hi->bitrate_av_window=10.;
-	if(hi->bitrate_av_window_center<0.)hi->bitrate_av_window=0.;
-	if(hi->bitrate_av_window_center>1.)hi->bitrate_av_window=1.;
-	
-	if( ( (hi->bitrate_av_lo<=0 && hi->bitrate_av_hi<=0)||
-	      (hi->bitrate_av_window<=0) ) &&
-	    ( (hi->bitrate_min<=0 && hi->bitrate_max<=0)||
-	      (hi->bitrate_limit_window<=0) ))
-	  hi->managed=0;
       }
       return(0);
+    /* now deprecated *****************/
     case OV_ECTL_RATEMANAGE_HARD:
       {
         struct ovectl_ratemanage_arg *ai=
@@ -1078,23 +1066,79 @@
         if(ai==NULL){
           hi->bitrate_min=0;
           hi->bitrate_max=0;
-	  hi->bitrate_limit_window=0;
         }else{
-	  hi->bitrate_limit_window=ai->bitrate_hard_window;
           hi->bitrate_min=ai->bitrate_hard_min;
           hi->bitrate_max=ai->bitrate_hard_max;
+	  hi->bitrate_reservoir=ai->bitrate_hard_window*
+	    (hi->bitrate_max+hi->bitrate_min)*.5;
         }
-	if(hi->bitrate_limit_window<0.)hi->bitrate_limit_window=0.;
-	if(hi->bitrate_limit_window>10.)hi->bitrate_limit_window=10.;
+	if(hi->bitrate_reservoir<128.)
+	  hi->bitrate_reservoir=128.;
+      }   
+      return(0);
+
+      /* replacement ratemanage interface */
+    case OV_ECTL_RATEMANAGE2_GET:
+      {
+	struct ovectl_ratemanage2_arg *ai=
+	  (struct ovectl_ratemanage2_arg *)arg;
+	if(ai==NULL)return OV_EINVAL;
         
-	if( ( (hi->bitrate_av_lo<=0 && hi->bitrate_av_hi<=0)||
-	      (hi->bitrate_av_window<=0) ) &&
-	    ( (hi->bitrate_min<=0 && hi->bitrate_max<=0)||
-	      (hi->bitrate_limit_window<=0) ))
-	  hi->managed=0;
+	ai->management_active=hi->managed;
+	ai->bitrate_limit_min_kbps=hi->bitrate_min;
+	ai->bitrate_limit_max_kbps=hi->bitrate_max;
+	ai->bitrate_average_kbps=hi->bitrate_av;
+	ai->bitrate_average_damping=hi->bitrate_av_damp;
+	ai->bitrate_limit_reservoir_bits=hi->bitrate_reservoir;
+	ai->bitrate_limit_reservoir_bias=hi->bitrate_reservoir_bias;
       }
-      return(0);
+      return (0);
+    case OV_ECTL_RATEMANAGE2_SET:
+      {
+	struct ovectl_ratemanage2_arg *ai=
+	  (struct ovectl_ratemanage2_arg *)arg;
+	if(ai==NULL){
+	  hi->managed=0;
+	}else{
+	  /* sanity check; only catch invariant violations */
+	  if(ai->bitrate_limit_min_kbps>0 &&
+	     ai->bitrate_average_kbps>0 &&
+	     ai->bitrate_limit_min_kbps>ai->bitrate_average_kbps)
+	    return OV_EINVAL;
+
+	  if(ai->bitrate_limit_max_kbps>0 &&
+	     ai->bitrate_average_kbps>0 &&
+	     ai->bitrate_limit_max_kbps<ai->bitrate_average_kbps)
+	    return OV_EINVAL;
+
+	  if(ai->bitrate_limit_min_kbps>0 &&
+	     ai->bitrate_limit_max_kbps>0 &&
+	     ai->bitrate_limit_min_kbps>ai->bitrate_limit_max_kbps)
+	    return OV_EINVAL;
+
+	  if(ai->bitrate_average_damping <= 0.)
+	    return OV_EINVAL;
+
+	  if(ai->bitrate_limit_reservoir_bits < 0)
+	    return OV_EINVAL;
+
+	  if(ai->bitrate_limit_reservoir_bias < 0.)
+	    return OV_EINVAL;
 
+	  if(ai->bitrate_limit_reservoir_bias > 1.)
+	    return OV_EINVAL;
+
+	  hi->managed=ai->management_active;
+	  hi->bitrate_min=ai->bitrate_limit_min_kbps;
+	  hi->bitrate_max=ai->bitrate_limit_max_kbps;
+	  hi->bitrate_av=ai->bitrate_average_kbps;
+	  hi->bitrate_av_damp=ai->bitrate_average_damping;
+	  hi->bitrate_reservoir=ai->bitrate_limit_reservoir_bits;
+	  hi->bitrate_reservoir_bias=ai->bitrate_limit_reservoir_bias;
+	}
+      }
+      return 0;
+      
     case OV_ECTL_LOWPASS_GET:
       {
         double *farg=(double *)arg;

<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