zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
bitrate.c
Go to the documentation of this file.
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-2009 *
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 16227 2009-07-08 06:58:46Z 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 */
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 
60  memset(bm,0,sizeof(*bm));
61  return;
62 }
63 
65  vorbis_dsp_state *vd=vb->vd;
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 */
76  vorbis_dsp_state *vd=vb->vd;
78  bitrate_manager_state *bm=&b->bms;
79  vorbis_info *vi=vd->vi;
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 
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){
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 }
#define PACKETBLOBS
Definition: ogg.h:90
vorbis_dsp_state * vd
Definition: codec.h:102
void oggpack_write(oggpack_buffer *b, unsigned long value, int bits)
Definition: bitwise.c:83
#define memset
Definition: SDL_malloc.c:633
long W
Definition: codec.h:94
void oggpack_writetrunc(oggpack_buffer *b, long bits)
Definition: bitwise.c:60
vorbis_info * vi
Definition: codec.h:61
double reservoir_bias
Definition: bitrate.h:47
int vorbis_bitrate_addblock(vorbis_block *vb)
Definition: bitrate.c:74
void * codec_setup
Definition: codec.h:53
bitrate_manager_state bms
long bytes
Definition: ogg.h:92
oggpack_buffer * packetblob[PACKETBLOBS]
int vorbis_bitrate_managed(vorbis_block *vb)
Definition: bitrate.c:64
GLsizei samples
Definition: gl2ext.h:970
vorbis_block * vb
Definition: bitrate.h:38
unsigned char * packet
Definition: ogg.h:91
void vorbis_bitrate_init(vorbis_info *vi, bitrate_manager_state *bm)
Definition: bitrate.c:29
int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd, ogg_packet *op)
Definition: bitrate.c:230
long b_o_s
Definition: ogg.h:93
XVisualInfo * vi
int eofflag
Definition: codec.h:99
void vorbis_bitrate_clear(bitrate_manager_state *bm)
Definition: bitrate.c:59
long rate
Definition: codec.h:31
ogg_int64_t granulepos
Definition: codec.h:100
long oggpack_bytes(oggpack_buffer *b)
Definition: bitwise.c:499
ogg_int64_t granulepos
Definition: ogg.h:96
GLdouble GLdouble GLdouble b
Definition: glew.h:8383
unsigned char * oggpack_get_buffer(oggpack_buffer *b)
Definition: bitwise.c:515
void * internal
Definition: codec.h:118
ogg_int64_t sequence
Definition: codec.h:101
long e_o_s
Definition: ogg.h:94
bitrate_manager_info bi
void * backend_state
Definition: codec.h:85
ogg_int64_t packetno
Definition: ogg.h:98