ref: 8a2fc54508801f6f4c17c69b3e7f8240993e2f05
parent: dc9d36c0a6c749616d5543aa208864d7b0181fea
author: Marco <[email protected]>
date: Mon Oct 26 10:56:46 EDT 2015
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
--- a/vp9/encoder/vp9_aq_cyclicrefresh.c
+++ b/vp9/encoder/vp9_aq_cyclicrefresh.c
@@ -486,10 +486,17 @@
// 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 &&
--- a/vp9/encoder/vp9_denoiser.c
+++ b/vp9/encoder/vp9_denoiser.c
@@ -323,7 +323,7 @@
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 @@
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 @@
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 @@
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;
}
}
}
--- a/vp9/encoder/vp9_denoiser.h
+++ b/vp9/encoder/vp9_denoiser.h
@@ -26,6 +26,12 @@
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;
@@ -32,7 +38,7 @@
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;
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -481,7 +481,7 @@
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 @@
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;
--- a/vp9/encoder/vp9_pickmode.c
+++ b/vp9/encoder/vp9_pickmode.c
@@ -1068,6 +1068,21 @@
{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 @@
// 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];