| 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,
|
|
|