Add a q index based frame superres mode

Refactors and adds superres-mode 3 and associated
paramters --superres-qthresh and --superres-kf-qthresh
that are used to trigger superres mode when the qindex
for any frame exceeds the thresholds provided for non-key
and key-frames respenctively. The superres scale factor
numerator is progressively reduced from 16 starting from
that q threshold following a fixed slope.

Change-Id: If1c782993667a6fbaaa01bbde77c4924008c0d28
diff --git a/aom/aom_encoder.h b/aom/aom_encoder.h
index add20b0..89b7396 100644
--- a/aom/aom_encoder.h
+++ b/aom/aom_encoder.h
@@ -395,7 +395,7 @@
    * using restoration filters should allow it to outperform normal resizing.
    *
    * Mode 0 is SUPERRES_NONE, mode 1 is SUPERRES_FIXED, and mode 2 is
-   * SUPERRES_DYNAMIC.
+   * SUPERRES_RANDOM.
    */
   unsigned int rc_superres_mode;
 
@@ -407,7 +407,7 @@
    *
    * Valid numerators are 8 to 16.
    *
-   * Ignored by SUPERRES_DYNAMIC.
+   * Used only by SUPERRES_FIXED.
    */
   unsigned int rc_superres_numerator;
 
@@ -421,6 +421,24 @@
    */
   unsigned int rc_superres_kf_numerator;
 
+  /*!\brief Frame super-resolution q threshold.
+   *
+   * The q level threshold after which superres is used.
+   * Valid values are 1 to 63.
+   *
+   * Used only by SUPERRES_QTHRESH
+   */
+  unsigned int rc_superres_qthresh;
+
+  /*!\brief Keyframe super-resolution q threshold.
+   *
+   * The q level threshold after which superres is used for key frames.
+   * Valid values are 1 to 63.
+   *
+   * Used only by SUPERRES_QTHRESH
+   */
+  unsigned int rc_superres_kf_qthresh;
+
   /*!\brief Rate control algorithm to use.
    *
    * Indicates whether the end usage of this stream is to be streamed over
diff --git a/aomenc.c b/aomenc.c
index d9e1f73..fd334fa 100644
--- a/aomenc.c
+++ b/aomenc.c
@@ -302,6 +302,11 @@
 static const arg_def_t superres_kf_numerator =
     ARG_DEF(NULL, "superres-kf-numerator", 1,
             "Frame super-resolution keyframe numerator");
+static const arg_def_t superres_qthresh = ARG_DEF(
+    NULL, "superres-qthresh", 1, "Frame super-resolution qindex threshold");
+static const arg_def_t superres_kf_qthresh =
+    ARG_DEF(NULL, "superres-kf-qthresh", 1,
+            "Frame super-resolution keyframe qindex threshold");
 #endif  // CONFIG_FRAME_SUPERRES
 static const struct arg_enum_list end_usage_enum[] = { { "vbr", AOM_VBR },
                                                        { "cbr", AOM_CBR },
@@ -334,6 +339,8 @@
                                       &superres_mode,
                                       &superres_numerator,
                                       &superres_kf_numerator,
+                                      &superres_qthresh,
+                                      &superres_kf_qthresh,
 #endif  // CONFIG_FRAME_SUPERRES
                                       &end_usage,
                                       &target_bitrate,
@@ -1055,6 +1062,10 @@
       config->cfg.rc_superres_numerator = arg_parse_uint(&arg);
     } else if (arg_match(&arg, &superres_kf_numerator, argi)) {
       config->cfg.rc_superres_kf_numerator = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &superres_qthresh, argi)) {
+      config->cfg.rc_superres_qthresh = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &superres_kf_qthresh, argi)) {
+      config->cfg.rc_superres_kf_qthresh = arg_parse_uint(&arg);
 #endif  // CONFIG_FRAME_SUPERRES
     } else if (arg_match(&arg, &end_usage, argi)) {
       config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
@@ -1267,6 +1278,8 @@
   SHOW(rc_superres_mode);
   SHOW(rc_superres_numerator);
   SHOW(rc_superres_kf_numerator);
+  SHOW(rc_superres_qthresh);
+  SHOW(rc_superres_kf_qthresh);
 #endif  // CONFIG_FRAME_SUPERRES
   SHOW(rc_end_usage);
   SHOW(rc_target_bitrate);
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 0f5e5f7..fe1c7c2 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -8,7 +8,6 @@
  * Media Patent License 1.0 was not distributed with this source code in the
  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
  */
-
 #include <stdlib.h>
 #include <string.h>
 
@@ -251,17 +250,19 @@
                 (MAX_LAG_BUFFERS - 1));
   }
 
-  RANGE_CHECK_HI(cfg, rc_resize_mode, RESIZE_DYNAMIC);
+  RANGE_CHECK_HI(cfg, rc_resize_mode, RESIZE_MODES - 1);
   RANGE_CHECK(cfg, rc_resize_numerator, SCALE_DENOMINATOR / 2,
               SCALE_DENOMINATOR);
   RANGE_CHECK(cfg, rc_resize_kf_numerator, SCALE_DENOMINATOR / 2,
               SCALE_DENOMINATOR);
 #if CONFIG_FRAME_SUPERRES
-  RANGE_CHECK_HI(cfg, rc_superres_mode, SUPERRES_DYNAMIC);
+  RANGE_CHECK_HI(cfg, rc_superres_mode, SUPERRES_MODES - 1);
   RANGE_CHECK(cfg, rc_superres_numerator, SCALE_DENOMINATOR / 2,
               SCALE_DENOMINATOR);
   RANGE_CHECK(cfg, rc_superres_kf_numerator, SCALE_DENOMINATOR / 2,
               SCALE_DENOMINATOR);
+  RANGE_CHECK(cfg, rc_superres_qthresh, 1, 63);
+  RANGE_CHECK(cfg, rc_superres_kf_qthresh, 1, 63);
 #endif  // CONFIG_FRAME_SUPERRES
 
   // AV1 does not support a lower bound on the keyframe interval in
@@ -513,10 +514,20 @@
   oxcf->superres_mode = (SUPERRES_MODE)cfg->rc_superres_mode;
   oxcf->superres_scale_numerator = (uint8_t)cfg->rc_superres_numerator;
   oxcf->superres_kf_scale_numerator = (uint8_t)cfg->rc_superres_kf_numerator;
+  oxcf->superres_qthresh =
+      extra_cfg->lossless ? 255
+                          : av1_quantizer_to_qindex(cfg->rc_superres_qthresh);
+  oxcf->superres_kf_qthresh =
+      extra_cfg->lossless
+          ? 255
+          : av1_quantizer_to_qindex(cfg->rc_superres_kf_qthresh);
   if (oxcf->superres_mode == SUPERRES_FIXED &&
       oxcf->superres_scale_numerator == SCALE_DENOMINATOR &&
       oxcf->superres_kf_scale_numerator == SCALE_DENOMINATOR)
     oxcf->superres_mode = SUPERRES_NONE;
+  if (oxcf->superres_mode == SUPERRES_QTHRESH &&
+      oxcf->superres_qthresh == 255 && oxcf->superres_kf_qthresh == 255)
+    oxcf->superres_mode = SUPERRES_NONE;
 #endif  // CONFIG_FRAME_SUPERRES
 
   oxcf->maximum_buffer_size_ms = is_vbr ? 240000 : cfg->rc_buf_sz;
@@ -1617,6 +1628,8 @@
         0,                  // rc_superres_mode
         SCALE_DENOMINATOR,  // rc_superres_numerator
         SCALE_DENOMINATOR,  // rc_superres_kf_numerator
+        63,                 // rc_superres_qthresh
+        63,                 // rc_superres_kf_qthresh
 
         AOM_VBR,      // rc_end_usage
         { NULL, 0 },  // rc_twopass_stats_in
diff --git a/av1/common/alloccommon.c b/av1/common/alloccommon.c
index c878939..357543e 100644
--- a/av1/common/alloccommon.c
+++ b/av1/common/alloccommon.c
@@ -19,6 +19,22 @@
 #include "av1/common/entropymv.h"
 #include "av1/common/onyxc_int.h"
 
+int av1_get_MBs(int width, int height) {
+  const int aligned_width = ALIGN_POWER_OF_TWO(width, 3);
+  const int aligned_height = ALIGN_POWER_OF_TWO(height, 3);
+  const int mi_cols = aligned_width >> MI_SIZE_LOG2;
+  const int mi_rows = aligned_height >> MI_SIZE_LOG2;
+
+#if CONFIG_CB4X4
+  const int mb_cols = (mi_cols + 2) >> 2;
+  const int mb_rows = (mi_rows + 2) >> 2;
+#else
+  const int mb_cols = (mi_cols + 1) >> 1;
+  const int mb_rows = (mi_rows + 1) >> 1;
+#endif
+  return mb_rows * mb_cols;
+}
+
 void av1_set_mb_mi(AV1_COMMON *cm, int width, int height) {
   // Ensure that the decoded width and height are both multiples of
   // 8 luma pixels (note: this may only be a multiple of 4 chroma pixels if
diff --git a/av1/common/alloccommon.h b/av1/common/alloccommon.h
index 51863cd..0d420f8 100644
--- a/av1/common/alloccommon.h
+++ b/av1/common/alloccommon.h
@@ -37,6 +37,7 @@
 void av1_free_state_buffers(struct AV1Common *cm);
 
 void av1_set_mb_mi(struct AV1Common *cm, int width, int height);
+int av1_get_MBs(int width, int height);
 
 void av1_swap_current_and_last_seg_map(struct AV1Common *cm);
 
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 1176dcb..320a8c2 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -56,6 +56,7 @@
 #if CONFIG_LOOP_RESTORATION
 #include "av1/encoder/pickrst.h"
 #endif  // CONFIG_LOOP_RESTORATION
+#include "av1/encoder/random.h"
 #include "av1/encoder/ratectrl.h"
 #include "av1/encoder/rd.h"
 #include "av1/encoder/segmentation.h"
@@ -848,7 +849,7 @@
   cpi->od_rc.framerate = cpi->framerate;
   od_enc_rc_resize(&cpi->od_rc);
 #else
-  av1_rc_update_framerate(cpi);
+  av1_rc_update_framerate(cpi, cpi->common.width, cpi->common.height);
 #endif
 }
 
@@ -3934,7 +3935,8 @@
       &cpi->od_rc, cpi->refresh_golden_frame, cpi->refresh_alt_ref_frame,
       frame_type, bottom_index, top_index);
 #else
-  *q = av1_rc_pick_q_and_bounds(cpi, bottom_index, top_index);
+  *q = av1_rc_pick_q_and_bounds(cpi, cm->width, cm->height, bottom_index,
+                                top_index);
 #endif
 
   if (!frame_is_intra_only(cm)) {
@@ -4076,7 +4078,7 @@
 
 #if !CONFIG_XIPHRC
   if (cpi->oxcf.pass == 2) {
-    av1_set_target_rate(cpi);
+    av1_set_target_rate(cpi, cm->width, cm->height);
   }
 #endif
 
@@ -4164,26 +4166,132 @@
   set_ref_ptrs(cm, xd, LAST_FRAME, LAST_FRAME);
 }
 
-static void setup_frame_size(AV1_COMP *cpi) {
+static uint8_t calculate_next_resize_scale(const AV1_COMP *cpi) {
+  // Choose an arbitrary random number
+  static unsigned int seed = 56789;
+  const AV1EncoderConfig *oxcf = &cpi->oxcf;
+  if (oxcf->pass == 1) return SCALE_DENOMINATOR;
+  uint8_t new_num = SCALE_DENOMINATOR;
+
+  switch (oxcf->resize_mode) {
+    case RESIZE_NONE: new_num = SCALE_DENOMINATOR; break;
+    case RESIZE_FIXED:
+      if (cpi->common.frame_type == KEY_FRAME)
+        new_num = oxcf->resize_kf_scale_numerator;
+      else
+        new_num = oxcf->resize_scale_numerator;
+      break;
+    case RESIZE_RANDOM: new_num = lcg_rand16(&seed) % 9 + 8; break;
+    default: assert(0);
+  }
+  return new_num;
+}
+
+#if CONFIG_FRAME_SUPERRES
+static uint8_t calculate_next_superres_scale(AV1_COMP *cpi) {
+  // Choose an arbitrary random number
+  static unsigned int seed = 34567;
+  const AV1EncoderConfig *oxcf = &cpi->oxcf;
+  if (oxcf->pass == 1) return SCALE_DENOMINATOR;
+  uint8_t new_num = SCALE_DENOMINATOR;
+  int bottom_index, top_index, q, qthresh;
+
+  switch (oxcf->superres_mode) {
+    case SUPERRES_NONE: new_num = SCALE_DENOMINATOR; break;
+    case SUPERRES_FIXED:
+      if (cpi->common.frame_type == KEY_FRAME)
+        new_num = oxcf->superres_kf_scale_numerator;
+      else
+        new_num = oxcf->superres_scale_numerator;
+      break;
+    case SUPERRES_RANDOM: new_num = lcg_rand16(&seed) % 9 + 8; break;
+    case SUPERRES_QTHRESH:
+      qthresh = (cpi->common.frame_type == KEY_FRAME ? oxcf->superres_kf_qthresh
+                                                     : oxcf->superres_qthresh);
+      av1_set_target_rate(cpi, cpi->oxcf.width, cpi->oxcf.height);
+      q = av1_rc_pick_q_and_bounds(cpi, cpi->oxcf.width, cpi->oxcf.height,
+                                   &bottom_index, &top_index);
+      if (q < qthresh) {
+        new_num = SCALE_DENOMINATOR;
+      } else {
+        new_num = SCALE_DENOMINATOR - 1 - ((q - qthresh) >> 3);
+        new_num = AOMMAX(SCALE_DENOMINATOR / 2, new_num);
+        // printf("SUPERRES: q %d, qthresh %d: num %d\n", q, qthresh, new_num);
+      }
+      break;
+    default: assert(0);
+  }
+  return new_num;
+}
+
+static int validate_size_scales(RESIZE_MODE resize_mode,
+                                SUPERRES_MODE superres_mode,
+                                size_params_type *rsz) {
+  if (rsz->resize_num * rsz->superres_num * 2 >
+      SCALE_DENOMINATOR * SCALE_DENOMINATOR)
+    return 1;
+  if (resize_mode != RESIZE_RANDOM && superres_mode == SUPERRES_RANDOM) {
+    rsz->superres_num =
+        (SCALE_DENOMINATOR * SCALE_DENOMINATOR + 2 * rsz->resize_num - 1) /
+        (2 * rsz->resize_num);
+  } else if (resize_mode == RESIZE_RANDOM && superres_mode != SUPERRES_RANDOM) {
+    rsz->resize_num =
+        (SCALE_DENOMINATOR * SCALE_DENOMINATOR + 2 * rsz->superres_num - 1) /
+        (2 * rsz->superres_num);
+  } else if (resize_mode == RESIZE_RANDOM && superres_mode == SUPERRES_RANDOM) {
+    do {
+      if (rsz->resize_num < rsz->superres_num)
+        ++rsz->resize_num;
+      else
+        ++rsz->superres_num;
+    } while (rsz->resize_num * rsz->superres_num * 2 <=
+             SCALE_DENOMINATOR * SCALE_DENOMINATOR);
+  } else {
+    return 0;
+  }
+  return 1;
+}
+#endif  // CONFIG_FRAME_SUPERRES
+
+size_params_type av1_calculate_next_size_params(AV1_COMP *cpi) {
+  const AV1EncoderConfig *oxcf = &cpi->oxcf;
+  size_params_type rsz = {
+    SCALE_DENOMINATOR,
+#if CONFIG_FRAME_SUPERRES
+    SCALE_DENOMINATOR
+#endif  // CONFIG_FRAME_SUPERRES
+  };
+  if (oxcf->pass == 1) return rsz;
+  rsz.resize_num = calculate_next_resize_scale(cpi);
+#if CONFIG_FRAME_SUPERRES
+  rsz.superres_num = calculate_next_superres_scale(cpi);
+  if (!validate_size_scales(oxcf->resize_mode, oxcf->superres_mode, &rsz))
+    assert(0 && "Invalid scale parameters");
+#endif  // CONFIG_FRAME_SUPERRES
+  return rsz;
+}
+
+static void setup_frame_size_from_params(AV1_COMP *cpi, size_params_type *rsz) {
   int encode_width = cpi->oxcf.width;
   int encode_height = cpi->oxcf.height;
-
-  uint8_t resize_num = av1_calculate_next_resize_scale(cpi);
-  av1_calculate_scaled_size(&encode_width, &encode_height, resize_num);
+  av1_calculate_scaled_size(&encode_width, &encode_height, rsz->resize_num);
 
 #if CONFIG_FRAME_SUPERRES
   AV1_COMMON *cm = &cpi->common;
   cm->superres_upscaled_width = encode_width;
   cm->superres_upscaled_height = encode_height;
-  cm->superres_scale_numerator =
-      av1_calculate_next_superres_scale(cpi, encode_width, encode_height);
-  av1_calculate_scaled_size(&encode_width, &encode_height,
-                            cm->superres_scale_numerator);
+  cm->superres_scale_numerator = rsz->superres_num;
+  av1_calculate_scaled_size(&encode_width, &encode_height, rsz->superres_num);
 #endif  // CONFIG_FRAME_SUPERRES
-
   set_frame_size(cpi, encode_width, encode_height);
 }
 
+static void setup_frame_size(AV1_COMP *cpi) {
+  size_params_type rsz;
+  rsz = av1_calculate_next_size_params(cpi);
+  setup_frame_size_from_params(cpi, &rsz);
+}
+
 #if CONFIG_FRAME_SUPERRES
 static void superres_post_encode(AV1_COMP *cpi) {
   AV1_COMMON *cm = &cpi->common;
@@ -4326,7 +4434,9 @@
   aom_clear_system_state();
 
   set_size_independent_vars(cpi);
+
   setup_frame_size(cpi);
+
   assert(cm->width == cpi->scaled_source.y_crop_width);
   assert(cm->height == cpi->scaled_source.y_crop_height);
 
@@ -4397,14 +4507,14 @@
   cpi->source->buf_8bit_valid = 0;
 #endif
 
+  aom_clear_system_state();
+  setup_frame_size(cpi);
+  set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
+
   do {
     aom_clear_system_state();
 
-    setup_frame_size(cpi);
-
     if (loop_count == 0) {
-      set_size_dependent_vars(cpi, &q, &bottom_index, &top_index);
-
       // TODO(agrange) Scale cpi->max_mv_magnitude if frame-size has changed.
       set_mv_search_params(cpi);
 
@@ -4572,20 +4682,22 @@
 
           if (undershoot_seen || loop_at_this_size > 1) {
             // Update rate_correction_factor unless
-            av1_rc_update_rate_correction_factors(cpi);
+            av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
 
             q = (q_high + q_low + 1) / 2;
           } else {
             // Update rate_correction_factor unless
-            av1_rc_update_rate_correction_factors(cpi);
+            av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
 
             q = av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index,
-                                  AOMMAX(q_high, top_index));
+                                  AOMMAX(q_high, top_index), cm->width,
+                                  cm->height);
 
             while (q < q_low && retries < 10) {
-              av1_rc_update_rate_correction_factors(cpi);
+              av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
               q = av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index,
-                                    AOMMAX(q_high, top_index));
+                                    AOMMAX(q_high, top_index), cm->width,
+                                    cm->height);
               retries++;
             }
           }
@@ -4596,12 +4708,12 @@
           q_high = q > q_low ? q - 1 : q_low;
 
           if (overshoot_seen || loop_at_this_size > 1) {
-            av1_rc_update_rate_correction_factors(cpi);
+            av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
             q = (q_high + q_low) / 2;
           } else {
-            av1_rc_update_rate_correction_factors(cpi);
+            av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
             q = av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index,
-                                  top_index);
+                                  top_index, cm->width, cm->height);
             // Special case reset for qlow for constrained quality.
             // This should only trigger where there is very substantial
             // undershoot on a frame and the auto cq level is above
@@ -4611,9 +4723,9 @@
             }
 
             while (q > q_high && retries < 10) {
-              av1_rc_update_rate_correction_factors(cpi);
+              av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
               q = av1_rc_regulate_q(cpi, rc->this_frame_target, bottom_index,
-                                    top_index);
+                                    top_index, cm->width, cm->height);
               retries++;
             }
           }
@@ -5004,7 +5116,7 @@
     // Since we allocate a spot for the OVERLAY frame in the gf group, we need
     // to do post-encoding update accordingly.
     if (cpi->rc.is_src_frame_alt_ref) {
-      av1_set_target_rate(cpi);
+      av1_set_target_rate(cpi, cm->width, cm->height);
 #if CONFIG_XIPHRC
       frame_type = cm->frame_type == INTER_FRAME ? OD_P_FRAME : OD_I_FRAME;
       drop_this_frame = od_enc_rc_update_state(
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index b26c241..9fc1f2d 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -134,14 +134,20 @@
 #endif
 typedef enum {
   RESIZE_NONE = 0,    // No frame resizing allowed.
-  RESIZE_FIXED = 1,   // All frames are coded at the specified dimension.
-  RESIZE_DYNAMIC = 2  // Coded size of each frame is determined by the codec.
+  RESIZE_FIXED = 1,   // All frames are coded at the specified scale.
+  RESIZE_RANDOM = 2,  // All frames are coded at a random scale.
+  RESIZE_MODES
 } RESIZE_MODE;
 #if CONFIG_FRAME_SUPERRES
 typedef enum {
-  SUPERRES_NONE = 0,
-  SUPERRES_FIXED = 1,
-  SUPERRES_DYNAMIC = 2
+  SUPERRES_NONE = 0,     // No frame superres allowed
+  SUPERRES_FIXED = 1,    // All frames are coded at the specified scale,
+                         // and super-resolved.
+  SUPERRES_RANDOM = 2,   // All frames are coded at a random scale,
+                         // and super-resolved.
+  SUPERRES_QTHRESH = 3,  // Superres scale for a frame is determined based on
+                         // q_index
+  SUPERRES_MODES
 } SUPERRES_MODE;
 #endif  // CONFIG_FRAME_SUPERRES
 
@@ -224,6 +230,8 @@
   SUPERRES_MODE superres_mode;
   uint8_t superres_scale_numerator;
   uint8_t superres_kf_scale_numerator;
+  int superres_qthresh;
+  int superres_kf_qthresh;
 #endif  // CONFIG_FRAME_SUPERRES
 
   // Enable feature to reduce the frame quantization every x frames.
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index b92befb..a90cb88 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -94,9 +94,11 @@
 static int kf_high = 5000;
 static int kf_low = 400;
 
-double av1_resize_rate_factor(const AV1_COMP *cpi) {
-  return (double)(cpi->oxcf.width * cpi->oxcf.height) /
-         (cpi->common.width * cpi->common.height);
+// How many times less pixels there are to encode given the current scaling.
+// Temporary replacement for rcf_mult and rate_thresh_mult.
+static double resize_rate_factor(const AV1_COMP *cpi, int width, int height) {
+  (void)cpi;
+  return (double)(cpi->oxcf.width * cpi->oxcf.height) / (width * height);
 }
 
 // Functions to compute the active minq lookup table entries based on a
@@ -372,7 +374,8 @@
   }
 }
 
-static double get_rate_correction_factor(const AV1_COMP *cpi) {
+static double get_rate_correction_factor(const AV1_COMP *cpi, int width,
+                                         int height) {
   const RATE_CONTROL *const rc = &cpi->rc;
   double rcf;
 
@@ -390,15 +393,16 @@
     else
       rcf = rc->rate_correction_factors[INTER_NORMAL];
   }
-  rcf *= av1_resize_rate_factor(cpi);
+  rcf *= resize_rate_factor(cpi, width, height);
   return fclamp(rcf, MIN_BPB_FACTOR, MAX_BPB_FACTOR);
 }
 
-static void set_rate_correction_factor(AV1_COMP *cpi, double factor) {
+static void set_rate_correction_factor(AV1_COMP *cpi, double factor, int width,
+                                       int height) {
   RATE_CONTROL *const rc = &cpi->rc;
 
   // Normalize RCF to account for the size-dependent scaling factor.
-  factor /= av1_resize_rate_factor(cpi);
+  factor /= resize_rate_factor(cpi, width, height);
 
   factor = fclamp(factor, MIN_BPB_FACTOR, MAX_BPB_FACTOR);
 
@@ -418,11 +422,14 @@
   }
 }
 
-void av1_rc_update_rate_correction_factors(AV1_COMP *cpi) {
+void av1_rc_update_rate_correction_factors(AV1_COMP *cpi, int width,
+                                           int height) {
   const AV1_COMMON *const cm = &cpi->common;
   int correction_factor = 100;
-  double rate_correction_factor = get_rate_correction_factor(cpi);
+  double rate_correction_factor =
+      get_rate_correction_factor(cpi, width, height);
   double adjustment_limit;
+  const int MBs = av1_get_MBs(width, height);
 
   int projected_size_based_on_q = 0;
 
@@ -440,7 +447,7 @@
         av1_cyclic_refresh_estimate_bits_at_q(cpi, rate_correction_factor);
   } else {
     projected_size_based_on_q =
-        av1_estimate_bits_at_q(cpi->common.frame_type, cm->base_qindex, cm->MBs,
+        av1_estimate_bits_at_q(cpi->common.frame_type, cm->base_qindex, MBs,
                                rate_correction_factor, cm->bit_depth);
   }
   // Work out a size correction factor.
@@ -486,21 +493,24 @@
       rate_correction_factor = MIN_BPB_FACTOR;
   }
 
-  set_rate_correction_factor(cpi, rate_correction_factor);
+  set_rate_correction_factor(cpi, rate_correction_factor, width, height);
 }
 
 int av1_rc_regulate_q(const AV1_COMP *cpi, int target_bits_per_frame,
-                      int active_best_quality, int active_worst_quality) {
+                      int active_best_quality, int active_worst_quality,
+                      int width, int height) {
   const AV1_COMMON *const cm = &cpi->common;
   int q = active_worst_quality;
   int last_error = INT_MAX;
   int i, target_bits_per_mb, bits_per_mb_at_this_q;
-  const double correction_factor = get_rate_correction_factor(cpi);
+  const int MBs = av1_get_MBs(width, height);
+  const double correction_factor =
+      get_rate_correction_factor(cpi, width, height);
 
   // Calculate required scaling factor based on target frame size and size of
   // frame produced using previous Q.
   target_bits_per_mb =
-      (int)((uint64_t)target_bits_per_frame << BPER_MB_NORMBITS) / cm->MBs;
+      (int)((uint64_t)(target_bits_per_frame) << BPER_MB_NORMBITS) / MBs;
 
   i = active_best_quality;
 
@@ -651,8 +661,8 @@
   return active_worst_quality;
 }
 
-static int rc_pick_q_and_bounds_one_pass_cbr(const AV1_COMP *cpi,
-                                             int *bottom_index,
+static int rc_pick_q_and_bounds_one_pass_cbr(const AV1_COMP *cpi, int width,
+                                             int height, int *bottom_index,
                                              int *top_index) {
   const AV1_COMMON *const cm = &cpi->common;
   const RATE_CONTROL *const rc = &cpi->rc;
@@ -682,7 +692,7 @@
           rc, rc->avg_frame_qindex[KEY_FRAME], cm->bit_depth);
 
       // Allow somewhat lower kf minq with small image formats.
-      if ((cm->width * cm->height) <= (352 * 288)) {
+      if ((width * height) <= (352 * 288)) {
         q_adj_factor -= 0.25;
       }
 
@@ -744,7 +754,7 @@
     q = rc->last_boosted_qindex;
   } else {
     q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality,
-                          active_worst_quality);
+                          active_worst_quality, width, height);
     if (q > *top_index) {
       // Special case when we are targeting the max allowed rate
       if (rc->this_frame_target >= rc->max_frame_bandwidth)
@@ -774,8 +784,8 @@
   return active_cq_level;
 }
 
-static int rc_pick_q_and_bounds_one_pass_vbr(const AV1_COMP *cpi,
-                                             int *bottom_index,
+static int rc_pick_q_and_bounds_one_pass_vbr(const AV1_COMP *cpi, int width,
+                                             int height, int *bottom_index,
                                              int *top_index) {
   const AV1_COMMON *const cm = &cpi->common;
   const RATE_CONTROL *const rc = &cpi->rc;
@@ -808,7 +818,7 @@
           rc, rc->avg_frame_qindex[KEY_FRAME], cm->bit_depth);
 
       // Allow somewhat lower kf minq with small image formats.
-      if ((cm->width * cm->height) <= (352 * 288)) {
+      if ((width * height) <= (352 * 288)) {
         q_adj_factor -= 0.25;
       }
 
@@ -903,7 +913,7 @@
     q = rc->last_boosted_qindex;
   } else {
     q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality,
-                          active_worst_quality);
+                          active_worst_quality, width, height);
     if (q > *top_index) {
       // Special case when we are targeting the max allowed rate
       if (rc->this_frame_target >= rc->max_frame_bandwidth)
@@ -949,7 +959,8 @@
 }
 
 #define STATIC_MOTION_THRESH 95
-static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int *bottom_index,
+static int rc_pick_q_and_bounds_two_pass(const AV1_COMP *cpi, int width,
+                                         int height, int *bottom_index,
                                          int *top_index) {
   const AV1_COMMON *const cm = &cpi->common;
   const RATE_CONTROL *const rc = &cpi->rc;
@@ -996,7 +1007,7 @@
           get_kf_active_quality(rc, active_worst_quality, cm->bit_depth);
 
       // Allow somewhat lower kf minq with small image formats.
-      if ((cm->width * cm->height) <= (352 * 288)) {
+      if ((width * height) <= (352 * 288)) {
         q_adj_factor -= 0.25;
       }
 
@@ -1119,7 +1130,7 @@
     }
   } else {
     q = av1_rc_regulate_q(cpi, rc->this_frame_target, active_best_quality,
-                          active_worst_quality);
+                          active_worst_quality, width, height);
     if (q > active_worst_quality) {
       // Special case when we are targeting the max allowed rate.
       if (rc->this_frame_target >= rc->max_frame_bandwidth)
@@ -1140,16 +1151,19 @@
   return q;
 }
 
-int av1_rc_pick_q_and_bounds(const AV1_COMP *cpi, int *bottom_index,
-                             int *top_index) {
+int av1_rc_pick_q_and_bounds(const AV1_COMP *cpi, int width, int height,
+                             int *bottom_index, int *top_index) {
   int q;
   if (cpi->oxcf.pass == 0) {
     if (cpi->oxcf.rc_mode == AOM_CBR)
-      q = rc_pick_q_and_bounds_one_pass_cbr(cpi, bottom_index, top_index);
+      q = rc_pick_q_and_bounds_one_pass_cbr(cpi, width, height, bottom_index,
+                                            top_index);
     else
-      q = rc_pick_q_and_bounds_one_pass_vbr(cpi, bottom_index, top_index);
+      q = rc_pick_q_and_bounds_one_pass_vbr(cpi, width, height, bottom_index,
+                                            top_index);
   } else {
-    q = rc_pick_q_and_bounds_two_pass(cpi, bottom_index, top_index);
+    q = rc_pick_q_and_bounds_two_pass(cpi, width, height, bottom_index,
+                                      top_index);
   }
 
   return q;
@@ -1171,7 +1185,8 @@
   }
 }
 
-void av1_rc_set_frame_target(AV1_COMP *cpi, int target) {
+static void rc_set_frame_target(AV1_COMP *cpi, int target, int width,
+                                int height) {
   const AV1_COMMON *const cm = &cpi->common;
   RATE_CONTROL *const rc = &cpi->rc;
 
@@ -1180,11 +1195,11 @@
   // Modify frame size target when down-scaled.
   if (!av1_frame_unscaled(cm))
     rc->this_frame_target =
-        (int)(rc->this_frame_target * av1_resize_rate_factor(cpi));
+        (int)(rc->this_frame_target * resize_rate_factor(cpi, width, height));
 
   // Target rate per SB64 (including partial SB64s.
-  rc->sb64_target_rate = (int)((int64_t)rc->this_frame_target * 64 * 64) /
-                         (cm->width * cm->height);
+  rc->sb64_target_rate =
+      (int)((int64_t)rc->this_frame_target * 64 * 64) / (width * height);
 }
 
 static void update_alt_ref_frame_stats(AV1_COMP *cpi) {
@@ -1258,7 +1273,7 @@
   rc->projected_frame_size = (int)(bytes_used << 3);
 
   // Post encode loop adjustment of Q prediction.
-  av1_rc_update_rate_correction_factors(cpi);
+  av1_rc_update_rate_correction_factors(cpi, cm->width, cm->height);
 
   // Keep a record of last Q and ambient average Q.
   if (cm->frame_type == KEY_FRAME) {
@@ -1305,6 +1320,10 @@
 
   // Rolling monitors of whether we are over or underspending used to help
   // regulate min and Max Q in two pass.
+  if (!av1_frame_unscaled(cm))
+    rc->this_frame_target =
+        (int)(rc->this_frame_target /
+              resize_rate_factor(cpi, cm->width, cm->height));
   if (cm->frame_type != KEY_FRAME) {
     rc->rolling_target_bits = ROUND_POWER_OF_TWO(
         rc->rolling_target_bits * 3 + rc->this_frame_target, 2);
@@ -1349,6 +1368,12 @@
     rc->frames_since_key++;
     rc->frames_to_key--;
   }
+  // if (cm->current_video_frame == 1 && cm->show_frame)
+  /*
+  rc->this_frame_target =
+      (int)(rc->this_frame_target / resize_rate_factor(cpi, cm->width,
+  cm->height));
+      */
 }
 
 void av1_rc_postencode_update_drop_frame(AV1_COMP *cpi) {
@@ -1423,7 +1448,7 @@
     target = calc_iframe_target_size_one_pass_vbr(cpi);
   else
     target = calc_pframe_target_size_one_pass_vbr(cpi);
-  av1_rc_set_frame_target(cpi, target);
+  rc_set_frame_target(cpi, target, cm->width, cm->height);
 }
 
 static int calc_pframe_target_size_one_pass_cbr(const AV1_COMP *cpi) {
@@ -1525,7 +1550,7 @@
   else
     target = calc_pframe_target_size_one_pass_cbr(cpi);
 
-  av1_rc_set_frame_target(cpi, target);
+  rc_set_frame_target(cpi, target, cm->width, cm->height);
   // TODO(afergs): Decide whether to scale up, down, or not at all
 }
 
@@ -1610,11 +1635,11 @@
   }
 }
 
-void av1_rc_update_framerate(AV1_COMP *cpi) {
-  const AV1_COMMON *const cm = &cpi->common;
+void av1_rc_update_framerate(AV1_COMP *cpi, int width, int height) {
   const AV1EncoderConfig *const oxcf = &cpi->oxcf;
   RATE_CONTROL *const rc = &cpi->rc;
   int vbr_max_bits;
+  const int MBs = av1_get_MBs(width, height);
 
   rc->avg_frame_bandwidth = (int)(oxcf->target_bandwidth / cpi->framerate);
   rc->min_frame_bandwidth =
@@ -1634,7 +1659,7 @@
       (int)(((int64_t)rc->avg_frame_bandwidth * oxcf->two_pass_vbrmax_section) /
             100);
   rc->max_frame_bandwidth =
-      AOMMAX(AOMMAX((cm->MBs * MAX_MB_RATE), MAXRATE_1080P), vbr_max_bits);
+      AOMMAX(AOMMAX((MBs * MAX_MB_RATE), MAXRATE_1080P), vbr_max_bits);
 
   av1_rc_set_gf_interval_range(cpi, rc);
 }
@@ -1683,68 +1708,12 @@
   }
 }
 
-void av1_set_target_rate(AV1_COMP *cpi) {
+void av1_set_target_rate(AV1_COMP *cpi, int width, int height) {
   RATE_CONTROL *const rc = &cpi->rc;
   int target_rate = rc->base_frame_target;
 
   // Correction to rate target based on prior over or under shoot.
   if (cpi->oxcf.rc_mode == AOM_VBR || cpi->oxcf.rc_mode == AOM_CQ)
     vbr_rate_correction(cpi, &target_rate);
-  av1_rc_set_frame_target(cpi, target_rate);
+  rc_set_frame_target(cpi, target_rate, width, height);
 }
-
-uint8_t av1_calculate_next_resize_scale(const AV1_COMP *cpi) {
-  static unsigned int seed = 56789;
-  const AV1EncoderConfig *oxcf = &cpi->oxcf;
-  if (oxcf->pass == 1) return SCALE_DENOMINATOR;
-  uint8_t new_num = SCALE_DENOMINATOR;
-
-  switch (oxcf->resize_mode) {
-    case RESIZE_NONE: new_num = SCALE_DENOMINATOR; break;
-    case RESIZE_FIXED:
-      if (cpi->common.frame_type == KEY_FRAME)
-        new_num = oxcf->resize_kf_scale_numerator;
-      else
-        new_num = oxcf->resize_scale_numerator;
-      break;
-    case RESIZE_DYNAMIC:
-      // RESIZE_DYNAMIC: Just random for now.
-      new_num = lcg_rand16(&seed) % 4 + 13;
-      break;
-    default: assert(0);
-  }
-  return new_num;
-}
-
-#if CONFIG_FRAME_SUPERRES
-// TODO(afergs): Rename av1_rc_update_superres_scale(...)?
-uint8_t av1_calculate_next_superres_scale(const AV1_COMP *cpi, int width,
-                                          int height) {
-  static unsigned int seed = 34567;
-  const AV1EncoderConfig *oxcf = &cpi->oxcf;
-  if (oxcf->pass == 1) return SCALE_DENOMINATOR;
-  uint8_t new_num = SCALE_DENOMINATOR;
-
-  switch (oxcf->superres_mode) {
-    case SUPERRES_NONE: new_num = SCALE_DENOMINATOR; break;
-    case SUPERRES_FIXED:
-      if (cpi->common.frame_type == KEY_FRAME)
-        new_num = oxcf->superres_kf_scale_numerator;
-      else
-        new_num = oxcf->superres_scale_numerator;
-      break;
-    case SUPERRES_DYNAMIC:
-      // SUPERRES_DYNAMIC: Just random for now.
-      new_num = lcg_rand16(&seed) % 9 + 8;
-      break;
-    default: assert(0);
-  }
-
-  // Make sure overall reduction is no more than 1/2 of the source size.
-  av1_calculate_scaled_size(&width, &height, new_num);
-  if (width * 2 < oxcf->width || height * 2 < oxcf->height)
-    new_num = SCALE_DENOMINATOR;
-
-  return new_num;
-}
-#endif  // CONFIG_FRAME_SUPERRES
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 4ebdfad..b82d29f 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -50,6 +50,13 @@
 #endif  // CONFIG_EXT_REFS
 
 typedef struct {
+  uint8_t resize_num;
+#if CONFIG_FRAME_SUPERRES
+  uint8_t superres_num;
+#endif  // CONFIG_FRAME_SUPERRES
+} size_params_type;
+
+typedef struct {
   // Rate targetting variables
   int base_frame_target;  // A baseline frame target before adjustment
                           // for previous under or over shoot.
@@ -189,10 +196,6 @@
 void av1_rc_get_one_pass_vbr_params(struct AV1_COMP *cpi);
 void av1_rc_get_one_pass_cbr_params(struct AV1_COMP *cpi);
 
-// How many times less pixels there are to encode given the current scaling.
-// Temporary replacement for rcf_mult and rate_thresh_mult.
-double av1_resize_rate_factor(const struct AV1_COMP *cpi);
-
 // Post encode update of the rate control parameters based
 // on bytes used
 void av1_rc_postencode_update(struct AV1_COMP *cpi, uint64_t bytes_used);
@@ -201,7 +204,8 @@
 
 // Updates rate correction factors
 // Changes only the rate correction factors in the rate control structure.
-void av1_rc_update_rate_correction_factors(struct AV1_COMP *cpi);
+void av1_rc_update_rate_correction_factors(struct AV1_COMP *cpi, int width,
+                                           int height);
 
 // Decide if we should drop this frame: For 1-pass CBR.
 // Changes only the decimation count in the rate control structure
@@ -214,12 +218,13 @@
                                       int *frame_over_shoot_limit);
 
 // Picks q and q bounds given the target for bits
-int av1_rc_pick_q_and_bounds(const struct AV1_COMP *cpi, int *bottom_index,
-                             int *top_index);
+int av1_rc_pick_q_and_bounds(const struct AV1_COMP *cpi, int width, int height,
+                             int *bottom_index, int *top_index);
 
 // Estimates q to achieve a target bits per frame
 int av1_rc_regulate_q(const struct AV1_COMP *cpi, int target_bits_per_frame,
-                      int active_best_quality, int active_worst_quality);
+                      int active_best_quality, int active_worst_quality,
+                      int width, int height);
 
 // Estimates bits per mb for a given qindex and correction factor.
 int av1_rc_bits_per_mb(FRAME_TYPE frame_type, int qindex,
@@ -247,20 +252,15 @@
 
 int av1_frame_type_qdelta(const struct AV1_COMP *cpi, int rf_level, int q);
 
-void av1_rc_update_framerate(struct AV1_COMP *cpi);
+void av1_rc_update_framerate(struct AV1_COMP *cpi, int width, int height);
 
 void av1_rc_set_gf_interval_range(const struct AV1_COMP *const cpi,
                                   RATE_CONTROL *const rc);
 
-void av1_set_target_rate(struct AV1_COMP *cpi);
+void av1_set_target_rate(struct AV1_COMP *cpi, int width, int height);
 
 int av1_resize_one_pass_cbr(struct AV1_COMP *cpi);
 
-uint8_t av1_calculate_next_resize_scale(const struct AV1_COMP *cpi);
-#if CONFIG_FRAME_SUPERRES
-uint8_t av1_calculate_next_superres_scale(const struct AV1_COMP *cpi, int width,
-                                          int height);
-#endif  // CONFIG_FRAME_SUPERRES
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 79e83a5..d31dd32 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -7067,7 +7067,7 @@
     if (tlevel < 5) step_param += 2;
 
     // prev_mv_sad is not setup for dynamically scaled frames.
-    if (cpi->oxcf.resize_mode != RESIZE_DYNAMIC) {
+    if (cpi->oxcf.resize_mode != RESIZE_RANDOM) {
       int i;
       for (i = LAST_FRAME; i <= ALTREF_FRAME && cm->show_frame; ++i) {
         if ((x->pred_mv_sad[ref] >> 3) > x->pred_mv_sad[i]) {