bitrate.c - vx32 - Local 9vx git repository for patches.
(HTM) git clone git://r-36.net/vx32
(DIR) Log
(DIR) Files
(DIR) Refs
---
bitrate.c (16539B)
---
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-2002 *
9 * by the XIPHOPHORUS Company http://www.xiph.org/ *
10 * *
11 ********************************************************************
12
13 function: bitrate tracking and management
14 last mod: $Id: bitrate.c 1919 2005-07-24 14:18:04Z baford $
15
16 ********************************************************************/
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <math.h>
22 #include <ogg/ogg.h>
23 #include "vorbis/codec.h"
24 #include "codec_internal.h"
25 #include "os.h"
26 #include "misc.h"
27 #include "bitrate.h"
28
29
30 static long BINBYTES(bitrate_manager_state *bm,long pos,long bin){
31 int bins=bm->queue_bins;
32 return(bm->queue_binned[pos*bins+bin]);
33 }
34
35 #define LIMITBYTES(pos,bin) (bm->minmax_binstack[(pos)*bins*2+((bin)+bins)])
36
37 static long LACING_ADJUST(long bytes){
38 int addto=bytes/255+1;
39 return(bytes+addto);
40 }
41
42 static int floater_interpolate(bitrate_manager_state *bm,vorbis_info *vi,
43 double desired_rate){
44 int bin=rint(bm->avgfloat);
45 double lobitrate,hibitrate;
46
47
48 lobitrate=(double)(bm->avg_binacc[bin]*8)/bm->avg_sampleacc*vi->rate;
49 while(lobitrate>desired_rate && bin>0){
50 bin--;
51 lobitrate=(double)(bm->avg_binacc[bin]*8)/bm->avg_sampleacc*vi->rate;
52 }
53
54 if(bin+1<bm->queue_bins){
55 hibitrate=(double)(bm->avg_binacc[bin+1]*8)/bm->avg_sampleacc*vi->rate;
56 if(fabs(hibitrate-desired_rate) < fabs(lobitrate-desired_rate))bin++;
57 }
58 return(bin);
59 }
60
61 /* try out a new limit */
62 static long limit_sum(bitrate_manager_state *bm,int limit){
63 int i=bm->minmax_stackptr;
64 long acc=bm->minmax_acctotal;
65 long bins=bm->queue_bins;
66
67 acc-=LIMITBYTES(i,0);
68 acc+=LIMITBYTES(i,limit);
69
70 while(i-->0){
71 if(bm->minmax_limitstack[i]<=limit)break;
72 acc-=LIMITBYTES(i,bm->minmax_limitstack[i]);
73 acc+=LIMITBYTES(i,limit);
74 }
75 return(acc);
76 }
77
78 /* compute bitrate tracking setup, allocate circular packet size queue */
79 void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){
80 int i;
81 codec_setup_info *ci=vi->codec_setup;
82 bitrate_manager_info *bi=&ci->bi;
83 long maxlatency;
84
85 memset(bm,0,sizeof(*bm));
86
87 if(bi){
88
89 bm->avg_sampledesired=bi->queue_avg_time*vi->rate;
90 bm->avg_centerdesired=bi->queue_avg_time*vi->rate*bi->queue_avg_center;
91 bm->minmax_sampledesired=bi->queue_minmax_time*vi->rate;
92
93 /* first find the max possible needed queue size */
94 maxlatency=max(bm->avg_sampledesired-bm->avg_centerdesired,
95 bm->minmax_sampledesired)+bm->avg_centerdesired;
96
97 if(maxlatency>0 &&
98 (bi->queue_avgmin>0 || bi->queue_avgmax>0 || bi->queue_hardmax>0 ||
99 bi->queue_hardmin>0)){
100 long maxpackets=maxlatency/(ci->blocksizes[0]>>1)+3;
101 long bins=PACKETBLOBS;
102
103 bm->queue_size=maxpackets;
104 bm->queue_bins=bins;
105 bm->queue_binned=_ogg_calloc(maxpackets,bins*sizeof(*bm->queue_binned));
106 bm->queue_actual=_ogg_calloc(maxpackets,sizeof(*bm->queue_actual));
107
108 if((bi->queue_avgmin>0 || bi->queue_avgmax>0) &&
109 bi->queue_avg_time>0){
110
111 bm->avg_binacc=_ogg_calloc(bins,sizeof(*bm->avg_binacc));
112 bm->avgfloat=PACKETBLOBS/2;
113
114 }else{
115 bm->avg_tail= -1;
116 }
117
118 if((bi->queue_hardmin>0 || bi->queue_hardmax>0) &&
119 bi->queue_minmax_time>0){
120
121 bm->minmax_binstack=_ogg_calloc((bins*2+1)*bins*2,
122 sizeof(*bm->minmax_binstack));
123 bm->minmax_posstack=_ogg_calloc((bins*2+1),
124 sizeof(*bm->minmax_posstack));
125 bm->minmax_limitstack=_ogg_calloc((bins*2+1),
126 sizeof(*bm->minmax_limitstack));
127 }else{
128 bm->minmax_tail= -1;
129 }
130
131 /* space for the packet queueing */
132 bm->packetbuffers=_ogg_calloc(maxpackets,sizeof(*bm->packetbuffers));
133 bm->packets=_ogg_calloc(maxpackets,sizeof(*bm->packets));
134 for(i=0;i<maxpackets;i++)
135 oggpack_writeinit(bm->packetbuffers+i);
136
137 }else{
138 bm->packetbuffers=_ogg_calloc(1,sizeof(*bm->packetbuffers));
139 bm->packets=_ogg_calloc(1,sizeof(*bm->packets));
140 oggpack_writeinit(bm->packetbuffers);
141
142 }
143 }
144 }
145
146 void vorbis_bitrate_clear(bitrate_manager_state *bm){
147 int i;
148 if(bm){
149 if(bm->queue_binned)_ogg_free(bm->queue_binned);
150 if(bm->queue_actual)_ogg_free(bm->queue_actual);
151 if(bm->avg_binacc)_ogg_free(bm->avg_binacc);
152 if(bm->minmax_binstack)_ogg_free(bm->minmax_binstack);
153 if(bm->minmax_posstack)_ogg_free(bm->minmax_posstack);
154 if(bm->minmax_limitstack)_ogg_free(bm->minmax_limitstack);
155
156 if(bm->packetbuffers){
157 if(bm->queue_size==0){
158 oggpack_writeclear(bm->packetbuffers);
159 }else{
160 for(i=0;i<bm->queue_size;i++)
161 oggpack_writeclear(bm->packetbuffers+i);
162 }
163 _ogg_free(bm->packetbuffers);
164 }
165 if(bm->packets)_ogg_free(bm->packets);
166
167 memset(bm,0,sizeof(*bm));
168 }
169 }
170
171 int vorbis_bitrate_managed(vorbis_block *vb){
172 vorbis_dsp_state *vd=vb->vd;
173 private_state *b=vd->backend_state;
174 bitrate_manager_state *bm=&b->bms;
175
176 if(bm->queue_binned)return(1);
177 return(0);
178 }
179
180 /* finish taking in the block we just processed */
181 int vorbis_bitrate_addblock(vorbis_block *vb){
182 int i;
183 vorbis_block_internal *vbi=vb->internal;
184 vorbis_dsp_state *vd=vb->vd;
185 private_state *b=vd->backend_state;
186 bitrate_manager_state *bm=&b->bms;
187 vorbis_info *vi=vd->vi;
188 codec_setup_info *ci=vi->codec_setup;
189 bitrate_manager_info *bi=&ci->bi;
190 int eofflag=vb->eofflag;
191 int head=bm->queue_head;
192 int next_head=head+1;
193 int bins=bm->queue_bins;
194 int minmax_head,new_minmax_head;
195
196 ogg_uint32_t *head_ptr;
197 oggpack_buffer temp;
198
199 if(!bm->queue_binned){
200 oggpack_buffer temp;
201 /* not a bitrate managed stream, but for API simplicity, we'll
202 buffer one packet to keep the code path clean */
203
204 if(bm->queue_head)return(-1); /* one has been submitted without
205 being claimed */
206 bm->queue_head++;
207
208 bm->packets[0].packet=oggpack_get_buffer(&vb->opb);
209 bm->packets[0].bytes=oggpack_bytes(&vb->opb);
210 bm->packets[0].b_o_s=0;
211 bm->packets[0].e_o_s=vb->eofflag;
212 bm->packets[0].granulepos=vb->granulepos;
213 bm->packets[0].packetno=vb->sequence; /* for sake of completeness */
214
215 memcpy(&temp,bm->packetbuffers,sizeof(vb->opb));
216 memcpy(bm->packetbuffers,&vb->opb,sizeof(vb->opb));
217 memcpy(&vb->opb,&temp,sizeof(vb->opb));
218
219 return(0);
220 }
221
222 /* add encoded packet to head */
223 if(next_head>=bm->queue_size)next_head=0;
224 head_ptr=bm->queue_binned+bins*head;
225
226 /* is there room to add a block? In proper use of the API, this will
227 never come up... but guard it anyway */
228 if(next_head==bm->avg_tail || next_head==bm->minmax_tail)return(-1);
229
230 /* add the block to the toplevel queue */
231 bm->queue_head=next_head;
232 bm->queue_actual[head]=(vb->W?0x80000000UL:0);
233
234 /* buffer packet fields */
235 bm->packets[head].packet=oggpack_get_buffer(&vb->opb);
236 bm->packets[head].bytes=oggpack_bytes(&vb->opb);
237 bm->packets[head].b_o_s=0;
238 bm->packets[head].e_o_s=vb->eofflag;
239 bm->packets[head].granulepos=vb->granulepos;
240 bm->packets[head].packetno=vb->sequence; /* for sake of completeness */
241
242 /* swap packet buffers */
243 memcpy(&temp,bm->packetbuffers+head,sizeof(vb->opb));
244 memcpy(bm->packetbuffers+head,&vb->opb,sizeof(vb->opb));
245 memcpy(&vb->opb,&temp,sizeof(vb->opb));
246
247 /* save markers */
248 head_ptr[0]=vbi->packetblob_markers[0];
249 for(i=1;i<PACKETBLOBS;i++){
250 head_ptr[i]=vbi->packetblob_markers[i]-vbi->packetblob_markers[i-1];
251 }
252
253 if(bm->avg_binacc)
254 new_minmax_head=minmax_head=bm->avg_center;
255 else
256 new_minmax_head=minmax_head=head;
257
258 /* the average tracking queue is updated first; its results (if it's
259 in use) are taken into account by the min/max limiter (if min/max
260 is in use) */
261 if(bm->avg_binacc){
262 unsigned long desired_center=bm->avg_centerdesired;
263 if(eofflag)desired_center=0;
264
265 /* update the avg head */
266 for(i=0;i<bins;i++)
267 bm->avg_binacc[i]+=LACING_ADJUST(head_ptr[i]);
268 bm->avg_sampleacc+=ci->blocksizes[vb->W]>>1;
269 bm->avg_centeracc+=ci->blocksizes[vb->W]>>1;
270
271 if(bm->avg_sampleacc>bm->avg_sampledesired || eofflag){
272
273 /* update the avg center */
274 if(bm->avg_centeracc>desired_center){
275 /* choose the new average floater */
276 int samples=ci->blocksizes[vb->W]>>1;
277 double upper=floater_interpolate(bm,vi,bi->queue_avgmax);
278 double lower=floater_interpolate(bm,vi,bi->queue_avgmin);
279 double new=PACKETBLOBS/2.,slew;
280 int bin;
281
282 if(upper<new)new=upper;
283 if(lower>new)new=lower;
284
285 slew=(new-bm->avgfloat)/samples*vi->rate;
286
287 if(slew<bi->avgfloat_downslew_max)
288 new=bm->avgfloat+bi->avgfloat_downslew_max/vi->rate*samples;
289 if(slew>bi->avgfloat_upslew_max)
290 new=bm->avgfloat+bi->avgfloat_upslew_max/vi->rate*samples;
291
292 bm->avgfloat=new;
293 /* apply the average floater to new blocks */
294 bin=rint(bm->avgfloat);
295
296 /*fprintf(stderr,"%d ",bin);*/
297
298 while(bm->avg_centeracc>desired_center){
299 samples=ci->blocksizes[bm->queue_actual[bm->avg_center]&
300 0x80000000UL?1:0]>>1;
301
302 bm->queue_actual[bm->avg_center]|=bin;
303
304 bm->avg_centeracc-=samples;
305 bm->avg_center++;
306 if(bm->avg_center>=bm->queue_size)bm->avg_center=0;
307 }
308 new_minmax_head=bm->avg_center;
309
310 }
311
312 /* update the avg tail if needed */
313 while(bm->avg_sampleacc>bm->avg_sampledesired){
314 int samples=
315 ci->blocksizes[bm->queue_actual[bm->avg_tail]&0x80000000UL?1:0]>>1;
316 for(i=0;i<bm->queue_bins;i++)
317 bm->avg_binacc[i]-=LACING_ADJUST(bm->queue_binned[bins*bm->avg_tail+i]);
318 bm->avg_sampleacc-=samples;
319 bm->avg_tail++;
320 if(bm->avg_tail>=bm->queue_size)bm->avg_tail=0;
321 }
322
323
324 }
325 }else{
326 /* if we're not using an average tracker, the 'float' is nailed to
327 the avgfloat_initial value. It needs to be set for the min/max
328 to deal properly */
329 long bin=PACKETBLOBS/2;
330 bm->queue_actual[head]|=bin;
331 new_minmax_head=next_head;
332 }
333
334 /* update the min/max queues and enforce limits */
335 if(bm->minmax_binstack){
336 unsigned long sampledesired=eofflag?0:bm->minmax_sampledesired;
337
338 /* add to stack recent */
339 while(minmax_head!=new_minmax_head){
340 unsigned int i;
341 int samples=ci->blocksizes[bm->queue_actual[minmax_head]&
342 0x80000000UL?1:0]>>1;
343 int actual=bm->queue_actual[minmax_head]&0x7fffffffUL;
344
345 for(i=0;i<(unsigned int)bins;i++){
346 bm->minmax_binstack[bm->minmax_stackptr*bins*2+bins+i]+=
347 LACING_ADJUST(BINBYTES(bm,minmax_head,
348 actual>i?actual:i));
349
350 bm->minmax_binstack[bm->minmax_stackptr*bins*2+i]+=
351 LACING_ADJUST(BINBYTES(bm,minmax_head,
352 actual<i?actual:i));
353 }
354
355 bm->minmax_posstack[bm->minmax_stackptr]=minmax_head; /* not one
356 past
357 like
358 typical */
359 bm->minmax_limitstack[bm->minmax_stackptr]=0;
360 bm->minmax_sampleacc+=samples;
361 bm->minmax_acctotal+=
362 LACING_ADJUST(BINBYTES(bm,minmax_head,actual));
363
364 minmax_head++;
365 if(minmax_head>=bm->queue_size)minmax_head=0;
366
367
368 }
369
370 /* check limits, enforce changes */
371 if(bm->minmax_sampleacc>sampledesired){
372 double bitrate=(double)(bm->minmax_acctotal*8)/
373 bm->minmax_sampleacc*vi->rate;
374 int limit=0;
375
376 if((bi->queue_hardmax>0 && bitrate>bi->queue_hardmax) ||
377 (bi->queue_hardmin>0 && bitrate<bi->queue_hardmin)){
378 int newstack;
379 int stackctr;
380 long bitsum=bm->minmax_acctotal*8;
381
382 bitrate=(double)bitsum/bm->minmax_sampleacc*vi->rate;
383
384 /* we're off rate. Iteratively try out new hard floater
385 limits until we find one that brings us inside. Here's
386 where we see the whole point of the limit stacks. */
387 if(bi->queue_hardmax>0 && bitrate>bi->queue_hardmax){
388 for(limit=-1;limit>-bins+1;limit--){
389 long bitsum=limit_sum(bm,limit)*8;
390 bitrate=(double)bitsum/bm->minmax_sampleacc*vi->rate;
391 if(bitrate<=bi->queue_hardmax)break;
392 }
393 }else if(bitrate<bi->queue_hardmin){
394 for(limit=1;limit<bins-1;limit++){
395 long bitsum=limit_sum(bm,limit)*8;
396 bitrate=(double)bitsum/bm->minmax_sampleacc*vi->rate;
397 if(bitrate>=bi->queue_hardmin)break;
398 }
399 if(bitrate>bi->queue_hardmax)limit--;
400 }
401
402 /* trace the limit backward, stop when we see a lower limit */
403 newstack=bm->minmax_stackptr-1;
404 while(newstack>=0){
405 if(bm->minmax_limitstack[newstack]<limit)break;
406 newstack--;
407 }
408
409 /* update bit counter with new limit and replace any stack
410 limits that have been replaced by our new lower limit */
411 stackctr=bm->minmax_stackptr;
412 while(stackctr>newstack){
413 bm->minmax_acctotal-=
414 LIMITBYTES(stackctr,bm->minmax_limitstack[stackctr]);
415 bm->minmax_acctotal+=LIMITBYTES(stackctr,limit);
416
417 if(stackctr<bm->minmax_stackptr)
418 for(i=0;i<bins*2;i++)
419 bm->minmax_binstack[stackctr*bins*2+i]+=
420 bm->minmax_binstack[(stackctr+1)*bins*2+i];
421
422 stackctr--;
423 }
424 stackctr++;
425 bm->minmax_posstack[stackctr]=bm->minmax_posstack[bm->minmax_stackptr];
426 bm->minmax_limitstack[stackctr]=limit;
427
428 /* set up new blank stack entry */
429 stackctr++;
430 bm->minmax_stackptr=stackctr;
431 memset(&bm->minmax_binstack[stackctr*bins*2],
432 0,
433 sizeof(*bm->minmax_binstack)*bins*2);
434 bm->minmax_limitstack[stackctr]=0;
435 bm->minmax_posstack[stackctr]=-1;
436
437 }
438 }
439
440 /* remove from tail */
441 while(bm->minmax_sampleacc>sampledesired){
442 int samples=
443 ci->blocksizes[bm->queue_actual[bm->minmax_tail]&0x80000000UL?1:0]>>1;
444 int actual=bm->queue_actual[bm->minmax_tail]&0x7fffffffUL;
445
446 for(i=0;i<bins;i++){
447 bm->minmax_binstack[bins+i]-= /* always comes off the stack bottom */
448 LACING_ADJUST(BINBYTES(bm,bm->minmax_tail,
449 actual>i?
450 actual:i));
451 bm->minmax_binstack[i]-=
452 LACING_ADJUST(BINBYTES(bm,bm->minmax_tail,
453 actual<i?
454 actual:i));
455 }
456
457 if(bm->minmax_limitstack[0]>actual)
458 actual=bm->minmax_limitstack[0];
459 if(bins+bm->minmax_limitstack[0]<actual)
460 actual=bins+bm->minmax_limitstack[0];
461
462 bm->minmax_acctotal-=LACING_ADJUST(BINBYTES(bm,bm->minmax_tail,actual));
463 bm->minmax_sampleacc-=samples;
464
465 /* revise queue_actual to reflect the limit */
466 bm->queue_actual[bm->minmax_tail]&=0x80000000UL;
467 bm->queue_actual[bm->minmax_tail]|=actual;
468
469 if(bm->minmax_tail==bm->minmax_posstack[0]){
470 /* the stack becomes a FIFO; the first data has fallen off */
471 memmove(bm->minmax_binstack,bm->minmax_binstack+bins*2,
472 sizeof(*bm->minmax_binstack)*bins*2*bm->minmax_stackptr);
473 memmove(bm->minmax_posstack,bm->minmax_posstack+1,
474 sizeof(*bm->minmax_posstack)*bm->minmax_stackptr);
475 memmove(bm->minmax_limitstack,bm->minmax_limitstack+1,
476 sizeof(*bm->minmax_limitstack)*bm->minmax_stackptr);
477 bm->minmax_stackptr--;
478 }
479
480 bm->minmax_tail++;
481 if(bm->minmax_tail>=bm->queue_size)bm->minmax_tail=0;
482
483 }
484
485
486 bm->last_to_flush=bm->minmax_tail;
487 }else{
488 bm->last_to_flush=bm->avg_center;
489 }
490 if(eofflag)
491 bm->last_to_flush=bm->queue_head;
492 return(0);
493 }
494
495 int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,ogg_packet *op){
496 private_state *b=vd->backend_state;
497 bitrate_manager_state *bm=&b->bms;
498
499 if(bm->queue_size==0){
500 if(bm->queue_head==0)return(0);
501
502 memcpy(op,bm->packets,sizeof(*op));
503 bm->queue_head=0;
504
505 }else{
506
507 if(bm->next_to_flush==bm->last_to_flush)return(0);
508
509 {
510 long bin=bm->queue_actual[bm->next_to_flush]&0x7fffffff,i;
511 long bins=bm->queue_bins;
512 ogg_uint32_t *markers=bm->queue_binned+bins*bm->next_to_flush;
513 long bytes=markers[bin];
514
515 memcpy(op,bm->packets+bm->next_to_flush,sizeof(*op));
516
517 /* we have [PACKETBLOBS] possible packets all squished together in
518 the buffer, in sequence. count in to number [bin] */
519 for(i=0;i<bin;i++)
520 op->packet+=markers[i];
521 op->bytes=bytes;
522
523 }
524
525 bm->next_to_flush++;
526 if(bm->next_to_flush>=bm->queue_size)bm->next_to_flush=0;
527
528 }
529
530 return(1);
531 }