Index: source/libvpx/vp8/encoder/denoising.c |
=================================================================== |
--- source/libvpx/vp8/encoder/denoising.c (revision 290053) |
+++ source/libvpx/vp8/encoder/denoising.c (working copy) |
@@ -8,6 +8,8 @@ |
* be found in the AUTHORS file in the root of the source tree. |
*/ |
+#include <limits.h> |
+ |
#include "denoising.h" |
#include "vp8/common/reconinter.h" |
@@ -333,8 +335,38 @@ |
return FILTER_BLOCK; |
} |
+void vp8_denoiser_set_parameters(VP8_DENOISER *denoiser, int mode) { |
+ assert(mode > 0); // Denoiser is allocated only if mode > 0. |
+ if (mode == 1) { |
+ denoiser->denoiser_mode = kDenoiserOnYOnly; |
+ } else if (mode == 2) { |
+ denoiser->denoiser_mode = kDenoiserOnYUV; |
+ } else if (mode == 3) { |
+ denoiser->denoiser_mode = kDenoiserOnYUVAggressive; |
+ } else { |
+ denoiser->denoiser_mode = kDenoiserOnAdaptive; |
+ } |
+ if (denoiser->denoiser_mode != kDenoiserOnYUVAggressive) { |
+ denoiser->denoise_pars.scale_sse_thresh = 1; |
+ denoiser->denoise_pars.scale_motion_thresh = 8; |
+ denoiser->denoise_pars.scale_increase_filter = 0; |
+ denoiser->denoise_pars.denoise_mv_bias = 95; |
+ denoiser->denoise_pars.pickmode_mv_bias = 100; |
+ denoiser->denoise_pars.qp_thresh = 0; |
+ denoiser->denoise_pars.consec_zerolast = UINT_MAX; |
+ } else { |
+ denoiser->denoise_pars.scale_sse_thresh = 2; |
+ denoiser->denoise_pars.scale_motion_thresh = 16; |
+ denoiser->denoise_pars.scale_increase_filter = 1; |
+ denoiser->denoise_pars.denoise_mv_bias = 60; |
+ denoiser->denoise_pars.pickmode_mv_bias = 60; |
+ denoiser->denoise_pars.qp_thresh = 100; |
+ denoiser->denoise_pars.consec_zerolast = 10; |
+ } |
+} |
+ |
int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height, |
- int num_mb_rows, int num_mb_cols) |
+ int num_mb_rows, int num_mb_cols, int mode) |
{ |
int i; |
assert(denoiser); |
@@ -367,12 +399,27 @@ |
vpx_memset(denoiser->yv12_mc_running_avg.buffer_alloc, 0, |
denoiser->yv12_mc_running_avg.frame_size); |
+ if (vp8_yv12_alloc_frame_buffer(&denoiser->yv12_last_source, width, |
+ height, VP8BORDERINPIXELS) < 0) { |
+ vp8_denoiser_free(denoiser); |
+ return 1; |
+ } |
+ vpx_memset(denoiser->yv12_last_source.buffer_alloc, 0, |
+ denoiser->yv12_last_source.frame_size); |
+ |
denoiser->denoise_state = vpx_calloc((num_mb_rows * num_mb_cols), 1); |
vpx_memset(denoiser->denoise_state, 0, (num_mb_rows * num_mb_cols)); |
- |
+ vp8_denoiser_set_parameters(denoiser, mode); |
+ denoiser->nmse_source_diff = 0; |
+ denoiser->nmse_source_diff_count = 0; |
+ // TODO(marpan): Adjust thresholds, including effect on resolution. |
+ denoiser->threshold_aggressive_mode = 40; |
+ if (width * height > 640 * 480) |
+ denoiser->threshold_aggressive_mode = 180; |
return 0; |
} |
+ |
void vp8_denoiser_free(VP8_DENOISER *denoiser) |
{ |
int i; |
@@ -396,11 +443,12 @@ |
loop_filter_info_n *lfi_n, |
int mb_row, |
int mb_col, |
- int block_index, |
- int uv_denoise) |
+ int block_index) |
+ |
{ |
int mv_row; |
int mv_col; |
+ unsigned int motion_threshold; |
unsigned int motion_magnitude2; |
unsigned int sse_thresh; |
int sse_diff_thresh = 0; |
@@ -424,7 +472,7 @@ |
MB_MODE_INFO *mbmi = &filter_xd->mode_info_context->mbmi; |
int sse_diff = 0; |
// Bias on zero motion vector sse. |
- int zero_bias = 95; |
+ const int zero_bias = denoiser->denoise_pars.denoise_mv_bias; |
zero_mv_sse = (unsigned int)((int64_t)zero_mv_sse * zero_bias / 100); |
sse_diff = zero_mv_sse - best_sse; |
@@ -502,15 +550,20 @@ |
mv_row = x->best_sse_mv.as_mv.row; |
mv_col = x->best_sse_mv.as_mv.col; |
motion_magnitude2 = mv_row * mv_row + mv_col * mv_col; |
- sse_thresh = SSE_THRESHOLD; |
- if (x->increase_denoising) sse_thresh = SSE_THRESHOLD_HIGH; |
+ motion_threshold = denoiser->denoise_pars.scale_motion_thresh * |
+ NOISE_MOTION_THRESHOLD; |
- if (best_sse > sse_thresh || motion_magnitude2 |
- > 8 * NOISE_MOTION_THRESHOLD) |
- { |
- decision = COPY_BLOCK; |
- } |
+ if (motion_magnitude2 < |
+ denoiser->denoise_pars.scale_increase_filter * NOISE_MOTION_THRESHOLD) |
+ x->increase_denoising = 1; |
+ sse_thresh = denoiser->denoise_pars.scale_sse_thresh * SSE_THRESHOLD; |
+ if (x->increase_denoising) |
+ sse_thresh = denoiser->denoise_pars.scale_sse_thresh * SSE_THRESHOLD_HIGH; |
+ |
+ if (best_sse > sse_thresh || motion_magnitude2 > motion_threshold) |
+ decision = COPY_BLOCK; |
+ |
if (decision == FILTER_BLOCK) |
{ |
unsigned char *mc_running_avg_y = |
@@ -528,7 +581,7 @@ |
denoiser->denoise_state[block_index] = motion_magnitude2 > 0 ? |
kFilterNonZeroMV : kFilterZeroMV; |
// Only denoise UV for zero motion, and if y channel was denoised. |
- if (uv_denoise && |
+ if (denoiser->denoiser_mode != kDenoiserOnYOnly && |
motion_magnitude2 == 0 && |
decision == FILTER_BLOCK) { |
unsigned char *mc_running_avg_u = |
@@ -565,7 +618,7 @@ |
denoiser->yv12_running_avg[INTRA_FRAME].y_stride); |
denoiser->denoise_state[block_index] = kNoFilter; |
} |
- if (uv_denoise) { |
+ if (denoiser->denoiser_mode != kDenoiserOnYOnly) { |
if (decision_u == COPY_BLOCK) { |
vp8_copy_mem8x8( |
x->block[16].src + *x->block[16].base_src, x->block[16].src_stride, |