Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/libvorbis-1.2.0/lib/bitrate.c @ 16

Last change on this file since 16 was 16, checked in by landauf, 17 years ago

added libvorbis

File size: 8.2 KB
Line 
1/********************************************************************
2 *                                                                  *
3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7 *                                                                  *
8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007             *
9 * by the Xiph.Org Foundation http://www.xiph.org/                  *
10 *                                                                  *
11 ********************************************************************
12
13 function: bitrate tracking and management
14 last mod: $Id: bitrate.c 13293 2007-07-24 00:09:47Z xiphmont $
15
16 ********************************************************************/
17
18#include <stdlib.h>
19#include <string.h>
20#include <math.h>
21#include <ogg/ogg.h>
22#include "vorbis/codec.h"
23#include "codec_internal.h"
24#include "os.h"
25#include "misc.h"
26#include "bitrate.h"
27
28/* compute bitrate tracking setup  */
29void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){
30  codec_setup_info *ci=vi->codec_setup;
31  bitrate_manager_info *bi=&ci->bi;
32
33  memset(bm,0,sizeof(*bm));
34 
35  if(bi && (bi->reservoir_bits>0)){
36    long ratesamples=vi->rate;
37    int  halfsamples=ci->blocksizes[0]>>1;
38
39    bm->short_per_long=ci->blocksizes[1]/ci->blocksizes[0];
40    bm->managed=1;
41
42    bm->avg_bitsper= rint(1.*bi->avg_rate*halfsamples/ratesamples);
43    bm->min_bitsper= rint(1.*bi->min_rate*halfsamples/ratesamples);
44    bm->max_bitsper= rint(1.*bi->max_rate*halfsamples/ratesamples);
45   
46    bm->avgfloat=PACKETBLOBS/2;   
47
48    /* not a necessary fix, but one that leads to a more balanced
49       typical initialization */
50    {
51      long desired_fill=bi->reservoir_bits*bi->reservoir_bias;
52      bm->minmax_reservoir=desired_fill;
53      bm->avg_reservoir=desired_fill;
54    }
55
56  }   
57}
58
59void vorbis_bitrate_clear(bitrate_manager_state *bm){
60  memset(bm,0,sizeof(*bm));
61  return;
62}
63
64int vorbis_bitrate_managed(vorbis_block *vb){
65  vorbis_dsp_state      *vd=vb->vd;
66  private_state         *b=vd->backend_state; 
67  bitrate_manager_state *bm=&b->bms;
68
69  if(bm && bm->managed)return(1);
70  return(0);
71}
72
73/* finish taking in the block we just processed */
74int vorbis_bitrate_addblock(vorbis_block *vb){
75  vorbis_block_internal *vbi=vb->internal;
76  vorbis_dsp_state      *vd=vb->vd;
77  private_state         *b=vd->backend_state; 
78  bitrate_manager_state *bm=&b->bms;
79  vorbis_info           *vi=vd->vi;
80  codec_setup_info      *ci=vi->codec_setup;
81  bitrate_manager_info  *bi=&ci->bi;
82
83  int  choice=rint(bm->avgfloat);
84  long this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
85  long min_target_bits=(vb->W?bm->min_bitsper*bm->short_per_long:bm->min_bitsper);
86  long max_target_bits=(vb->W?bm->max_bitsper*bm->short_per_long:bm->max_bitsper);
87  int  samples=ci->blocksizes[vb->W]>>1;
88  long desired_fill=bi->reservoir_bits*bi->reservoir_bias;
89  if(!bm->managed){
90    /* not a bitrate managed stream, but for API simplicity, we'll
91       buffer the packet to keep the code path clean */
92   
93    if(bm->vb)return(-1); /* one has been submitted without
94                             being claimed */
95    bm->vb=vb;
96    return(0);
97  }
98
99  bm->vb=vb;
100 
101  /* look ahead for avg floater */
102  if(bm->avg_bitsper>0){
103    double slew=0.;
104    long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper);
105    double slewlimit= 15./bi->slew_damp;
106
107    /* choosing a new floater:
108       if we're over target, we slew down
109       if we're under target, we slew up
110
111       choose slew as follows: look through packetblobs of this frame
112       and set slew as the first in the appropriate direction that
113       gives us the slew we want.  This may mean no slew if delta is
114       already favorable.
115
116       Then limit slew to slew max */
117
118    if(bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){
119      while(choice>0 && this_bits>avg_target_bits &&
120            bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){
121        choice--;
122        this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
123      }
124    }else if(bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){
125      while(choice+1<PACKETBLOBS && this_bits<avg_target_bits &&
126            bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){
127        choice++;
128        this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
129      }
130    }
131
132    slew=rint(choice-bm->avgfloat)/samples*vi->rate;
133    if(slew<-slewlimit)slew=-slewlimit;
134    if(slew>slewlimit)slew=slewlimit;
135    choice=rint(bm->avgfloat+= slew/vi->rate*samples);
136    this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
137  }
138
139
140
141  /* enforce min(if used) on the current floater (if used) */
142  if(bm->min_bitsper>0){
143    /* do we need to force the bitrate up? */
144    if(this_bits<min_target_bits){
145      while(bm->minmax_reservoir-(min_target_bits-this_bits)<0){
146        choice++;
147        if(choice>=PACKETBLOBS)break;
148        this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
149      }
150    }
151  }
152 
153  /* enforce max (if used) on the current floater (if used) */
154  if(bm->max_bitsper>0){
155    /* do we need to force the bitrate down? */
156    if(this_bits>max_target_bits){
157      while(bm->minmax_reservoir+(this_bits-max_target_bits)>bi->reservoir_bits){
158        choice--;
159        if(choice<0)break;
160        this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
161      }
162    }
163  }
164
165  /* Choice of packetblobs now made based on floater, and min/max
166     requirements. Now boundary check extreme choices */
167
168  if(choice<0){
169    /* choosing a smaller packetblob is insufficient to trim bitrate.
170       frame will need to be truncated */
171    long maxsize=(max_target_bits+(bi->reservoir_bits-bm->minmax_reservoir))/8;
172    bm->choice=choice=0;
173   
174    if(oggpack_bytes(vbi->packetblob[choice])>maxsize){
175     
176      oggpack_writetrunc(vbi->packetblob[choice],maxsize*8);
177      this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
178    }
179  }else{
180    long minsize=(min_target_bits-bm->minmax_reservoir+7)/8;
181    if(choice>=PACKETBLOBS)
182      choice=PACKETBLOBS-1;
183
184    bm->choice=choice;
185
186    /* prop up bitrate according to demand. pad this frame out with zeroes */
187    minsize-=oggpack_bytes(vbi->packetblob[choice]);
188    while(minsize-->0)oggpack_write(vbi->packetblob[choice],0,8);
189    this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
190
191  }
192
193  /* now we have the final packet and the final packet size.  Update statistics */
194  /* min and max reservoir */
195  if(bm->min_bitsper>0 || bm->max_bitsper>0){
196
197    if(max_target_bits>0 && this_bits>max_target_bits){
198      bm->minmax_reservoir+=(this_bits-max_target_bits);
199    }else if(min_target_bits>0 && this_bits<min_target_bits){
200      bm->minmax_reservoir+=(this_bits-min_target_bits);
201    }else{
202      /* inbetween; we want to take reservoir toward but not past desired_fill */
203      if(bm->minmax_reservoir>desired_fill){
204        if(max_target_bits>0){ /* logical bulletproofing against initialization state */
205          bm->minmax_reservoir+=(this_bits-max_target_bits);
206          if(bm->minmax_reservoir<desired_fill)bm->minmax_reservoir=desired_fill;
207        }else{
208          bm->minmax_reservoir=desired_fill;
209        }
210      }else{
211        if(min_target_bits>0){ /* logical bulletproofing against initialization state */
212          bm->minmax_reservoir+=(this_bits-min_target_bits);
213          if(bm->minmax_reservoir>desired_fill)bm->minmax_reservoir=desired_fill;
214        }else{
215          bm->minmax_reservoir=desired_fill;
216        }
217      }
218    }
219  }
220
221  /* avg reservoir */
222  if(bm->avg_bitsper>0){
223    long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper);   
224    bm->avg_reservoir+=this_bits-avg_target_bits;
225  }
226
227  return(0);
228}
229
230int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,ogg_packet *op){
231  private_state         *b=vd->backend_state;
232  bitrate_manager_state *bm=&b->bms;
233  vorbis_block          *vb=bm->vb;
234  int                    choice=PACKETBLOBS/2;
235  if(!vb)return 0;
236
237  if(op){
238    vorbis_block_internal *vbi=vb->internal;
239   
240    if(vorbis_bitrate_managed(vb))
241      choice=bm->choice;
242
243    op->packet=oggpack_get_buffer(vbi->packetblob[choice]);
244    op->bytes=oggpack_bytes(vbi->packetblob[choice]);
245    op->b_o_s=0;
246    op->e_o_s=vb->eofflag;
247    op->granulepos=vb->granulepos;
248    op->packetno=vb->sequence; /* for sake of completeness */
249  }
250 
251  bm->vb=0;
252  return(1);
253}
Note: See TracBrowser for help on using the repository browser.