1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138 |
- /********************************************************************
- * *
- * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
- * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
- * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
- * *
- * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009 *
- * by the Xiph.Org Foundation http://www.xiph.org/ *
- * *
- ********************************************************************
- function:
- last mod: $Id: rate.c 16503 2009-08-22 18:14:02Z giles $
- ********************************************************************/
- #include <stdlib.h>
- #include <string.h>
- #include "encint.h"
- /*A rough lookup table for tan(x), 0<=x<pi/2.
- The values are Q12 fixed-point and spaced at 5 degree intervals.
- These decisions are somewhat arbitrary, but sufficient for the 2nd order
- Bessel follower below.
- Values of x larger than 85 degrees are extrapolated from the last inteval,
- which is way off, but "good enough".*/
- static unsigned short OC_ROUGH_TAN_LOOKUP[18]={
- 0, 358, 722, 1098, 1491, 1910,
- 2365, 2868, 3437, 4096, 4881, 5850,
- 7094, 8784,11254,15286,23230,46817
- };
- /*_alpha is Q24 in the range [0,0.5).
- The return values is 5.12.*/
- static int oc_warp_alpha(int _alpha){
- int i;
- int d;
- int t0;
- int t1;
- i=_alpha*36>>24;
- if(i>=17)i=16;
- t0=OC_ROUGH_TAN_LOOKUP[i];
- t1=OC_ROUGH_TAN_LOOKUP[i+1];
- d=_alpha*36-(i<<24);
- return (int)(((ogg_int64_t)t0<<32)+(t1-t0<<8)*(ogg_int64_t)d>>32);
- }
- /*Re-initialize the Bessel filter coefficients with the specified delay.
- This does not alter the x/y state, but changes the reaction time of the
- filter.
- Altering the time constant of a reactive filter without alterning internal
- state is something that has to be done carefuly, but our design operates at
- high enough delays and with small enough time constant changes to make it
- safe.*/
- static void oc_iir_filter_reinit(oc_iir_filter *_f,int _delay){
- int alpha;
- ogg_int64_t one48;
- ogg_int64_t warp;
- ogg_int64_t k1;
- ogg_int64_t k2;
- ogg_int64_t d;
- ogg_int64_t a;
- ogg_int64_t ik2;
- ogg_int64_t b1;
- ogg_int64_t b2;
- /*This borrows some code from an unreleased version of Postfish.
- See the recipe at http://unicorn.us.com/alex/2polefilters.html for details
- on deriving the filter coefficients.*/
- /*alpha is Q24*/
- alpha=(1<<24)/_delay;
- one48=(ogg_int64_t)1<<48;
- /*warp is 7.12*/
- warp=OC_MAXI(oc_warp_alpha(alpha),1);
- /*k1 is 9.12*/
- k1=3*warp;
- /*k2 is 16.24.*/
- k2=k1*warp;
- /*d is 16.15.*/
- d=((1<<12)+k1<<12)+k2+256>>9;
- /*a is 0.32, since d is larger than both 1.0 and k2.*/
- a=(k2<<23)/d;
- /*ik2 is 25.24.*/
- ik2=one48/k2;
- /*b1 is Q56; in practice, the integer ranges between -2 and 2.*/
- b1=2*a*(ik2-(1<<24));
- /*b2 is Q56; in practice, the integer ranges between -2 and 2.*/
- b2=(one48<<8)-(4*a<<24)-b1;
- /*All of the filter parameters are Q24.*/
- _f->c[0]=(ogg_int32_t)(b1+((ogg_int64_t)1<<31)>>32);
- _f->c[1]=(ogg_int32_t)(b2+((ogg_int64_t)1<<31)>>32);
- _f->g=(ogg_int32_t)(a+128>>8);
- }
- /*Initialize a 2nd order low-pass Bessel filter with the corresponding delay
- and initial value.
- _value is Q24.*/
- static void oc_iir_filter_init(oc_iir_filter *_f,int _delay,ogg_int32_t _value){
- oc_iir_filter_reinit(_f,_delay);
- _f->y[1]=_f->y[0]=_f->x[1]=_f->x[0]=_value;
- }
- static ogg_int64_t oc_iir_filter_update(oc_iir_filter *_f,ogg_int32_t _x){
- ogg_int64_t c0;
- ogg_int64_t c1;
- ogg_int64_t g;
- ogg_int64_t x0;
- ogg_int64_t x1;
- ogg_int64_t y0;
- ogg_int64_t y1;
- ogg_int64_t ya;
- c0=_f->c[0];
- c1=_f->c[1];
- g=_f->g;
- x0=_f->x[0];
- x1=_f->x[1];
- y0=_f->y[0];
- y1=_f->y[1];
- ya=(_x+x0*2+x1)*g+y0*c0+y1*c1+(1<<23)>>24;
- _f->x[1]=(ogg_int32_t)x0;
- _f->x[0]=_x;
- _f->y[1]=(ogg_int32_t)y0;
- _f->y[0]=(ogg_int32_t)ya;
- return ya;
- }
- /*Search for the quantizer that matches the target most closely.
- We don't assume a linear ordering, but when there are ties we pick the
- quantizer closest to the old one.*/
- static int oc_enc_find_qi_for_target(oc_enc_ctx *_enc,int _qti,int _qi_old,
- int _qi_min,ogg_int64_t _log_qtarget){
- ogg_int64_t best_qdiff;
- int best_qi;
- int qi;
- best_qi=_qi_min;
- best_qdiff=_enc->log_qavg[_qti][best_qi]-_log_qtarget;
- best_qdiff=best_qdiff+OC_SIGNMASK(best_qdiff)^OC_SIGNMASK(best_qdiff);
- for(qi=_qi_min+1;qi<64;qi++){
- ogg_int64_t qdiff;
- qdiff=_enc->log_qavg[_qti][qi]-_log_qtarget;
- qdiff=qdiff+OC_SIGNMASK(qdiff)^OC_SIGNMASK(qdiff);
- if(qdiff<best_qdiff||
- qdiff==best_qdiff&&abs(qi-_qi_old)<abs(best_qi-_qi_old)){
- best_qi=qi;
- best_qdiff=qdiff;
- }
- }
- return best_qi;
- }
- void oc_enc_calc_lambda(oc_enc_ctx *_enc,int _qti){
- ogg_int64_t lq;
- int qi;
- int qi1;
- int nqis;
- /*For now, lambda is fixed depending on the qi value and frame type:
- lambda=qscale*(qavg[qti][qi]**2),
- where qscale=0.2125.
- This was derived by exhaustively searching for the optimal quantizer for
- the AC coefficients in each block from a number of test sequences for a
- number of fixed lambda values and fitting the peaks of the resulting
- histograms (on the log(qavg) scale).
- The same model applies to both inter and intra frames.
- A more adaptive scheme might perform better.*/
- qi=_enc->state.qis[0];
- /*If rate control is active, use the lambda for the _target_ quantizer.
- This allows us to scale to rates slightly lower than we'd normally be able
- to reach, and give the rate control a semblance of "fractional qi"
- precision.
- TODO: Add API for changing QI, and allow extra precision.*/
- if(_enc->state.info.target_bitrate>0)lq=_enc->rc.log_qtarget;
- else lq=_enc->log_qavg[_qti][qi];
- /*The resulting lambda value is less than 0x500000.*/
- _enc->lambda=(int)oc_bexp64(2*lq-0x4780BD468D6B62BLL);
- /*Select additional quantizers.
- The R-D optimal block AC quantizer statistics suggest that the distribution
- is roughly Gaussian-like with a slight positive skew.
- K-means clustering on log_qavg to select 3 quantizers produces cluster
- centers of {log_qavg-0.6,log_qavg,log_qavg+0.7}.
- Experiments confirm these are relatively good choices.
- Although we do greedy R-D optimization of the qii flags to avoid switching
- too frequently, this becomes ineffective at low rates, either because we
- do a poor job of predicting the actual R-D cost, or the greedy
- optimization is not sufficient.
- Therefore adaptive quantization is disabled above an (experimentally
- suggested) threshold of log_qavg=7.00 (e.g., below INTRA qi=12 or
- INTER qi=20 with current matrices).
- This may need to be revised if the R-D cost estimation or qii flag
- optimization strategies change.*/
- nqis=1;
- if(lq<(OC_Q57(56)>>3)&&!_enc->vp3_compatible){
- qi1=oc_enc_find_qi_for_target(_enc,_qti,OC_MAXI(qi-1,0),0,
- lq+(OC_Q57(7)+5)/10);
- if(qi1!=qi)_enc->state.qis[nqis++]=qi1;
- qi1=oc_enc_find_qi_for_target(_enc,_qti,OC_MINI(qi+1,63),0,
- lq-(OC_Q57(6)+5)/10);
- if(qi1!=qi&&qi1!=_enc->state.qis[nqis-1])_enc->state.qis[nqis++]=qi1;
- }
- _enc->state.nqis=nqis;
- }
- /*Binary exponential of _log_scale with 24-bit fractional precision and
- saturation.
- _log_scale: A binary logarithm in Q24 format.
- Return: The binary exponential in Q24 format, saturated to 2**47-1 if
- _log_scale was too large.*/
- static ogg_int64_t oc_bexp_q24(ogg_int32_t _log_scale){
- if(_log_scale<(ogg_int32_t)23<<24){
- ogg_int64_t ret;
- ret=oc_bexp64(((ogg_int64_t)_log_scale<<33)+OC_Q57(24));
- return ret<0x7FFFFFFFFFFFLL?ret:0x7FFFFFFFFFFFLL;
- }
- return 0x7FFFFFFFFFFFLL;
- }
- /*Convenience function converts Q57 value to a clamped 32-bit Q24 value
- _in: input in Q57 format.
- Return: same number in Q24 */
- static ogg_int32_t oc_q57_to_q24(ogg_int64_t _in){
- ogg_int64_t ret;
- ret=_in+((ogg_int64_t)1<<32)>>33;
- /*0x80000000 is automatically converted to unsigned on 32-bit systems.
- -0x7FFFFFFF-1 is needed to avoid "promoting" the whole expression to
- unsigned.*/
- return (ogg_int32_t)OC_CLAMPI(-0x7FFFFFFF-1,ret,0x7FFFFFFF);
- }
- /*Binary exponential of _log_scale with 24-bit fractional precision and
- saturation.
- _log_scale: A binary logarithm in Q57 format.
- Return: The binary exponential in Q24 format, saturated to 2**31-1 if
- _log_scale was too large.*/
- static ogg_int32_t oc_bexp64_q24(ogg_int64_t _log_scale){
- if(_log_scale<OC_Q57(8)){
- ogg_int64_t ret;
- ret=oc_bexp64(_log_scale+OC_Q57(24));
- return ret<0x7FFFFFFF?(ogg_int32_t)ret:0x7FFFFFFF;
- }
- return 0x7FFFFFFF;
- }
- static void oc_enc_rc_reset(oc_enc_ctx *_enc){
- ogg_int64_t npixels;
- ogg_int64_t ibpp;
- int inter_delay;
- /*TODO: These parameters should be exposed in a th_encode_ctl() API.*/
- _enc->rc.bits_per_frame=(_enc->state.info.target_bitrate*
- (ogg_int64_t)_enc->state.info.fps_denominator)/
- _enc->state.info.fps_numerator;
- /*Insane framerates or frame sizes mean insane bitrates.
- Let's not get carried away.*/
- if(_enc->rc.bits_per_frame>0x400000000000LL){
- _enc->rc.bits_per_frame=(ogg_int64_t)0x400000000000LL;
- }
- else if(_enc->rc.bits_per_frame<32)_enc->rc.bits_per_frame=32;
- _enc->rc.buf_delay=OC_MAXI(_enc->rc.buf_delay,12);
- _enc->rc.max=_enc->rc.bits_per_frame*_enc->rc.buf_delay;
- /*Start with a buffer fullness of 50% plus 25% of the amount we plan to spend
- on a single keyframe interval.
- We can require fully half the bits in an interval for a keyframe, so this
- initial level gives us maximum flexibility for over/under-shooting in
- subsequent frames.*/
- _enc->rc.target=(_enc->rc.max+1>>1)+(_enc->rc.bits_per_frame+2>>2)*
- OC_MINI(_enc->keyframe_frequency_force,_enc->rc.buf_delay);
- _enc->rc.fullness=_enc->rc.target;
- /*Pick exponents and initial scales for quantizer selection.*/
- npixels=_enc->state.info.frame_width*
- (ogg_int64_t)_enc->state.info.frame_height;
- _enc->rc.log_npixels=oc_blog64(npixels);
- ibpp=npixels/_enc->rc.bits_per_frame;
- if(ibpp<1){
- _enc->rc.exp[0]=59;
- _enc->rc.log_scale[0]=oc_blog64(1997)-OC_Q57(8);
- }
- else if(ibpp<2){
- _enc->rc.exp[0]=55;
- _enc->rc.log_scale[0]=oc_blog64(1604)-OC_Q57(8);
- }
- else{
- _enc->rc.exp[0]=48;
- _enc->rc.log_scale[0]=oc_blog64(834)-OC_Q57(8);
- }
- if(ibpp<4){
- _enc->rc.exp[1]=100;
- _enc->rc.log_scale[1]=oc_blog64(2249)-OC_Q57(8);
- }
- else if(ibpp<8){
- _enc->rc.exp[1]=95;
- _enc->rc.log_scale[1]=oc_blog64(1751)-OC_Q57(8);
- }
- else{
- _enc->rc.exp[1]=73;
- _enc->rc.log_scale[1]=oc_blog64(1260)-OC_Q57(8);
- }
- _enc->rc.prev_drop_count=0;
- _enc->rc.log_drop_scale=OC_Q57(0);
- /*Set up second order followers, initialized according to corresponding
- time constants.*/
- oc_iir_filter_init(&_enc->rc.scalefilter[0],4,
- oc_q57_to_q24(_enc->rc.log_scale[0]));
- inter_delay=(_enc->rc.twopass?
- OC_MAXI(_enc->keyframe_frequency_force,12):_enc->rc.buf_delay)>>1;
- _enc->rc.inter_count=0;
- /*We clamp the actual inter_delay to a minimum of 10 to work within the range
- of values where later incrementing the delay works as designed.
- 10 is not an exact choice, but rather a good working trade-off.*/
- _enc->rc.inter_delay=10;
- _enc->rc.inter_delay_target=inter_delay;
- oc_iir_filter_init(&_enc->rc.scalefilter[1],_enc->rc.inter_delay,
- oc_q57_to_q24(_enc->rc.log_scale[1]));
- oc_iir_filter_init(&_enc->rc.vfrfilter,4,
- oc_bexp64_q24(_enc->rc.log_drop_scale));
- }
- void oc_rc_state_init(oc_rc_state *_rc,oc_enc_ctx *_enc){
- _rc->twopass=0;
- _rc->twopass_buffer_bytes=0;
- _rc->twopass_force_kf=0;
- _rc->frame_metrics=NULL;
- _rc->rate_bias=0;
- if(_enc->state.info.target_bitrate>0){
- /*The buffer size is set equal to the keyframe interval, clamped to the
- range [12,256] frames.
- The 12 frame minimum gives us some chance to distribute bit estimation
- errors.
- The 256 frame maximum means we'll require 8-10 seconds of pre-buffering
- at 24-30 fps, which is not unreasonable.*/
- _rc->buf_delay=_enc->keyframe_frequency_force>256?
- 256:_enc->keyframe_frequency_force;
- /*By default, enforce all buffer constraints.*/
- _rc->drop_frames=1;
- _rc->cap_overflow=1;
- _rc->cap_underflow=0;
- oc_enc_rc_reset(_enc);
- }
- }
- void oc_rc_state_clear(oc_rc_state *_rc){
- _ogg_free(_rc->frame_metrics);
- }
- void oc_enc_rc_resize(oc_enc_ctx *_enc){
- /*If encoding has not yet begun, reset the buffer state.*/
- if(_enc->state.curframe_num<0)oc_enc_rc_reset(_enc);
- else{
- int idt;
- /*Otherwise, update the bounds on the buffer, but not the current
- fullness.*/
- _enc->rc.bits_per_frame=(_enc->state.info.target_bitrate*
- (ogg_int64_t)_enc->state.info.fps_denominator)/
- _enc->state.info.fps_numerator;
- /*Insane framerates or frame sizes mean insane bitrates.
- Let's not get carried away.*/
- if(_enc->rc.bits_per_frame>0x400000000000LL){
- _enc->rc.bits_per_frame=(ogg_int64_t)0x400000000000LL;
- }
- else if(_enc->rc.bits_per_frame<32)_enc->rc.bits_per_frame=32;
- _enc->rc.buf_delay=OC_MAXI(_enc->rc.buf_delay,12);
- _enc->rc.max=_enc->rc.bits_per_frame*_enc->rc.buf_delay;
- _enc->rc.target=(_enc->rc.max+1>>1)+(_enc->rc.bits_per_frame+2>>2)*
- OC_MINI(_enc->keyframe_frequency_force,_enc->rc.buf_delay);
- /*Update the INTER-frame scale filter delay.
- We jump to it immediately if we've already seen enough frames; otherwise
- it is simply set as the new target.*/
- _enc->rc.inter_delay_target=idt=OC_MAXI(_enc->rc.buf_delay>>1,10);
- if(idt<OC_MINI(_enc->rc.inter_delay,_enc->rc.inter_count)){
- oc_iir_filter_init(&_enc->rc.scalefilter[1],idt,
- _enc->rc.scalefilter[1].y[0]);
- _enc->rc.inter_delay=idt;
- }
- }
- /*If we're in pass-2 mode, make sure the frame metrics array is big enough
- to hold frame statistics for the full buffer.*/
- if(_enc->rc.twopass==2){
- int cfm;
- int buf_delay;
- int reset_window;
- buf_delay=_enc->rc.buf_delay;
- reset_window=_enc->rc.frame_metrics==NULL&&(_enc->rc.frames_total[0]==0||
- buf_delay<_enc->rc.frames_total[0]+_enc->rc.frames_total[1]
- +_enc->rc.frames_total[2]);
- cfm=_enc->rc.cframe_metrics;
- /*Only try to resize the frame metrics buffer if a) it's too small and
- b) we were using a finite buffer, or are about to start.*/
- if(cfm<buf_delay&&(_enc->rc.frame_metrics!=NULL||reset_window)){
- oc_frame_metrics *fm;
- int nfm;
- int fmh;
- fm=(oc_frame_metrics *)_ogg_realloc(_enc->rc.frame_metrics,
- buf_delay*sizeof(*_enc->rc.frame_metrics));
- if(fm==NULL){
- /*We failed to allocate a finite buffer.*/
- /*If we don't have a valid 2-pass header yet, just return; we'll reset
- the buffer size when we read the header.*/
- if(_enc->rc.frames_total[0]==0)return;
- /*Otherwise revert to the largest finite buffer previously set, or to
- whole-file buffering if we were still using that.*/
- _enc->rc.buf_delay=_enc->rc.frame_metrics!=NULL?
- cfm:_enc->rc.frames_total[0]+_enc->rc.frames_total[1]
- +_enc->rc.frames_total[2];
- oc_enc_rc_resize(_enc);
- return;
- }
- _enc->rc.frame_metrics=fm;
- _enc->rc.cframe_metrics=buf_delay;
- /*Re-organize the circular buffer.*/
- fmh=_enc->rc.frame_metrics_head;
- nfm=_enc->rc.nframe_metrics;
- if(fmh+nfm>cfm){
- int shift;
- shift=OC_MINI(fmh+nfm-cfm,buf_delay-cfm);
- memcpy(fm+cfm,fm,OC_MINI(fmh+nfm-cfm,buf_delay-cfm)*sizeof(*fm));
- if(fmh+nfm>buf_delay)memmove(fm,fm+shift,fmh+nfm-buf_delay);
- }
- }
- /*We were using whole-file buffering; now we're not.*/
- if(reset_window){
- _enc->rc.nframes[0]=_enc->rc.nframes[1]=_enc->rc.nframes[2]=0;
- _enc->rc.scale_sum[0]=_enc->rc.scale_sum[1]=0;
- _enc->rc.scale_window_end=_enc->rc.scale_window0=
- _enc->state.curframe_num+_enc->prev_dup_count+1;
- if(_enc->rc.twopass_buffer_bytes){
- int qti;
- /*We already read the metrics for the first frame in the window.*/
- *(_enc->rc.frame_metrics)=*&_enc->rc.cur_metrics;
- _enc->rc.nframe_metrics++;
- qti=_enc->rc.cur_metrics.frame_type;
- _enc->rc.nframes[qti]++;
- _enc->rc.nframes[2]+=_enc->rc.cur_metrics.dup_count;
- _enc->rc.scale_sum[qti]+=oc_bexp_q24(_enc->rc.cur_metrics.log_scale);
- _enc->rc.scale_window_end+=_enc->rc.cur_metrics.dup_count+1;
- if(_enc->rc.scale_window_end-_enc->rc.scale_window0<buf_delay){
- /*We need more frame data.*/
- _enc->rc.twopass_buffer_bytes=0;
- }
- }
- }
- /*Otherwise, we could shrink the size of the current window, if necessary,
- but leaving it like it is lets us adapt to the new buffer size more
- gracefully.*/
- }
- }
- /*Scale the number of frames by the number of expected drops/duplicates.*/
- static int oc_rc_scale_drop(oc_rc_state *_rc,int _nframes){
- if(_rc->prev_drop_count>0||_rc->log_drop_scale>OC_Q57(0)){
- ogg_int64_t dup_scale;
- dup_scale=oc_bexp64((_rc->log_drop_scale
- +oc_blog64(_rc->prev_drop_count+1)>>1)+OC_Q57(8));
- if(dup_scale<_nframes<<8){
- int dup_scalei;
- dup_scalei=(int)dup_scale;
- if(dup_scalei>0)_nframes=((_nframes<<8)+dup_scalei-1)/dup_scalei;
- }
- else _nframes=!!_nframes;
- }
- return _nframes;
- }
- int oc_enc_select_qi(oc_enc_ctx *_enc,int _qti,int _clamp){
- ogg_int64_t rate_total;
- ogg_int64_t rate_bias;
- int nframes[2];
- int buf_delay;
- int buf_pad;
- ogg_int64_t log_qtarget;
- ogg_int64_t log_scale0;
- ogg_int64_t log_cur_scale;
- ogg_int64_t log_qexp;
- int exp0;
- int old_qi;
- int qi;
- /*Figure out how to re-distribute bits so that we hit our fullness target
- before the last keyframe in our current buffer window (after the current
- frame), or the end of the buffer window, whichever comes first.*/
- log_cur_scale=(ogg_int64_t)_enc->rc.scalefilter[_qti].y[0]<<33;
- buf_pad=0;
- switch(_enc->rc.twopass){
- default:{
- ogg_uint32_t next_key_frame;
- /*Single pass mode: assume only forced keyframes and attempt to estimate
- the drop count for VFR content.*/
- next_key_frame=_qti?_enc->keyframe_frequency_force
- -(_enc->state.curframe_num-_enc->state.keyframe_num):0;
- nframes[0]=(_enc->rc.buf_delay-OC_MINI(next_key_frame,_enc->rc.buf_delay)
- +_enc->keyframe_frequency_force-1)/_enc->keyframe_frequency_force;
- if(nframes[0]+_qti>1){
- nframes[0]--;
- buf_delay=next_key_frame+nframes[0]*_enc->keyframe_frequency_force;
- }
- else buf_delay=_enc->rc.buf_delay;
- nframes[1]=buf_delay-nframes[0];
- /*Downgrade the delta frame rate to correspond to the recent drop count
- history.*/
- nframes[1]=oc_rc_scale_drop(&_enc->rc,nframes[1]);
- }break;
- case 1:{
- /*Pass 1 mode: use a fixed qi value.*/
- qi=_enc->state.qis[0];
- _enc->rc.log_qtarget=_enc->log_qavg[_qti][qi];
- return qi;
- }break;
- case 2:{
- ogg_int64_t scale_sum[2];
- int qti;
- /*Pass 2 mode: we know exactly how much of each frame type there is in
- the current buffer window, and have estimates for the scales.*/
- nframes[0]=_enc->rc.nframes[0];
- nframes[1]=_enc->rc.nframes[1];
- scale_sum[0]=_enc->rc.scale_sum[0];
- scale_sum[1]=_enc->rc.scale_sum[1];
- /*The window size can be slightly larger than the buffer window for VFR
- content; clamp it down, if appropriate (the excess will all be dup
- frames).*/
- buf_delay=OC_MINI(_enc->rc.scale_window_end-_enc->rc.scale_window0,
- _enc->rc.buf_delay);
- /*If we're approaching the end of the file, add some slack to keep us
- from slamming into a rail.
- Our rate accuracy goes down, but it keeps the result sensible.
- We position the target where the first forced keyframe beyond the end
- of the file would be (for consistency with 1-pass mode).*/
- buf_pad=OC_MINI(_enc->rc.buf_delay,_enc->state.keyframe_num
- +_enc->keyframe_frequency_force-_enc->rc.scale_window0);
- if(buf_delay<buf_pad)buf_pad-=buf_delay;
- else{
- /*Otherwise, search for the last keyframe in the buffer window and
- target that.*/
- buf_pad=0;
- /*TODO: Currently we only do this when using a finite buffer; we could
- save the position of the last keyframe in the summary data and do it
- with a whole-file buffer as well, but it isn't likely to make a
- difference.*/
- if(_enc->rc.frame_metrics!=NULL){
- int fmi;
- int fm_tail;
- fm_tail=_enc->rc.frame_metrics_head+_enc->rc.nframe_metrics;
- if(fm_tail>=_enc->rc.cframe_metrics)fm_tail-=_enc->rc.cframe_metrics;
- for(fmi=fm_tail;;){
- oc_frame_metrics *m;
- fmi--;
- if(fmi<0)fmi+=_enc->rc.cframe_metrics;
- /*Stop before we remove the first frame.*/
- if(fmi==_enc->rc.frame_metrics_head)break;
- m=_enc->rc.frame_metrics+fmi;
- /*If we find a keyframe, remove it and everything past it.*/
- if(m->frame_type==OC_INTRA_FRAME){
- do{
- qti=m->frame_type;
- nframes[qti]--;
- scale_sum[qti]-=oc_bexp_q24(m->log_scale);
- buf_delay-=m->dup_count+1;
- fmi++;
- if(fmi>=_enc->rc.cframe_metrics)fmi=0;
- m=_enc->rc.frame_metrics+fmi;
- }
- while(fmi!=fm_tail);
- /*And stop scanning backwards.*/
- break;
- }
- }
- }
- }
- /*If we're not using the same frame type as in pass 1 (because someone
- changed the keyframe interval), remove that scale estimate.
- We'll add in a replacement for the correct frame type below.*/
- qti=_enc->rc.cur_metrics.frame_type;
- if(qti!=_qti){
- nframes[qti]--;
- scale_sum[qti]-=oc_bexp_q24(_enc->rc.cur_metrics.log_scale);
- }
- /*Compute log_scale estimates for each frame type from the pass-1 scales
- we measured in the current window.*/
- for(qti=0;qti<2;qti++){
- _enc->rc.log_scale[qti]=nframes[qti]>0?
- oc_blog64(scale_sum[qti])-oc_blog64(nframes[qti])-OC_Q57(24):
- -_enc->rc.log_npixels;
- }
- /*If we're not using the same frame type as in pass 1, add a scale
- estimate for the corresponding frame using the current low-pass
- filter value.
- This is mostly to ensure we have a valid estimate even when pass 1 had
- no frames of this type in the buffer window.
- TODO: We could also plan ahead and figure out how many keyframes we'll
- be forced to add in the current buffer window.*/
- qti=_enc->rc.cur_metrics.frame_type;
- if(qti!=_qti){
- ogg_int64_t scale;
- scale=_enc->rc.log_scale[_qti]<OC_Q57(23)?
- oc_bexp64(_enc->rc.log_scale[_qti]+OC_Q57(24)):0x7FFFFFFFFFFFLL;
- scale*=nframes[_qti];
- nframes[_qti]++;
- scale+=oc_bexp_q24(log_cur_scale>>33);
- _enc->rc.log_scale[_qti]=oc_blog64(scale)
- -oc_blog64(nframes[qti])-OC_Q57(24);
- }
- else log_cur_scale=(ogg_int64_t)_enc->rc.cur_metrics.log_scale<<33;
- /*Add the padding from above.
- This basically reverts to 1-pass estimations in the last keyframe
- interval.*/
- if(buf_pad>0){
- ogg_int64_t scale;
- int nextra_frames;
- /*Extend the buffer.*/
- buf_delay+=buf_pad;
- /*Add virtual delta frames according to the estimated drop count.*/
- nextra_frames=oc_rc_scale_drop(&_enc->rc,buf_pad);
- /*And blend in the low-pass filtered scale according to how many frames
- we added.*/
- scale=
- oc_bexp64(_enc->rc.log_scale[1]+OC_Q57(24))*(ogg_int64_t)nframes[1]
- +oc_bexp_q24(_enc->rc.scalefilter[1].y[0])*(ogg_int64_t)nextra_frames;
- nframes[1]+=nextra_frames;
- _enc->rc.log_scale[1]=oc_blog64(scale)-oc_blog64(nframes[1])-OC_Q57(24);
- }
- }break;
- }
- /*If we've been missing our target, add a penalty term.*/
- rate_bias=(_enc->rc.rate_bias/(_enc->state.curframe_num+1000))*
- (buf_delay-buf_pad);
- /*rate_total is the total bits available over the next buf_delay frames.*/
- rate_total=_enc->rc.fullness-_enc->rc.target+rate_bias
- +buf_delay*_enc->rc.bits_per_frame;
- log_scale0=_enc->rc.log_scale[_qti]+_enc->rc.log_npixels;
- /*If there aren't enough bits to achieve our desired fullness level, use the
- minimum quality permitted.*/
- if(rate_total<=buf_delay)log_qtarget=OC_QUANT_MAX_LOG;
- else{
- static const ogg_int64_t LOG_KEY_RATIO=0x0137222BB70747BALL;
- ogg_int64_t log_scale1;
- ogg_int64_t rlo;
- ogg_int64_t rhi;
- log_scale1=_enc->rc.log_scale[1-_qti]+_enc->rc.log_npixels;
- rlo=0;
- rhi=(rate_total+nframes[_qti]-1)/nframes[_qti];
- while(rlo<rhi){
- ogg_int64_t curr;
- ogg_int64_t rdiff;
- ogg_int64_t log_rpow;
- ogg_int64_t rscale;
- curr=rlo+rhi>>1;
- log_rpow=oc_blog64(curr)-log_scale0;
- log_rpow=(log_rpow+(_enc->rc.exp[_qti]>>1))/_enc->rc.exp[_qti];
- if(_qti)log_rpow+=LOG_KEY_RATIO>>6;
- else log_rpow-=LOG_KEY_RATIO>>6;
- log_rpow*=_enc->rc.exp[1-_qti];
- rscale=nframes[1-_qti]*oc_bexp64(log_scale1+log_rpow);
- rdiff=nframes[_qti]*curr+rscale-rate_total;
- if(rdiff<0)rlo=curr+1;
- else if(rdiff>0)rhi=curr-1;
- else break;
- }
- log_qtarget=OC_Q57(2)-((oc_blog64(rlo)-log_scale0+(_enc->rc.exp[_qti]>>1))/
- _enc->rc.exp[_qti]<<6);
- log_qtarget=OC_MINI(log_qtarget,OC_QUANT_MAX_LOG);
- }
- /*The above allocation looks only at the total rate we'll accumulate in the
- next buf_delay frames.
- However, we could overflow the buffer on the very next frame, so check for
- that here, if we're not using a soft target.*/
- exp0=_enc->rc.exp[_qti];
- if(_enc->rc.cap_overflow){
- ogg_int64_t margin;
- ogg_int64_t soft_limit;
- ogg_int64_t log_soft_limit;
- /*Allow 3% of the buffer for prediction error.
- This should be plenty, and we don't mind if we go a bit over; we only
- want to keep these bits from being completely wasted.*/
- margin=_enc->rc.max+31>>5;
- /*We want to use at least this many bits next frame.*/
- soft_limit=_enc->rc.fullness+_enc->rc.bits_per_frame-(_enc->rc.max-margin);
- log_soft_limit=oc_blog64(soft_limit);
- /*If we're predicting we won't use that many...*/
- log_qexp=(log_qtarget-OC_Q57(2)>>6)*exp0;
- if(log_scale0-log_qexp<log_soft_limit){
- /*Scale the adjustment based on how far into the margin we are.*/
- log_qexp+=(log_scale0-log_soft_limit-log_qexp>>32)*
- ((OC_MINI(margin,soft_limit)<<32)/margin);
- log_qtarget=((log_qexp+(exp0>>1))/exp0<<6)+OC_Q57(2);
- }
- }
- /*If this was not one of the initial frames, limit the change in quality.*/
- old_qi=_enc->state.qis[0];
- if(_clamp){
- ogg_int64_t log_qmin;
- ogg_int64_t log_qmax;
- /*Clamp the target quantizer to within [0.8*Q,1.2*Q], where Q is the
- current quantizer.
- TODO: With user-specified quant matrices, we need to enlarge these limits
- if they don't actually let us change qi values.*/
- log_qmin=_enc->log_qavg[_qti][old_qi]-0x00A4D3C25E68DC58LL;
- log_qmax=_enc->log_qavg[_qti][old_qi]+0x00A4D3C25E68DC58LL;
- log_qtarget=OC_CLAMPI(log_qmin,log_qtarget,log_qmax);
- }
- /*The above allocation looks only at the total rate we'll accumulate in the
- next buf_delay frames.
- However, we could bust the budget on the very next frame, so check for that
- here, if we're not using a soft target.*/
- /* Disabled when our minimum qi > 0; if we saturate log_qtarget to
- to the maximum possible size when we have a minimum qi, the
- resulting lambda will interact very strangely with SKIP. The
- resulting artifacts look like waterfalls. */
- if(_enc->state.info.quality==0){
- ogg_int64_t log_hard_limit;
- /*Compute the maximum number of bits we can use in the next frame.
- Allow 50% of the rate for a single frame for prediction error.
- This may not be enough for keyframes or sudden changes in complexity.*/
- log_hard_limit=oc_blog64(_enc->rc.fullness+(_enc->rc.bits_per_frame>>1));
- /*If we're predicting we'll use more than this...*/
- log_qexp=(log_qtarget-OC_Q57(2)>>6)*exp0;
- if(log_scale0-log_qexp>log_hard_limit){
- /*Force the target to hit our limit exactly.*/
- log_qexp=log_scale0-log_hard_limit;
- log_qtarget=((log_qexp+(exp0>>1))/exp0<<6)+OC_Q57(2);
- /*If that target is unreasonable, oh well; we'll have to drop.*/
- log_qtarget=OC_MINI(log_qtarget,OC_QUANT_MAX_LOG);
- }
- }
- /*Compute a final estimate of the number of bits we plan to use.*/
- log_qexp=(log_qtarget-OC_Q57(2)>>6)*_enc->rc.exp[_qti];
- _enc->rc.rate_bias+=oc_bexp64(log_cur_scale+_enc->rc.log_npixels-log_qexp);
- qi=oc_enc_find_qi_for_target(_enc,_qti,old_qi,
- _enc->state.info.quality,log_qtarget);
- /*Save the quantizer target for lambda calculations.*/
- _enc->rc.log_qtarget=log_qtarget;
- return qi;
- }
- int oc_enc_update_rc_state(oc_enc_ctx *_enc,
- long _bits,int _qti,int _qi,int _trial,int _droppable){
- ogg_int64_t buf_delta;
- ogg_int64_t log_scale;
- int dropped;
- dropped=0;
- /* Drop frames also disabled for now in the case of infinite-buffer
- two-pass mode */
- if(!_enc->rc.drop_frames||_enc->rc.twopass&&_enc->rc.frame_metrics==NULL){
- _droppable=0;
- }
- buf_delta=_enc->rc.bits_per_frame*(1+_enc->dup_count);
- if(_bits<=0){
- /*We didn't code any blocks in this frame.*/
- log_scale=OC_Q57(-64);
- _bits=0;
- }
- else{
- ogg_int64_t log_bits;
- ogg_int64_t log_qexp;
- /*Compute the estimated scale factor for this frame type.*/
- log_bits=oc_blog64(_bits);
- log_qexp=_enc->rc.log_qtarget-OC_Q57(2);
- log_qexp=(log_qexp>>6)*(_enc->rc.exp[_qti]);
- log_scale=OC_MINI(log_bits-_enc->rc.log_npixels+log_qexp,OC_Q57(16));
- }
- /*Special two-pass processing.*/
- switch(_enc->rc.twopass){
- case 1:{
- /*Pass 1 mode: save the metrics for this frame.*/
- _enc->rc.cur_metrics.log_scale=oc_q57_to_q24(log_scale);
- _enc->rc.cur_metrics.dup_count=_enc->dup_count;
- _enc->rc.cur_metrics.frame_type=_enc->state.frame_type;
- _enc->rc.twopass_buffer_bytes=0;
- }break;
- case 2:{
- /*Pass 2 mode:*/
- if(!_trial){
- ogg_int64_t next_frame_num;
- int qti;
- /*Move the current metrics back one frame.*/
- *&_enc->rc.prev_metrics=*&_enc->rc.cur_metrics;
- next_frame_num=_enc->state.curframe_num+_enc->dup_count+1;
- /*Back out the last frame's statistics from the sliding window.*/
- qti=_enc->rc.prev_metrics.frame_type;
- _enc->rc.frames_left[qti]--;
- _enc->rc.frames_left[2]-=_enc->rc.prev_metrics.dup_count;
- _enc->rc.nframes[qti]--;
- _enc->rc.nframes[2]-=_enc->rc.prev_metrics.dup_count;
- _enc->rc.scale_sum[qti]-=oc_bexp_q24(_enc->rc.prev_metrics.log_scale);
- _enc->rc.scale_window0=(int)next_frame_num;
- /*Free the corresponding entry in the circular buffer.*/
- if(_enc->rc.frame_metrics!=NULL){
- _enc->rc.nframe_metrics--;
- _enc->rc.frame_metrics_head++;
- if(_enc->rc.frame_metrics_head>=_enc->rc.cframe_metrics){
- _enc->rc.frame_metrics_head=0;
- }
- }
- /*Mark us ready for the next 2-pass packet.*/
- _enc->rc.twopass_buffer_bytes=0;
- /*Update state, so the user doesn't have to keep calling 2pass_in after
- they've fed in all the data when we're using a finite buffer.*/
- _enc->prev_dup_count=_enc->dup_count;
- oc_enc_rc_2pass_in(_enc,NULL,0);
- }
- }break;
- }
- /*Common to all passes:*/
- if(_bits>0){
- if(_trial){
- oc_iir_filter *f;
- /*Use the estimated scale factor directly if this was a trial.*/
- f=_enc->rc.scalefilter+_qti;
- f->y[1]=f->y[0]=f->x[1]=f->x[0]=oc_q57_to_q24(log_scale);
- _enc->rc.log_scale[_qti]=log_scale;
- }
- else{
- /*Lengthen the time constant for the INTER filter as we collect more
- frame statistics, until we reach our target.*/
- if(_enc->rc.inter_delay<_enc->rc.inter_delay_target&&
- _enc->rc.inter_count>=_enc->rc.inter_delay&&_qti==OC_INTER_FRAME){
- oc_iir_filter_reinit(&_enc->rc.scalefilter[1],++_enc->rc.inter_delay);
- }
- /*Otherwise update the low-pass scale filter for this frame type,
- regardless of whether or not we dropped this frame.*/
- _enc->rc.log_scale[_qti]=oc_iir_filter_update(
- _enc->rc.scalefilter+_qti,oc_q57_to_q24(log_scale))<<33;
- /*If this frame busts our budget, it must be dropped.*/
- if(_droppable&&_enc->rc.fullness+buf_delta<_bits){
- _enc->rc.prev_drop_count+=1+_enc->dup_count;
- _bits=0;
- dropped=1;
- }
- else{
- ogg_uint32_t drop_count;
- /*Update a low-pass filter to estimate the "real" frame rate taking
- drops and duplicates into account.
- This is only done if the frame is coded, as it needs the final
- count of dropped frames.*/
- drop_count=_enc->rc.prev_drop_count+1;
- if(drop_count>0x7F)drop_count=0x7FFFFFFF;
- else drop_count<<=24;
- _enc->rc.log_drop_scale=oc_blog64(oc_iir_filter_update(
- &_enc->rc.vfrfilter,drop_count))-OC_Q57(24);
- /*Initialize the drop count for this frame to the user-requested dup
- count.
- It will be increased if we drop more frames.*/
- _enc->rc.prev_drop_count=_enc->dup_count;
- }
- }
- /*Increment the INTER frame count, for filter adaptation purposes.*/
- if(_enc->rc.inter_count<INT_MAX)_enc->rc.inter_count+=_qti;
- }
- /*Increase the drop count.*/
- else _enc->rc.prev_drop_count+=1+_enc->dup_count;
- /*And update the buffer fullness level.*/
- if(!_trial){
- _enc->rc.fullness+=buf_delta-_bits;
- /*If we're too quick filling the buffer and overflow is capped,
- that rate is lost forever.*/
- if(_enc->rc.cap_overflow&&_enc->rc.fullness>_enc->rc.max){
- _enc->rc.fullness=_enc->rc.max;
- }
- /*If we're too quick draining the buffer and underflow is capped,
- don't try to make up that rate later.*/
- if(_enc->rc.cap_underflow&&_enc->rc.fullness<0){
- _enc->rc.fullness=0;
- }
- /*Adjust the bias for the real bits we've used.*/
- _enc->rc.rate_bias-=_bits;
- }
- return dropped;
- }
- #define OC_RC_2PASS_VERSION (1)
- #define OC_RC_2PASS_HDR_SZ (38)
- #define OC_RC_2PASS_PACKET_SZ (8)
- static void oc_rc_buffer_val(oc_rc_state *_rc,ogg_int64_t _val,int _bytes){
- while(_bytes-->0){
- _rc->twopass_buffer[_rc->twopass_buffer_bytes++]=(unsigned char)(_val&0xFF);
- _val>>=8;
- }
- }
- int oc_enc_rc_2pass_out(oc_enc_ctx *_enc,unsigned char **_buf){
- if(_enc->rc.twopass_buffer_bytes==0){
- if(_enc->rc.twopass==0){
- int qi;
- /*Pick first-pass qi for scale calculations.*/
- qi=oc_enc_select_qi(_enc,0,0);
- _enc->state.nqis=1;
- _enc->state.qis[0]=qi;
- _enc->rc.twopass=1;
- _enc->rc.frames_total[0]=_enc->rc.frames_total[1]=
- _enc->rc.frames_total[2]=0;
- _enc->rc.scale_sum[0]=_enc->rc.scale_sum[1]=0;
- /*Fill in dummy summary values.*/
- oc_rc_buffer_val(&_enc->rc,0x5032544F,4);
- oc_rc_buffer_val(&_enc->rc,OC_RC_2PASS_VERSION,4);
- oc_rc_buffer_val(&_enc->rc,0,OC_RC_2PASS_HDR_SZ-8);
- }
- else{
- int qti;
- qti=_enc->rc.cur_metrics.frame_type;
- _enc->rc.scale_sum[qti]+=oc_bexp_q24(_enc->rc.cur_metrics.log_scale);
- _enc->rc.frames_total[qti]++;
- _enc->rc.frames_total[2]+=_enc->rc.cur_metrics.dup_count;
- oc_rc_buffer_val(&_enc->rc,
- _enc->rc.cur_metrics.dup_count|_enc->rc.cur_metrics.frame_type<<31,4);
- oc_rc_buffer_val(&_enc->rc,_enc->rc.cur_metrics.log_scale,4);
- }
- }
- else if(_enc->packet_state==OC_PACKET_DONE&&
- _enc->rc.twopass_buffer_bytes!=OC_RC_2PASS_HDR_SZ){
- _enc->rc.twopass_buffer_bytes=0;
- oc_rc_buffer_val(&_enc->rc,0x5032544F,4);
- oc_rc_buffer_val(&_enc->rc,OC_RC_2PASS_VERSION,4);
- oc_rc_buffer_val(&_enc->rc,_enc->rc.frames_total[0],4);
- oc_rc_buffer_val(&_enc->rc,_enc->rc.frames_total[1],4);
- oc_rc_buffer_val(&_enc->rc,_enc->rc.frames_total[2],4);
- oc_rc_buffer_val(&_enc->rc,_enc->rc.exp[0],1);
- oc_rc_buffer_val(&_enc->rc,_enc->rc.exp[1],1);
- oc_rc_buffer_val(&_enc->rc,_enc->rc.scale_sum[0],8);
- oc_rc_buffer_val(&_enc->rc,_enc->rc.scale_sum[1],8);
- }
- else{
- /*The data for this frame has already been retrieved.*/
- *_buf=NULL;
- return 0;
- }
- *_buf=_enc->rc.twopass_buffer;
- return _enc->rc.twopass_buffer_bytes;
- }
- static size_t oc_rc_buffer_fill(oc_rc_state *_rc,
- unsigned char *_buf,size_t _bytes,size_t _consumed,size_t _goal){
- while(_rc->twopass_buffer_fill<_goal&&_consumed<_bytes){
- _rc->twopass_buffer[_rc->twopass_buffer_fill++]=_buf[_consumed++];
- }
- return _consumed;
- }
- static ogg_int64_t oc_rc_unbuffer_val(oc_rc_state *_rc,int _bytes){
- ogg_int64_t ret;
- int shift;
- ret=0;
- shift=0;
- while(_bytes-->0){
- ret|=((ogg_int64_t)_rc->twopass_buffer[_rc->twopass_buffer_bytes++])<<shift;
- shift+=8;
- }
- return ret;
- }
- int oc_enc_rc_2pass_in(oc_enc_ctx *_enc,unsigned char *_buf,size_t _bytes){
- size_t consumed;
- consumed=0;
- /*Enable pass 2 mode if this is the first call.*/
- if(_enc->rc.twopass==0){
- _enc->rc.twopass=2;
- _enc->rc.twopass_buffer_fill=0;
- _enc->rc.frames_total[0]=0;
- _enc->rc.nframe_metrics=0;
- _enc->rc.cframe_metrics=0;
- _enc->rc.frame_metrics_head=0;
- _enc->rc.scale_window0=0;
- _enc->rc.scale_window_end=0;
- }
- /*If we haven't got a valid summary header yet, try to parse one.*/
- if(_enc->rc.frames_total[0]==0){
- if(!_buf){
- int frames_needed;
- /*If we're using a whole-file buffer, we just need the first frame.
- Otherwise, we may need as many as one per buffer slot.*/
- frames_needed=_enc->rc.frame_metrics==NULL?1:_enc->rc.buf_delay;
- return OC_RC_2PASS_HDR_SZ+frames_needed*OC_RC_2PASS_PACKET_SZ
- -_enc->rc.twopass_buffer_fill;
- }
- consumed=oc_rc_buffer_fill(&_enc->rc,
- _buf,_bytes,consumed,OC_RC_2PASS_HDR_SZ);
- if(_enc->rc.twopass_buffer_fill>=OC_RC_2PASS_HDR_SZ){
- ogg_int64_t scale_sum[2];
- int exp[2];
- int buf_delay;
- /*Read the summary header data.*/
- /*Check the magic value and version number.*/
- if(oc_rc_unbuffer_val(&_enc->rc,4)!=0x5032544F||
- oc_rc_unbuffer_val(&_enc->rc,4)!=OC_RC_2PASS_VERSION){
- _enc->rc.twopass_buffer_bytes=0;
- return TH_ENOTFORMAT;
- }
- _enc->rc.frames_total[0]=(ogg_uint32_t)oc_rc_unbuffer_val(&_enc->rc,4);
- _enc->rc.frames_total[1]=(ogg_uint32_t)oc_rc_unbuffer_val(&_enc->rc,4);
- _enc->rc.frames_total[2]=(ogg_uint32_t)oc_rc_unbuffer_val(&_enc->rc,4);
- exp[0]=(int)oc_rc_unbuffer_val(&_enc->rc,1);
- exp[1]=(int)oc_rc_unbuffer_val(&_enc->rc,1);
- scale_sum[0]=oc_rc_unbuffer_val(&_enc->rc,8);
- scale_sum[1]=oc_rc_unbuffer_val(&_enc->rc,8);
- /*Make sure the file claims to have at least one frame.
- Otherwise we probably got the placeholder data from an aborted pass 1.
- Also make sure the total frame count doesn't overflow an integer.*/
- buf_delay=_enc->rc.frames_total[0]+_enc->rc.frames_total[1]
- +_enc->rc.frames_total[2];
- if(_enc->rc.frames_total[0]==0||buf_delay<0||
- (ogg_uint32_t)buf_delay<_enc->rc.frames_total[0]||
- (ogg_uint32_t)buf_delay<_enc->rc.frames_total[1]){
- _enc->rc.frames_total[0]=0;
- _enc->rc.twopass_buffer_bytes=0;
- return TH_EBADHEADER;
- }
- /*Got a valid header; set up pass 2.*/
- _enc->rc.frames_left[0]=_enc->rc.frames_total[0];
- _enc->rc.frames_left[1]=_enc->rc.frames_total[1];
- _enc->rc.frames_left[2]=_enc->rc.frames_total[2];
- /*If the user hasn't specified a buffer size, use the whole file.*/
- if(_enc->rc.frame_metrics==NULL){
- _enc->rc.buf_delay=buf_delay;
- _enc->rc.nframes[0]=_enc->rc.frames_total[0];
- _enc->rc.nframes[1]=_enc->rc.frames_total[1];
- _enc->rc.nframes[2]=_enc->rc.frames_total[2];
- _enc->rc.scale_sum[0]=scale_sum[0];
- _enc->rc.scale_sum[1]=scale_sum[1];
- _enc->rc.scale_window_end=buf_delay;
- oc_enc_rc_reset(_enc);
- }
- _enc->rc.exp[0]=exp[0];
- _enc->rc.exp[1]=exp[1];
- /*Clear the header data from the buffer to make room for packet data.*/
- _enc->rc.twopass_buffer_fill=0;
- _enc->rc.twopass_buffer_bytes=0;
- }
- }
- if(_enc->rc.frames_total[0]!=0){
- ogg_int64_t curframe_num;
- int nframes_total;
- curframe_num=_enc->state.curframe_num;
- if(curframe_num>=0){
- /*We just encoded a frame; make sure things matched.*/
- if(_enc->rc.prev_metrics.dup_count!=_enc->prev_dup_count){
- _enc->rc.twopass_buffer_bytes=0;
- return TH_EINVAL;
- }
- }
- curframe_num+=_enc->prev_dup_count+1;
- nframes_total=_enc->rc.frames_total[0]+_enc->rc.frames_total[1]
- +_enc->rc.frames_total[2];
- if(curframe_num>=nframes_total){
- /*We don't want any more data after the last frame, and we don't want to
- allow any more frames to be encoded.*/
- _enc->rc.twopass_buffer_bytes=0;
- }
- else if(_enc->rc.twopass_buffer_bytes==0){
- if(_enc->rc.frame_metrics==NULL){
- /*We're using a whole-file buffer:*/
- if(!_buf)return OC_RC_2PASS_PACKET_SZ-_enc->rc.twopass_buffer_fill;
- consumed=oc_rc_buffer_fill(&_enc->rc,
- _buf,_bytes,consumed,OC_RC_2PASS_PACKET_SZ);
- if(_enc->rc.twopass_buffer_fill>=OC_RC_2PASS_PACKET_SZ){
- ogg_uint32_t dup_count;
- ogg_int32_t log_scale;
- int qti;
- int arg;
- /*Read the metrics for the next frame.*/
- dup_count=oc_rc_unbuffer_val(&_enc->rc,4);
- log_scale=oc_rc_unbuffer_val(&_enc->rc,4);
- _enc->rc.cur_metrics.log_scale=log_scale;
- qti=(dup_count&0x80000000)>>31;
- _enc->rc.cur_metrics.dup_count=dup_count&0x7FFFFFFF;
- _enc->rc.cur_metrics.frame_type=qti;
- _enc->rc.twopass_force_kf=qti==OC_INTRA_FRAME;
- /*"Helpfully" set the dup count back to what it was in pass 1.*/
- arg=_enc->rc.cur_metrics.dup_count;
- th_encode_ctl(_enc,TH_ENCCTL_SET_DUP_COUNT,&arg,sizeof(arg));
- /*Clear the buffer for the next frame.*/
- _enc->rc.twopass_buffer_fill=0;
- }
- }
- else{
- int frames_needed;
- /*We're using a finite buffer:*/
- frames_needed=OC_CLAMPI(0,_enc->rc.buf_delay
- -(_enc->rc.scale_window_end-_enc->rc.scale_window0),
- _enc->rc.frames_left[0]+_enc->rc.frames_left[1]
- -_enc->rc.nframes[0]-_enc->rc.nframes[1]);
- while(frames_needed>0){
- if(!_buf){
- return OC_RC_2PASS_PACKET_SZ*frames_needed
- -_enc->rc.twopass_buffer_fill;
- }
- consumed=oc_rc_buffer_fill(&_enc->rc,
- _buf,_bytes,consumed,OC_RC_2PASS_PACKET_SZ);
- if(_enc->rc.twopass_buffer_fill>=OC_RC_2PASS_PACKET_SZ){
- oc_frame_metrics *m;
- int fmi;
- ogg_uint32_t dup_count;
- ogg_int32_t log_scale;
- int qti;
- /*Read the metrics for the next frame.*/
- dup_count=oc_rc_unbuffer_val(&_enc->rc,4);
- log_scale=oc_rc_unbuffer_val(&_enc->rc,4);
- /*Add the to the circular buffer.*/
- fmi=_enc->rc.frame_metrics_head+_enc->rc.nframe_metrics++;
- if(fmi>=_enc->rc.cframe_metrics)fmi-=_enc->rc.cframe_metrics;
- m=_enc->rc.frame_metrics+fmi;
- m->log_scale=log_scale;
- qti=(dup_count&0x80000000)>>31;
- m->dup_count=dup_count&0x7FFFFFFF;
- m->frame_type=qti;
- /*And accumulate the statistics over the window.*/
- _enc->rc.nframes[qti]++;
- _enc->rc.nframes[2]+=m->dup_count;
- _enc->rc.scale_sum[qti]+=oc_bexp_q24(m->log_scale);
- _enc->rc.scale_window_end+=m->dup_count+1;
- /*Compute an upper bound on the number of remaining packets needed
- for the current window.*/
- frames_needed=OC_CLAMPI(0,_enc->rc.buf_delay
- -(_enc->rc.scale_window_end-_enc->rc.scale_window0),
- _enc->rc.frames_left[0]+_enc->rc.frames_left[1]
- -_enc->rc.nframes[0]-_enc->rc.nframes[1]);
- /*Clear the buffer for the next frame.*/
- _enc->rc.twopass_buffer_fill=0;
- _enc->rc.twopass_buffer_bytes=0;
- }
- /*Go back for more data.*/
- else break;
- }
- /*If we've got all the frames we need, fill in the current metrics.
- We're ready to go.*/
- if(frames_needed<=0){
- int arg;
- *&_enc->rc.cur_metrics=
- *(_enc->rc.frame_metrics+_enc->rc.frame_metrics_head);
- _enc->rc.twopass_force_kf=
- _enc->rc.cur_metrics.frame_type==OC_INTRA_FRAME;
- /*"Helpfully" set the dup count back to what it was in pass 1.*/
- arg=_enc->rc.cur_metrics.dup_count;
- th_encode_ctl(_enc,TH_ENCCTL_SET_DUP_COUNT,&arg,sizeof(arg));
- /*Mark us ready for the next frame.*/
- _enc->rc.twopass_buffer_bytes=1;
- }
- }
- }
- }
- return (int)consumed;
- }
|