[xiph-commits] r16483 - trunk/theora/lib
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Tue Aug 18 14:56:31 PDT 2009
Author: xiphmont
Date: 2009-08-18 14:56:31 -0700 (Tue, 18 Aug 2009)
New Revision: 16483
Modified:
trunk/theora/lib/encint.h
trunk/theora/lib/rate.c
Log:
Commit derf's "simple_bias" patch to add a simpler but also more
robust rate-error bias correction to two-pass encoding mode. It
doesn't hold a specific rate quite as tightly, but is also not prone
to being thrown way off by assymetrical scale error between passes.
Modified: trunk/theora/lib/encint.h
===================================================================
--- trunk/theora/lib/encint.h 2009-08-14 06:14:33 UTC (rev 16482)
+++ trunk/theora/lib/encint.h 2009-08-18 21:56:31 UTC (rev 16483)
@@ -35,7 +35,6 @@
typedef struct oc_mb_enc_info oc_mb_enc_info;
typedef struct oc_mode_scheme_chooser oc_mode_scheme_chooser;
typedef struct oc_iir_filter oc_iir_filter;
-typedef struct oc_log_linear_fit oc_log_linear_fit;
typedef struct oc_frame_metrics oc_frame_metrics;
typedef struct oc_rc_state oc_rc_state;
typedef struct th_enc_ctx oc_enc_ctx;
@@ -183,17 +182,6 @@
-/*A linear fit for the log-domain scale factors used in 2-pass.*/
-struct oc_log_linear_fit{
- ogg_int64_t x;
- ogg_int64_t y;
- ogg_int64_t x2;
- ogg_int64_t xy;
- ogg_uint32_t n;
-};
-
-
-
/*The 2-pass metrics associated with a single frame.*/
struct oc_frame_metrics{
/*The log base 2 of the scale factor for this frame in Q24 format.*/
@@ -282,8 +270,8 @@
/*The frame count of each type in the current 2-pass window; this does not
include dup frames.*/
int nframes[3];
- /*Bias correction fits for the 1st-pass scale factors.*/
- oc_log_linear_fit corr[2];
+ /*The total accumulated estimation bias.*/
+ ogg_int64_t rate_bias;
};
Modified: trunk/theora/lib/rate.c
===================================================================
--- trunk/theora/lib/rate.c 2009-08-14 06:14:33 UTC (rev 16482)
+++ trunk/theora/lib/rate.c 2009-08-18 21:56:31 UTC (rev 16483)
@@ -303,6 +303,7 @@
_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.
@@ -436,15 +437,21 @@
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;
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;
+ oc_restore_fpu(&_enc->state);
/*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;
switch(_enc->rc.twopass){
default:{
ogg_uint32_t next_key_frame;
@@ -539,46 +546,12 @@
nframes[qti]--;
scale_sum[qti]-=oc_bexp_q24(_enc->rc.cur_metrics.log_scale);
}
- /*Compute corrected log_scale estimates for each frame type from the
- pass-1 scales we measured in the current window.*/
+ /*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++){
- oc_log_linear_fit *fit;
- ogg_int64_t x;
- x=nframes[qti]>0?
+ _enc->rc.log_scale[qti]=nframes[qti]>0?
oc_blog64(scale_sum[qti])-oc_blog64(nframes[qti])-OC_Q57(24):
-_enc->rc.log_npixels;
- fit=_enc->rc.corr+qti;
- if(fit->n>0){
- ogg_int64_t var;
- ogg_uint32_t n_2;
- n_2=fit->n>>1;
- var=fit->x2;
- var-=(fit->x+2048>>12)*(((fit->x+2048>>12)+n_2)/fit->n);
- if(var>fit->n){
- ogg_int64_t cov;
- ogg_int64_t beta;
- ogg_int64_t alpha;
- ogg_int64_t y;
- cov=fit->xy;
- cov-=(fit->y+2048>>12)*(((fit->x+2048>>12)+n_2)/fit->n);
- /*beta is Q33.*/
- beta=((cov+n_2)/fit->n<<33)/((var+n_2)/fit->n);
- /*alpha is Q57.*/
- alpha=((fit->y+n_2)/fit->n<<33)-beta*((fit->x+n_2)/fit->n);
- /*Predict the mean y from the mean x.
- What we're really trying to compensate for is error in exp[], not
- error in the scales, and hence we can apply the correction to
- the mean scale instead of applying it to each pass-1 scale and
- then taking the mean.*/
- y=(x+((ogg_int64_t)1<<32)>>33)*beta+alpha;
- /*If we have enough points for a good estimation, use the corrected
- predictor value directly.*/
- if(fit->n>=(128<<qti))x=y;
- /*Otherwise interpolate between the two.*/
- else x+=fit->n*(y-x>>7+qti);
- }
- }
- _enc->rc.log_scale[qti]=x;
}
/*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
@@ -594,10 +567,11 @@
oc_bexp64(_enc->rc.log_scale[_qti]+OC_Q57(24)):0x7FFFFFFFFFFFLL;
scale*=nframes[_qti];
nframes[_qti]++;
- scale+=oc_bexp_q24(_enc->rc.scalefilter[_qti].y[0]);
+ 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.*/
@@ -618,8 +592,10 @@
}
}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;
/*rate_total is the total bits available over the next buf_delay frames.*/
- rate_total=_enc->rc.fullness-_enc->rc.target
+ 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
@@ -658,12 +634,11 @@
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;
- ogg_int64_t log_qexp;
- int exp0;
/*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.*/
@@ -672,7 +647,6 @@
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...*/
- exp0=_enc->rc.exp[_qti];
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.*/
@@ -700,14 +674,11 @@
here, if we're not using a soft target.*/
if(!_enc->rc.cap_underflow||_enc->rc.drop_frames){
ogg_int64_t log_hard_limit;
- ogg_int64_t log_qexp;
- int exp0;
/*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...*/
- exp0=_enc->rc.exp[_qti];
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.*/
@@ -717,6 +688,9 @@
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.*/
@@ -759,29 +733,6 @@
}break;
case 2:{
/*Pass 2 mode:*/
- /*Accumulate statistics for estimation bias correction.
- Everything is done in Q24 format.*/
- if(_bits>0&&_enc->rc.cur_metrics.frame_type==_qti){
- oc_log_linear_fit *fit;
- ogg_int64_t x;
- ogg_int64_t y;
- x=_enc->rc.cur_metrics.log_scale;
- y=log_scale>>33;
- fit=_enc->rc.corr+_qti;
- /*Use long-term exponential moving averages for the fit statistics.*/
- if(fit->n>=1000){
- fit->n>>=1;
- fit->x>>=1;
- fit->y>>=1;
- fit->x2>>=1;
- fit->xy>>=1;
- }
- fit->n++;
- fit->x+=x;
- fit->y+=y;
- fit->x2+=(x+2048>>12)*(x+2048>>12);
- fit->xy+=(x+2048>>12)*(y+2048>>12);
- }
if(!_trial){
ogg_int64_t next_frame_num;
int qti;
@@ -866,6 +817,8 @@
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;
}
@@ -1024,7 +977,6 @@
}
_enc->rc.exp[0]=exp[0];
_enc->rc.exp[1]=exp[1];
- memset(_enc->rc.corr,0,sizeof(_enc->rc.corr));
/*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;
More information about the commits
mailing list