Misc. adjustment of boost and gf length

This patch mostly improve the coding performance for small
keyframe interval by reducing boost on the last ARF and also
trying to balance the lengths of last two gf groups.

The boost reduction on the last GF group is now set as constant.
Experiments on finding the optimal boost reduction factor for
different GF lengths are working in progress.

BDRATE Results (overall psnr):
		    lowres	midres
keyframe interval
	30	    -0.447      -0.722
	40          -0.530      -0.669
	60	    -0.081      -0.253
	------------------------------
	19	    -1.294      -1.141
	21	    -0.725      -0.730
	23          -0.784      -1.067
	25          -1.650	-1.472
	27     	    -0.501	-0.765
	29	    -0.397	-0.629

AWCY: -0.20 gain on PSNR

STATS_CHANGED

Change-Id: I9fc4fadab547b98164d765b556ebea01fbf4fea8
diff --git a/av1/encoder/firstpass.c b/av1/encoder/firstpass.c
index 8ee72e3..225204a 100644
--- a/av1/encoder/firstpass.c
+++ b/av1/encoder/firstpass.c
@@ -2455,21 +2455,36 @@
   assert(num_mbs > 0);
   if (i) avg_sr_coded_error /= i;
 
-#define REDUCE_GF_LENGTH_THRESH 10
+#define REDUCE_GF_LENGTH_THRESH 4
 #define REDUCE_GF_LENGTH_TO_KEY_THRESH 9
 #define REDUCE_GF_LENGTH_BY 1
   int alt_offset = 0;
 #if REDUCE_LAST_GF_LENGTH
-  // We are going to have an alt ref.
+  // We are going to have an alt ref, but we don't have do adjustment for
+  // lossless mode
   if (allow_alt_ref && (i < cpi->oxcf.lag_in_frames) &&
-      (i >= rc->min_gf_interval)) {
-    // If the last gf is too long, then we have to reduce
-    // the current gf length
-    if (rc->frames_to_key - i < REDUCE_GF_LENGTH_TO_KEY_THRESH &&
-        i > REDUCE_GF_LENGTH_THRESH) {
-      // too long, reduce the length by one
-      alt_offset = -REDUCE_GF_LENGTH_BY;
-      i -= REDUCE_GF_LENGTH_BY;
+      (i >= rc->min_gf_interval) && !is_lossless_requested(&cpi->oxcf)) {
+    // adjust length of this gf group if one of the following condition met
+    // 1: only one overlay frame left and this gf is too long
+    // 2: next gf group is too short to have arf compared to the current gf
+
+    // maximum length of next gf group
+    const int next_gf_len = rc->frames_to_key - i;
+    const int single_overlay_left =
+        next_gf_len == 0 && i > REDUCE_GF_LENGTH_THRESH;
+    // the next gf is probably going to have a ARF but it will be shorter than
+    // this gf
+    const int unbalanced_gf =
+        i > REDUCE_GF_LENGTH_TO_KEY_THRESH &&
+        next_gf_len + 1 < REDUCE_GF_LENGTH_TO_KEY_THRESH &&
+        next_gf_len + 1 >= rc->min_gf_interval;
+
+    if (single_overlay_left || unbalanced_gf) {
+      // Note: Tried roll_back = DIVIDE_AND_ROUND(i, 8), but is does not work
+      // better in the current setting
+      const int roll_back = REDUCE_GF_LENGTH_BY;
+      alt_offset = -roll_back;
+      i -= roll_back;
     }
   }
 #endif
@@ -2501,13 +2516,13 @@
   }
 
 #if REDUCE_LAST_ALT_BOOST
+#define LAST_ALR_BOOST_FACTOR 0.2f
   rc->arf_boost_factor = 1.0;
-  if (rc->source_alt_ref_pending) {
-    // If the last gf is too long, then we have to reduce
-    // the boost factor on current alt ref
-    if (rc->frames_to_key - i == REDUCE_GF_LENGTH_BY &&
-        i > REDUCE_GF_LENGTH_THRESH) {
-      rc->arf_boost_factor = 0;
+  if (rc->source_alt_ref_pending && !is_lossless_requested(&cpi->oxcf)) {
+    // Reduce the boost of altref in the last gf group
+    if (rc->frames_to_key - i == REDUCE_GF_LENGTH_BY ||
+        rc->frames_to_key - i == 0) {
+      rc->arf_boost_factor = LAST_ALR_BOOST_FACTOR;
     }
   }
 #endif
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index 6eb6741..8237459 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -1025,10 +1025,8 @@
           active_best_quality = get_gf_active_quality(rc, q, bit_depth);
           *arf_q = active_best_quality;
 #if REDUCE_LAST_ALT_BOOST
-          int min_boost = (get_gf_high_motion_quality(q, bit_depth) +
-                           3 * active_best_quality) /
-                          4;
-          int boost = min_boost - active_best_quality;
+          const int min_boost = get_gf_high_motion_quality(q, bit_depth);
+          const int boost = min_boost - active_best_quality;
 
           active_best_quality = min_boost - (int)(boost * rc->arf_boost_factor);
 #endif