Allow super-res for altref.

Also, make a variety of changes in qthresh and auto modes.

Change-Id: I455d3490ba0ce94a3d74da2cb8acdfc43e2ffa20
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 263a2ce..51a999c 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -1593,6 +1593,7 @@
   const AV1_COMMON *const cm = &cpi->common;
   MACROBLOCK *const x = &td->mb;
   MACROBLOCKD *const xd = &x->e_mbd;
+  assert(bsize < BLOCK_SIZES_ALL);
   const int hbs = mi_size_wide[bsize] / 2;
   const int is_partition_root = bsize >= BLOCK_8X8;
   const int ctx = is_partition_root
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 271946f..20367c0 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -3714,10 +3714,13 @@
 }
 
 static void init_motion_estimation(AV1_COMP *cpi) {
+  AV1_COMMON *const cm = &cpi->common;
   const int y_stride = cpi->scaled_source.y_stride;
-  const int y_stride_src = (cpi->oxcf.resize_mode || cpi->oxcf.superres_mode)
-                               ? y_stride
-                               : cpi->lookahead->buf->img.y_stride;
+  const int y_stride_src =
+      ((cpi->oxcf.width != cm->width || cpi->oxcf.height != cm->height) ||
+       av1_superres_scaled(cm))
+          ? y_stride
+          : cpi->lookahead->buf->img.y_stride;
   // Update if ss_cfg is uninitialized or the current frame has a new stride
   const int should_update = !cpi->ss_cfg[SS_CFG_SRC].stride ||
                             !cpi->ss_cfg[SS_CFG_LOOKAHEAD].stride ||
@@ -3920,8 +3923,27 @@
   return new_denom;
 }
 
-#define ENERGY_BY_Q2_THRESH 0.01
-#define ENERGY_BY_AC_THRESH 0.2
+#define SUPERRES_ENERGY_BY_Q2_THRESH_KEYFRAME_SOLO 0.012
+#define SUPERRES_ENERGY_BY_Q2_THRESH_KEYFRAME 0.01
+#define SUPERRES_ENERGY_BY_Q2_THRESH_ARFFRAME 0.01
+#define SUPERRES_ENERGY_BY_AC_THRESH 0.2
+
+static double get_energy_by_q2_thresh(const GF_GROUP *gf_group,
+                                      const RATE_CONTROL *rc) {
+  // TODO(now): Return keyframe thresh * factor based on frame type / pyramid
+  // level.
+  if (gf_group->update_type[gf_group->index] == ARF_UPDATE) {
+    return SUPERRES_ENERGY_BY_Q2_THRESH_ARFFRAME;
+  } else if (gf_group->update_type[gf_group->index] == KF_UPDATE) {
+    if (rc->frames_to_key <= 1)
+      return SUPERRES_ENERGY_BY_Q2_THRESH_KEYFRAME_SOLO;
+    else
+      return SUPERRES_ENERGY_BY_Q2_THRESH_KEYFRAME;
+  } else {
+    assert(0);
+  }
+  return 0;
+}
 
 static uint8_t get_superres_denom_from_qindex_energy(int qindex, double *energy,
                                                      double threshq,
@@ -3937,16 +3959,34 @@
   return 3 * SCALE_NUMERATOR - k;
 }
 
-static uint8_t get_superres_denom_for_qindex(const AV1_COMP *cpi, int qindex) {
+static uint8_t get_superres_denom_for_qindex(const AV1_COMP *cpi, int qindex,
+                                             int sr_kf, int sr_arf) {
+  // Use superres for Key-frames and Alt-ref frames only.
+  const GF_GROUP *gf_group = &cpi->gf_group;
+  if (gf_group->update_type[gf_group->index] != KF_UPDATE &&
+      gf_group->update_type[gf_group->index] != ARF_UPDATE) {
+    return SCALE_NUMERATOR;
+  }
+  if (gf_group->update_type[gf_group->index] == KF_UPDATE && !sr_kf) {
+    return SCALE_NUMERATOR;
+  }
+  if (gf_group->update_type[gf_group->index] == ARF_UPDATE && !sr_arf) {
+    return SCALE_NUMERATOR;
+  }
+
   double energy[16];
   analyze_hor_freq(cpi, energy);
+
+  const double energy_by_q2_thresh =
+      get_energy_by_q2_thresh(gf_group, &cpi->rc);
   /*
   printf("\nenergy = [");
   for (int k = 1; k < 16; ++k) printf("%f, ", energy[k]);
   printf("]\n");
   */
-  return get_superres_denom_from_qindex_energy(
-      qindex, energy, ENERGY_BY_Q2_THRESH, ENERGY_BY_AC_THRESH);
+  const int denom = get_superres_denom_from_qindex_energy(
+      qindex, energy, energy_by_q2_thresh, SUPERRES_ENERGY_BY_AC_THRESH);
+  return denom;
 }
 
 static uint8_t calculate_next_superres_scale(AV1_COMP *cpi) {
@@ -3977,6 +4017,8 @@
       if (cpi->common.allow_screen_content_tools) break;
       if (oxcf->rc_mode == AOM_VBR || oxcf->rc_mode == AOM_CQ)
         av1_set_target_rate(cpi, cpi->oxcf.width, cpi->oxcf.height);
+
+      // Now decide the use of superres based on 'q'.
       int bottom_index, top_index;
       const int q = av1_rc_pick_q_and_bounds(
           cpi, cpi->oxcf.width, cpi->oxcf.height, &bottom_index, &top_index);
@@ -3987,18 +4029,15 @@
       if (q <= qthresh) {
         new_denom = SCALE_NUMERATOR;
       } else {
-        new_denom = get_superres_denom_for_qindex(cpi, q);
+        new_denom = get_superres_denom_for_qindex(cpi, q, 1, 1);
       }
       break;
     }
     case SUPERRES_AUTO: {
-      // Don't use when screen content tools are used.
+      // Do not use superres when screen content tools are used.
       if (cpi->common.allow_screen_content_tools) break;
-      // Don't use for inter frames.
-      if (!frame_is_intra_only(&cpi->common)) break;
-      // Don't use for keyframes that can be used as references, except when
-      // using AOM_Q mode.
-      if (cpi->rc.frames_to_key != 1 && cpi->oxcf.rc_mode != AOM_Q) break;
+      if (oxcf->rc_mode == AOM_VBR || oxcf->rc_mode == AOM_CQ)
+        av1_set_target_rate(cpi, cpi->oxcf.width, cpi->oxcf.height);
 
       // Now decide the use of superres based on 'q'.
       int bottom_index, top_index;
@@ -4009,7 +4048,7 @@
       if (q <= qthresh) {
         new_denom = SCALE_NUMERATOR;
       } else {
-        new_denom = get_superres_denom_for_qindex(cpi, q);
+        new_denom = get_superres_denom_for_qindex(cpi, q, 1, 1);
       }
       break;
     }
@@ -4089,7 +4128,7 @@
 static size_params_type calculate_next_size_params(AV1_COMP *cpi) {
   const AV1EncoderConfig *oxcf = &cpi->oxcf;
   size_params_type rsz = { oxcf->width, oxcf->height, SCALE_NUMERATOR };
-  int resize_denom;
+  int resize_denom = SCALE_NUMERATOR;
   if (oxcf->pass == 1) return rsz;
   if (cpi->resize_pending_width && cpi->resize_pending_height) {
     rsz.resize_width = cpi->resize_pending_width;
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 55c5c62..77f223f 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -44,6 +44,10 @@
 #define MIN_BPB_FACTOR 0.005
 #define MAX_BPB_FACTOR 50
 
+#define SUPERRES_QADJ_PER_DENOM_KEYFRAME_SOLO 0
+#define SUPERRES_QADJ_PER_DENOM_KEYFRAME 2
+#define SUPERRES_QADJ_PER_DENOM_ARFFRAME 2
+
 #define FRAME_OVERHEAD_BITS 200
 #define ASSIGN_MINQ_TABLE(bit_depth, name)                   \
   do {                                                       \
@@ -816,11 +820,19 @@
   if (oxcf->rc_mode == AOM_CQ || oxcf->rc_mode == AOM_Q) {
     // printf("Superres %d %d %d = %d\n", superres_denom, intra_only,
     //        rc->frames_to_key, !(intra_only && rc->frames_to_key <= 1));
-    if (oxcf->superres_mode == SUPERRES_QTHRESH &&
-        superres_denom != SCALE_NUMERATOR &&
-        !(intra_only && rc->frames_to_key <= 1)) {
-      active_cq_level =
-          AOMMAX(active_cq_level - ((superres_denom - SCALE_NUMERATOR) * 4), 0);
+    if ((oxcf->superres_mode == SUPERRES_QTHRESH ||
+         oxcf->superres_mode == SUPERRES_AUTO) &&
+        superres_denom != SCALE_NUMERATOR) {
+      int mult = SUPERRES_QADJ_PER_DENOM_KEYFRAME_SOLO;
+      if (intra_only && rc->frames_to_key <= 1) {
+        mult = 0;
+      } else if (intra_only) {
+        mult = SUPERRES_QADJ_PER_DENOM_KEYFRAME;
+      } else {
+        mult = SUPERRES_QADJ_PER_DENOM_ARFFRAME;
+      }
+      active_cq_level = AOMMAX(
+          active_cq_level - ((superres_denom - SCALE_NUMERATOR) * mult), 0);
     }
   }
   if (oxcf->rc_mode == AOM_CQ && rc->total_target_bits > 0) {
@@ -1109,7 +1121,8 @@
         cm->superres_scale_denominator != SCALE_NUMERATOR) {
       active_best_quality =
           AOMMAX(active_best_quality -
-                     ((cm->superres_scale_denominator - SCALE_NUMERATOR) * 4),
+                     ((cm->superres_scale_denominator - SCALE_NUMERATOR) *
+                      SUPERRES_QADJ_PER_DENOM_KEYFRAME),
                  0);
     }
   }
@@ -1256,6 +1269,17 @@
 
         active_best_quality = min_boost - (int)(boost * rc->arf_boost_factor);
         *arf_q = active_best_quality;
+        // Tweak active_best_quality for AOM_Q mode when superres is on, as this
+        // will be used directly as 'q' later.
+        if ((oxcf->superres_mode == SUPERRES_QTHRESH ||
+             oxcf->superres_mode == SUPERRES_AUTO) &&
+            cm->superres_scale_denominator != SCALE_NUMERATOR) {
+          active_best_quality =
+              AOMMAX(active_best_quality -
+                         ((cm->superres_scale_denominator - SCALE_NUMERATOR) *
+                          SUPERRES_QADJ_PER_DENOM_ARFFRAME),
+                     0);
+        }
       } else {
         assert(rc->arf_q >= 0);  // Ensure it is set to a valid value.
         assert(is_intrl_arf_boost);