This source file includes following definitions.
- log_dpb_content
- has_free_dpb_picture
- DPB_index_of_picture_with_POC
- DPB_index_of_picture_with_LSB
- DPB_index_of_picture_with_ID
- output_next_picture_in_reorder_buffer
- flush_reorder_buffer
- clear
- new_image
- pop_next_picture_in_output_queue
- log_dpb_queues
#include "dpb.h"
#include "decctx.h"
#include <string.h>
#include <assert.h>
#define DPB_DEFAULT_MAX_IMAGES 30
decoded_picture_buffer::decoded_picture_buffer()
{
max_images_in_DPB = DPB_DEFAULT_MAX_IMAGES;
norm_images_in_DPB = DPB_DEFAULT_MAX_IMAGES;
}
decoded_picture_buffer::~decoded_picture_buffer()
{
for (int i=0;i<dpb.size();i++)
delete dpb[i];
}
void decoded_picture_buffer::log_dpb_content() const
{
for (int i=0;i<dpb.size();i++) {
loginfo(LogHighlevel, " DPB %d: POC=%d, ID=%d %s %s\n", i,
dpb[i]->PicOrderCntVal,
dpb[i]->get_ID(),
dpb[i]->PicState == UnusedForReference ? "unused" :
dpb[i]->PicState == UsedForShortTermReference ? "short-term" : "long-term",
dpb[i]->PicOutputFlag ? "output" : "---");
}
}
bool decoded_picture_buffer::has_free_dpb_picture(bool high_priority) const
{
if (high_priority) return true;
if (dpb.size() < max_images_in_DPB) return true;
for (int i=0;i<dpb.size();i++) {
if (dpb[i]->PicOutputFlag==false && dpb[i]->PicState == UnusedForReference) {
return true;
}
}
return false;
}
int decoded_picture_buffer::DPB_index_of_picture_with_POC(int poc, int currentID, bool preferLongTerm) const
{
logdebug(LogHeaders,"DPB_index_of_picture_with_POC POC=%d\n",poc);
if (preferLongTerm) {
for (int k=0;k<dpb.size();k++) {
if (dpb[k]->PicOrderCntVal == poc &&
dpb[k]->removed_at_picture_id > currentID &&
dpb[k]->PicState == UsedForLongTermReference) {
return k;
}
}
}
for (int k=0;k<dpb.size();k++) {
if (dpb[k]->PicOrderCntVal == poc &&
dpb[k]->removed_at_picture_id > currentID &&
dpb[k]->PicState != UnusedForReference) {
return k;
}
}
return -1;
}
int decoded_picture_buffer::DPB_index_of_picture_with_LSB(int lsb, int currentID, bool preferLongTerm) const
{
logdebug(LogHeaders,"get access to picture with LSB %d from DPB\n",lsb);
if (preferLongTerm) {
for (int k=0;k<dpb.size();k++) {
if (dpb[k]->picture_order_cnt_lsb == lsb &&
dpb[k]->removed_at_picture_id > currentID &&
dpb[k]->PicState == UsedForLongTermReference) {
return k;
}
}
}
for (int k=0;k<dpb.size();k++) {
if (dpb[k]->picture_order_cnt_lsb == lsb &&
dpb[k]->removed_at_picture_id > currentID &&
dpb[k]->PicState != UnusedForReference) {
return k;
}
}
return -1;
}
int decoded_picture_buffer::DPB_index_of_picture_with_ID(int id) const
{
logdebug(LogHeaders,"get access to picture with ID %d from DPB\n",id);
for (int k=0;k<dpb.size();k++) {
if (dpb[k]->get_ID() == id) {
return k;
}
}
return -1;
}
void decoded_picture_buffer::output_next_picture_in_reorder_buffer()
{
assert(!reorder_output_queue.empty());
int minPOC = reorder_output_queue[0]->PicOrderCntVal;
int minIdx = 0;
for (int i=1;i<reorder_output_queue.size();i++)
{
if (reorder_output_queue[i]->PicOrderCntVal < minPOC) {
minPOC = reorder_output_queue[i]->PicOrderCntVal;
minIdx = i;
}
}
image_output_queue.push_back(reorder_output_queue[minIdx]);
reorder_output_queue[minIdx] = reorder_output_queue.back();
reorder_output_queue.pop_back();
}
bool decoded_picture_buffer::flush_reorder_buffer()
{
if (reorder_output_queue.empty()) return false;
while (!reorder_output_queue.empty()) {
output_next_picture_in_reorder_buffer();
}
return true;
}
void decoded_picture_buffer::clear()
{
for (int i=0;i<dpb.size();i++) {
if (dpb[i]->PicOutputFlag ||
dpb[i]->PicState != UnusedForReference)
{
dpb[i]->PicOutputFlag = false;
dpb[i]->PicState = UnusedForReference;
dpb[i]->release();
}
}
reorder_output_queue.clear();
image_output_queue.clear();
}
int decoded_picture_buffer::new_image(std::shared_ptr<const seq_parameter_set> sps,
decoder_context* decctx,
de265_PTS pts, void* user_data, bool isOutputImage)
{
loginfo(LogHeaders,"DPB::new_image\n");
log_dpb_content();
int free_image_buffer_idx = -1;
for (int i=0;i<dpb.size();i++) {
if (dpb[i]->can_be_released()) {
dpb[i]->release();
free_image_buffer_idx = i;
break;
}
}
if (dpb.size() > norm_images_in_DPB &&
free_image_buffer_idx != dpb.size()-1 &&
dpb.back()->can_be_released())
{
delete dpb.back();
dpb.pop_back();
}
if (free_image_buffer_idx == -1) {
free_image_buffer_idx = dpb.size();
dpb.push_back(new de265_image);
}
de265_image* img = dpb[free_image_buffer_idx];
int w = sps->pic_width_in_luma_samples;
int h = sps->pic_height_in_luma_samples;
enum de265_chroma chroma;
switch (sps->chroma_format_idc) {
case 0: chroma = de265_chroma_mono; break;
case 1: chroma = de265_chroma_420; break;
case 2: chroma = de265_chroma_422; break;
case 3: chroma = de265_chroma_444; break;
default: chroma = de265_chroma_420; assert(0); break;
}
img->alloc_image(w,h, chroma, sps, true, decctx, NULL, pts, user_data, isOutputImage);
img->integrity = INTEGRITY_CORRECT;
return free_image_buffer_idx;
}
void decoded_picture_buffer::pop_next_picture_in_output_queue()
{
image_output_queue.pop_front();
loginfo(LogDPB, "DPB output queue: ");
for (int i=0;i<image_output_queue.size();i++) {
loginfo(LogDPB, "*%d ", image_output_queue[i]->PicOrderCntVal);
}
loginfo(LogDPB,"*\n");
}
void decoded_picture_buffer::log_dpb_queues() const
{
loginfo(LogDPB, "DPB reorder queue (after push): ");
for (int i=0;i<num_pictures_in_reorder_buffer();i++) {
loginfo(LogDPB, "*%d ", reorder_output_queue[i]->PicOrderCntVal);
}
loginfo(LogDPB,"*\n");
loginfo(LogDPB, "DPB output queue (after push): ");
for (int i=0;i<num_pictures_in_output_queue();i++) {
loginfo(LogDPB, "*%d ", image_output_queue[i]->PicOrderCntVal);
}
loginfo(LogDPB,"*\n");
}