Commit 0abf15d2 authored by Loren Merritt's avatar Loren Merritt

dct-domain noise reduction (ported from lavc)



git-svn-id: svn://svn.videolan.org/x264/trunk@398 df754926-b1dd-0310-bc7b-ec298dee348c
parent 6bf39eaa
......@@ -261,6 +261,10 @@ struct x264_t
int unquant4_mf[4][52][16];
int unquant8_mf[2][52][64];
uint32_t nr_residual_sum[4][64];
uint32_t nr_offset[4][64];
uint32_t nr_count[4];
/* Slice header */
x264_slice_header_t sh;
......@@ -343,6 +347,8 @@ struct x264_t
int i_subpel_refine;
int b_chroma_me;
int b_trellis;
int b_noise_reduction;
/* Allowed qpel MV range to stay within the picture + emulated edge pixels */
int mv_min[2];
int mv_max[2];
......
......@@ -48,6 +48,12 @@ static const int x264_dct8_weight_tab[64] = {
#define W(i) (i==0 ? FIX8(3.125) :\
i==1 ? FIX8(1.25) :\
i==2 ? FIX8(0.5) :0)
static const int x264_dct4_weight2_tab[16] = {
W(0), W(1), W(0), W(1),
W(1), W(2), W(1), W(2),
W(0), W(1), W(0), W(1),
W(1), W(2), W(1), W(2)
};
static const int x264_dct4_weight2_zigzag[16] = {
W(0), W(1), W(1), W(0), W(2), W(0), W(1), W(1),
W(1), W(1), W(2), W(0), W(2), W(1), W(1), W(2)
......@@ -60,6 +66,17 @@ static const int x264_dct4_weight2_zigzag[16] = {
i==3 ? FIX8(0.88637) :\
i==4 ? FIX8(1.60040) :\
i==5 ? FIX8(1.41850) :0)
static const int x264_dct8_weight2_tab[64] = {
W(0), W(3), W(4), W(3), W(0), W(3), W(4), W(3),
W(3), W(1), W(5), W(1), W(3), W(1), W(5), W(1),
W(4), W(5), W(2), W(5), W(4), W(5), W(2), W(5),
W(3), W(1), W(5), W(1), W(3), W(1), W(5), W(1),
W(0), W(3), W(4), W(3), W(0), W(3), W(4), W(3),
W(3), W(1), W(5), W(1), W(3), W(1), W(5), W(1),
W(4), W(5), W(2), W(5), W(4), W(5), W(2), W(5),
W(3), W(1), W(5), W(1), W(3), W(1), W(5), W(1)
};
static const int x264_dct8_weight2_zigzag[64] = {
W(0), W(3), W(3), W(4), W(1), W(4), W(3), W(5),
W(5), W(3), W(0), W(1), W(2), W(1), W(0), W(3),
......
......@@ -198,6 +198,7 @@ static void x264_mb_analyse_init( x264_t *h, x264_mb_analysis_t *a, int i_qp )
&& h->mb.i_subpel_refine >= 5;
h->mb.b_trellis = h->param.analyse.i_trellis > 1;
h->mb.b_transform_8x8 = 0;
h->mb.b_noise_reduction = 0;
/* I: Intra part */
a->i_sad_i16x16 =
......@@ -2271,6 +2272,7 @@ void x264_macroblock_analyse( x264_t *h )
x264_mb_analyse_transform( h );
h->mb.b_trellis = h->param.analyse.i_trellis;
h->mb.b_noise_reduction = h->param.analyse.i_noise_reduction;
}
/*-------------------- Update MB from the analysis ----------------------*/
......
......@@ -370,6 +370,7 @@ static int x264_validate_parameters( x264_t *h )
h->param.analyse.i_chroma_qp_offset = 0;
h->param.analyse.i_trellis = 0;
h->param.analyse.b_fast_pskip = 0;
h->param.analyse.i_noise_reduction = 0;
}
if( ( h->param.i_width % 16 || h->param.i_height % 16 ) && !h->mb.b_lossless )
......@@ -421,6 +422,7 @@ static int x264_validate_parameters( x264_t *h )
if( !h->param.b_cabac )
h->param.analyse.i_trellis = 0;
h->param.analyse.i_trellis = x264_clip3( h->param.analyse.i_trellis, 0, 2 );
h->param.analyse.i_noise_reduction = x264_clip3( h->param.analyse.i_noise_reduction, 0, 1<<16 );
{
const x264_level_t *l = x264_levels;
......@@ -1508,6 +1510,8 @@ do_encode:
x264_frame_put( h->frames.unused, h->fenc );
x264_noise_reduction_update( h );
TIMER_STOP( i_mtime_encode_frame );
/* ---------------------- Compute/Print statistics --------------------- */
......
......@@ -207,6 +207,8 @@ void x264_mb_encode_i4x4( x264_t *h, int idx, int i_qscale )
h->dctf.sub4x4_dct( dct4x4, p_src, i_stride, p_dst, i_stride );
if( h->mb.b_noise_reduction )
x264_denoise_dct( h, (int16_t*)dct4x4 );
if( h->mb.b_trellis )
x264_quant_4x4_trellis( h, dct4x4, CQM_4IY, i_qscale, DCT_LUMA_4x4, 1 );
else
......@@ -229,6 +231,8 @@ void x264_mb_encode_i8x8( x264_t *h, int idx, int i_qscale )
h->dctf.sub8x8_dct8( dct8x8, p_src, i_stride, p_dst, i_stride );
if( h->mb.b_noise_reduction )
x264_denoise_dct( h, (int16_t*)dct8x8 );
if( h->mb.b_trellis )
x264_quant_8x8_trellis( h, dct8x8, CQM_8IY, i_qscale, 1 );
else
......@@ -269,6 +273,8 @@ static void x264_mb_encode_i16x16( x264_t *h, int i_qscale )
dct4x4[0][block_idx_y[i]][block_idx_x[i]] = dct4x4[1+i][0][0];
/* quant/scan/dequant */
if( h->mb.b_noise_reduction )
x264_denoise_dct( h, (int16_t*)dct4x4[i] );
if( h->mb.b_trellis )
x264_quant_4x4_trellis( h, dct4x4[1+i], CQM_4IY, i_qscale, DCT_LUMA_AC, 1 );
else
......@@ -501,6 +507,8 @@ void x264_macroblock_encode( x264_t *h )
for( idx = 0; idx < 4; idx++ )
{
if( h->mb.b_noise_reduction )
x264_denoise_dct( h, (int16_t*)dct8x8[idx] );
if( h->mb.b_trellis )
x264_quant_8x8_trellis( h, dct8x8[idx], CQM_8PY, i_qp, 0 );
else
......@@ -552,6 +560,8 @@ void x264_macroblock_encode( x264_t *h )
{
idx = i8x8 * 4 + i4x4;
if( h->mb.b_noise_reduction )
x264_denoise_dct( h, (int16_t*)dct4x4[idx] );
if( h->mb.b_trellis )
x264_quant_4x4_trellis( h, dct4x4[idx], CQM_4PY, i_qp, DCT_LUMA_4x4, 0 );
else
......@@ -790,3 +800,63 @@ int x264_macroblock_probe_skip( x264_t *h, int b_bidir )
return 1;
}
/****************************************************************************
* DCT-domain noise reduction / adaptive deadzone
* from libavcodec
****************************************************************************/
void x264_noise_reduction_update( x264_t *h )
{
int cat, i;
for( cat = 0; cat < 4; cat++ )
{
int b_8x8 = cat >= 2;
int size = b_8x8 ? 64 : 16;
const int *weight = b_8x8 ? x264_dct8_weight2_tab : x264_dct4_weight2_tab;
if( h->nr_count[cat] > (b_8x8 ? (1<<16) : (1<<18)) )
{
for( i = 0; i < size; i++ )
h->nr_residual_sum[cat][i] >>= 1;
h->nr_count[cat] >>= 1;
}
for( i = 0; i < size; i++ )
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);
}
}
void x264_denoise_dct( x264_t *h, int16_t *dct )
{
const int cat = !IS_INTRA(h->mb.i_type) + 2*h->mb.b_transform_8x8;
int i;
h->nr_count[cat]++;
for( i = (cat >= 2 ? 63 : 15); i >= 1; i-- )
{
int level = dct[i];
if( level )
{
if( level > 0 )
{
h->nr_residual_sum[cat][i] += level;
level -= h->nr_offset[cat][i];
if( level < 0 )
level = 0;
}
else
{
h->nr_residual_sum[cat][i] -= level;
level += h->nr_offset[cat][i];
if( level > 0 )
level = 0;
}
dct[i] = level;
}
}
}
......@@ -46,6 +46,9 @@ void x264_quant_4x4_trellis( x264_t *h, int16_t dct[4][4], int i_quant_cat,
void x264_quant_8x8_trellis( x264_t *h, int16_t dct[8][8], int i_quant_cat,
int i_qp, int b_intra );
void x264_noise_reduction_update( x264_t *h );
void x264_denoise_dct( x264_t *h, int16_t *dct );
static inline int array_non_zero( int *v, int i_count )
{
int i;
......
......@@ -263,6 +263,7 @@ static void Help( x264_param_t *defaults )
" - 1: enabled only on the final encode of a MB\n"
" - 2: enabled on all mode decisions\n"
" --no-fast-pskip Disables early SKIP detection on P-frames\n"
" --nr <integer> Noise reduction [%d]\n"
"\n"
" --cqm <string> Preset quant matrices [\"flat\"]\n"
" - jvt, flat\n"
......@@ -356,6 +357,7 @@ static void Help( x264_param_t *defaults )
defaults->analyse.i_me_range,
defaults->analyse.i_subpel_refine,
defaults->analyse.i_trellis,
defaults->analyse.i_noise_reduction,
strtable_lookup( overscan_str, defaults->vui.i_overscan ),
strtable_lookup( vidformat_str, defaults->vui.i_vidformat ),
strtable_lookup( fullrange_str, defaults->vui.b_fullrange ),
......@@ -482,6 +484,7 @@ static int Parse( int argc, char **argv,
#define OPT_B_RDO 316
#define OPT_NO_FAST_PSKIP 317
#define OPT_BIME 318
#define OPT_NR 319
static struct option long_options[] =
{
......@@ -544,6 +547,7 @@ static int Parse( int argc, char **argv,
{ "progress",no_argument, NULL, OPT_PROGRESS },
{ "visualize",no_argument, NULL, OPT_VISUALIZE },
{ "aud", no_argument, NULL, OPT_AUD },
{ "nr", required_argument, NULL, OPT_NR },
{ "cqm", required_argument, NULL, OPT_CQM },
{ "cqmfile", required_argument, NULL, OPT_CQMFILE },
{ "cqm4", required_argument, NULL, OPT_CQM4 },
......@@ -844,6 +848,9 @@ static int Parse( int argc, char **argv,
fprintf( stderr, "not compiled with visualization support\n" );
#endif
break;
case OPT_NR:
param->analyse.i_noise_reduction = atoi(optarg);
break;
case OPT_CQM:
if( strstr( optarg, "flat" ) )
param->i_cqm_preset = X264_CQM_FLAT;
......
......@@ -202,6 +202,7 @@ typedef struct
int b_mixed_references; /* allow each mb partition in P-frames to have it's own reference number */
int i_trellis; /* trellis RD quantization */
int b_fast_pskip; /* early SKIP detection on P-frames */
int i_noise_reduction; /* adaptive pseudo-deadzone */
int b_psnr; /* Do we compute PSNR stats (save a few % of cpu) */
} analyse;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment