Apply multi-level boost on VBR and AOM_CQ mode

Reduce the bits by half for the frames in the
bottom level of the pyramid struture, and increase the
bits allocated for the other frames according to their
levels.

This bit allocation strategy generally improve for
psnr but have less improvement on ssim.

Experiments are on-going to determine a better strategy
for assigning bit boost.

Results (vbr mode, speed 1):
          30 frames     60 frames
	ovr_psnr/ssim  ovr_psnr/ssim
lowres  -0.295/-0.059  -1.120/-0.646
midres  -0.601/-0.197  -0.698/-0.491

STATS_CHANGED

Change-Id: Iaa22bc70d8db149b8a72c428368c3a739c0b4346
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index dc6e481..3b90a5c 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -2198,20 +2198,27 @@
       // BIPRED_UPDATE frames need to be further adjusted.
       gf_group->bit_allocation[frame_index] = target_frame_size;
 #if USE_SYMM_MULTI_LAYER
-    } else if (cpi->new_bwdref_update_rule == 1 &&
+    } else if (cpi->new_bwdref_update_rule &&
                gf_group->update_type[frame_index] == INTNL_OVERLAY_UPDATE) {
       int arf_pos = gf_group->arf_pos_in_gf[frame_index];
       gf_group->bit_allocation[frame_index] = 0;
 
-      // Tried boosting up the allocated bits on backward reference frame
-      // by (target_frame_size >> 2) as in the original setting. However it
-      // does not bring gains for pyramid structure with GF length = 16.
       gf_group->bit_allocation[arf_pos] = target_frame_size;
-#endif
+#if MULTI_LVL_BOOST_VBR_CQ
+      if (gf_group->pyramid_level[arf_pos] == (gf_group->pyramid_height - 1))
+        gf_group->bit_allocation[arf_pos] += target_frame_size;
+      else
+        gf_group->bit_allocation[arf_pos] += (target_frame_size >> 1);
+#endif  // MULTI_LVL_BOOST_VBR_CQ
+#endif  // USE_SYMM_MULTI_LAYER
     } else {
       assert(gf_group->update_type[frame_index] == LF_UPDATE ||
              gf_group->update_type[frame_index] == INTNL_OVERLAY_UPDATE);
       gf_group->bit_allocation[frame_index] = target_frame_size;
+#if MULTI_LVL_BOOST_VBR_CQ
+      if (cpi->new_bwdref_update_rule)
+        gf_group->bit_allocation[frame_index] -= (target_frame_size >> 1);
+#endif
     }
 
     ++frame_index;
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 842d611..049598a 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -1011,12 +1011,33 @@
     // For constrained quality dont allow Q less than the cq level
     if (oxcf->rc_mode == AOM_CQ) {
       if (q < cq_level) q = cq_level;
+#if USE_SYMM_MULTI_LAYER && MULTI_LVL_BOOST_VBR_CQ
+      if (gf_group->update_type[gf_group->index] == ARF_UPDATE ||
+          (is_intrl_arf_boost && !cpi->new_bwdref_update_rule)) {
+#endif  // USE_SYMM_MULTI_LAYER && MULTI_LVL_BOOST_VBR_CQ
+        active_best_quality = get_gf_active_quality(rc, q, bit_depth);
 
-      active_best_quality = get_gf_active_quality(rc, q, bit_depth);
+        // Constrained quality use slightly lower active best.
+        active_best_quality = active_best_quality * 15 / 16;
+#if REDUCE_LAST_ALT_BOOST
+        if (gf_group->update_type[gf_group->index] == ARF_UPDATE) {
+          const int min_boost = get_gf_high_motion_quality(q, bit_depth);
+          const int boost = min_boost - active_best_quality;
 
-      // Constrained quality use slightly lower active best.
-      active_best_quality = active_best_quality * 15 / 16;
-
+          active_best_quality = min_boost - (int)(boost * rc->arf_boost_factor);
+        }
+#endif
+        *arf_q = active_best_quality;
+#if USE_SYMM_MULTI_LAYER && MULTI_LVL_BOOST_VBR_CQ
+      } else {
+        active_best_quality = rc->arf_q;
+        int this_height = gf_group->pyramid_level[gf_group->index];
+        while (this_height < gf_group->pyramid_height) {
+          active_best_quality = (active_best_quality + cq_level + 1) / 2;
+          ++this_height;
+        }
+      }
+#endif  // USE_SYMM_MULTI_LAYER && MULTI_LVL_BOOST_VBR_CQ
     } else if (oxcf->rc_mode == AOM_Q) {
       if (!cpi->refresh_alt_ref_frame && !is_intrl_arf_boost) {
         active_best_quality = cq_level;
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index 22e85f4..8e8ae2e 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -25,6 +25,7 @@
 #define BPER_MB_NORMBITS 9
 
 #define CUSTOMIZED_GF 1
+#define MULTI_LVL_BOOST_VBR_CQ 1
 
 #if CONFIG_FIX_GF_LENGTH
 #define FIXED_GF_LENGTH 16