Qmode rc: make last frame always the nearest backward frame

This provides good gains:

hd2 (%):
avgpsnr ovrpsnr	ssim	vmaf
-2.246	-2.237	-2.188	-2.302

qmode (%):
avgpsnr ovrpsnr	ssim	vmaf
-3.887	-3.286	-4.073	-3.727

Change-Id: Ib95274f6b4c5bcd41980289634cae835b4481d4e
diff --git a/av1/qmode_rc/reference_manager.cc b/av1/qmode_rc/reference_manager.cc
index eea7b7d..eefd188 100644
--- a/av1/qmode_rc/reference_manager.cc
+++ b/av1/qmode_rc/reference_manager.cc
@@ -209,20 +209,30 @@
 
 void RefFrameManager::UpdateOrder(int global_order_idx) {
   cur_global_order_idx_ = global_order_idx;
-  if (forward_stack_.empty()) {
-    return;
-  }
-  int ref_idx = forward_stack_.back();
-  const GopFrame &gf_frame = ref_frame_table_[ref_idx];
 
-  // If the current processing frame is an overlay / show existing frame.
-  if (gf_frame.global_order_idx == global_order_idx) {
-    forward_stack_.pop_back();
-    if (gf_frame.is_golden_frame) {
-      // high quality frame
-      backward_queue_.push_back(ref_idx);
-    } else {
+  if (!forward_stack_.empty()) {
+    int ref_idx = forward_stack_.back();
+    const GopFrame &gf_frame = ref_frame_table_[ref_idx];
+    // If the current processing frame is an overlay / show existing frame, move
+    // the corresponding arf or intermediate arf frame from forward_stack_ to
+    // last_queue_. In this way this arf will be the last frame for the next
+    // frame.
+    if (gf_frame.global_order_idx == global_order_idx) {
+      forward_stack_.pop_back();
       last_queue_.push_back(ref_idx);
+      return;
+    }
+  }
+
+  if (!last_queue_.empty()) {
+    int this_ref_idx = last_queue_.back();
+    GopFrame &this_gf_frame = ref_frame_table_[this_ref_idx];
+    // If the last (stack top) of last_queue_ is an arf frame, then move it to
+    // the backward_queue_ so it will become the golden frame of future leaf
+    // frames.
+    if (this_gf_frame.is_arf_frame) {
+      last_queue_.pop_back();
+      backward_queue_.push_back(this_ref_idx);
     }
   }
 }
diff --git a/test/ratectrl_qmode_test.cc b/test/ratectrl_qmode_test.cc
index 760ae70..39ce2be 100644
--- a/test/ratectrl_qmode_test.cc
+++ b/test/ratectrl_qmode_test.cc
@@ -680,8 +680,8 @@
   // After the first kShowExisting, the kIntermediateArf should be moved from
   // kForward to kLast due to the cur_global_order_idx_ update
   EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kForward), 1);
-  EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kBackward), 2);
-  EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kLast), 1);
+  EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kBackward), 1);
+  EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kLast), 2);
 
   const int second_leaf_idx = 5;
   EXPECT_EQ(type_list[second_leaf_idx], GopFrameType::kRegularLeaf);
@@ -710,10 +710,10 @@
   EXPECT_EQ(ref_manager.GetRefFrameCount(), 5);
   EXPECT_EQ(ref_manager.CurGlobalOrderIdx(), 4);
   // After the kOverlay, the kRegularArf should be moved from
-  // kForward to kBackward due to the cur_global_order_idx_ update
+  // kForward to kLast due to the cur_global_order_idx_ update
   EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kForward), 0);
-  EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kBackward), 3);
-  EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kLast), 2);
+  EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kBackward), 2);
+  EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kLast), 3);
 }
 
 void TestRefFrameManagerPriority(const RefFrameManager &ref_manager,
@@ -772,9 +772,9 @@
     ref_manager.UpdateRefFrameTable(&gop_frame);
   }
 
-  EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kBackward), 3);
+  EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kBackward), 2);
   TestRefFrameManagerPriority(ref_manager, RefUpdateType::kBackward);
-  EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kLast), 2);
+  EXPECT_EQ(ref_manager.GetRefFrameCountByType(RefUpdateType::kLast), 3);
   TestRefFrameManagerPriority(ref_manager, RefUpdateType::kLast);
 }