Index: source/libvpx/vp9/encoder/vp9_denoiser.c |
=================================================================== |
--- source/libvpx/vp9/encoder/vp9_denoiser.c (revision 293588) |
+++ source/libvpx/vp9/encoder/vp9_denoiser.c (working copy) |
@@ -49,9 +49,7 @@ |
} |
static unsigned int sse_thresh(BLOCK_SIZE bs, int increase_denoising) { |
- return (4 << b_width_log2_lookup[bs]) * |
- (4 << b_height_log2_lookup[bs]) * |
- (increase_denoising ? 60 : 40); |
+ return (1 << num_pels_log2_lookup[bs]) * (increase_denoising ? 60 : 40); |
} |
static int sse_diff_thresh(BLOCK_SIZE bs, int increase_denoising, |
@@ -60,19 +58,16 @@ |
noise_motion_thresh(bs, increase_denoising)) { |
return 0; |
} else { |
- return (4 << b_width_log2_lookup[bs]) * |
- (4 << b_height_log2_lookup[bs]) * 20; |
+ return (1 << num_pels_log2_lookup[bs]) * 20; |
} |
} |
int total_adj_strong_thresh(BLOCK_SIZE bs, int increase_denoising) { |
- return (4 << b_width_log2_lookup[bs]) * |
- (4 << b_height_log2_lookup[bs]) * (increase_denoising ? 3 : 2); |
+ return (1 << num_pels_log2_lookup[bs]) * (increase_denoising ? 3 : 2); |
} |
static int total_adj_weak_thresh(BLOCK_SIZE bs, int increase_denoising) { |
- return (4 << b_width_log2_lookup[bs]) * |
- (4 << b_height_log2_lookup[bs]) * (increase_denoising ? 3 : 2); |
+ return (1 << num_pels_log2_lookup[bs]) * (increase_denoising ? 3 : 2); |
} |
// TODO(jackychen): If increase_denoising is enabled in the future, |
@@ -195,16 +190,6 @@ |
return framebuf + (stride * mi_row * 8) + (mi_col * 8); |
} |
-static void copy_block(uint8_t *dest, int dest_stride, |
- const uint8_t *src, int src_stride, BLOCK_SIZE bs) { |
- int r; |
- for (r = 0; r < (4 << b_height_log2_lookup[bs]); ++r) { |
- vpx_memcpy(dest, src, (4 << b_width_log2_lookup[bs])); |
- dest += dest_stride; |
- src += src_stride; |
- } |
-} |
- |
static VP9_DENOISER_DECISION perform_motion_compensation(VP9_DENOISER *denoiser, |
MACROBLOCK *mb, |
BLOCK_SIZE bs, |
@@ -219,28 +204,18 @@ |
MV_REFERENCE_FRAME frame; |
MACROBLOCKD *filter_mbd = &mb->e_mbd; |
MB_MODE_INFO *mbmi = &filter_mbd->mi[0].src_mi->mbmi; |
- |
MB_MODE_INFO saved_mbmi; |
int i, j; |
struct buf_2d saved_dst[MAX_MB_PLANE]; |
struct buf_2d saved_pre[MAX_MB_PLANE][2]; // 2 pre buffers |
- // We will restore these after motion compensation. |
- saved_mbmi = *mbmi; |
- for (i = 0; i < MAX_MB_PLANE; ++i) { |
- for (j = 0; j < 2; ++j) { |
- saved_pre[i][j] = filter_mbd->plane[i].pre[j]; |
- } |
- saved_dst[i] = filter_mbd->plane[i].dst; |
- } |
- |
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; |
+ saved_mbmi = *mbmi; |
+ |
// If the best reference frame uses inter-prediction and there is enough of a |
// difference in sum-squared-error, use it. |
if (frame != INTRA_FRAME && |
@@ -261,6 +236,26 @@ |
ctx->newmv_sse = ctx->zeromv_sse; |
} |
+ if (ctx->newmv_sse > sse_thresh(bs, increase_denoising)) { |
+ // Restore everything to its original state |
+ *mbmi = saved_mbmi; |
+ return COPY_BLOCK; |
+ } |
+ if (mv_row * mv_row + mv_col * mv_col > |
+ 8 * noise_motion_thresh(bs, increase_denoising)) { |
+ // Restore everything to its original state |
+ *mbmi = saved_mbmi; |
+ return COPY_BLOCK; |
+ } |
+ |
+ // We will restore these after motion compensation. |
+ for (i = 0; i < MAX_MB_PLANE; ++i) { |
+ for (j = 0; j < 2; ++j) { |
+ saved_pre[i][j] = filter_mbd->plane[i].pre[j]; |
+ } |
+ saved_dst[i] = filter_mbd->plane[i].dst; |
+ } |
+ |
// Set the pointers in the MACROBLOCKD to point to the buffers in the denoiser |
// struct. |
for (j = 0; j < 2; ++j) { |
@@ -313,13 +308,6 @@ |
mv_row = ctx->best_sse_mv.as_mv.row; |
mv_col = ctx->best_sse_mv.as_mv.col; |
- if (ctx->newmv_sse > sse_thresh(bs, increase_denoising)) { |
- return COPY_BLOCK; |
- } |
- if (mv_row * mv_row + mv_col * mv_col > |
- 8 * noise_motion_thresh(bs, increase_denoising)) { |
- return COPY_BLOCK; |
- } |
return FILTER_BLOCK; |
} |
@@ -348,9 +336,15 @@ |
} |
if (decision == FILTER_BLOCK) { |
- copy_block(src.buf, src.stride, avg_start, avg.y_stride, bs); |
+ vp9_convolve_copy(avg_start, avg.y_stride, src.buf, src.stride, |
+ NULL, 0, NULL, 0, |
+ num_4x4_blocks_wide_lookup[bs] << 2, |
+ num_4x4_blocks_high_lookup[bs] << 2); |
} else { // COPY_BLOCK |
- copy_block(avg_start, avg.y_stride, src.buf, src.stride, bs); |
+ vp9_convolve_copy(src.buf, src.stride, avg_start, avg.y_stride, |
+ NULL, 0, NULL, 0, |
+ num_4x4_blocks_wide_lookup[bs] << 2, |
+ num_4x4_blocks_high_lookup[bs] << 2); |
} |
} |
@@ -368,6 +362,15 @@ |
} |
} |
+static void swap_frame_buffer(YV12_BUFFER_CONFIG dest, |
+ YV12_BUFFER_CONFIG src) { |
+ uint8_t *tmp_buf = dest.y_buffer; |
+ assert(dest.y_width == src.y_width); |
+ assert(dest.y_height == src.y_height); |
+ dest.y_buffer = src.y_buffer; |
+ src.y_buffer = tmp_buf; |
+} |
+ |
void vp9_denoiser_update_frame_info(VP9_DENOISER *denoiser, |
YV12_BUFFER_CONFIG src, |
FRAME_TYPE frame_type, |
@@ -377,28 +380,32 @@ |
if (frame_type == KEY_FRAME) { |
int i; |
// Start at 1 so as not to overwrite the INTRA_FRAME |
- for (i = 1; i < MAX_REF_FRAMES; ++i) { |
+ for (i = 1; i < MAX_REF_FRAMES; ++i) |
copy_frame(denoiser->running_avg_y[i], src); |
- } |
- } else { /* For non key frames */ |
- if (refresh_alt_ref_frame) { |
- copy_frame(denoiser->running_avg_y[ALTREF_FRAME], |
- denoiser->running_avg_y[INTRA_FRAME]); |
- } |
- if (refresh_golden_frame) { |
- copy_frame(denoiser->running_avg_y[GOLDEN_FRAME], |
- denoiser->running_avg_y[INTRA_FRAME]); |
- } |
- if (refresh_last_frame) { |
- copy_frame(denoiser->running_avg_y[LAST_FRAME], |
- denoiser->running_avg_y[INTRA_FRAME]); |
- } |
+ return; |
} |
+ |
+ /* For non key frames */ |
+ if (refresh_alt_ref_frame) { |
+ swap_frame_buffer(denoiser->running_avg_y[ALTREF_FRAME], |
+ denoiser->running_avg_y[INTRA_FRAME]); |
+ } |
+ if (refresh_golden_frame) { |
+ swap_frame_buffer(denoiser->running_avg_y[GOLDEN_FRAME], |
+ denoiser->running_avg_y[INTRA_FRAME]); |
+ } |
+ if (refresh_last_frame) { |
+ swap_frame_buffer(denoiser->running_avg_y[LAST_FRAME], |
+ denoiser->running_avg_y[INTRA_FRAME]); |
+ } |
} |
void vp9_denoiser_reset_frame_stats(PICK_MODE_CONTEXT *ctx) { |
ctx->zeromv_sse = UINT_MAX; |
- ctx->newmv_sse = UINT_MAX; |
+ // This should be initialized as zero since mode search stage might skip |
+ // NEWMV mode if inferred motion vector modes provide sufficiently good |
+ // prediction quality. |
+ ctx->newmv_sse = 0; |
} |
void vp9_denoiser_update_frame_stats(MB_MODE_INFO *mbmi, unsigned int sse, |
@@ -425,6 +432,7 @@ |
#endif |
int border) { |
int i, fail; |
+ const int legacy_byte_alignment = 0; |
assert(denoiser != NULL); |
for (i = 0; i < MAX_REF_FRAMES; ++i) { |
@@ -433,7 +441,7 @@ |
#if CONFIG_VP9_HIGHBITDEPTH |
use_highbitdepth, |
#endif |
- border); |
+ border, legacy_byte_alignment); |
if (fail) { |
vp9_denoiser_free(denoiser); |
return 1; |
@@ -448,7 +456,7 @@ |
#if CONFIG_VP9_HIGHBITDEPTH |
use_highbitdepth, |
#endif |
- border); |
+ border, legacy_byte_alignment); |
if (fail) { |
vp9_denoiser_free(denoiser); |
return 1; |
@@ -457,6 +465,7 @@ |
make_grayscale(&denoiser->running_avg_y[i]); |
#endif |
denoiser->increase_denoising = 0; |
+ denoiser->frame_buffer_initialized = 1; |
return 0; |
} |
@@ -463,6 +472,7 @@ |
void vp9_denoiser_free(VP9_DENOISER *denoiser) { |
int i; |
+ denoiser->frame_buffer_initialized = 0; |
if (denoiser == NULL) { |
return; |
} |
@@ -482,15 +492,13 @@ |
uint8_t *u = yuv->u_buffer; |
uint8_t *v = yuv->v_buffer; |
- // The '/2's are there because we have a 440 buffer, but we want to output |
- // 420. |
- for (r = 0; r < yuv->uv_height / 2; ++r) { |
- for (c = 0; c < yuv->uv_width / 2; ++c) { |
+ for (r = 0; r < yuv->uv_height; ++r) { |
+ for (c = 0; c < yuv->uv_width; ++c) { |
u[c] = UINT8_MAX / 2; |
v[c] = UINT8_MAX / 2; |
} |
- u += yuv->uv_stride + yuv->uv_width / 2; |
- v += yuv->uv_stride + yuv->uv_width / 2; |
+ u += yuv->uv_stride; |
+ v += yuv->uv_stride; |
} |
} |
#endif |