blob: 71075965127f9662fca4e7d97251f91e180e860e [file] [log] [blame]
/*
* 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.
*/
#include "av1/reference_manager.h"
namespace aom {
void RefFrameManager::Reset() {
free_ref_idx_list_.clear();
for (int i = 0; i < kRefFrameTableSize; ++i) {
free_ref_idx_list_.push_back(i);
}
forward_stack_.clear();
backward_queue_.clear();
last_queue_.clear();
}
int RefFrameManager::AllocateRefIdx() {
if (free_ref_idx_list_.empty()) {
size_t backward_size = backward_queue_.size();
size_t last_size = last_queue_.size();
if (last_size >= backward_size) {
int ref_idx = last_queue_.front();
last_queue_.pop_front();
free_ref_idx_list_.push_back(ref_idx);
} else {
int ref_idx = backward_queue_.front();
backward_queue_.pop_front();
free_ref_idx_list_.push_back(ref_idx);
}
}
int ref_idx = free_ref_idx_list_.front();
free_ref_idx_list_.pop_front();
return ref_idx;
}
void RefFrameManager::UpdateOrder(int order_idx) {
if (forward_stack_.empty()) {
return;
}
int ref_idx = forward_stack_.back();
const GopFrame &gf_frame = ref_frame_table_[ref_idx];
if (gf_frame.order_idx <= order_idx) {
forward_stack_.pop_back();
if (gf_frame.is_golden_frame) {
// high quality frame
backward_queue_.push_back(ref_idx);
} else {
last_queue_.push_back(ref_idx);
}
}
}
int RefFrameManager::ColocatedRefIdx(int order_idx) {
if (forward_stack_.size() == 0) return -1;
int ref_idx = forward_stack_.back();
int arf_order_idx = ref_frame_table_[ref_idx].order_idx;
if (arf_order_idx == order_idx) {
return ref_idx;
}
return -1;
}
void RefFrameManager::UpdateFrame(GopFrame *gop_frame,
RefUpdateType ref_update_type,
EncodeRefMode encode_ref_mode) {
gop_frame->colocated_ref_idx = ColocatedRefIdx(gop_frame->order_idx);
if (gop_frame->is_show_frame) {
UpdateOrder(gop_frame->order_idx);
}
if (ref_update_type == RefUpdateType::kNone) {
gop_frame->update_ref_idx = -1;
} else {
const int ref_idx = AllocateRefIdx();
gop_frame->update_ref_idx = ref_idx;
switch (ref_update_type) {
case RefUpdateType::kForward: forward_stack_.push_back(ref_idx); break;
case RefUpdateType::kBackward: backward_queue_.push_back(ref_idx); break;
case RefUpdateType::kLast: last_queue_.push_back(ref_idx); break;
case RefUpdateType::kNone: break;
}
ref_frame_table_[ref_idx] = *gop_frame;
}
gop_frame->encode_ref_mode = encode_ref_mode;
}
} // namespace aom