Merge "Adds a motion compensated temporal denoiser to the encoder."
This commit is contained in:
@@ -24,6 +24,9 @@
|
||||
#include "mcomp.h"
|
||||
#include "rdopt.h"
|
||||
#include "vpx_mem/vpx_mem.h"
|
||||
#if CONFIG_TEMPORAL_DENOISING
|
||||
#include "denoising.h"
|
||||
#endif
|
||||
|
||||
extern int VP8_UVSSE(MACROBLOCK *x);
|
||||
|
||||
@@ -450,6 +453,48 @@ void get_lower_res_motion_info(VP8_COMP *cpi, MACROBLOCKD *xd, int *dissim,
|
||||
}
|
||||
#endif
|
||||
|
||||
static void check_for_encode_breakout(unsigned int sse, MACROBLOCK* x)
|
||||
{
|
||||
if (sse < x->encode_breakout)
|
||||
{
|
||||
// Check u and v to make sure skip is ok
|
||||
int sse2 = 0;
|
||||
|
||||
sse2 = VP8_UVSSE(x);
|
||||
|
||||
if (sse2 * 2 < x->encode_breakout)
|
||||
x->skip = 1;
|
||||
else
|
||||
x->skip = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int evaluate_inter_mode(unsigned int* sse, int rate2, int* distortion2, VP8_COMP *cpi, MACROBLOCK *x)
|
||||
{
|
||||
MB_PREDICTION_MODE this_mode = x->e_mbd.mode_info_context->mbmi.mode;
|
||||
int_mv mv = x->e_mbd.mode_info_context->mbmi.mv;
|
||||
int this_rd;
|
||||
/* Exit early and don't compute the distortion if this macroblock
|
||||
* is marked inactive. */
|
||||
if (cpi->active_map_enabled && x->active_ptr[0] == 0)
|
||||
{
|
||||
*sse = 0;
|
||||
*distortion2 = 0;
|
||||
x->skip = 1;
|
||||
return INT_MAX;
|
||||
}
|
||||
|
||||
if((this_mode != NEWMV) ||
|
||||
!(cpi->sf.half_pixel_search) || cpi->common.full_pixel==1)
|
||||
*distortion2 = get_inter_mbpred_error(x,
|
||||
&cpi->fn_ptr[BLOCK_16X16],
|
||||
sse, mv);
|
||||
|
||||
this_rd = RDCOST(x->rdmult, x->rddiv, rate2, *distortion2);
|
||||
|
||||
check_for_encode_breakout(*sse, x);
|
||||
return this_rd;
|
||||
}
|
||||
|
||||
void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
|
||||
int recon_uvoffset, int *returnrate,
|
||||
@@ -476,7 +521,10 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
|
||||
int distortion2;
|
||||
int bestsme = INT_MAX;
|
||||
int best_mode_index = 0;
|
||||
unsigned int sse = INT_MAX, best_sse = INT_MAX;
|
||||
unsigned int sse = INT_MAX, best_rd_sse = INT_MAX;
|
||||
#if CONFIG_TEMPORAL_DENOISING
|
||||
unsigned int zero_mv_sse = 0, best_sse = INT_MAX;
|
||||
#endif
|
||||
|
||||
int_mv mvp;
|
||||
|
||||
@@ -488,9 +536,6 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
|
||||
int ref_frame_map[4];
|
||||
int sign_bias = 0;
|
||||
|
||||
int have_subp_search = cpi->sf.half_pixel_search; /* In real-time mode,
|
||||
when Speed >= 15, no sub-pixel search. */
|
||||
|
||||
#if CONFIG_MULTI_RES_ENCODING
|
||||
int dissim = INT_MAX;
|
||||
int parent_ref_frame = 0;
|
||||
@@ -657,7 +702,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
|
||||
{
|
||||
case B_PRED:
|
||||
/* Pass best so far to pick_intra4x4mby_modes to use as breakout */
|
||||
distortion2 = best_sse;
|
||||
distortion2 = best_rd_sse;
|
||||
pick_intra4x4mby_modes(x, &rate, &distortion2);
|
||||
|
||||
if (distortion2 == INT_MAX)
|
||||
@@ -905,43 +950,38 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
|
||||
rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
|
||||
x->e_mbd.mode_info_context->mbmi.mv.as_int =
|
||||
mode_mv[this_mode].as_int;
|
||||
|
||||
/* Exit early and don't compute the distortion if this macroblock
|
||||
* is marked inactive. */
|
||||
if (cpi->active_map_enabled && x->active_ptr[0] == 0)
|
||||
{
|
||||
sse = 0;
|
||||
distortion2 = 0;
|
||||
x->skip = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if((this_mode != NEWMV) ||
|
||||
!(have_subp_search) || cpi->common.full_pixel==1)
|
||||
distortion2 = get_inter_mbpred_error(x,
|
||||
&cpi->fn_ptr[BLOCK_16X16],
|
||||
&sse, mode_mv[this_mode]);
|
||||
|
||||
this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
|
||||
|
||||
if (sse < x->encode_breakout)
|
||||
{
|
||||
// Check u and v to make sure skip is ok
|
||||
int sse2 = 0;
|
||||
|
||||
sse2 = VP8_UVSSE(x);
|
||||
|
||||
if (sse2 * 2 < x->encode_breakout)
|
||||
x->skip = 1;
|
||||
else
|
||||
x->skip = 0;
|
||||
}
|
||||
this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#if CONFIG_TEMPORAL_DENOISING
|
||||
if (cpi->oxcf.noise_sensitivity)
|
||||
{
|
||||
// Store for later use by denoiser.
|
||||
if (this_mode == ZEROMV &&
|
||||
x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME)
|
||||
{
|
||||
zero_mv_sse = sse;
|
||||
}
|
||||
|
||||
// Store the best NEWMV in x for later use in the denoiser.
|
||||
// We are restricted to the LAST_FRAME since the denoiser only keeps
|
||||
// one filter state.
|
||||
if (x->e_mbd.mode_info_context->mbmi.mode == NEWMV &&
|
||||
x->e_mbd.mode_info_context->mbmi.ref_frame == LAST_FRAME)
|
||||
{
|
||||
best_sse = sse;
|
||||
x->e_mbd.best_sse_inter_mode = NEWMV;
|
||||
x->e_mbd.best_sse_mv = x->e_mbd.mode_info_context->mbmi.mv;
|
||||
x->e_mbd.need_to_clamp_best_mvs =
|
||||
x->e_mbd.mode_info_context->mbmi.need_to_clamp_mvs;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (this_rd < best_rd || x->skip)
|
||||
{
|
||||
// Note index of best mode
|
||||
@@ -949,7 +989,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
|
||||
|
||||
*returnrate = rate2;
|
||||
*returndistortion = distortion2;
|
||||
best_sse = sse;
|
||||
best_rd_sse = sse;
|
||||
best_rd = this_rd;
|
||||
vpx_memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi,
|
||||
sizeof(MB_MODE_INFO));
|
||||
@@ -1011,6 +1051,43 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
|
||||
cpi->error_bins[this_rdbin] ++;
|
||||
}
|
||||
|
||||
#if CONFIG_TEMPORAL_DENOISING
|
||||
if (cpi->oxcf.noise_sensitivity)
|
||||
{
|
||||
if (x->e_mbd.best_sse_inter_mode == DC_PRED) {
|
||||
// No best MV found.
|
||||
x->e_mbd.best_sse_inter_mode = best_mbmode.mode;
|
||||
x->e_mbd.best_sse_mv = best_mbmode.mv;
|
||||
x->e_mbd.need_to_clamp_best_mvs = best_mbmode.need_to_clamp_mvs;
|
||||
best_sse = best_rd_sse;
|
||||
}
|
||||
vp8_denoiser_denoise_mb(&cpi->denoiser, x, best_sse, zero_mv_sse,
|
||||
recon_yoffset, recon_uvoffset);
|
||||
|
||||
// Reevaluate ZEROMV after denoising.
|
||||
if (best_mbmode.ref_frame == INTRA_FRAME)
|
||||
{
|
||||
int this_rd = 0;
|
||||
rate2 = 0;
|
||||
distortion2 = 0;
|
||||
x->e_mbd.mode_info_context->mbmi.ref_frame = LAST_FRAME;
|
||||
rate2 += x->ref_frame_cost[x->e_mbd.mode_info_context->mbmi.ref_frame];
|
||||
this_mode = ZEROMV;
|
||||
rate2 += vp8_cost_mv_ref(this_mode, mdcounts);
|
||||
x->e_mbd.mode_info_context->mbmi.mode = this_mode;
|
||||
x->e_mbd.mode_info_context->mbmi.uv_mode = DC_PRED;
|
||||
x->e_mbd.mode_info_context->mbmi.mv.as_int = 0;
|
||||
this_rd = evaluate_inter_mode(&sse, rate2, &distortion2, cpi, x);
|
||||
|
||||
if (this_rd < best_rd || x->skip)
|
||||
{
|
||||
vpx_memcpy(&best_mbmode, &x->e_mbd.mode_info_context->mbmi,
|
||||
sizeof(MB_MODE_INFO));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cpi->is_src_frame_alt_ref &&
|
||||
(best_mbmode.mode != ZEROMV || best_mbmode.ref_frame != ALTREF_FRAME))
|
||||
{
|
||||
|
Reference in New Issue
Block a user