From: Jerome Jiang Date: Fri, 13 Jan 2017 22:20:59 +0000 (-0800) Subject: vp9: Stop copying partition every a fixed number of frames. X-Git-Tag: v1.7.0~796 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ee5b29ae30d7f7f0b2d9fa7c6a611d840316981c;p=libvpx 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 --- diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c index b6fadafa3..73d277313 100644 --- a/vp9/encoder/vp9_encodeframe.c +++ b/vp9/encoder/vp9_encodeframe.c @@ -1043,19 +1043,25 @@ static int choose_partitioning(VP9_COMP *cpi, const TileInfo *const tile, // 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; diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 63d005ee9..934afc152 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -459,6 +459,9 @@ static void dealloc_compressor_data(VP9_COMP *cpi) { 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; diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index 6741a24b6..cb10e5074 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -639,6 +639,8 @@ typedef struct VP9_COMP { // 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; diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c index 17e2bdbd8..934897df0 100644 --- a/vp9/encoder/vp9_speed_features.c +++ b/vp9/encoder/vp9_speed_features.c @@ -502,8 +502,9 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf, int speed, 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 @@ static void set_rt_speed_feature(VP9_COMP *cpi, SPEED_FEATURES *sf, int speed, (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.