[xiph-commits] r16447 - trunk/theora/lib
xiphmont at svn.xiph.org
xiphmont at svn.xiph.org
Thu Aug 6 15:05:48 PDT 2009
Author: xiphmont
Date: 2009-08-06 15:05:48 -0700 (Thu, 06 Aug 2009)
New Revision: 16447
Modified:
trunk/theora/lib/encint.h
trunk/theora/lib/internal.h
trunk/theora/lib/rate.c
Log:
Commit fix for rate control 'scale' parameter calculations hitting the
maximum value clamp hard (as seen in the clip huskies_cif.y4m).
Also, temporarily disable all frame dropping in two-pass as it does
not yet work properly and never did.
Bump vendor version string to 20090806
Modified: trunk/theora/lib/encint.h
===================================================================
--- trunk/theora/lib/encint.h 2009-08-06 21:34:57 UTC (rev 16446)
+++ trunk/theora/lib/encint.h 2009-08-06 22:05:48 UTC (rev 16447)
@@ -188,7 +188,8 @@
/*The 2-pass metrics associated with a single frame.*/
struct oc_frame_metrics{
- ogg_int32_t scale;
+ ogg_int64_t log_scale; /* Q24; int64 to avoid casting each time we
+ wish to convert back to Q57 */
unsigned dup_count:31;
unsigned frame_type:1;
};
Modified: trunk/theora/lib/internal.h
===================================================================
--- trunk/theora/lib/internal.h 2009-08-06 21:34:57 UTC (rev 16446)
+++ trunk/theora/lib/internal.h 2009-08-06 22:05:48 UTC (rev 16447)
@@ -72,7 +72,7 @@
/*This library's version.*/
-# define OC_VENDOR_STRING "Xiph.Org libtheora 1.1 20090805 (Thusnelda)"
+# define OC_VENDOR_STRING "Xiph.Org libtheora 1.1 20090806 (Thusnelda)"
/*Theora bitstream version.*/
# define TH_VERSION_MAJOR (3)
Modified: trunk/theora/lib/rate.c
===================================================================
--- trunk/theora/lib/rate.c 2009-08-06 21:34:57 UTC (rev 16446)
+++ trunk/theora/lib/rate.c 2009-08-06 22:05:48 UTC (rev 16447)
@@ -112,8 +112,6 @@
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.*/
@@ -193,19 +191,20 @@
/*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_bexp_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;
+ Return: The binary exponential in Q24 format.*/
+static ogg_int64_t oc_bexp_q24(ogg_int64_t _log_scale){
+ return oc_bexp64(_log_scale+OC_Q57(24));
}
+/*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_q24(ogg_int64_t _in){
+ ogg_int64_t ret;
+ ret=_in+((ogg_int64_t)1<<32)>>33;
+ return (ret>2147483647?2147483647:(ret<-2147483648?-2147483648:ret));
+}
-
static void oc_enc_rc_reset(oc_enc_ctx *_enc){
ogg_int64_t npixels;
ogg_int64_t ibpp;
@@ -264,11 +263,11 @@
/*Set up second order followers, initialized according to corresponding
time constants.*/
oc_iir_filter_init(&_enc->rc.scalefilter[0],2,
- oc_bexp_q24(_enc->rc.log_scale[0]));
+ oc_q57_q24(_enc->rc.log_scale[0]));
inter_delay=_enc->rc.twopass?
OC_MAXI(_enc->keyframe_frequency_force,12):_enc->rc.buf_delay;
oc_iir_filter_init(&_enc->rc.scalefilter[1],inter_delay>>1,
- oc_bexp_q24(_enc->rc.log_scale[1]));
+ oc_q57_q24(_enc->rc.log_scale[1]));
oc_iir_filter_init(&_enc->rc.vfrfilter,2,
oc_bexp_q24(_enc->rc.log_drop_scale));
}
@@ -319,7 +318,7 @@
_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);
oc_iir_filter_init(&_enc->rc.scalefilter[1],_enc->rc.buf_delay>>1,
- oc_bexp_q24(_enc->rc.log_scale[1]));
+ oc_q57_q24(_enc->rc.log_scale[1]));
}
/*If we're in pass-2 mode, make sure the frame metrics array is big enough
to hold frame statistics for the full buffer.*/
@@ -379,7 +378,7 @@
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]+=_enc->rc.cur_metrics.scale;
+ _enc->rc.scale_sum[qti]+=oc_bexp_q24(_enc->rc.cur_metrics.log_scale<<33);
_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.*/
@@ -493,7 +492,7 @@
do{
qti=m->frame_type;
nframes[qti]--;
- scale_sum[qti]-=m->scale;
+ scale_sum[qti]-=oc_bexp_q24(m->log_scale<<33);
buf_delay-=m->dup_count+1;
fmi++;
if(fmi>=_enc->rc.cframe_metrics)fmi=0;
@@ -512,7 +511,7 @@
qti=_enc->rc.cur_metrics.frame_type;
if(qti!=_qti){
nframes[qti]--;
- scale_sum[qti]-=_enc->rc.cur_metrics.scale;
+ scale_sum[qti]-=oc_bexp_q24(_enc->rc.cur_metrics.log_scale<<33);
}
/*Compute corrected log_scale estimates for each frame type from the
pass-1 scales we measured in the current window.*/
@@ -567,7 +566,7 @@
ogg_int64_t scale;
scale=oc_bexp_q24(_enc->rc.log_scale[_qti])*(ogg_int64_t)nframes[_qti];
nframes[_qti]++;
- scale+=_enc->rc.scalefilter[_qti].y[0];
+ scale+=oc_bexp_q24((ogg_int64_t)_enc->rc.scalefilter[_qti].y[0]<<33);
_enc->rc.log_scale[_qti]=oc_blog64(scale)-OC_Q57(24);
}
/*Add the padding from above.
@@ -583,7 +582,8 @@
/*And blend in the low-pass filtered scale according to how many frames
we added.*/
scale=oc_bexp_q24(_enc->rc.log_scale[1])*(ogg_int64_t)nframes[1]
- +_enc->rc.scalefilter[1].y[0]*(ogg_int64_t)nextra_frames;
+ +oc_bexp_q24((ogg_int64_t)_enc->rc.scalefilter[1].y[0]<<33)*
+ (ogg_int64_t)nextra_frames;
nframes[1]+=nextra_frames;
_enc->rc.log_scale[1]=
oc_blog64((scale+(nframes[1]>>1))/nframes[1])-OC_Q57(24);
@@ -700,16 +700,14 @@
long _bits,int _qti,int _qi,int _trial,int _droppable){
ogg_int64_t buf_delta;
ogg_int64_t log_scale;
- ogg_int32_t scale;
int dropped;
dropped=0;
- if(!_enc->rc.drop_frames)_droppable=0;
+ if(!_enc->rc.drop_frames || _enc->rc.twopass)_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;
- scale=0;
}
else{
ogg_int64_t log_bits;
@@ -719,13 +717,12 @@
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));
- scale=oc_bexp_q24(log_scale);
}
/*Special two-pass processing.*/
switch(_enc->rc.twopass){
case 1:{
- /*Pass-1 mode: save the metrics for this frame.*/
- _enc->rc.cur_metrics.scale=scale;
+ /*Pass 1 mode: save the metrics for this frame.*/
+ _enc->rc.cur_metrics.log_scale=oc_q57_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;
@@ -738,7 +735,7 @@
oc_log_linear_fit *fit;
ogg_int64_t x;
ogg_int64_t y;
- x=oc_blog64(_enc->rc.cur_metrics.scale)-OC_Q57(24)>>33;
+ 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.*/
@@ -767,7 +764,7 @@
_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]-=_enc->rc.prev_metrics.scale;
+ _enc->rc.scale_sum[qti]-=oc_bexp_q24(_enc->rc.prev_metrics.log_scale<<33);
_enc->rc.scale_window0=(int)next_frame_num;
/*Free the corresponding entry in the circular buffer.*/
if(_enc->rc.frame_metrics!=NULL){
@@ -794,8 +791,8 @@
else{
/*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_blog64(oc_iir_filter_update(
- _enc->rc.scalefilter+_qti,scale))-OC_Q57(24);
+ _enc->rc.log_scale[_qti]=oc_iir_filter_update(
+ _enc->rc.scalefilter+_qti,oc_q57_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;
@@ -869,12 +866,12 @@
else{
int qti;
qti=_enc->rc.cur_metrics.frame_type;
- _enc->rc.scale_sum[qti]+=_enc->rc.cur_metrics.scale;
+ _enc->rc.scale_sum[qti]+=oc_bexp_q24(_enc->rc.cur_metrics.log_scale<<33);
_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.scale,4);
+ oc_rc_buffer_val(&_enc->rc,_enc->rc.cur_metrics.log_scale,4);
}
}
else if(_enc->packet_state==OC_PACKET_DONE&&
@@ -1025,13 +1022,13 @@
_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 scale;
+ 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);
- scale=oc_rc_unbuffer_val(&_enc->rc,4);
- _enc->rc.cur_metrics.scale=scale;
+ 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;
@@ -1061,23 +1058,23 @@
oc_frame_metrics *m;
int fmi;
ogg_uint32_t dup_count;
- ogg_int32_t scale;
+ ogg_int32_t log_scale;
int qti;
/*Read the metrics for the next frame.*/
dup_count=oc_rc_unbuffer_val(&_enc->rc,4);
- scale=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->scale=scale;
+ 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]+=m->scale;
+ _enc->rc.scale_sum[qti]+=oc_bexp_q24(m->log_scale<<33);
_enc->rc.scale_window_end+=m->dup_count+1;
/*Compute an upper bound on the number of remaining packets needed
for the current window.*/
More information about the commits
mailing list