Abstract code in var_based_part.c to set certain parameters

This patch abstracts the following operations.
- set_ref_frame_for_partition
- force_zeromv_skip_for_sb flag
- thresholds based on qindex,resolution and noisy content

Change-Id: I520b525c1bfdb4ffaf03be95e7bc76d73a22ad75
diff --git a/av1/encoder/var_based_part.c b/av1/encoder/var_based_part.c
index df6f83c..ba77091 100644
--- a/av1/encoder/var_based_part.c
+++ b/av1/encoder/var_based_part.c
@@ -438,96 +438,123 @@
   return threshold;
 }
 
-static AOM_INLINE void tune_thresh_based_on_qindex_window(
-    int qindex, int th, int win, int fac, int64_t thresholds[]) {
+// Tune thresholds less or more aggressively to prefer larger partitions
+static AOM_INLINE void tune_thresh_based_on_qindex(
+    AV1_COMP *cpi, int64_t thresholds[], uint64_t blk_sad, int current_qindex,
+    int num_pixels, bool is_segment_id_boosted, int source_sad_nonrd,
+    int lighting_change) {
   double weight;
-
-  if (qindex < th - win)
-    weight = 1.0;
-  else if (qindex > th + win)
-    weight = 0.0;
-  else
-    weight = 1.0 - (qindex - th + win) / (2 * win);
-  thresholds[1] =
-      (int)((1 - weight) * (thresholds[1] << 1) + weight * thresholds[1]);
-  thresholds[2] =
-      (int)((1 - weight) * (thresholds[2] << 1) + weight * thresholds[2]);
-  thresholds[3] =
-      (int)((1 - weight) * (thresholds[3] << fac) + weight * thresholds[3]);
+  if (cpi->sf.rt_sf.prefer_large_partition_blocks >= 3) {
+    const int win = 20;
+    if (current_qindex < QINDEX_LARGE_BLOCK_THR - win)
+      weight = 1.0;
+    else if (current_qindex > QINDEX_LARGE_BLOCK_THR + win)
+      weight = 0.0;
+    else
+      weight =
+          1.0 - (current_qindex - QINDEX_LARGE_BLOCK_THR + win) / (2 * win);
+    if (num_pixels > RESOLUTION_480P) {
+      for (int i = 0; i < 4; i++) {
+        thresholds[i] <<= 1;
+      }
+    }
+    if (num_pixels <= RESOLUTION_288P) {
+      thresholds[3] = INT64_MAX;
+      if (is_segment_id_boosted == false) {
+        thresholds[1] <<= 2;
+        thresholds[2] <<= (source_sad_nonrd <= kLowSad) ? 5 : 4;
+      } else {
+        thresholds[1] <<= 1;
+        thresholds[2] <<= 3;
+      }
+      // Allow for split to 8x8 for superblocks where part of it has
+      // moving boundary. So allow for sb with source_sad above threshold,
+      // and avoid very large source_sad or high source content, to avoid
+      // too many 8x8 within superblock.
+      if (is_segment_id_boosted == false && cpi->rc.avg_source_sad < 25000 &&
+          blk_sad > 25000 && blk_sad < 50000 && !lighting_change) {
+        thresholds[2] = (3 * thresholds[2]) >> 2;
+        thresholds[3] = thresholds[2] << 3;
+      }
+      // Condition the increase of partition thresholds on the segment
+      // and the content. Avoid the increase for superblocks which have
+      // high source sad, unless the whole frame has very high motion
+      // (i.e, cpi->rc.avg_source_sad is very large, in which case all blocks
+      // have high source sad).
+    } else if (num_pixels > RESOLUTION_480P && is_segment_id_boosted == false &&
+               (source_sad_nonrd != kHighSad ||
+                cpi->rc.avg_source_sad > 50000)) {
+      thresholds[0] = (3 * thresholds[0]) >> 1;
+      thresholds[3] = INT64_MAX;
+      if (current_qindex > QINDEX_LARGE_BLOCK_THR) {
+        thresholds[1] =
+            (int)((1 - weight) * (thresholds[1] << 1) + weight * thresholds[1]);
+        thresholds[2] =
+            (int)((1 - weight) * (thresholds[2] << 1) + weight * thresholds[2]);
+      }
+    } else if (current_qindex > QINDEX_LARGE_BLOCK_THR &&
+               is_segment_id_boosted == false &&
+               (source_sad_nonrd != kHighSad ||
+                cpi->rc.avg_source_sad > 50000)) {
+      thresholds[1] =
+          (int)((1 - weight) * (thresholds[1] << 2) + weight * thresholds[1]);
+      thresholds[2] =
+          (int)((1 - weight) * (thresholds[2] << 4) + weight * thresholds[2]);
+      thresholds[3] = INT64_MAX;
+    }
+  } else if (cpi->sf.rt_sf.prefer_large_partition_blocks >= 2) {
+    thresholds[1] <<= (source_sad_nonrd <= kLowSad) ? 2 : 0;
+    thresholds[2] =
+        (source_sad_nonrd <= kLowSad) ? (3 * thresholds[2]) : thresholds[2];
+  } else if (cpi->sf.rt_sf.prefer_large_partition_blocks >= 1) {
+    const int fac = (source_sad_nonrd <= kLowSad) ? 2 : 1;
+    if (current_qindex < QINDEX_LARGE_BLOCK_THR - 45)
+      weight = 1.0;
+    else if (current_qindex > QINDEX_LARGE_BLOCK_THR + 45)
+      weight = 0.0;
+    else
+      weight = 1.0 - (current_qindex - QINDEX_LARGE_BLOCK_THR + 45) / (2 * 45);
+    thresholds[1] =
+        (int)((1 - weight) * (thresholds[1] << 1) + weight * thresholds[1]);
+    thresholds[2] =
+        (int)((1 - weight) * (thresholds[2] << 1) + weight * thresholds[2]);
+    thresholds[3] =
+        (int)((1 - weight) * (thresholds[3] << fac) + weight * thresholds[3]);
+  }
+  if (cpi->sf.part_sf.disable_8x8_part_based_on_qidx && (current_qindex < 128))
+    thresholds[3] = INT64_MAX;
 }
 
-static AOM_INLINE void set_vbp_thresholds(
-    AV1_COMP *cpi, int64_t thresholds[], uint64_t blk_sad, int qindex,
-    int content_lowsumdiff, int source_sad_nonrd, int source_sad_rd,
-    bool is_segment_id_boosted, int lighting_change) {
-  AV1_COMMON *const cm = &cpi->common;
-  const int is_key_frame = frame_is_intra_only(cm);
-  const int threshold_multiplier = is_key_frame ? 120 : 1;
-  const int ac_q = av1_ac_quant_QTX(qindex, 0, cm->seq_params->bit_depth);
-  int64_t threshold_base = (int64_t)(threshold_multiplier * ac_q);
-  const int current_qindex = cm->quant_params.base_qindex;
-  const int threshold_left_shift = cpi->sf.rt_sf.var_part_split_threshold_shift;
-  const int num_pixels = cm->width * cm->height;
-
-  if (is_key_frame) {
-    if (cpi->sf.rt_sf.force_large_partition_blocks_intra) {
-      const int shift_steps =
-          threshold_left_shift - (cpi->oxcf.mode == ALLINTRA ? 7 : 8);
-      assert(shift_steps >= 0);
-      threshold_base <<= shift_steps;
-    }
-    thresholds[0] = threshold_base;
-    thresholds[1] = threshold_base;
-    if (num_pixels < RESOLUTION_720P) {
-      thresholds[2] = threshold_base / 3;
-      thresholds[3] = threshold_base >> 1;
-    } else {
-      int shift_val = 2;
-      if (cpi->sf.rt_sf.force_large_partition_blocks_intra) {
-        shift_val = 0;
-      }
-
-      thresholds[2] = threshold_base >> shift_val;
-      thresholds[3] = threshold_base >> shift_val;
-    }
-    thresholds[4] = threshold_base << 2;
-    return;
+static void set_vbp_thresholds_key_frame(AV1_COMP *cpi, int64_t thresholds[],
+                                         int64_t threshold_base,
+                                         int threshold_left_shift,
+                                         int num_pixels) {
+  if (cpi->sf.rt_sf.force_large_partition_blocks_intra) {
+    const int shift_steps =
+        threshold_left_shift - (cpi->oxcf.mode == ALLINTRA ? 7 : 8);
+    assert(shift_steps >= 0);
+    threshold_base <<= shift_steps;
   }
-
-  // Increase partition thresholds for noisy content. Apply it only for
-  // superblocks where sumdiff is low, as we assume the sumdiff of superblock
-  // whose only change is due to noise will be low (i.e, noise will average
-  // out over large block).
-  if (cpi->noise_estimate.enabled && content_lowsumdiff &&
-      num_pixels > RESOLUTION_480P && cm->current_frame.frame_number > 60) {
-    NOISE_LEVEL noise_level =
-        av1_noise_estimate_extract_level(&cpi->noise_estimate);
-    if (noise_level == kHigh)
-      threshold_base = (5 * threshold_base) >> 1;
-    else if (noise_level == kMedium &&
-             !cpi->sf.rt_sf.prefer_large_partition_blocks)
-      threshold_base = (5 * threshold_base) >> 2;
-  }
-  // TODO(kyslov) Enable var based partition adjusment on temporal denoising
-#if 0  // CONFIG_AV1_TEMPORAL_DENOISING
-  if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc(cpi) &&
-      cpi->oxcf.speed > 5 && cpi->denoiser.denoising_level >= kDenLow)
-      threshold_base =
-          av1_scale_part_thresh(threshold_base, cpi->denoiser.denoising_level,
-                                content_state, cpi->svc.temporal_layer_id);
-  else
-    threshold_base =
-        scale_part_thresh_content(threshold_base, cpi->oxcf.speed, cm->width,
-                                  cm->height, cpi->ppi->rtc_ref.non_reference_frame);
-#else
-  // Increase base variance threshold based on content_state/sum_diff level.
-  threshold_base = scale_part_thresh_content(
-      threshold_base, cpi->oxcf.speed, cm->width, cm->height,
-      cpi->ppi->rtc_ref.non_reference_frame);
-#endif
-  thresholds[0] = threshold_base >> 1;
+  thresholds[0] = threshold_base;
   thresholds[1] = threshold_base;
-  thresholds[3] = threshold_base << threshold_left_shift;
+  if (num_pixels < RESOLUTION_720P) {
+    thresholds[2] = threshold_base / 3;
+    thresholds[3] = threshold_base >> 1;
+  } else {
+    int shift_val = 2;
+    if (cpi->sf.rt_sf.force_large_partition_blocks_intra) {
+      shift_val = 0;
+    }
+
+    thresholds[2] = threshold_base >> shift_val;
+    thresholds[3] = threshold_base >> shift_val;
+  }
+  thresholds[4] = threshold_base << 2;
+}
+
+static AOM_INLINE void tune_thresh_based_on_resolution(
+    AV1_COMP *cpi, int64_t thresholds[], int64_t threshold_base,
+    int current_qindex, int source_sad_rd, int num_pixels) {
   if (num_pixels >= RESOLUTION_720P) thresholds[3] = thresholds[3] << 1;
   if (num_pixels <= RESOLUTION_288P) {
     const int qindex_thr[5][2] = {
@@ -588,77 +615,79 @@
       }
     }
   }
-  // Tune thresholds less or more aggressively to prefer larger partitions
-  if (cpi->sf.rt_sf.prefer_large_partition_blocks >= 3) {
-    double weight;
-    const int win = 20;
-    if (current_qindex < QINDEX_LARGE_BLOCK_THR - win)
-      weight = 1.0;
-    else if (current_qindex > QINDEX_LARGE_BLOCK_THR + win)
-      weight = 0.0;
-    else
-      weight =
-          1.0 - (current_qindex - QINDEX_LARGE_BLOCK_THR + win) / (2 * win);
-    if (num_pixels > RESOLUTION_480P) {
-      for (int idx = 0; idx < 4; idx++) {
-        thresholds[idx] <<= 1;
-      }
-    }
-    if (num_pixels <= RESOLUTION_288P) {
-      thresholds[3] = INT64_MAX;
-      if (is_segment_id_boosted == false) {
-        thresholds[1] <<= 2;
-        thresholds[2] <<= (source_sad_nonrd <= kLowSad) ? 5 : 4;
-      } else {
-        thresholds[1] <<= 1;
-        thresholds[2] <<= 3;
-      }
-      // Allow for split to 8x8 for superblocks where part of it has
-      // moving boundary. So allow for sb with source_sad above threshold,
-      // and avoid very large source_sad or high source content, to avoid
-      // too many 8x8 within superblock.
-      if (is_segment_id_boosted == false && cpi->rc.avg_source_sad < 25000 &&
-          blk_sad > 25000 && blk_sad < 50000 && !lighting_change) {
-        thresholds[2] = (3 * thresholds[2]) >> 2;
-        thresholds[3] = thresholds[2] << 3;
-      }
-      // Condition the increase of partition thresholds on the segment
-      // and the content. Avoid the increase for superblocks which have
-      // high source sad, unless the whole frame has very high motion
-      // (i.e, cpi->rc.avg_source_sad is very large, in which case all blocks
-      // have high source sad).
-    } else if (num_pixels > RESOLUTION_480P && is_segment_id_boosted == false &&
-               (source_sad_nonrd != kHighSad ||
-                cpi->rc.avg_source_sad > 50000)) {
-      thresholds[0] = (3 * thresholds[0]) >> 1;
-      thresholds[3] = INT64_MAX;
-      if (current_qindex > QINDEX_LARGE_BLOCK_THR) {
-        thresholds[1] =
-            (int)((1 - weight) * (thresholds[1] << 1) + weight * thresholds[1]);
-        thresholds[2] =
-            (int)((1 - weight) * (thresholds[2] << 1) + weight * thresholds[2]);
-      }
-    } else if (current_qindex > QINDEX_LARGE_BLOCK_THR &&
-               is_segment_id_boosted == false &&
-               (source_sad_nonrd != kHighSad ||
-                cpi->rc.avg_source_sad > 50000)) {
-      thresholds[1] =
-          (int)((1 - weight) * (thresholds[1] << 2) + weight * thresholds[1]);
-      thresholds[2] =
-          (int)((1 - weight) * (thresholds[2] << 4) + weight * thresholds[2]);
-      thresholds[3] = INT64_MAX;
-    }
-  } else if (cpi->sf.rt_sf.prefer_large_partition_blocks >= 2) {
-    thresholds[1] <<= (source_sad_nonrd <= kLowSad) ? 2 : 0;
-    thresholds[2] =
-        (source_sad_nonrd <= kLowSad) ? (3 * thresholds[2]) : thresholds[2];
-  } else if (cpi->sf.rt_sf.prefer_large_partition_blocks >= 1) {
-    const int fac = (source_sad_nonrd <= kLowSad) ? 2 : 1;
-    tune_thresh_based_on_qindex_window(current_qindex, QINDEX_LARGE_BLOCK_THR,
-                                       45, fac, thresholds);
+}
+
+// Increase partition thresholds for noisy content. Apply it only for
+// superblocks where sumdiff is low, as we assume the sumdiff of superblock
+// whose only change is due to noise will be low (i.e, noise will average
+// out over large block).
+static AOM_INLINE int64_t tune_thresh_noisy_content(AV1_COMP *cpi,
+                                                    int64_t threshold_base,
+                                                    int content_lowsumdiff,
+                                                    int num_pixels) {
+  AV1_COMMON *const cm = &cpi->common;
+  int64_t updated_thresh_base = threshold_base;
+  if (cpi->noise_estimate.enabled && content_lowsumdiff &&
+      num_pixels > RESOLUTION_480P && cm->current_frame.frame_number > 60) {
+    NOISE_LEVEL noise_level =
+        av1_noise_estimate_extract_level(&cpi->noise_estimate);
+    if (noise_level == kHigh)
+      updated_thresh_base = (5 * updated_thresh_base) >> 1;
+    else if (noise_level == kMedium &&
+             !cpi->sf.rt_sf.prefer_large_partition_blocks)
+      updated_thresh_base = (5 * updated_thresh_base) >> 2;
   }
-  if (cpi->sf.part_sf.disable_8x8_part_based_on_qidx && (current_qindex < 128))
-    thresholds[3] = INT64_MAX;
+  // TODO(kyslov) Enable var based partition adjusment on temporal denoising
+#if 0  // CONFIG_AV1_TEMPORAL_DENOISING
+  if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc(cpi) &&
+      cpi->oxcf.speed > 5 && cpi->denoiser.denoising_level >= kDenLow)
+      updated_thresh_base =
+          av1_scale_part_thresh(updated_thresh_base, cpi->denoiser.denoising_level,
+                                content_state, cpi->svc.temporal_layer_id);
+  else
+    threshold_base =
+        scale_part_thresh_content(updated_thresh_base, cpi->oxcf.speed, cm->width,
+                                  cm->height, cpi->ppi->rtc_ref.non_reference_frame);
+#else
+  // Increase base variance threshold based on content_state/sum_diff level.
+  updated_thresh_base = scale_part_thresh_content(
+      updated_thresh_base, cpi->oxcf.speed, cm->width, cm->height,
+      cpi->ppi->rtc_ref.non_reference_frame);
+#endif
+  return updated_thresh_base;
+}
+
+static AOM_INLINE void set_vbp_thresholds(
+    AV1_COMP *cpi, int64_t thresholds[], uint64_t blk_sad, int qindex,
+    int content_lowsumdiff, int source_sad_nonrd, int source_sad_rd,
+    bool is_segment_id_boosted, int lighting_change) {
+  AV1_COMMON *const cm = &cpi->common;
+  const int is_key_frame = frame_is_intra_only(cm);
+  const int threshold_multiplier = is_key_frame ? 120 : 1;
+  const int ac_q = av1_ac_quant_QTX(qindex, 0, cm->seq_params->bit_depth);
+  int64_t threshold_base = (int64_t)(threshold_multiplier * ac_q);
+  const int current_qindex = cm->quant_params.base_qindex;
+  const int threshold_left_shift = cpi->sf.rt_sf.var_part_split_threshold_shift;
+  const int num_pixels = cm->width * cm->height;
+
+  if (is_key_frame) {
+    set_vbp_thresholds_key_frame(cpi, thresholds, threshold_base,
+                                 threshold_left_shift, num_pixels);
+    return;
+  }
+
+  threshold_base = tune_thresh_noisy_content(cpi, threshold_base,
+                                             content_lowsumdiff, num_pixels);
+  thresholds[0] = threshold_base >> 1;
+  thresholds[1] = threshold_base;
+  thresholds[3] = threshold_base << threshold_left_shift;
+
+  tune_thresh_based_on_resolution(cpi, thresholds, threshold_base,
+                                  current_qindex, source_sad_rd, num_pixels);
+
+  tune_thresh_based_on_qindex(cpi, thresholds, blk_sad, current_qindex,
+                              num_pixels, is_segment_id_boosted,
+                              source_sad_nonrd, lighting_change);
 }
 
 // Set temporal variance low flag for superblock 64x64.
@@ -1146,6 +1175,41 @@
   }
 }
 
+static AOM_INLINE void set_ref_frame_for_partition(
+    AV1_COMP *cpi, MACROBLOCK *x, MACROBLOCKD *xd,
+    MV_REFERENCE_FRAME *ref_frame_partition, MB_MODE_INFO *mi,
+    unsigned int *y_sad, unsigned int *y_sad_g, unsigned int *y_sad_alt,
+    const YV12_BUFFER_CONFIG *yv12_g, const YV12_BUFFER_CONFIG *yv12_alt,
+    int mi_row, int mi_col, int num_planes) {
+  AV1_COMMON *const cm = &cpi->common;
+  const bool is_set_golden_ref_frame =
+      *y_sad_g < 0.9 * *y_sad && *y_sad_g < *y_sad_alt;
+  const bool is_set_altref_ref_frame =
+      *y_sad_alt < 0.9 * *y_sad && *y_sad_alt < *y_sad_g;
+
+  if (is_set_golden_ref_frame) {
+    av1_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
+                         get_ref_scale_factors(cm, GOLDEN_FRAME), num_planes);
+    mi->ref_frame[0] = GOLDEN_FRAME;
+    mi->mv[0].as_int = 0;
+    *y_sad = *y_sad_g;
+    *ref_frame_partition = GOLDEN_FRAME;
+    x->nonrd_prune_ref_frame_search = 0;
+  } else if (is_set_altref_ref_frame) {
+    av1_setup_pre_planes(xd, 0, yv12_alt, mi_row, mi_col,
+                         get_ref_scale_factors(cm, ALTREF_FRAME), num_planes);
+    mi->ref_frame[0] = ALTREF_FRAME;
+    mi->mv[0].as_int = 0;
+    *y_sad = *y_sad_alt;
+    *ref_frame_partition = ALTREF_FRAME;
+    x->nonrd_prune_ref_frame_search = 0;
+  } else {
+    *ref_frame_partition = LAST_FRAME;
+    x->nonrd_prune_ref_frame_search =
+        cpi->sf.rt_sf.nonrd_prune_ref_frame_search;
+  }
+}
+
 static void setup_planes(AV1_COMP *cpi, MACROBLOCK *x, unsigned int *y_sad,
                          unsigned int *y_sad_g, unsigned int *y_sad_alt,
                          unsigned int *y_sad_last,
@@ -1226,27 +1290,9 @@
 
   // Pick the ref frame for partitioning, use golden or altref frame only if
   // its lower sad, bias to LAST with factor 0.9.
-  if (*y_sad_g < 0.9 * *y_sad && *y_sad_g < *y_sad_alt) {
-    av1_setup_pre_planes(xd, 0, yv12_g, mi_row, mi_col,
-                         get_ref_scale_factors(cm, GOLDEN_FRAME), num_planes);
-    mi->ref_frame[0] = GOLDEN_FRAME;
-    mi->mv[0].as_int = 0;
-    *y_sad = *y_sad_g;
-    *ref_frame_partition = GOLDEN_FRAME;
-    x->nonrd_prune_ref_frame_search = 0;
-  } else if (*y_sad_alt < 0.9 * *y_sad && *y_sad_alt < *y_sad_g) {
-    av1_setup_pre_planes(xd, 0, yv12_alt, mi_row, mi_col,
-                         get_ref_scale_factors(cm, ALTREF_FRAME), num_planes);
-    mi->ref_frame[0] = ALTREF_FRAME;
-    mi->mv[0].as_int = 0;
-    *y_sad = *y_sad_alt;
-    *ref_frame_partition = ALTREF_FRAME;
-    x->nonrd_prune_ref_frame_search = 0;
-  } else {
-    *ref_frame_partition = LAST_FRAME;
-    x->nonrd_prune_ref_frame_search =
-        cpi->sf.rt_sf.nonrd_prune_ref_frame_search;
-  }
+  set_ref_frame_for_partition(cpi, x, xd, ref_frame_partition, mi, y_sad,
+                              y_sad_g, y_sad_alt, yv12_g, yv12_alt, mi_row,
+                              mi_col, num_planes);
 
   // Only calculate the predictor for non-zero MV.
   if (mi->mv[0].as_int != 0) {
@@ -1290,6 +1336,37 @@
   return false;
 }
 
+static AOM_INLINE bool set_force_zeromv_skip_for_sb(
+    AV1_COMP *cpi, MACROBLOCK *x, const TileInfo *const tile, VP16x16 *vt2,
+    VP128x128 *vt, unsigned int *uv_sad, int mi_row, int mi_col,
+    unsigned int y_sad, BLOCK_SIZE bsize) {
+  AV1_COMMON *const cm = &cpi->common;
+  if (!is_set_force_zeromv_skip_based_on_src_sad(
+          cpi->sf.rt_sf.set_zeromv_skip_based_on_source_sad,
+          x->content_state_sb.source_sad_nonrd))
+    return false;
+  const int block_width = mi_size_wide[cm->seq_params->sb_size];
+  const int block_height = mi_size_high[cm->seq_params->sb_size];
+  const unsigned int thresh_exit_part_y =
+      cpi->zeromv_skip_thresh_exit_part[bsize];
+  const unsigned int thresh_exit_part_uv =
+      CALC_CHROMA_THRESH_FOR_ZEROMV_SKIP(thresh_exit_part_y);
+  if (mi_col + block_width <= tile->mi_col_end &&
+      mi_row + block_height <= tile->mi_row_end && y_sad < thresh_exit_part_y &&
+      uv_sad[0] < thresh_exit_part_uv && uv_sad[1] < thresh_exit_part_uv) {
+    set_block_size(cpi, mi_row, mi_col, bsize);
+    x->force_zeromv_skip_for_sb = 1;
+    if (vt2) aom_free(vt2);
+    if (vt) aom_free(vt);
+    // Partition shape is set here at SB level.
+    // Exit needs to happen from av1_choose_var_based_partitioning().
+    return true;
+  } else if (x->content_state_sb.source_sad_nonrd == kZeroSad &&
+             cpi->sf.rt_sf.part_early_exit_zeromv >= 2)
+    x->force_zeromv_skip_for_sb = 2;
+  return false;
+}
+
 int av1_choose_var_based_partitioning(AV1_COMP *cpi, const TileInfo *const tile,
                                       ThreadData *td, MACROBLOCK *x, int mi_row,
                                       int mi_col) {
@@ -1426,10 +1503,6 @@
                uv_sad);
 
   x->force_zeromv_skip_for_sb = 0;
-  const bool is_set_force_zeromv_skip =
-      is_set_force_zeromv_skip_based_on_src_sad(
-          cpi->sf.rt_sf.set_zeromv_skip_based_on_source_sad,
-          x->content_state_sb.source_sad_nonrd);
 
   // If the superblock is completely static (zero source sad) and
   // the y_sad (relative to LAST ref) is very small, take the sb_size partition
@@ -1439,28 +1512,11 @@
   // Condition on color uv_sad is also added.
   if (!is_key_frame && cpi->sf.rt_sf.part_early_exit_zeromv &&
       cpi->rc.frames_since_key > 30 && segment_id == CR_SEGMENT_ID_BASE &&
-      is_set_force_zeromv_skip && ref_frame_partition == LAST_FRAME &&
-      xd->mi[0]->mv[0].as_int == 0) {
-    const int block_width = mi_size_wide[cm->seq_params->sb_size];
-    const int block_height = mi_size_high[cm->seq_params->sb_size];
-    const unsigned int thresh_exit_part_y =
-        cpi->zeromv_skip_thresh_exit_part[bsize];
-    const unsigned int thresh_exit_part_uv =
-        CALC_CHROMA_THRESH_FOR_ZEROMV_SKIP(thresh_exit_part_y);
-    if (mi_col + block_width <= tile->mi_col_end &&
-        mi_row + block_height <= tile->mi_row_end &&
-        y_sad < thresh_exit_part_y &&
-        uv_sad[AOM_PLANE_U - 1] < thresh_exit_part_uv &&
-        uv_sad[AOM_PLANE_V - 1] < thresh_exit_part_uv) {
-      set_block_size(cpi, mi_row, mi_col, bsize);
-      x->force_zeromv_skip_for_sb = 1;
-      if (vt2) aom_free(vt2);
-      if (vt) aom_free(vt);
+      ref_frame_partition == LAST_FRAME && xd->mi[0]->mv[0].as_int == 0) {
+    // Exit here, if zero mv skip flag is set at SB level.
+    if (set_force_zeromv_skip_for_sb(cpi, x, tile, vt2, vt, uv_sad, mi_row,
+                                     mi_col, y_sad, bsize))
       return 0;
-    } else if (x->content_state_sb.source_sad_nonrd == kZeroSad &&
-               cpi->sf.rt_sf.part_early_exit_zeromv >= 2) {
-      x->force_zeromv_skip_for_sb = 2;
-    }
   }
 
   if (cpi->noise_estimate.enabled)