ref: ee5b29ae30d7f7f0b2d9fa7c6a611d840316981c
parent: e758f9d45704ea0247c1b654f8602c967fa44199
author: Jerome Jiang <[email protected]>
date: Fri Jan 13 09:20:59 EST 2017
vp9: Stop copying partition every a fixed number of frames. Avoid quality loss when copying partition of superblock with large motions. Maximum consecutively copied frames can be set (currently 5). Change-Id: I11c30575514f02194c0f001444cf4021609e5049
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -1043,19 +1043,25 @@
// If the y_sad is small enough, copy the partition of the superblock in the
// last frame to current frame only if the last frame is not a keyframe.
+ // Stop the copy every cpi->max_copied_frame to refresh the partition.
// TODO(jianj) : tune the threshold.
if (cpi->sf.copy_partition_flag && cpi->rc.frames_since_key > 1 &&
segment_id == CR_SEGMENT_ID_BASE &&
cpi->prev_segment_id[sb_offset] == CR_SEGMENT_ID_BASE &&
- y_sad_last < cpi->vbp_threshold_copy) {
+ y_sad_last < cpi->vbp_threshold_copy &&
+ cpi->copied_frame_cnt[sb_offset] < cpi->max_copied_frame) {
if (cpi->prev_partition != NULL) {
copy_prev_partition(cpi, BLOCK_64X64, mi_row, mi_col);
chroma_check(cpi, x, bsize, y_sad, is_key_frame);
+ cpi->copied_frame_cnt[sb_offset] += 1;
memcpy(x->variance_low, &(cpi->prev_variance_low[sb_offset * 25]),
sizeof(x->variance_low));
return 0;
}
}
+ if (cpi->sf.copy_partition_flag &&
+ cpi->copied_frame_cnt[sb_offset] == cpi->max_copied_frame)
+ cpi->copied_frame_cnt[sb_offset] = 0;
} else {
d = VP9_VAR_OFFS;
dp = 0;
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -459,6 +459,9 @@
vpx_free(cpi->prev_variance_low);
cpi->prev_variance_low = NULL;
+ vpx_free(cpi->copied_frame_cnt);
+ cpi->copied_frame_cnt = NULL;
+
vp9_cyclic_refresh_free(cpi->cyclic_refresh);
cpi->cyclic_refresh = NULL;
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -639,6 +639,8 @@
// This is for the last frame and is copied to the current frame
// when partition copy happens.
uint8_t *prev_variance_low;
+ uint8_t *copied_frame_cnt;
+ uint8_t max_copied_frame;
LevelConstraint level_constraint;
} VP9_COMP;
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -502,8 +502,9 @@
if (!cpi->use_svc && !cpi->resize_pending && !cpi->resize_state &&
!cpi->external_resize && cpi->oxcf.resize_mode == RESIZE_NONE)
sf->copy_partition_flag = 1;
+
if (sf->copy_partition_flag) {
- sf->use_source_sad = 1;
+ cpi->max_copied_frame = 5;
if (cpi->prev_partition == NULL) {
cpi->prev_partition = (BLOCK_SIZE *)vpx_calloc(
cm->mi_stride * cm->mi_rows, sizeof(BLOCK_SIZE));
@@ -517,7 +518,12 @@
(cm->mi_stride >> 3) * ((cm->mi_rows >> 3) + 1) * 25,
sizeof(uint8_t));
}
+ if (cpi->copied_frame_cnt == NULL) {
+ cpi->copied_frame_cnt = (uint8_t *)vpx_calloc(
+ (cm->mi_stride >> 3) * ((cm->mi_rows >> 3) + 1), sizeof(uint8_t));
+ }
}
+
sf->mv.subpel_force_stop = (content == VP9E_CONTENT_SCREEN) ? 3 : 2;
if (content == VP9E_CONTENT_SCREEN) sf->lpf_pick = LPF_PICK_MINIMAL_LPF;
// Only keep INTRA_DC mode for speed 8.