Index: source/libvpx/vp9/encoder/vp9_denoiser.c |
=================================================================== |
--- source/libvpx/vp9/encoder/vp9_denoiser.c (revision 291857) |
+++ source/libvpx/vp9/encoder/vp9_denoiser.c (working copy) |
@@ -78,7 +78,8 @@ |
int mc_avg_stride, |
uint8_t *avg, int avg_stride, |
int increase_denoising, |
- BLOCK_SIZE bs) { |
+ BLOCK_SIZE bs, |
+ int motion_magnitude) { |
int r, c; |
const uint8_t *sig_start = sig; |
const uint8_t *mc_avg_start = mc_avg; |
@@ -86,7 +87,20 @@ |
int diff, adj, absdiff, delta; |
int adj_val[] = {3, 4, 6}; |
int total_adj = 0; |
+ int shift_inc = 1; |
+ /* If motion_magnitude is small, making the denoiser more aggressive by |
+ * increasing the adjustment for each level. Add another increment for |
+ * blocks that are labeled for increase denoising. */ |
+ if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) { |
+ if (increase_denoising) { |
+ shift_inc = 2; |
+ } |
+ adj_val[0] += shift_inc; |
+ adj_val[1] += shift_inc; |
+ adj_val[2] += shift_inc; |
+ } |
+ |
// First attempt to apply a strong temporal denoising filter. |
for (r = 0; r < heights[bs]; ++r) { |
for (c = 0; c < widths[bs]; ++c) { |
@@ -130,7 +144,8 @@ |
// Otherwise, we try to dampen the filter if the delta is not too high. |
delta = ((abs(total_adj) - total_adj_strong_thresh(bs, increase_denoising)) |
>> 8) + 1; |
- if (delta > delta_thresh(bs, increase_denoising)) { |
+ |
+ if (delta >= delta_thresh(bs, increase_denoising)) { |
return COPY_BLOCK; |
} |
@@ -145,11 +160,17 @@ |
adj = delta; |
} |
if (diff > 0) { |
+ // Diff positive means we made positive adjustment above |
+ // (in first try/attempt), so now make negative adjustment to bring |
+ // denoised signal down. |
avg[c] = MAX(0, avg[c] - adj); |
- total_adj += adj; |
+ total_adj -= adj; |
} else { |
+ // Diff negative means we made negative adjustment above |
+ // (in first try/attempt), so now make positive adjustment to bring |
+ // denoised signal up. |
avg[c] = MIN(UINT8_MAX, avg[c] + adj); |
- total_adj -= adj; |
+ total_adj += adj; |
} |
} |
sig += sig_stride; |
@@ -185,7 +206,8 @@ |
int increase_denoising, |
int mi_row, |
int mi_col, |
- PICK_MODE_CONTEXT *ctx |
+ PICK_MODE_CONTEXT *ctx, |
+ int *motion_magnitude |
) { |
int mv_col, mv_row; |
int sse_diff = ctx->zeromv_sse - ctx->newmv_sse; |
@@ -210,6 +232,8 @@ |
mv_col = ctx->best_sse_mv.as_mv.col; |
mv_row = ctx->best_sse_mv.as_mv.row; |
+ *motion_magnitude = mv_row * mv_row + mv_col * mv_col; |
+ |
frame = ctx->best_reference_frame; |
// If the best reference frame uses inter-prediction and there is enough of a |
@@ -297,6 +321,7 @@ |
void vp9_denoiser_denoise(VP9_DENOISER *denoiser, MACROBLOCK *mb, |
int mi_row, int mi_col, BLOCK_SIZE bs, |
PICK_MODE_CONTEXT *ctx) { |
+ int motion_magnitude = 0; |
VP9_DENOISER_DECISION decision = FILTER_BLOCK; |
YV12_BUFFER_CONFIG avg = denoiser->running_avg_y[INTRA_FRAME]; |
YV12_BUFFER_CONFIG mc_avg = denoiser->mc_running_avg_y; |
@@ -307,13 +332,14 @@ |
decision = perform_motion_compensation(denoiser, mb, bs, |
denoiser->increase_denoising, |
- mi_row, mi_col, ctx); |
+ mi_row, mi_col, ctx, |
+ &motion_magnitude); |
if (decision == FILTER_BLOCK) { |
decision = denoiser_filter(src.buf, src.stride, |
mc_avg_start, mc_avg.y_stride, |
avg_start, avg.y_stride, |
- 0, bs); |
+ 0, bs, motion_magnitude); |
} |
if (decision == FILTER_BLOCK) { |
@@ -370,8 +396,8 @@ |
ctx->newmv_sse = UINT_MAX; |
} |
-void vp9_denoiser_update_frame_stats(VP9_DENOISER *denoiser, MB_MODE_INFO *mbmi, |
- unsigned int sse, PREDICTION_MODE mode, |
+void vp9_denoiser_update_frame_stats(MB_MODE_INFO *mbmi, unsigned int sse, |
+ PREDICTION_MODE mode, |
PICK_MODE_CONTEXT *ctx) { |
// TODO(tkopp): Use both MVs if possible |
if (mbmi->mv[0].as_int == 0 && sse < ctx->zeromv_sse) { |
@@ -388,13 +414,21 @@ |
} |
int vp9_denoiser_alloc(VP9_DENOISER *denoiser, int width, int height, |
- int ssx, int ssy, int border) { |
+ int ssx, int ssy, |
+#if CONFIG_VP9_HIGHBITDEPTH |
+ int use_highbitdepth, |
+#endif |
+ int border) { |
int i, fail; |
assert(denoiser != NULL); |
for (i = 0; i < MAX_REF_FRAMES; ++i) { |
fail = vp9_alloc_frame_buffer(&denoiser->running_avg_y[i], width, height, |
- ssx, ssy, border); |
+ ssx, ssy, |
+#if CONFIG_VP9_HIGHBITDEPTH |
+ use_highbitdepth, |
+#endif |
+ border); |
if (fail) { |
vp9_denoiser_free(denoiser); |
return 1; |
@@ -405,7 +439,11 @@ |
} |
fail = vp9_alloc_frame_buffer(&denoiser->mc_running_avg_y, width, height, |
- ssx, ssy, border); |
+ ssx, ssy, |
+#if CONFIG_VP9_HIGHBITDEPTH |
+ use_highbitdepth, |
+#endif |
+ border); |
if (fail) { |
vp9_denoiser_free(denoiser); |
return 1; |