diff options
Diffstat (limited to 'vp8/encoder/denoising.c')
-rw-r--r-- | vp8/encoder/denoising.c | 205 |
1 files changed, 114 insertions, 91 deletions
diff --git a/vp8/encoder/denoising.c b/vp8/encoder/denoising.c index 45d54ee01..194d42229 100644 --- a/vp8/encoder/denoising.c +++ b/vp8/encoder/denoising.c @@ -22,68 +22,6 @@ static const unsigned int SSE_DIFF_THRESHOLD = 16 * 16 * 20; static const unsigned int SSE_THRESHOLD = 16 * 16 * 40; -static unsigned int denoiser_motion_compensate(YV12_BUFFER_CONFIG *src, - YV12_BUFFER_CONFIG *dst, - MACROBLOCK *x, - unsigned int best_sse, - unsigned int zero_mv_sse, - int recon_yoffset, - int recon_uvoffset) -{ - MACROBLOCKD filter_xd = x->e_mbd; - int mv_col; - int mv_row; - int sse_diff = zero_mv_sse - best_sse; - // Compensate the running average. - filter_xd.pre.y_buffer = src->y_buffer + recon_yoffset; - filter_xd.pre.u_buffer = src->u_buffer + recon_uvoffset; - filter_xd.pre.v_buffer = src->v_buffer + recon_uvoffset; - // Write the compensated running average to the destination buffer. - filter_xd.dst.y_buffer = dst->y_buffer + recon_yoffset; - filter_xd.dst.u_buffer = dst->u_buffer + recon_uvoffset; - filter_xd.dst.v_buffer = dst->v_buffer + recon_uvoffset; - // Use the best MV for the compensation. - filter_xd.mode_info_context->mbmi.ref_frame = LAST_FRAME; - filter_xd.mode_info_context->mbmi.mode = filter_xd.best_sse_inter_mode; - filter_xd.mode_info_context->mbmi.mv = filter_xd.best_sse_mv; - filter_xd.mode_info_context->mbmi.need_to_clamp_mvs = - filter_xd.need_to_clamp_best_mvs; - mv_col = filter_xd.best_sse_mv.as_mv.col; - mv_row = filter_xd.best_sse_mv.as_mv.row; - - if (filter_xd.mode_info_context->mbmi.mode <= B_PRED || - (mv_row *mv_row + mv_col *mv_col <= NOISE_MOTION_THRESHOLD && - sse_diff < SSE_DIFF_THRESHOLD)) - { - // Handle intra blocks as referring to last frame with zero motion and - // let the absolute pixel difference affect the filter factor. - // Also consider small amount of motion as being random walk due to - // noise, if it doesn't mean that we get a much bigger error. - // Note that any changes to the mode info only affects the denoising. - filter_xd.mode_info_context->mbmi.ref_frame = LAST_FRAME; - filter_xd.mode_info_context->mbmi.mode = ZEROMV; - filter_xd.mode_info_context->mbmi.mv.as_int = 0; - x->e_mbd.best_sse_inter_mode = ZEROMV; - x->e_mbd.best_sse_mv.as_int = 0; - best_sse = zero_mv_sse; - } - - if (!x->skip) - { - vp8_build_inter_predictors_mb(&filter_xd); - } - else - { - vp8_build_inter16x16_predictors_mb(&filter_xd, - filter_xd.dst.y_buffer, - filter_xd.dst.u_buffer, - filter_xd.dst.v_buffer, - filter_xd.dst.y_stride, - filter_xd.dst.uv_stride); - } - - return best_sse; -} // The filtering coefficients used for denoizing are adjusted for static // blocks, or blocks with very small motion vectors. This is done through @@ -216,27 +154,34 @@ void vp8_denoiser_filter_c(YV12_BUFFER_CONFIG *mc_running_avg, int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height) { + int i; assert(denoiser); - denoiser->yv12_running_avg.flags = 0; - if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_running_avg), width, - height, VP8BORDERINPIXELS) < 0) + /* don't need one for intra start at 1 */ + for (i = 1; i < MAX_REF_FRAMES; i++) { - vp8_denoiser_free(denoiser); - return 1; - } + denoiser->yv12_running_avg[i].flags = 0; + if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_running_avg[i]), width, + height, VP8BORDERINPIXELS) + < 0) + { + vp8_denoiser_free(denoiser); + return 1; + } + vpx_memset(denoiser->yv12_running_avg[i].buffer_alloc, 0, + denoiser->yv12_running_avg[i].frame_size); + + } denoiser->yv12_mc_running_avg.flags = 0; if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_mc_running_avg), width, - height, VP8BORDERINPIXELS) < 0) + height, VP8BORDERINPIXELS) < 0) { vp8_denoiser_free(denoiser); return 1; } - vpx_memset(denoiser->yv12_running_avg.buffer_alloc, 0, - denoiser->yv12_running_avg.frame_size); vpx_memset(denoiser->yv12_mc_running_avg.buffer_alloc, 0, denoiser->yv12_mc_running_avg.frame_size); return 0; @@ -244,11 +189,18 @@ int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height) void vp8_denoiser_free(VP8_DENOISER *denoiser) { + int i; assert(denoiser); - vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_running_avg); + + /* we don't have one for intra ref frame */ + for (i = 1; i < MAX_REF_FRAMES ; i++) + { + vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_running_avg[i]); + } vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_mc_running_avg); } + void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, MACROBLOCK *x, unsigned int best_sse, @@ -259,32 +211,103 @@ void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, int mv_row; int mv_col; unsigned int motion_magnitude2; + + MV_REFERENCE_FRAME frame = x->best_reference_frame; + MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame; + // Motion compensate the running average. - best_sse = denoiser_motion_compensate(&denoiser->yv12_running_avg, - &denoiser->yv12_mc_running_avg, - x, - best_sse, - zero_mv_sse, - recon_yoffset, - recon_uvoffset); - - mv_row = x->e_mbd.best_sse_mv.as_mv.row; - mv_col = x->e_mbd.best_sse_mv.as_mv.col; - motion_magnitude2 = mv_row * mv_row + mv_col * mv_col; + if(zero_frame) + { + YV12_BUFFER_CONFIG *src = &denoiser->yv12_running_avg[frame]; + YV12_BUFFER_CONFIG *dst = &denoiser->yv12_mc_running_avg; + YV12_BUFFER_CONFIG saved_pre,saved_dst; + MB_MODE_INFO saved_mbmi; + MACROBLOCKD *filter_xd = &x->e_mbd; + MB_MODE_INFO *mbmi = &filter_xd->mode_info_context->mbmi; + int mv_col; + int mv_row; + int sse_diff = zero_mv_sse - best_sse; + + saved_mbmi = *mbmi; + + // Use the best MV for the compensation. + mbmi->ref_frame = x->best_reference_frame; + mbmi->mode = x->best_sse_inter_mode; + mbmi->mv = x->best_sse_mv; + mbmi->need_to_clamp_mvs = x->need_to_clamp_best_mvs; + mv_col = x->best_sse_mv.as_mv.col; + mv_row = x->best_sse_mv.as_mv.row; + + if(frame == INTRA_FRAME || + (mv_row *mv_row + mv_col *mv_col <= NOISE_MOTION_THRESHOLD && + sse_diff < SSE_DIFF_THRESHOLD)) + { + // Handle intra blocks as referring to last frame with zero motion + // and let the absolute pixel difference affect the filter factor. + // Also consider small amount of motion as being random walk due to + // noise, if it doesn't mean that we get a much bigger error. + // Note that any changes to the mode info only affects the denoising. + mbmi->ref_frame = + x->best_zeromv_reference_frame; + + src = &denoiser->yv12_running_avg[zero_frame]; + + mbmi->mode = ZEROMV; + mbmi->mv.as_int = 0; + x->best_sse_inter_mode = ZEROMV; + x->best_sse_mv.as_int = 0; + best_sse = zero_mv_sse; + } + + saved_pre = filter_xd->pre; + saved_dst = filter_xd->dst; - if (best_sse > SSE_THRESHOLD || - motion_magnitude2 > 8 * NOISE_MOTION_THRESHOLD) + // Compensate the running average. + filter_xd->pre.y_buffer = src->y_buffer + recon_yoffset; + filter_xd->pre.u_buffer = src->u_buffer + recon_uvoffset; + filter_xd->pre.v_buffer = src->v_buffer + recon_uvoffset; + // Write the compensated running average to the destination buffer. + filter_xd->dst.y_buffer = dst->y_buffer + recon_yoffset; + filter_xd->dst.u_buffer = dst->u_buffer + recon_uvoffset; + filter_xd->dst.v_buffer = dst->v_buffer + recon_uvoffset; + + if (!x->skip) + { + vp8_build_inter_predictors_mb(filter_xd); + } + else + { + vp8_build_inter16x16_predictors_mb(filter_xd, + filter_xd->dst.y_buffer, + filter_xd->dst.u_buffer, + filter_xd->dst.v_buffer, + filter_xd->dst.y_stride, + filter_xd->dst.uv_stride); + } + filter_xd->pre = saved_pre; + filter_xd->dst = saved_dst; + *mbmi = saved_mbmi; + + } + + 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; + if (best_sse > SSE_THRESHOLD || motion_magnitude2 + > 8 * NOISE_MOTION_THRESHOLD) { - // No filtering of this block since it differs too much from the - // predictor, or the motion vector magnitude is considered too big. - vp8_copy_mem16x16(x->thismb, 16, - denoiser->yv12_running_avg.y_buffer + recon_yoffset, - denoiser->yv12_running_avg.y_stride); + // No filtering of this block; it differs too much from the predictor, + // or the motion vector magnitude is considered too big. + vp8_copy_mem16x16( + x->thismb, 16, + denoiser->yv12_running_avg[LAST_FRAME].y_buffer + recon_yoffset, + denoiser->yv12_running_avg[LAST_FRAME].y_stride); return; } // Filter. vp8_denoiser_filter(&denoiser->yv12_mc_running_avg, - &denoiser->yv12_running_avg, x, motion_magnitude2, + &denoiser->yv12_running_avg[LAST_FRAME], x, + motion_magnitude2, recon_yoffset, recon_uvoffset); } |