Free plane-wise filtering from estimated weights.
Plane-wise temporal filtering strategy is actually independent from the
filtering weight estimation used in YUV strategy. However, the current
code makes an early return if the estimated weights are 0 no matter what
filtering strategy is being used.
This CL fixes this bug by only making early return when using YUV
strategy. Only midres and hdres are affected since plane-wise strategy
is only applied to high resolution videos.
Experimental resutls:
Under Speed-4 (two-pass mode):
avg PSNR ovr PSNR SSIM
midres 0.006 -0.054 -0.045
midres2 0.016 0.044 0.104
hdres -0.008 -0.044 -0.033
hdres2 0.026 -0.021 0.037
Under Speed-1 (two-pass mode):
avg PSNR ovr PSNR SSIM
midres 0.008 -0.106 -0.062
midres2 -0.021 -0.049 -0.008
hdres -0.041 -0.046 -0.032
hdres2 -0.040 -0.079 -0.007
STATS_CHANGED
Change-Id: Ifb5ce0a53fa6a9b634bf810d9d5f9b2dcc6a4ee4
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index d0ae473..61341e3 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -801,6 +801,10 @@
noise_levels, pred, accum, count);
}
} else { // Commonly used for low-resolution video.
+ if (subblock_filter_weights[0] == 0 && subblock_filter_weights[1] == 0 &&
+ subblock_filter_weights[2] == 0 && subblock_filter_weights[3] == 0) {
+ return;
+ }
const int adj_strength = strength + 2 * (mbd->bd - 8);
if (num_planes == 3 && TF_YUV_FILTER_WEIGHT_SCALE == 3) {
av1_apply_temporal_filter_yuv(frame_to_filter, mbd, block_size, mb_row,
@@ -966,6 +970,7 @@
for (int frame = 0; frame < num_frames; frame++) {
if (frames[frame] == NULL) continue;
+ // Motion search.
MV subblock_mvs[4] = { kZeroMv, kZeroMv, kZeroMv, kZeroMv };
int subblock_filter_weights[4] = { 0, 0, 0, 0 };
int block_error = INT_MAX;
@@ -986,24 +991,24 @@
ref_mv = kZeroMv;
}
}
+
+ // Build predictor.
int use_subblock = tf_get_filter_weight(
block_error, subblock_errors, use_planewise_strategy, is_second_arf,
subblock_filter_weights);
- if (subblock_filter_weights[0] || subblock_filter_weights[1] ||
- subblock_filter_weights[2] || subblock_filter_weights[3]) {
- tf_build_predictor(frames[frame], mbd, block_size, mb_row, mb_col,
- num_planes, scale, use_subblock, subblock_mvs,
- pred);
- if (frame == filter_frame_idx) { // Frame to be filtered.
- av1_apply_temporal_filter_self(mbd, block_size, num_planes,
- subblock_filter_weights[0], pred,
- accum, count);
- } else {
- av1_apply_temporal_filter_others( // Other reference frames.
- frame_to_filter, mbd, block_size, mb_row, mb_col, num_planes,
- use_planewise_strategy, strength, use_subblock,
- subblock_filter_weights, noise_levels, pred, accum, count);
- }
+ tf_build_predictor(frames[frame], mbd, block_size, mb_row, mb_col,
+ num_planes, scale, use_subblock, subblock_mvs, pred);
+
+ // Perform weighted averaging.
+ if (frame == filter_frame_idx) { // Frame to be filtered.
+ av1_apply_temporal_filter_self(mbd, block_size, num_planes,
+ subblock_filter_weights[0], pred,
+ accum, count);
+ } else { // Other reference frames.
+ av1_apply_temporal_filter_others(
+ frame_to_filter, mbd, block_size, mb_row, mb_col, num_planes,
+ use_planewise_strategy, strength, use_subblock,
+ subblock_filter_weights, noise_levels, pred, accum, count);
}
}