Adjustments to vp9-denoising.

Adjust variance threshold, delta-qp, and intra penalty cost,
based on estimated noise level in source.

Replace denoising_on with a level value=L/M/H.

Change-Id: I0c017dae75a5d897367d2c42dec26f2f37e447c1
This commit is contained in:
Marco 2015-10-26 14:56:46 -07:00
parent dc9d36c0a6
commit 8a2fc54508
5 changed files with 56 additions and 17 deletions

View File

@ -486,10 +486,17 @@ void vp9_cyclic_refresh_update_parameters(VP9_COMP *const cpi) {
// Account for larger interval on base layer for temporal layers.
if (cr->percent_refresh > 0 &&
rc->frames_since_key < (4 * cpi->svc.number_temporal_layers) *
(100 / cr->percent_refresh))
(100 / cr->percent_refresh)) {
cr->rate_ratio_qdelta = 3.0;
else
} else {
cr->rate_ratio_qdelta = 2.0;
#if CONFIG_VP9_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity > 0 &&
cpi->denoiser.denoising_level >= kMedium)
// Reduce the delta-qp if the estimated source noise is above threshold.
cr->rate_ratio_qdelta = 1.5;
#endif
}
// Adjust some parameters for low resolutions at low bitrates.
if (cm->width <= 352 &&
cm->height <= 288 &&

View File

@ -323,7 +323,7 @@ void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb,
struct buf_2d src = mb->plane[0].src;
int is_skin = 0;
if (bs <= BLOCK_16X16 && denoiser->denoising_on) {
if (bs <= BLOCK_16X16 && denoiser->denoising_level >= kMedium) {
// Take center pixel in block to determine is_skin.
const int y_width_shift = (4 << b_width_log2_lookup[bs]) >> 1;
const int y_height_shift = (4 << b_height_log2_lookup[bs]) >> 1;
@ -340,7 +340,7 @@ void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb,
is_skin = vp9_skin_pixel(ysource, usource, vsource);
}
if (denoiser->denoising_on)
if (denoiser->denoising_level >= kMedium)
decision = perform_motion_compensation(denoiser, mb, bs,
denoiser->increase_denoising,
mi_row, mi_col, ctx,
@ -523,8 +523,8 @@ void vp9_denoiser_init_noise_estimate(VP9_DENOISER *denoiser,
int height) {
// Denoiser is off by default, i.e., no denoising is performed.
// Noise level is measured periodically, and if observed to be above
// thresh_noise_estimate, then denoising is performed, i.e., denoising_on = 1.
denoiser->denoising_on = 0;
// thresh_noise_estimate, then denoising is performed.
denoiser->denoising_level = kLow;
denoiser->noise_estimate = 0;
denoiser->noise_estimate_count = 0;
denoiser->thresh_noise_estimate = 20;
@ -651,10 +651,15 @@ void vp9_denoiser_update_noise_estimate(VP9_COMP *const cpi) {
if (cpi->denoiser.noise_estimate_count == num_frames_estimate) {
// Reset counter and check noise level condition.
cpi->denoiser.noise_estimate_count = 0;
if (cpi->denoiser.noise_estimate > cpi->denoiser.thresh_noise_estimate)
cpi->denoiser.denoising_on = 1;
else
cpi->denoiser.denoising_on = 0;
if (cpi->denoiser.noise_estimate >
(cpi->denoiser.thresh_noise_estimate << 1))
cpi->denoiser.denoising_level = kHigh;
else
if (cpi->denoiser.noise_estimate >
cpi->denoiser.thresh_noise_estimate)
cpi->denoiser.denoising_level = kMedium;
else
cpi->denoiser.denoising_level = kLow;
}
}
}

View File

@ -26,13 +26,19 @@ typedef enum vp9_denoiser_decision {
FILTER_BLOCK
} VP9_DENOISER_DECISION;
typedef enum vp9_denoiser_level {
kLow,
kMedium,
kHigh
} VP9_DENOISER_LEVEL;
typedef struct vp9_denoiser {
YV12_BUFFER_CONFIG running_avg_y[MAX_REF_FRAMES];
YV12_BUFFER_CONFIG mc_running_avg_y;
YV12_BUFFER_CONFIG last_source;
int increase_denoising;
int frame_buffer_initialized;
int denoising_on;
VP9_DENOISER_LEVEL denoising_level;
int noise_estimate;
int thresh_noise_estimate;
int noise_estimate_count;

View File

@ -481,7 +481,7 @@ static void set_vbp_thresholds(VP9_COMP *cpi, int64_t thresholds[], int q) {
VP9_COMMON *const cm = &cpi->common;
const int is_key_frame = (cm->frame_type == KEY_FRAME);
const int threshold_multiplier = is_key_frame ? 20 : 1;
const int64_t threshold_base = (int64_t)(threshold_multiplier *
int64_t threshold_base = (int64_t)(threshold_multiplier *
cpi->y_dequant[q][1]);
if (is_key_frame) {
thresholds[0] = threshold_base;
@ -489,6 +489,16 @@ static void set_vbp_thresholds(VP9_COMP *cpi, int64_t thresholds[], int q) {
thresholds[2] = threshold_base >> 2;
thresholds[3] = threshold_base << 2;
} else {
#if CONFIG_VP9_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity > 0) {
// Increase base variance threshold is estimated noise level is high.
if (cpi->denoiser.denoising_level == kHigh)
threshold_base = threshold_base << 2;
else
if (cpi->denoiser.denoising_level == kMedium)
threshold_base = threshold_base << 1;
}
#endif
thresholds[1] = threshold_base;
if (cm->width <= 352 && cm->height <= 288) {
thresholds[0] = threshold_base >> 2;

View File

@ -1068,6 +1068,21 @@ static const REF_MODE ref_mode_set_svc[RT_INTER_MODES] = {
{GOLDEN_FRAME, NEWMV}
};
int set_intra_cost_penalty(const VP9_COMP *const cpi, BLOCK_SIZE bsize) {
const VP9_COMMON *const cm = &cpi->common;
// Reduce the intra cost penalty for small blocks (<=16x16).
int reduction_fac =
(bsize <= BLOCK_16X16) ? ((bsize <= BLOCK_8X8) ? 4 : 2) : 0;
#if CONFIG_VP9_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity > 0 &&
cpi->denoiser.denoising_level == kHigh)
// Don't reduce intra cost penalty if estimated noise level is high.
reduction_fac = 0;
#endif
return vp9_get_intra_cost_penalty(
cm->base_qindex, cm->y_dc_delta_q, cm->bit_depth) >> reduction_fac;
}
// TODO(jingning) placeholder for inter-frame non-RD mode decision.
// this needs various further optimizations. to be continued..
void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
@ -1094,11 +1109,7 @@ void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x,
// var_y and sse_y are saved to be used in skipping checking
unsigned int var_y = UINT_MAX;
unsigned int sse_y = UINT_MAX;
// Reduce the intra cost penalty for small blocks (<=16x16).
const int reduction_fac = (bsize <= BLOCK_16X16) ?
((bsize <= BLOCK_8X8) ? 4 : 2) : 0;
const int intra_cost_penalty = vp9_get_intra_cost_penalty(
cm->base_qindex, cm->y_dc_delta_q, cm->bit_depth) >> reduction_fac;
const int intra_cost_penalty = set_intra_cost_penalty(cpi, bsize);
const int64_t inter_mode_thresh = RDCOST(x->rdmult, x->rddiv,
intra_cost_penalty, 0);
const int *const rd_threshes = cpi->rd.threshes[mbmi->segment_id][bsize];