Merge "Merge tag 'v2.0.1'"
diff --git a/aom_dsp/x86/aom_subpixel_8t_intrin_ssse3.c b/aom_dsp/x86/aom_subpixel_8t_intrin_ssse3.c
index 18e8a2a..b6ca63d 100644
--- a/aom_dsp/x86/aom_subpixel_8t_intrin_ssse3.c
+++ b/aom_dsp/x86/aom_subpixel_8t_intrin_ssse3.c
@@ -826,7 +826,7 @@
                                   const ptrdiff_t src_stride,
                                   uint8_t *const dst,
                                   const int16_t *const filter) {
-  __m128i s[4], ss[2];
+  __m128i s[4], ss[4];
   __m128i temp;
 
   load_8bit_8x4(src, src_stride, s);
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index cc681bc..9dade55 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -1541,6 +1541,7 @@
 #endif
   if (mt_info->num_workers > 1) {
     av1_loop_filter_dealloc(&mt_info->lf_row_sync);
+    av1_cdef_mt_dealloc(&mt_info->cdef_sync);
 #if !CONFIG_REALTIME_ONLY
     av1_loop_restoration_dealloc(&mt_info->lr_row_sync, mt_info->num_workers);
     av1_gm_dealloc(&mt_info->gm_sync);
@@ -2041,7 +2042,7 @@
     start_timing(cpi, cdef_time);
 #endif
     // Find CDEF parameters
-    av1_cdef_search(&cm->cur_frame->buf, cpi->source, cm, xd,
+    av1_cdef_search(&cpi->mt_info, &cm->cur_frame->buf, cpi->source, cm, xd,
                     cpi->sf.lpf_sf.cdef_pick_method, cpi->td.mb.rdmult);
 
     // Apply the filter
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index ed79ba0..b4bc58d 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -40,6 +40,7 @@
 #include "av1/encoder/level.h"
 #include "av1/encoder/lookahead.h"
 #include "av1/encoder/mcomp.h"
+#include "av1/encoder/pickcdef.h"
 #include "av1/encoder/ratectrl.h"
 #include "av1/encoder/rd.h"
 #include "av1/encoder/speed_features.h"
@@ -1337,7 +1338,7 @@
 /*!
  * \brief Encoder parameters related to multi-threading.
  */
-typedef struct {
+typedef struct MultiThreadInfo {
   /*!
    * Number of workers created for multi-threading.
    */
@@ -1399,6 +1400,11 @@
    * Temporal Filter multi-threading object.
    */
   AV1TemporalFilterSync tf_sync;
+
+  /*!
+   * CDEF search multi-threading object.
+   */
+  AV1CdefSync cdef_sync;
 } MultiThreadInfo;
 
 /*!\cond */
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c
index bf22743..730eedb 100644
--- a/av1/encoder/ethread.c
+++ b/av1/encoder/ethread.c
@@ -545,6 +545,12 @@
     CHECK_MEM_ERROR(cm, tf_sync->mutex_, aom_malloc(sizeof(*tf_sync->mutex_)));
     if (tf_sync->mutex_) pthread_mutex_init(tf_sync->mutex_, NULL);
   }
+  AV1CdefSync *cdef_sync = &mt_info->cdef_sync;
+  if (cdef_sync->mutex_ == NULL) {
+    CHECK_MEM_ERROR(cm, cdef_sync->mutex_,
+                    aom_malloc(sizeof(*(cdef_sync->mutex_))));
+    if (cdef_sync->mutex_) pthread_mutex_init(cdef_sync->mutex_, NULL);
+  }
 #endif
 
   for (int i = num_workers - 1; i >= 0; i--) {
@@ -1662,3 +1668,110 @@
   sync_enc_workers(&cpi->mt_info, &cpi->common, num_workers);
 }
 #endif  // !CONFIG_REALTIME_ONLY
+
+// Deallocate memory for CDEF search multi-thread synchronization.
+void av1_cdef_mt_dealloc(AV1CdefSync *cdef_sync) {
+  (void)cdef_sync;
+  assert(cdef_sync != NULL);
+#if CONFIG_MULTITHREAD
+  if (cdef_sync->mutex_ != NULL) {
+    pthread_mutex_destroy(cdef_sync->mutex_);
+    aom_free(cdef_sync->mutex_);
+  }
+#endif  // CONFIG_MULTITHREAD
+}
+
+// Updates the row and column indices of the next job to be processed.
+// Also updates end_of_frame flag when the processing of all blocks is complete.
+static void update_next_job_info(AV1CdefSync *cdef_sync, int nvfb, int nhfb) {
+  cdef_sync->fbc++;
+  if (cdef_sync->fbc == nhfb) {
+    cdef_sync->fbr++;
+    if (cdef_sync->fbr == nvfb) {
+      cdef_sync->end_of_frame = 1;
+    } else {
+      cdef_sync->fbc = 0;
+    }
+  }
+}
+
+// Initializes cdef_sync parameters.
+static AOM_INLINE void cdef_reset_job_info(AV1CdefSync *cdef_sync) {
+  cdef_sync->end_of_frame = 0;
+  cdef_sync->fbr = 0;
+  cdef_sync->fbc = 0;
+}
+
+// Checks if a job is available. If job is available,
+// populates next job information and returns 1, else returns 0.
+static AOM_INLINE int cdef_get_next_job(AV1CdefSync *cdef_sync,
+                                        CdefSearchCtx *cdef_search_ctx,
+                                        int *cur_fbr, int *cur_fbc,
+                                        int *sb_count) {
+#if CONFIG_MULTITHREAD
+  pthread_mutex_lock(cdef_sync->mutex_);
+#endif  // CONFIG_MULTITHREAD
+  int do_next_block = 0;
+  const int nvfb = cdef_search_ctx->nvfb;
+  const int nhfb = cdef_search_ctx->nhfb;
+
+  // If a block is skip, do not process the block and
+  // check the skip condition for the next block.
+  while ((!cdef_sync->end_of_frame) &&
+         (cdef_sb_skip(cdef_search_ctx->mi_params, cdef_sync->fbr,
+                       cdef_sync->fbc))) {
+    update_next_job_info(cdef_sync, nvfb, nhfb);
+  }
+
+  // Populates information needed for current job and update the row,
+  // column indices of the next block to be processed.
+  if (cdef_sync->end_of_frame == 0) {
+    do_next_block = 1;
+    *cur_fbr = cdef_sync->fbr;
+    *cur_fbc = cdef_sync->fbc;
+    *sb_count = cdef_search_ctx->sb_count;
+    cdef_search_ctx->sb_count++;
+    update_next_job_info(cdef_sync, nvfb, nhfb);
+  }
+#if CONFIG_MULTITHREAD
+  pthread_mutex_unlock(cdef_sync->mutex_);
+#endif  // CONFIG_MULTITHREAD
+  return do_next_block;
+}
+
+// Hook function for each thread in CDEF search multi-threading.
+static int cdef_filter_block_worker_hook(void *arg1, void *arg2) {
+  AV1CdefSync *const cdef_sync = (AV1CdefSync *)arg1;
+  CdefSearchCtx *cdef_search_ctx = (CdefSearchCtx *)arg2;
+  int cur_fbr, cur_fbc, sb_count;
+  while (cdef_get_next_job(cdef_sync, cdef_search_ctx, &cur_fbr, &cur_fbc,
+                           &sb_count)) {
+    av1_cdef_mse_calc_block(cdef_search_ctx, cur_fbr, cur_fbc, sb_count);
+  }
+  return 1;
+}
+
+// Assigns CDEF search hook function and thread data to each worker.
+static void prepare_cdef_workers(MultiThreadInfo *mt_info,
+                                 CdefSearchCtx *cdef_search_ctx,
+                                 AVxWorkerHook hook, int num_workers) {
+  for (int i = num_workers - 1; i >= 0; i--) {
+    AVxWorker *worker = &mt_info->workers[i];
+    worker->hook = hook;
+    worker->data1 = &mt_info->cdef_sync;
+    worker->data2 = cdef_search_ctx;
+  }
+}
+
+// Implements multi-threading for CDEF search.
+void av1_cdef_mse_calc_frame_mt(AV1_COMMON *cm, MultiThreadInfo *mt_info,
+                                CdefSearchCtx *cdef_search_ctx) {
+  AV1CdefSync *cdef_sync = &mt_info->cdef_sync;
+  const int num_workers = mt_info->num_workers;
+
+  cdef_reset_job_info(cdef_sync);
+  prepare_cdef_workers(mt_info, cdef_search_ctx, cdef_filter_block_worker_hook,
+                       num_workers);
+  launch_workers(mt_info, num_workers);
+  sync_enc_workers(mt_info, cm, num_workers);
+}
diff --git a/av1/encoder/ethread.h b/av1/encoder/ethread.h
index ab8e1bb..e8b8ad3 100644
--- a/av1/encoder/ethread.h
+++ b/av1/encoder/ethread.h
@@ -78,6 +78,11 @@
 
 void av1_create_workers(AV1_COMP *cpi, int num_workers);
 
+void av1_cdef_mse_calc_frame_mt(AV1_COMMON *cm, MultiThreadInfo *mt_info,
+                                CdefSearchCtx *cdef_search_ctx);
+
+void av1_cdef_mt_dealloc(AV1CdefSync *cdef_sync);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index f16b0d2..d067d50e8 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -180,14 +180,24 @@
   return fclamp(pow(error_term, power_term), 0.05, 5.0);
 }
 
-static void twopass_update_bpm_factor(TWO_PASS *twopass) {
+static void twopass_update_bpm_factor(TWO_PASS *twopass, int err_estimate,
+                                      int rate_err_tol) {
   // Based on recent history adjust expectations of bits per macroblock.
   double last_group_rate_err =
       (double)twopass->rolling_arf_group_actual_bits /
       DOUBLE_DIVIDE_CHECK((double)twopass->rolling_arf_group_target_bits);
-  last_group_rate_err = AOMMAX(0.25, AOMMIN(4.0, last_group_rate_err));
-  twopass->bpm_factor *= (3.0 + last_group_rate_err) / 4.0;
-  twopass->bpm_factor = AOMMAX(0.25, AOMMIN(4.0, twopass->bpm_factor));
+  double damp_fac = AOMMAX(5.0, rate_err_tol / 10.0);
+
+  last_group_rate_err = AOMMAX(0.75, AOMMIN(1.25, last_group_rate_err));
+  last_group_rate_err = 1.0 + ((last_group_rate_err - 1.0) / damp_fac);
+
+  // Is the last GOP error making the total error worse or better? Only make
+  // an adjustment if things are getting worse.
+  if ((last_group_rate_err < 1.0 && err_estimate > 0) ||
+      (last_group_rate_err > 1.0 && err_estimate < 0)) {
+    twopass->bpm_factor *= last_group_rate_err;
+    twopass->bpm_factor = AOMMAX(0.75, AOMMIN(1.25, twopass->bpm_factor));
+  }
 }
 
 static int qbpm_enumerator(int rate_err_tol) {
@@ -240,15 +250,12 @@
  *                                   Here we want to ignore the bands at the
  *                                   top and bottom.
  * \param[in]    av_target_bandwidth The target bits per frame
- * \param[in]    group_weight_factor A correction factor allowing the algorithm
- *                                   to correct for errors over time.
  *
  * \return The maximum Q for frames in the group.
  */
 static int get_twopass_worst_quality(AV1_COMP *cpi, const double av_frame_err,
                                      double inactive_zone,
-                                     int av_target_bandwidth,
-                                     double group_weight_factor) {
+                                     int av_target_bandwidth) {
   const RATE_CONTROL *const rc = &cpi->rc;
   const AV1EncoderConfig *const oxcf = &cpi->oxcf;
   const RateControlCfg *const rc_cfg = &oxcf->rc_cfg;
@@ -266,12 +273,15 @@
         (int)((uint64_t)av_target_bandwidth << BPER_MB_NORMBITS) / active_mbs;
     int rate_err_tol = AOMMIN(rc_cfg->under_shoot_pct, rc_cfg->over_shoot_pct);
 
-    twopass_update_bpm_factor(&cpi->twopass);
+    // Update bpm correction factor based on previous GOP rate error.
+    twopass_update_bpm_factor(&cpi->twopass, rc->rate_error_estimate,
+                              rate_err_tol);
+
     // Try and pick a max Q that will be high enough to encode the
     // content at the given rate.
     int q = find_qindex_by_rate_with_correction(
         target_norm_bits_per_mb, cpi->common.seq_params.bit_depth,
-        av_err_per_mb, group_weight_factor, rate_err_tol, rc->best_quality,
+        av_err_per_mb, cpi->twopass.bpm_factor, rate_err_tol, rc->best_quality,
         rc->worst_quality);
 
     // Restriction on active max q for constrained quality mode.
@@ -971,11 +981,6 @@
   return 0;
 }
 
-#if GROUP_ADAPTIVE_MAXQ
-#define RC_FACTOR_MIN 0.75
-#define RC_FACTOR_MAX 1.25
-#endif  // GROUP_ADAPTIVE_MAXQ
-
 #define MIN_FWD_KF_INTERVAL 8
 #define MIN_SHRINK_LEN 6  // the minimum length of gf if we are shrinking
 #define SMOOTH_FILT_LEN 7
@@ -2519,25 +2524,9 @@
          (rc->baseline_gf_interval * (double)cm->mi_params.mb_rows));
 
     int tmp_q;
-    // rc factor is a weight factor that corrects for local rate control drift.
-    double rc_factor = 1.0;
-    int64_t bits = rc_cfg->target_bandwidth;
-
-    if (bits > 0) {
-      int rate_error;
-
-      rate_error = (int)((rc->vbr_bits_off_target * 100) / bits);
-      rate_error = clamp(rate_error, -100, 100);
-      if (rate_error > 0) {
-        rc_factor = AOMMAX(RC_FACTOR_MIN, (double)(100 - rate_error) / 100.0);
-      } else {
-        rc_factor = AOMMIN(RC_FACTOR_MAX, (double)(100 - rate_error) / 100.0);
-      }
-    }
-
     tmp_q = get_twopass_worst_quality(
         cpi, group_av_err, (group_av_skip_pct + group_av_inactive_zone),
-        vbr_group_bits_per_frame, rc_factor);
+        vbr_group_bits_per_frame);
     rc->active_worst_quality = AOMMAX(tmp_q, rc->active_worst_quality >> 1);
   }
 #endif
@@ -3321,7 +3310,6 @@
 #if ARF_STATS_OUTPUT
 unsigned int arf_count = 0;
 #endif
-#define DEFAULT_GRP_WEIGHT 1.0
 
 static int get_section_target_bandwidth(AV1_COMP *cpi) {
   AV1_COMMON *const cm = &cpi->common;
@@ -3370,7 +3358,7 @@
         ((double)cm->mi_params.mb_rows * section_length);
     const int tmp_q = get_twopass_worst_quality(
         cpi, section_error, section_intra_skip + section_inactive_zone,
-        section_target_bandwidth, DEFAULT_GRP_WEIGHT);
+        section_target_bandwidth);
 
     rc->active_worst_quality = tmp_q;
     rc->ni_av_qi = tmp_q;
@@ -3780,7 +3768,6 @@
 void av1_twopass_postencode_update(AV1_COMP *cpi) {
   TWO_PASS *const twopass = &cpi->twopass;
   RATE_CONTROL *const rc = &cpi->rc;
-  const int bits_used = rc->base_frame_target;
   const RateControlCfg *const rc_cfg = &cpi->oxcf.rc_cfg;
 
   // VBR correction is done through rc->vbr_bits_off_target. Based on the
@@ -3789,10 +3776,10 @@
   // is designed to prevent extreme behaviour at the end of a clip
   // or group of frames.
   rc->vbr_bits_off_target += rc->base_frame_target - rc->projected_frame_size;
-  twopass->bits_left = AOMMAX(twopass->bits_left - bits_used, 0);
+  twopass->bits_left = AOMMAX(twopass->bits_left - rc->base_frame_target, 0);
 
   // Target vs actual bits for this arf group.
-  twopass->rolling_arf_group_target_bits += rc->this_frame_target;
+  twopass->rolling_arf_group_target_bits += rc->base_frame_target;
   twopass->rolling_arf_group_actual_bits += rc->projected_frame_size;
 
   // Calculate the pct rc error.
@@ -3845,7 +3832,7 @@
 #endif
 
   if (cpi->common.current_frame.frame_type != KEY_FRAME) {
-    twopass->kf_group_bits -= bits_used;
+    twopass->kf_group_bits -= rc->base_frame_target;
     twopass->last_kfgroup_zeromotion_pct = twopass->kf_zeromotion_pct;
   }
   twopass->kf_group_bits = AOMMAX(twopass->kf_group_bits, 0);
diff --git a/av1/encoder/pickcdef.c b/av1/encoder/pickcdef.c
index c71ef31..55e466d 100644
--- a/av1/encoder/pickcdef.c
+++ b/av1/encoder/pickcdef.c
@@ -20,6 +20,7 @@
 #include "av1/common/av1_common_int.h"
 #include "av1/common/reconinter.h"
 #include "av1/encoder/encoder.h"
+#include "av1/encoder/ethread.h"
 #include "av1/encoder/pickcdef.h"
 
 // Get primary and secondary filter strength for the given strength index and
@@ -289,11 +290,10 @@
 //   fbc: Column index in units of 64x64 block
 // Returns:
 //   Nothing will be returned. Contents of cdef_search_ctx will be modified.
-static void cdef_mse_calc_block(CdefSearchCtx *cdef_search_ctx, int fbr,
-                                int fbc) {
-  const CommonModeInfoParams *const mi_params = &cdef_search_ctx->cm->mi_params;
+void av1_cdef_mse_calc_block(CdefSearchCtx *cdef_search_ctx, int fbr, int fbc,
+                             int sb_count) {
+  const CommonModeInfoParams *const mi_params = cdef_search_ctx->mi_params;
   const YV12_BUFFER_CONFIG *ref = cdef_search_ctx->ref;
-  const int sb_count = cdef_search_ctx->sb_count;
   const int coeff_shift = cdef_search_ctx->coeff_shift;
   const int *mi_wide_l2 = cdef_search_ctx->mi_wide_l2;
   const int *mi_high_l2 = cdef_search_ctx->mi_high_l2;
@@ -387,14 +387,14 @@
 // Returns:
 //   Nothing will be returned. Contents of cdef_search_ctx will be modified.
 static void cdef_mse_calc_frame(CdefSearchCtx *cdef_search_ctx) {
-  const CommonModeInfoParams *const mi_params = &cdef_search_ctx->cm->mi_params;
   // Loop over each sb.
   for (int fbr = 0; fbr < cdef_search_ctx->nvfb; ++fbr) {
     for (int fbc = 0; fbc < cdef_search_ctx->nhfb; ++fbc) {
       // Checks if cdef processing can be skipped for particular sb.
-      if (cdef_sb_skip(mi_params, fbr, fbc)) continue;
+      if (cdef_sb_skip(cdef_search_ctx->mi_params, fbr, fbc)) continue;
       // Calculate mse for each sb and store the relevant sb index.
-      cdef_mse_calc_block(cdef_search_ctx, fbr, fbc);
+      av1_cdef_mse_calc_block(cdef_search_ctx, fbr, fbc,
+                              cdef_search_ctx->sb_count);
       cdef_search_ctx->sb_count++;
     }
   }
@@ -448,7 +448,7 @@
                                         CDEF_PICK_METHOD pick_method) {
   const CommonModeInfoParams *const mi_params = &cm->mi_params;
   const int num_planes = av1_num_planes(cm);
-  cdef_search_ctx->cm = cm;
+  cdef_search_ctx->mi_params = &cm->mi_params;
   cdef_search_ctx->ref = ref;
   cdef_search_ctx->nvfb =
       (mi_params->mi_rows + MI_SIZE_64X64 - 1) / MI_SIZE_64X64;
@@ -549,7 +549,7 @@
   }
 }
 
-void av1_cdef_search(const YV12_BUFFER_CONFIG *frame,
+void av1_cdef_search(MultiThreadInfo *mt_info, const YV12_BUFFER_CONFIG *frame,
                      const YV12_BUFFER_CONFIG *ref, AV1_COMMON *cm,
                      MACROBLOCKD *xd, CDEF_PICK_METHOD pick_method,
                      int rdmult) {
@@ -568,7 +568,11 @@
   // Allocate CDEF search context buffers.
   cdef_alloc_data(&cdef_search_ctx);
   // Frame level mse calculation.
-  cdef_mse_calc_frame(&cdef_search_ctx);
+  if (mt_info->num_workers > 1) {
+    av1_cdef_mse_calc_frame_mt(cm, mt_info, &cdef_search_ctx);
+  } else {
+    cdef_mse_calc_frame(&cdef_search_ctx);
+  }
 
   /* Search for different number of signaling bits. */
   int nb_strength_bits = 0;
diff --git a/av1/encoder/pickcdef.h b/av1/encoder/pickcdef.h
index ef342dc..7fe1edb 100644
--- a/av1/encoder/pickcdef.h
+++ b/av1/encoder/pickcdef.h
@@ -19,6 +19,8 @@
 #endif
 
 /*!\cond */
+struct MultiThreadInfo;
+
 #define REDUCED_PRI_STRENGTHS_LVL1 8
 #define REDUCED_PRI_STRENGTHS_LVL2 5
 #define REDUCED_SEC_STRENGTHS_LVL3 2
@@ -56,6 +58,20 @@
                                         BLOCK_SIZE bsize, int coeff_shift,
                                         int row, int col);
 
+// Data related to CDEF search multi-thread synchronization.
+typedef struct AV1CdefSyncData {
+#if CONFIG_MULTITHREAD
+  // Mutex lock used while dispatching jobs.
+  pthread_mutex_t *mutex_;
+#endif  // CONFIG_MULTITHREAD
+  // Flag to indicate all blocks are processed and end of frame is reached
+  int end_of_frame;
+  // Row index in units of 64x64 block
+  int fbr;
+  // Column index in units of 64x64 block
+  int fbc;
+} AV1CdefSync;
+
 /*! \brief CDEF search context.
  */
 typedef struct {
@@ -64,9 +80,9 @@
    */
   const YV12_BUFFER_CONFIG *ref;
   /*!
-   * Pointer to top level common structure
+   * Pointer to params related to MB_MODE_INFO arrays and related info
    */
-  AV1_COMMON *cm;
+  CommonModeInfoParams *mi_params;
   /*!
    * Info specific to each plane
    */
@@ -190,6 +206,9 @@
     return 1;
   return 0;
 }
+
+void av1_cdef_mse_calc_block(CdefSearchCtx *cdef_search_ctx, int fbr, int fbc,
+                             int sb_count);
 /*!\endcond */
 
 /*!\brief AV1 CDEF parameter search
@@ -198,6 +217,7 @@
  *
  * Searches for optimal CDEF parameters for frame
  *
+ * \param[in]      mt_info      Pointer to multi-threading parameters
  * \param[in]      frame        Compressed frame buffer
  * \param[in]      ref          Source frame buffer
  * \param[in,out]  cm           Pointer to top level common structure
@@ -216,7 +236,8 @@
  * \arg \c damping_factor: CDEF damping factor.
  *
  */
-void av1_cdef_search(const YV12_BUFFER_CONFIG *frame,
+void av1_cdef_search(struct MultiThreadInfo *mt_info,
+                     const YV12_BUFFER_CONFIG *frame,
                      const YV12_BUFFER_CONFIG *ref, AV1_COMMON *cm,
                      MACROBLOCKD *xd, CDEF_PICK_METHOD pick_method, int rdmult);
 
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index aaa9dfd..7f595fc 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -310,7 +310,6 @@
 
   rc->total_actual_bits = 0;
   rc->total_target_bits = 0;
-  rc->total_target_vs_actual = 0;
 
   rc->frames_since_key = 8;  // Sensible default for first frame.
   rc->this_key_frame_forced = 0;
@@ -1829,8 +1828,6 @@
   rc->total_actual_bits += rc->projected_frame_size;
   rc->total_target_bits += cm->show_frame ? rc->avg_frame_bandwidth : 0;
 
-  rc->total_target_vs_actual = rc->total_actual_bits - rc->total_target_bits;
-
   if (is_altref_enabled(cpi->oxcf.gf_cfg.lag_in_frames,
                         cpi->oxcf.gf_cfg.enable_auto_arf) &&
       refresh_frame_flags->alt_ref_frame &&
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index aefb5b4..3f1756f 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -258,7 +258,6 @@
 
   int64_t total_actual_bits;
   int64_t total_target_bits;
-  int64_t total_target_vs_actual;
 
   /*!\endcond */
   /*!
diff --git a/av1/encoder/svc_layercontext.c b/av1/encoder/svc_layercontext.c
index c43edf9..e75ad3c 100644
--- a/av1/encoder/svc_layercontext.c
+++ b/av1/encoder/svc_layercontext.c
@@ -38,7 +38,6 @@
       RATE_CONTROL *const lrc = &lc->rc;
       lrc->ni_av_qi = oxcf->rc_cfg.worst_allowed_q;
       lrc->total_actual_bits = 0;
-      lrc->total_target_vs_actual = 0;
       lrc->ni_tot_qi = 0;
       lrc->tot_q = 0.0;
       lrc->avg_q = 0.0;
diff --git a/av1/encoder/var_based_part.c b/av1/encoder/var_based_part.c
index c6d0f05..c22dc10 100644
--- a/av1/encoder/var_based_part.c
+++ b/av1/encoder/var_based_part.c
@@ -847,6 +847,7 @@
   const uint8_t *d;
   int sp;
   int dp;
+  NOISE_LEVEL noise_level = kLow;
 
   int is_key_frame =
       (frame_is_intra_only(cm) ||
@@ -923,6 +924,8 @@
     d = AV1_VAR_OFFS;
     dp = 0;
   }
+  if (cpi->noise_estimate.enabled)
+    noise_level = av1_noise_estimate_extract_level(&cpi->noise_estimate);
 
   if (low_res && threshold_4x4avg < INT64_MAX)
     CHECK_MEM_ERROR(cm, vt2, aom_malloc(sizeof(*vt2)));
@@ -996,14 +999,18 @@
       var_64x64 = vt->split[m].part_variances.none.variance;
       max_var_64x64 = AOMMAX(var_64x64, max_var_64x64);
       min_var_64x64 = AOMMIN(var_64x64, min_var_64x64);
-      // If variance of this 64x64 block is above (some threshold of) the
-      // average variance over the sub-32x32 blocks, then force this block to
-      // split. Only checking this for noise level >= medium for now.
+      // If the difference of the max-min variances of sub-blocks or max
+      // variance of a sub-block is above some threshold of then force this
+      // block to split. Only checking this for noise level >= medium or if
+      // encoder is in SVC.
 
       if (!is_key_frame &&
           (max_var_32x32[m] - min_var_32x32[m]) > 3 * (thresholds[1] >> 3) &&
-          max_var_32x32[m] > thresholds[1] >> 1)
+          max_var_32x32[m] > thresholds[1] >> 1 &&
+          (noise_level >= kMedium || cpi->use_svc)) {
         force_split[1 + m] = 1;
+        force_split[0] = 1;
+      }
       avg_64x64 += var_64x64;
     }
     if (is_small_sb) force_split[0] = 1;