Integrate motion information in RTC TF decision
Improved RTC temporal filter for >= 360p videos. Integrated this
block and its neighbor blocks' motion information into the deci-
sion making. The threshold was also adjusted. These improvements
gave further BDrate gains.
Borg test results:
avg_psnr: ovr_psnr: ssim:
speed 7: -0.462 -0.404 -0.414
speed 8: -0.390 -0.375 -0.381
speed 9: -0.215 -0.211 -0.111
speed 10: -0.403 -0.371 -0.359
Almost no speed drop (~0.1%).
STATS_CHANGED for >= 360p and speed >= 7
Change-Id: Ia1a5358b1ef80446e72c27434b0290821b00ee18
diff --git a/av1/encoder/encodeframe_utils.c b/av1/encoder/encodeframe_utils.c
index 2bc61c7..75e0fcc 100644
--- a/av1/encoder/encodeframe_utils.c
+++ b/av1/encoder/encodeframe_utils.c
@@ -1433,9 +1433,8 @@
if (cpi->last_source->y_width != cpi->source->y_width ||
cpi->last_source->y_height != cpi->source->y_height)
return;
- if (!cpi->sf.rt_sf.use_rtc_tf || tmp_sse == 0) return;
- if (cpi->sf.rt_sf.use_rtc_tf == 2 &&
- (cpi->rc.high_source_sad || cpi->rc.frame_source_sad > 20000))
+ if (!cpi->sf.rt_sf.use_rtc_tf || tmp_sse == 0 || cpi->rc.high_source_sad ||
+ cpi->rc.frame_source_sad > 20000)
return;
// In-place temporal filter. If psnr calculation is enabled, we store the
@@ -1445,34 +1444,34 @@
const unsigned int nmean2 = tmp_sse - tmp_variance;
const int ac_q_step = av1_ac_quant_QTX(cm->quant_params.base_qindex, 0,
cm->seq_params->bit_depth);
- // Keep the threshold for >= 360p unchanged. It will be tested and modified
- // later when needed.
- const unsigned int threshold = (cpi->sf.rt_sf.use_rtc_tf == 1)
- ? ((3 * ac_q_step * ac_q_step) >> 1)
- : 250 * ac_q_step;
+ const PRIMARY_RATE_CONTROL *const p_rc = &cpi->ppi->p_rc;
+ const int avg_q_step = av1_ac_quant_QTX(p_rc->avg_frame_qindex[INTER_FRAME],
+ 0, cm->seq_params->bit_depth);
+
+ const unsigned int threshold =
+ (cpi->sf.rt_sf.use_rtc_tf == 1)
+ ? (clamp(avg_q_step, 250, 1000)) * ac_q_step
+ : 250 * ac_q_step;
// TODO(yunqing): use a weighted sum instead of averaging in filtering.
if (tmp_variance <= threshold && nmean2 <= 15) {
- if (cpi->sf.rt_sf.use_rtc_tf == 2) {
- // Check neighbor blocks. If neighbor blocks aren't low-motion blocks,
- // skip temporal filtering for this block.
- MB_MODE_INFO **mi = cm->mi_params.mi_grid_base +
- get_mi_grid_idx(&cm->mi_params, mi_row, mi_col);
- const TileInfo *const tile_info = &tile_data->tile_info;
- const int is_neighbor_blocks_low_motion = check_neighbor_blocks(
- mi, cm->mi_params.mi_stride, tile_info, mi_row, mi_col);
- if (!is_neighbor_blocks_low_motion) return;
+ // Check neighbor blocks. If neighbor blocks aren't low-motion blocks,
+ // skip temporal filtering for this block.
+ MB_MODE_INFO **mi = cm->mi_params.mi_grid_base +
+ get_mi_grid_idx(&cm->mi_params, mi_row, mi_col);
+ const TileInfo *const tile_info = &tile_data->tile_info;
+ const int is_neighbor_blocks_low_motion = check_neighbor_blocks(
+ mi, cm->mi_params.mi_stride, tile_info, mi_row, mi_col);
+ if (!is_neighbor_blocks_low_motion) return;
- // Only consider 64x64 SB for now. Need to extend to 128x128 for large SB
- // size.
- // Test several nearby points. If non-zero mv exists, don't do temporal
- // filtering.
- const int is_this_blk_low_motion =
- fast_detect_non_zero_motion(cpi, src_y, src_ystride, last_src_y,
- last_src_ystride, mi_row, mi_col);
+ // Only consider 64x64 SB for now. Need to extend to 128x128 for large SB
+ // size.
+ // Test several nearby points. If non-zero mv exists, don't do temporal
+ // filtering.
+ const int is_this_blk_low_motion = fast_detect_non_zero_motion(
+ cpi, src_y, src_ystride, last_src_y, last_src_ystride, mi_row, mi_col);
- if (!is_this_blk_low_motion) return;
- }
+ if (!is_this_blk_low_motion) return;
const int shift_x[2] = { 0, cpi->source->subsampling_x };
const int shift_y[2] = { 0, cpi->source->subsampling_y };
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 601895e..1dbc95d 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -1317,7 +1317,6 @@
if (speed >= 6) sf->rt_sf.skip_newmv_mode_based_on_sse = 2;
if (speed == 7) sf->rt_sf.prefer_large_partition_blocks = 1;
if (speed >= 7) {
- // TODO(yunqing): extend this sf to other speeds and/or other resolutions.
sf->rt_sf.use_rtc_tf = 1;
}
if (speed == 8 && !cpi->ppi->use_svc) {
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index 26735c49..7605a03 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -1536,6 +1536,7 @@
int gf_refresh_based_on_qp;
// Temporal filtering
+ // The value can be 1 or 2, which indicates the threshold to use.
int use_rtc_tf;
// Prune the use of the identity transform in nonrd_pickmode,