added code to clear 2nd order block when appropriate

It is discovered that in rare situations the 2nd order block may
produce a few small magnitude coefficients that has no effect on
reconstruction. The situations are a combination of low quantizer
values (high quality) and low energy in residual signals (content
dependent). This commit added code to detect such cases and reset
the 2nd order block to all 0.

Patch 1 to 4 used code to do all-zero-check on idct result buffer,
and tests on derf set showed a consistent gain of .12%-.14% on all
metrics.But due to a recent change Ie31d90b, the idct result buffer
is not longer populated. So patch 5&6 use an alternative method to
detect the situations. Tests on derf set now shows a consistent
quality gain of .16%-.20%.

As suggested by Jim, Patch 7&8 removed the condition of all first
order block not having any coefficient, instead we reset 2nd order
coefficients to all 0 if sum of absolute value of the coefficients
is small. So it does slightly more than just detecting the oddity
as discussed above, but tests on derf set now show a consistent
gain of .20%-.23% on all metrics.

It is worth noting here that this change does not have any effect
on mid/high quantizer range, it only affects the quantizer value
18 or blow. Within this range, the change helps compression by up
to 2.5% on clips in the derf set.

Change-Id: I718e19cf59a4fc2462cb7070832759beb9f7e7dd
This commit is contained in:
Yaowu Xu 2011-10-20 15:32:34 -04:00
Родитель 3579baa115
Коммит 88e24f07ae
2 изменённых файлов: 45 добавлений и 2 удалений

Просмотреть файл

@ -94,7 +94,8 @@ void vp8_encode_intra16x16mby(const VP8_ENCODER_RTCD *rtcd, MACROBLOCK *x)
RECON_INVOKE(&rtcd->common->recon, build_intra_predictors_mby)(&x->e_mbd);
ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, *(b->base_src), x->e_mbd.predictor, b->src_stride);
ENCODEMB_INVOKE(&rtcd->encodemb, submby)(x->src_diff, *(b->base_src),
x->e_mbd.predictor, b->src_stride);
vp8_transform_intra_mby(x);

Просмотреть файл

@ -469,12 +469,50 @@ static void optimize_b(MACROBLOCK *mb, int ib, int type,
d->eob = final_eob;
*a = *l = (d->eob != !type);
}
static void check_reset_2nd_coeffs(MACROBLOCKD *x, int type,
ENTROPY_CONTEXT *a, ENTROPY_CONTEXT *l)
{
int sum=0;
int i;
BLOCKD *bd = &x->block[24];
if(bd->dequant[0]>=35 && bd->dequant[1]>=35)
return;
for(i=0;i<bd->eob;i++)
{
int coef = bd->dqcoeff[vp8_default_zig_zag1d[i]];
sum+= (coef>=0)?coef:-coef;
if(sum>=35)
return;
}
/**************************************************************************
our inverse hadamard transform effectively is weighted sum of all 16 inputs
with weight either 1 or -1. It has a last stage scaling of (sum+3)>>3. And
dc only idct is (dc+4)>>3. So if all the sums are between -35 and 29, the
output after inverse wht and idct will be all zero. A sum of absolute value
smaller than 35 guarantees all 16 different (+1/-1) weighted sums in wht
fall between -35 and +35.
**************************************************************************/
if(sum < 35)
{
for(i=0;i<bd->eob;i++)
{
int rc = vp8_default_zig_zag1d[i];
bd->qcoeff[rc]=0;
bd->dqcoeff[rc]=0;
}
bd->eob = 0;
*a = *l = (bd->eob != !type);
}
}
static void optimize_mb(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
{
int b;
int type;
int has_2nd_order;
ENTROPY_CONTEXT_PLANES t_above, t_left;
ENTROPY_CONTEXT *ta;
ENTROPY_CONTEXT *tl;
@ -506,6 +544,8 @@ static void optimize_mb(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
b=24;
optimize_b(x, b, PLANE_TYPE_Y2,
ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
check_reset_2nd_coeffs(&x->e_mbd, PLANE_TYPE_Y2,
ta + vp8_block2above[b], tl + vp8_block2left[b]);
}
}
@ -539,7 +579,7 @@ void vp8_optimize_mby(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
for (b = 0; b < 16; b++)
{
optimize_b(x, b, type,
ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
}
@ -548,6 +588,8 @@ void vp8_optimize_mby(MACROBLOCK *x, const VP8_ENCODER_RTCD *rtcd)
b=24;
optimize_b(x, b, PLANE_TYPE_Y2,
ta + vp8_block2above[b], tl + vp8_block2left[b], rtcd);
check_reset_2nd_coeffs(&x->e_mbd, PLANE_TYPE_Y2,
ta + vp8_block2above[b], tl + vp8_block2left[b]);
}
}