| /* | 
 |  * Copyright (c) 2022, Alliance for Open Media. All rights reserved | 
 |  * | 
 |  * This source code is subject to the terms of the BSD 2 Clause License and | 
 |  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License | 
 |  * was not distributed with this source code in the LICENSE file, you can | 
 |  * obtain it at www.aomedia.org/license/software. If the Alliance for Open | 
 |  * Media Patent License 1.0 was not distributed with this source code in the | 
 |  * PATENTS file, you can obtain it at www.aomedia.org/license/patent. | 
 |  */ | 
 |  | 
 | #ifndef AOM_AV1_QMODE_RC_REFERENCE_MANAGER_H_ | 
 | #define AOM_AV1_QMODE_RC_REFERENCE_MANAGER_H_ | 
 |  | 
 | #include <deque> | 
 | #include <iostream> | 
 | #include <vector> | 
 |  | 
 | #include "av1/qmode_rc/ratectrl_qmode_interface.h" | 
 |  | 
 | namespace aom { | 
 |  | 
 | enum class RefUpdateType { kForward, kBackward, kLast, kNone }; | 
 |  | 
 | class RefFrameManager { | 
 |  public: | 
 |   explicit RefFrameManager(int ref_frame_table_size, int max_ref_frames) | 
 |       : ref_frame_table_(ref_frame_table_size), | 
 |         max_ref_frames_(max_ref_frames) { | 
 |     // forward_max_size_ define max number of arf frames that can exists at | 
 |     // the same time. In the other words, it's the max size of forward_stack_. | 
 |     // TODO(angiebird): Figure out if this number is optimal. | 
 |     forward_max_size_ = ref_frame_table_size - 2; | 
 |     cur_global_order_idx_ = 0; | 
 |     Reset(); | 
 |   } | 
 |   ~RefFrameManager() = default; | 
 |  | 
 |   RefFrameManager(const RefFrameManager &) = delete; | 
 |   RefFrameManager &operator=(const RefFrameManager &) = delete; | 
 |  | 
 |   friend std::ostream &operator<<(std::ostream &os, | 
 |                                   const RefFrameManager &rfm) { | 
 |     os << "=" << std::endl; | 
 |     os << "forward: "; | 
 |     for (const auto &ref_idx : rfm.forward_stack_) { | 
 |       os << rfm.ref_frame_table_[ref_idx].order_idx << " "; | 
 |     } | 
 |     os << std::endl; | 
 |     os << "backward: "; | 
 |     for (const auto &ref_idx : rfm.backward_queue_) { | 
 |       os << rfm.ref_frame_table_[ref_idx].order_idx << " "; | 
 |     } | 
 |     os << std::endl; | 
 |     os << "last: "; | 
 |     for (const auto &ref_idx : rfm.last_queue_) { | 
 |       os << rfm.ref_frame_table_[ref_idx].order_idx << " "; | 
 |     } | 
 |     os << std::endl; | 
 |     return os; | 
 |   } | 
 |  | 
 |   void Reset(); | 
 |   int AllocateRefIdx(); | 
 |   int GetRefFrameCountByType(RefUpdateType ref_update_type) const; | 
 |   int GetRefFrameCount() const; | 
 |   std::vector<ReferenceFrame> GetRefFrameListByPriority() const; | 
 |   int GetRefFrameIdxByPriority(RefUpdateType ref_update_type, | 
 |                                int priority_idx) const; | 
 |   GopFrame GetRefFrameByPriority(RefUpdateType ref_update_type, | 
 |                                  int priority_idx) const; | 
 |   GopFrame GetRefFrameByIndex(int ref_idx) const; | 
 |   void UpdateOrder(int global_order_idx); | 
 |   int ColocatedRefIdx(int global_order_idx); | 
 |   int ForwardMaxSize() const { return forward_max_size_; } | 
 |   int MaxRefFrame() const { return max_ref_frames_; } | 
 |   int CurGlobalOrderIdx() const { return cur_global_order_idx_; } | 
 |   void UpdateRefFrameTable(GopFrame *gop_frame); | 
 |   ReferenceFrame GetPrimaryRefFrame(const GopFrame &gop_frame) const; | 
 |  | 
 |  private: | 
 |   int forward_max_size_; | 
 |   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_; | 
 |   std::deque<int> last_queue_; | 
 | }; | 
 |  | 
 | }  // namespace aom | 
 |  | 
 | #endif  // AOM_AV1_QMODE_RC_REFERENCE_MANAGER_H_ |