1 参数设定
OPT("nr")
p->analyse.i_noise_reduction = atoi(value);
2 参数clip
h->param.analyse.i_noise_reduction = x264_clip3( h->param.analyse.i_noise_reduction, 0, 1<<16 ); //最大到65535
3 参数使用
h->mb.i_skip_intra = //帧内块skip, 周围块可以直接通过平铺方式 还原当前帧内块
h->mb.b_lossless ? 0 : //如果是无损压缩,这里需要关闭
a->i_mbrd ? 2 : //至少有rdo,
!h->param.analyse.i_trellis && !h->param.analyse.i_noise_reduction;
/*trellis 关闭状态,并且nr也是关闭状态*/
h->mb.b_noise_reduction =
h->mb.b_noise_reduction || (!!h->param.analyse.i_noise_reduction && !IS_INTRA( h->mb.i_type ));
//帧内块不做 nr ,必须要打开了开关,并且不是帧内块
4 实际是否开nr,取决于初始qp
if( qp > QP_MAX_SPEC ) //qp非常大的时候,才会打开nr qp非常大的时候才需要 nr_residual_sum_buf[1]
{
h->nr_offset = h->nr_offset_emergency[qp-QP_MAX_SPEC-1]; //紧急数组
h->nr_residual_sum = h->nr_residual_sum_buf[1]; //qp非常大的时候, > 51,才需要数组1
h->nr_count = h->nr_count_buf[1]; //
h->mb.b_noise_reduction = 1; //过大的qp值一定会打开nr
qp = QP_MAX_SPEC; /* 过大的qp会被clip 回范围内 Out-of-spec QPs are just used for calculating lambda values. */
}
else //普通大小的qp值
{//不起作用
h->nr_offset = h->nr_offset_denoise; //nr系数数组
h->nr_residual_sum = h->nr_residual_sum_buf[0]; //qp正常范围内的时候,残差sum buf
h->nr_count = h->nr_count_buf[0]; //
h->mb.b_noise_reduction = 0; //自动关闭nr
}
5 计算nr 偏移数组
/****************************************************************************
* DCT-domain noise reduction / adaptive deadzone
* from libavcodec
****************************************************************************/
void x264_noise_reduction_update( x264_t *h )
{
h->nr_offset = h->nr_offset_denoise; // nr数组
h->nr_residual_sum = h->nr_residual_sum_buf[0]; //
h->nr_count = h->nr_count_buf[0];
for( int cat = 0; cat < 3 + CHROMA444; cat++ ) //如果是yuv444, 就是4个通道,
{
int dct8x8 = cat&1; //偶数是4x4 奇数是8x8
int size = dct8x8 ? 64 : 16;
const uint32_t *weight = dct8x8 ? s264_dct8_weight2_tab : s264_dct4_weight2_tab;
if( h->nr_count[cat] > (dct8x8 ? (1<<16) : (1<<18)) )
{
for( int i = 0; i < size; i++ ) //计算 nr_residual_sum数组
h->nr_residual_sum[cat][i] >>= 1;
h->nr_count[cat] >>= 1;
}
for( int i = 0; i < size; i++ ) //计算 nr_offset数组
h->nr_offset[cat][i] =
((uint64_t)h->param.analyse.i_noise_reduction * h->nr_count[cat]
+ h->nr_residual_sum[cat][i]/2)
/ ((uint64_t)h->nr_residual_sum[cat][i] * weight[i]/256 + 1);
/* Don't denoise DC coefficients */
h->nr_offset[cat][0] = 0;
}
}
6 nr实际作用的地方
if( h->mb.b_noise_reduction ) //例如这里对高频系数nr
{
h->nr_count[0+!!p*2] += 16;
for( int idx = 0; idx < 16; idx++ )
h->quantf.denoise_dct( dct4x4[idx], h->nr_residual_sum[0+!!p*2], h->nr_offset[0+!!p*2], 16 );
}