examples/SFExamples/oggvorbiscodec/src/libvorbis/lib/bitrate.c

00001 /********************************************************************
00002  *                                                                  *
00003  * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
00004  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
00005  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
00006  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
00007  *                                                                  *
00008  * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002             *
00009  * by the XIPHOPHORUS Company http://www.xiph.org/                  *
00010  *                                                                  *
00011  ********************************************************************
00012 
00013  function: bitrate tracking and management
00014  last mod: $Id: bitrate.c 7497 2004-08-08 04:31:40Z xiphmont $
00015 
00016  ********************************************************************/
00017 
00018 #include <stdlib.h>
00019 #include <string.h>
00020 #include <math.h>
00021 #include "ogg/ogg.h"
00022 #include "vorbis/codec.h"
00023 #include "codec_internal.h"
00024 #include "os.h"
00025 #include "misc.h"
00026 #include "bitrate.h"
00027 
00028 /* compute bitrate tracking setup  */
00029 void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){
00030   codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
00031   bitrate_manager_info *bi=&ci->bi;
00032 
00033   memset(bm,0,sizeof(*bm));
00034   
00035   if(bi && (bi->reservoir_bits>0)){
00036     long ratesamples=vi->rate;
00037     int  halfsamples=ci->blocksizes[0]>>1;
00038 
00039     bm->short_per_long=ci->blocksizes[1]/ci->blocksizes[0];
00040     bm->managed=1;
00041 
00042     bm->avg_bitsper= rint(1.*bi->avg_rate*halfsamples/ratesamples);
00043     bm->min_bitsper= rint(1.*bi->min_rate*halfsamples/ratesamples);
00044     bm->max_bitsper= rint(1.*bi->max_rate*halfsamples/ratesamples);
00045     
00046     bm->avgfloat=PACKETBLOBS/2;    
00047 
00048     /* not a necessary fix, but one that leads to a more balanced
00049        typical initialization */
00050     {
00051       long desired_fill=bi->reservoir_bits*bi->reservoir_bias;
00052       bm->minmax_reservoir=desired_fill;
00053       bm->avg_reservoir=desired_fill;
00054     }
00055 
00056   }    
00057 }
00058 
00059 void vorbis_bitrate_clear(bitrate_manager_state *bm){
00060   memset(bm,0,sizeof(*bm));
00061   return;
00062 }
00063 
00064 int vorbis_bitrate_managed(vorbis_block *vb){
00065   vorbis_dsp_state      *vd=vb->vd;
00066   private_state         *b=(private_state*)vd->backend_state; 
00067   bitrate_manager_state *bm=&b->bms;
00068 
00069   if(bm && bm->managed)return(1);
00070   return(0);
00071 }
00072 
00073 /* finish taking in the block we just processed */
00074 int vorbis_bitrate_addblock(vorbis_block *vb){
00075   vorbis_block_internal *vbi=(vorbis_block_internal*)vb->internal;
00076   vorbis_dsp_state      *vd=vb->vd;
00077   private_state         *b=(private_state*)vd->backend_state; 
00078   bitrate_manager_state *bm=&b->bms;
00079   vorbis_info           *vi=vd->vi;
00080   codec_setup_info      *ci=(codec_setup_info*)vi->codec_setup;
00081   bitrate_manager_info  *bi=&ci->bi;
00082 
00083   int  choice=rint(bm->avgfloat);
00084   long this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
00085   long min_target_bits=(vb->W?bm->min_bitsper*bm->short_per_long:bm->min_bitsper);
00086   long max_target_bits=(vb->W?bm->max_bitsper*bm->short_per_long:bm->max_bitsper);
00087   int  samples=ci->blocksizes[vb->W]>>1;
00088   long desired_fill=bi->reservoir_bits*bi->reservoir_bias;
00089   if(!bm->managed){
00090     /* not a bitrate managed stream, but for API simplicity, we'll
00091        buffer the packet to keep the code path clean */
00092     
00093     if(bm->vb)return(-1); /* one has been submitted without
00094                              being claimed */
00095     bm->vb=vb;
00096     return(0);
00097   }
00098 
00099   bm->vb=vb;
00100   
00101   /* look ahead for avg floater */
00102   if(bm->avg_bitsper>0){
00103     double slew=0.;
00104     long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper);
00105     double slewlimit= 15./bi->slew_damp;
00106 
00107     /* choosing a new floater:
00108        if we're over target, we slew down
00109        if we're under target, we slew up
00110 
00111        choose slew as follows: look through packetblobs of this frame
00112        and set slew as the first in the appropriate direction that
00113        gives us the slew we want.  This may mean no slew if delta is
00114        already favorable.
00115 
00116        Then limit slew to slew max */
00117 
00118     if(bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){
00119       while(choice>0 && this_bits>avg_target_bits &&
00120             bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){
00121         choice--;
00122         this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
00123       }
00124     }else if(bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){
00125       while(choice+1<PACKETBLOBS && this_bits<avg_target_bits &&
00126             bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){
00127         choice++;
00128         this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
00129       }
00130     }
00131 
00132     slew=rint(choice-bm->avgfloat)/samples*vi->rate;
00133     if(slew<-slewlimit)slew=-slewlimit;
00134     if(slew>slewlimit)slew=slewlimit;
00135     choice=rint(bm->avgfloat+= slew/vi->rate*samples);
00136     this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
00137   }
00138 
00139 
00140 
00141   /* enforce min(if used) on the current floater (if used) */
00142   if(bm->min_bitsper>0){
00143     /* do we need to force the bitrate up? */
00144     if(this_bits<min_target_bits){
00145       while(bm->minmax_reservoir-(min_target_bits-this_bits)<0){
00146         choice++;
00147         if(choice>=PACKETBLOBS)break;
00148         this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
00149       }
00150     }
00151   }
00152   
00153   /* enforce max (if used) on the current floater (if used) */
00154   if(bm->max_bitsper>0){
00155     /* do we need to force the bitrate down? */
00156     if(this_bits>max_target_bits){
00157       while(bm->minmax_reservoir+(this_bits-max_target_bits)>bi->reservoir_bits){
00158         choice--;
00159         if(choice<0)break;
00160         this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
00161       }
00162     }
00163   }
00164 
00165   /* Choice of packetblobs now made based on floater, and min/max
00166      requirements. Now boundary check extreme choices */
00167 
00168   if(choice<0){
00169     /* choosing a smaller packetblob is insufficient to trim bitrate.
00170        frame will need to be truncated */
00171     long maxsize=(max_target_bits+(bi->reservoir_bits-bm->minmax_reservoir))/8;
00172     bm->choice=choice=0;
00173     
00174     if(oggpack_bytes(vbi->packetblob[choice])>maxsize){
00175       
00176       oggpack_writetrunc(vbi->packetblob[choice],maxsize*8);
00177       this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
00178     }
00179   }else{
00180     long minsize=(min_target_bits-bm->minmax_reservoir+7)/8;
00181     if(choice>=PACKETBLOBS)
00182       choice=PACKETBLOBS-1;
00183 
00184     bm->choice=choice;
00185 
00186     /* prop up bitrate according to demand. pad this frame out with zeroes */
00187     minsize-=oggpack_bytes(vbi->packetblob[choice]);
00188     while(minsize-->0)oggpack_write(vbi->packetblob[choice],0,8);
00189     this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
00190 
00191   }
00192 
00193   /* now we have the final packet and the final packet size.  Update statistics */
00194   /* min and max reservoir */
00195   if(bm->min_bitsper>0 || bm->max_bitsper>0){
00196 
00197     if(max_target_bits>0 && this_bits>max_target_bits){
00198       bm->minmax_reservoir+=(this_bits-max_target_bits);
00199     }else if(min_target_bits>0 && this_bits<min_target_bits){
00200       bm->minmax_reservoir+=(this_bits-min_target_bits);
00201     }else{
00202       /* inbetween; we want to take reservoir toward but not past desired_fill */
00203       if(bm->minmax_reservoir>desired_fill){
00204         if(max_target_bits>0){ /* logical bulletproofing against initialization state */
00205           bm->minmax_reservoir+=(this_bits-max_target_bits);
00206           if(bm->minmax_reservoir<desired_fill)bm->minmax_reservoir=desired_fill;
00207         }else{
00208           bm->minmax_reservoir=desired_fill;
00209         }
00210       }else{
00211         if(min_target_bits>0){ /* logical bulletproofing against initialization state */
00212           bm->minmax_reservoir+=(this_bits-min_target_bits);
00213           if(bm->minmax_reservoir>desired_fill)bm->minmax_reservoir=desired_fill;
00214         }else{
00215           bm->minmax_reservoir=desired_fill;
00216         }
00217       }
00218     }
00219   }
00220 
00221   /* avg reservoir */
00222   if(bm->avg_bitsper>0){
00223     long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper);    
00224     bm->avg_reservoir+=this_bits-avg_target_bits;
00225   }
00226 
00227   return(0);
00228 }
00229 
00230 int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,ogg_packet *op){
00231   private_state         *b=(private_state*)vd->backend_state;
00232   bitrate_manager_state *bm=&b->bms;
00233   vorbis_block          *vb=bm->vb;
00234   int                    choice=PACKETBLOBS/2;
00235   if(!vb)return 0;
00236 
00237   if(op){
00238     vorbis_block_internal *vbi=(vorbis_block_internal*)vb->internal;
00239     
00240     if(vorbis_bitrate_managed(vb))
00241       choice=bm->choice;
00242 
00243     op->packet=oggpack_get_buffer(vbi->packetblob[choice]);
00244     op->bytes=oggpack_bytes(vbi->packetblob[choice]);
00245     op->b_o_s=0;
00246     op->e_o_s=vb->eofflag;
00247     op->granulepos=vb->granulepos;
00248     op->packetno=vb->sequence; /* for sake of completeness */
00249   }
00250   
00251   bm->vb=0;
00252   return(1);
00253 }

Generated by  doxygen 1.6.2