shithub: libvpx

Download patch

ref: ee5b29ae30d7f7f0b2d9fa7c6a611d840316981c
parent: e758f9d45704ea0247c1b654f8602c967fa44199
author: Jerome Jiang <jianj@google.com>
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.