Mercurial > hg > sv-dependency-builds
comparison src/libvorbis-1.3.3/lib/bitrate.c @ 86:98c1576536ae
Bring in flac, ogg, vorbis
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Tue, 19 Mar 2013 17:37:49 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
85:545efbb81310 | 86:98c1576536ae |
---|---|
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 */ | |
29 void 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 | |
59 void vorbis_bitrate_clear(bitrate_manager_state *bm){ | |
60 memset(bm,0,sizeof(*bm)); | |
61 return; | |
62 } | |
63 | |
64 int 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 */ | |
74 int 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 | |
230 int 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 } |