Add a special ref frame scheduling for max 3 frames

Handle the special case where one can only use up to 3 reference
frames per coding frame.

BUG=b/240412144

Change-Id: I4d389b40a934df75d72d372973cee336fd99eb3e
diff --git a/av1/reference_manager.cc b/av1/reference_manager.cc
index 2a7fd7b..032a0b8 100644
--- a/av1/reference_manager.cc
+++ b/av1/reference_manager.cc
@@ -80,11 +80,18 @@
                                               int priority_idx) const {
   if (ref_update_type == RefUpdateType::kForward) {
     int size = static_cast<int>(forward_stack_.size());
+    // When two or more forward reference frames can be used, first get
+    // the highest quality one as the ARF, then going from nearest to
+    // the more distant ones in the forward reference frame list.
     if (priority_idx < size) {
-      if (priority_idx == 0)
-        return forward_stack_[priority_idx];
-      else
+      if (allow_two_fwd_frames_) {
+        if (priority_idx == 0) return forward_stack_[0];
         return forward_stack_[size - priority_idx];
+      }
+
+      // Handle the special case where only one forward reference frame
+      // can be used. In this setting, we prefer the nearest frame.
+      return forward_stack_[size - 1 - priority_idx];
     }
   } else if (ref_update_type == RefUpdateType::kBackward) {
     int size = static_cast<int>(backward_queue_.size());
@@ -178,6 +185,7 @@
   std::vector<ReferenceFrame> ref_frame_list;
   int ref_frame_count = 0;
   int round_robin_idx = 0;
+
   std::set<ReferenceName> used_name_set;
   while (ref_frame_count < available_ref_frames &&
          ref_frame_count < max_ref_frames_) {
@@ -299,6 +307,9 @@
 }
 
 void RefFrameManager::UpdateRefFrameTable(GopFrame *gop_frame) {
+  allow_two_fwd_frames_ =
+      (max_ref_frames_ - !!GetRefFrameCountByType(RefUpdateType::kBackward) -
+       !!GetRefFrameCountByType(RefUpdateType::kLast)) >= 2;
   gop_frame->ref_frame_list = GetRefFrameListByPriority();
   gop_frame->primary_ref_frame = GetPrimaryRefFrame(*gop_frame);
   gop_frame->colocated_ref_idx = ColocatedRefIdx(gop_frame->global_order_idx);
diff --git a/av1/reference_manager.h b/av1/reference_manager.h
index 2ddae3a..c2098ec 100644
--- a/av1/reference_manager.h
+++ b/av1/reference_manager.h
@@ -82,6 +82,7 @@
   int cur_global_order_idx_;
   RefFrameTable ref_frame_table_;
   int max_ref_frames_;
+  bool allow_two_fwd_frames_;
   std::deque<int> free_ref_idx_list_;
   std::vector<int> forward_stack_;
   std::deque<int> backward_queue_;