📄 mbuffer.cpp
字号:
/*!
***********************************************************************
* \file
* mbuffer.c
*
* \brief
* Frame buffer functions
*
* \author
* Main contributors (see contributors.h for copyright, address and affiliation details)
* - Karsten Suehring <suehring@hhi.de>
* - Alexis Tourapis <alexismt@ieee.org>
***********************************************************************
*/
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <string.h>
#include "global.h"
#include "mbuffer.h"
#include "memalloc.h"
#include "output.h"
#include "image.h"
static void insert_picture_in_dpb(FrameStore* fs, StorablePicture* p);
static void output_one_frame_from_dpb();
static int is_used_for_reference(FrameStore* fs);
static void get_smallest_poc(int *poc,int * pos);
static int remove_unused_frame_from_dpb();
static int is_short_term_reference(FrameStore* fs);
static int is_long_term_reference(FrameStore* fs);
DecodedPictureBuffer dpb;
StorablePicture **listX[2];
extern StorablePicture *dec_picture;
extern int dpb_size;
extern FILE *p_out;
extern seq_parameter_set_rbsp_t *active_sps;
int listXsize[2];
/*!
************************************************************************
* \brief
* Allocate memory for decoded picture buffer an initialize with sane values.
*
* \param inp
* Input Parameters
*
************************************************************************
*/
void init_dpb()
{
unsigned i,j;
dpb.size = dpb_size;
dpb.used_size = 0;
dpb.ref_frames_in_buffer = 0;
dpb.fs =(struct frame_store **) calloc(dpb.size, sizeof (FrameStore*));
if (NULL==dpb.fs)
error ("init_dpb: Could not allocate dpb->fs memory", 100);
dpb.fs_ref =(struct frame_store **) calloc(dpb.size, sizeof (FrameStore*));
if (NULL==dpb.fs_ref)
error ("init_dpb: Could not allocate dpb->fs_ref memory", 100);
dpb.fs_ltref =(struct frame_store **) calloc(dpb.size, sizeof (FrameStore*));
if (NULL==dpb.fs_ltref)
error ("init_dpb: Could not allocate dpb->fs_ltref memory", 100);
for (i=0; i<dpb.size; i++)
{
dpb.fs[i] = alloc_frame_store();
dpb.fs_ref[i] = NULL;
dpb.fs_ltref[i] = NULL;
}
for (i=0; i<2; i++)
{
listX[i] =(struct storable_picture **) calloc(dpb.size * 2 + 1, sizeof (StorablePicture*)); // +1 for reordering
if (NULL==listX[i])
error ("init_dpb: Could not allocate listX[i] memory", 100);
}
for (j=0;j<2;j++)
{
for (i=0; i<(2*dpb.size)+1; i++)
{
listX[j][i] = NULL;
}
listXsize[j]=0;
}
dpb.last_output_poc = INT_MIN;
img->last_has_mmco_5 = 0;
}
/*!
************************************************************************
* \brief
* Free memory for decoded picture buffer.
************************************************************************
*/
void free_dpb()
{
unsigned i;
if (dpb.fs)
{
for (i=0; i<dpb.size; i++)
{
free_frame_store(dpb.fs[i]);
}
free (dpb.fs);
dpb.fs=NULL;
}
if (dpb.fs_ref)
{
free (dpb.fs_ref);
}
if (dpb.fs_ltref)
{
free (dpb.fs_ltref);
}
dpb.last_output_poc = INT_MIN;
for (i=0; i<2; i++)
if (listX[i])
{
free (listX[i]);
listX[i] = NULL;
}
}
/*!
************************************************************************
* \brief
* Allocate memory for decoded picture buffer frame stores an initialize with sane values.
*
* \return
* the allocated FrameStore structure
************************************************************************
*/
FrameStore* alloc_frame_store()
{
FrameStore *f;
f =(struct frame_store *) calloc (1, sizeof(FrameStore));
if (NULL==f)
error ("alloc_frame_store: Could not allocate f memory", 100);
f->is_used = 0;
f->is_reference = 0;
f->is_long_term = 0;
f->is_output = 0;
f->frame = NULL;
return f;
}
/*!
************************************************************************
* \brief
* Allocate memory for a stored picture.
*
* \param structure
* picture structure
* \param size_x
* horizontal luma size
* \param size_y
* vertical luma size
* \param size_x_cr
* horizontal chroma size
* \param size_y_cr
* vertical chroma size
*
* \return
* the allocated StorablePicture structure
************************************************************************
*/
StorablePicture* alloc_storable_picture(/*PictureStructure structure,*/ int size_x, int size_y, int size_x_cr, int size_y_cr)
{
StorablePicture *s;
int sizeX,sizeY;
sizeX = size_x >>2;
sizeY = size_y >>2;
s =(struct storable_picture *) calloc (1, sizeof(StorablePicture));
if (NULL==s)
error ("alloc_storable_picture: Could not allocate s memory", 100);
get_mem2D (&(s->imgY), size_y, size_x);
get_mem3D (&(s->imgUV), 2, size_y_cr, size_x_cr );
get_mem3Dint (&(s->ref_idx), 2, sizeX, sizeY);
get_mem3Dint64 (&(s->ref_pic_id), 2, sizeX, sizeY);
get_mem4Dint (&(s->mv), 2, sizeX, sizeY,2 );
get_mem2D (&(s->moving_block), sizeX, sizeY);
s->pic_num=0;
s->long_term_frame_idx=0;
s->long_term_pic_num=0;
s->used_for_reference=0;
s->is_long_term=0;
s->is_output = 0;
s->size_x = size_x;
s->size_y = size_y;
s->size_x_cr = size_x_cr;
s->size_y_cr = size_y_cr;
s->frame = NULL;
s->mb_adaptive_frame_field_flag = 0;
return s;
}
/*!
************************************************************************
* \brief
* Free frame store memory.
*
* \param f
* FrameStore to be freed
*
************************************************************************
*/
void free_frame_store(FrameStore* f)
{
if (f)
{
free_storable_picture(f->frame);
f->frame=NULL;
free(f);
}
}
/*!
************************************************************************
* \brief
* Free picture memory.
*
* \param p
* Picture to be freed
*
************************************************************************
*/
void free_storable_picture(StorablePicture* p)
{
if (p)
{
free_mem3Dint (p->ref_idx, 2);
free_mem3Dint64 (p->ref_pic_id, 2);
free_mem4Dint (p->mv, 2, p->size_x >>2);
if (p->moving_block)
{
free_mem2D (p->moving_block);
p->moving_block=NULL;
}
if (p->imgY)
{
free_mem2D (p->imgY);
p->imgY=NULL;
}
if (p->imgUV)
{
free_mem3D (p->imgUV, 2);
p->imgUV=NULL;
}
free(p);
}
}
/*!
************************************************************************
* \brief
* mark FrameStore unused for reference
*
************************************************************************
*/
static void unmark_for_reference(FrameStore* fs)
{
fs->frame->used_for_reference = 0;
fs->is_reference = 0;
}
/*!
************************************************************************
* \brief
* mark FrameStore unused for reference and reset long term flags
*
************************************************************************
*/
static void unmark_for_long_term_reference(FrameStore* fs)
{
fs->frame->used_for_reference = 0;
fs->frame->is_long_term = 0;
fs->is_reference = 0;
fs->is_long_term = 0;
}
/*!
************************************************************************
* \brief
* compares two stored pictures by picture number for qsort in descending order
*
************************************************************************
*/
static int compare_pic_by_pic_num_desc( const void *arg1, const void *arg2 )
{
if ( (*(StorablePicture**)arg1)->pic_num < (*(StorablePicture**)arg2)->pic_num)
return 1;
if ( (*(StorablePicture**)arg1)->pic_num > (*(StorablePicture**)arg2)->pic_num)
return -1;
else
return 0;
}
/*!
************************************************************************
* \brief
* compares two stored pictures by picture number for qsort in descending order
*
************************************************************************
*/
static int compare_pic_by_lt_pic_num_asc( const void *arg1, const void *arg2 )
{
if ( (*(StorablePicture**)arg1)->long_term_pic_num < (*(StorablePicture**)arg2)->long_term_pic_num)
return -1;
if ( (*(StorablePicture**)arg1)->long_term_pic_num > (*(StorablePicture**)arg2)->long_term_pic_num)
return 1;
else
return 0;
}
/*!
************************************************************************
* \brief
* Initialize listX[0] and list 1 depending on current picture type
*
************************************************************************
*/
void init_lists(int currSliceType)
{
unsigned i;
int j;
int MaxFrameNum = 1 << (active_sps->log2_max_frame_num_minus4 + 4);
int diff;
int list0idx = 0;
StorablePicture *tmp_s;
for (i=0; i<dpb.ref_frames_in_buffer; i++)
{
if (dpb.fs_ref[i]->is_used==3)
{
if ((dpb.fs_ref[i]->frame->used_for_reference)&&(!dpb.fs_ref[i]->frame->is_long_term))
{
if( dpb.fs_ref[i]->frame_num > img->frame_num )
{
dpb.fs_ref[i]->frame_num_wrap = dpb.fs_ref[i]->frame_num - MaxFrameNum;
}
else
{
dpb.fs_ref[i]->frame_num_wrap = dpb.fs_ref[i]->frame_num;
}
dpb.fs_ref[i]->frame->pic_num = dpb.fs_ref[i]->frame_num_wrap;
dpb.fs_ref[i]->frame->order_num=list0idx;
}
}
}
if (currSliceType == I_SLICE)
{
listXsize[0] = 0;
listXsize[1] = 0;
return;
}
else if (currSliceType == P_SLICE)
{
// Calculate FrameNumWrap and PicNum
for (i=0; i<dpb.ref_frames_in_buffer; i++)
{
if (dpb.fs_ref[i]->is_used==3)
{
if ((dpb.fs_ref[i]->frame->used_for_reference)&&(!dpb.fs_ref[i]->frame->is_long_term))
{
listX[0][list0idx++] = dpb.fs_ref[i]->frame;
}
}
}
// order list 0 by PicNum
qsort((void *)listX[0], list0idx, sizeof(StorablePicture*), compare_pic_by_pic_num_desc);
listXsize[0] = list0idx;
// long term handling
for (i=0; i<dpb.ltref_frames_in_buffer; i++)
{
if (dpb.fs_ltref[i]->is_used==3)
{
// if we have two fields, both must be long-term
dpb.fs_ltref[i]->frame->long_term_pic_num = dpb.fs_ltref[i]->frame->long_term_frame_idx;
dpb.fs_ltref[i]->frame->order_num=list0idx;
listX[0][list0idx++]=dpb.fs_ltref[i]->frame;
}
}
qsort((void *)&listX[0][listXsize[0]], list0idx-listXsize[0], sizeof(StorablePicture*), compare_pic_by_lt_pic_num_asc);
listXsize[0] = list0idx;
listXsize[1] = 0;
}
if ((listXsize[0] == listXsize[1]) && (listXsize[0] > 1))
{
// check if lists are identical, if yes swap first two elements of listX[1]
diff=0;
for (j = 0; j< listXsize[0]; j++)
{
if (listX[0][j]!=listX[1][j])
diff=1;
}
if (!diff)
{
tmp_s = listX[1][0];
listX[1][0]=listX[1][1];
listX[1][1]=tmp_s;
}
}
// set max size
listXsize[0] = min (listXsize[0], img->num_ref_idx_l0_active);
// set the unused list entries to NULL
for (i=listXsize[0]; i< (2*dpb.size) ; i++)
{
listX[0][i] = NULL;
}
}
/*!
************************************************************************
* \brief
* Returns short term pic with given picNum
*
************************************************************************
*/
static StorablePicture* get_short_term_pic(int picNum)
{
unsigned i;
for (i=0; i<dpb.ref_frames_in_buffer; i++)
{
if (dpb.fs_ref[i]->is_reference == 3)
if ((!dpb.fs_ref[i]->frame->is_long_term)&&(dpb.fs_ref[i]->frame->pic_num == picNum))
return dpb.fs_ref[i]->frame;
}
return NULL;
}
/*!
************************************************************************
* \brief
* Returns short term pic with given LongtermPicNum
*
************************************************************************
*/
static StorablePicture* get_long_term_pic(int LongtermPicNum)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -