📄 mbuffer.c
字号:
/*!
***********************************************************************
* \file
* mbuffer.c
*
* \brief
* Frame buffer functions
*
* \author
* Main contributors (see contributors.h for copyright, address and affiliation details)
* - Karsten S黨ring <suehring@hhi.de>
* - Alexis Tourapis <alexismt@ieee.org>
* - Jill Boyce <jill.boyce@thomson.net>
* - Saurav K Bandyopadhyay <saurav@ieee.org>
* - Zhenyu Wu <Zhenyu.Wu@thomson.net
* - Purvin Pandit <Purvin.Pandit@thomson.net>
*
***********************************************************************
*/
#include <limits.h>
#include "global.h"
#include "mbuffer.h"
#include "memalloc.h"
#include "output.h"
#include "image.h"
#include "header.h"
// picture error concealment
#include "erc_api.h"
static void insert_picture_in_dpb(FrameStore* fs, StorablePicture* p);
static void output_one_frame_from_dpb(void);
static int is_used_for_reference(FrameStore* fs);
static void get_smallest_poc(int *poc,int * pos);
static int remove_unused_frame_from_dpb(void);
static int is_short_term_reference(FrameStore* fs);
static int is_long_term_reference(FrameStore* fs);
void gen_field_ref_ids(StorablePicture *p);
DecodedPictureBuffer dpb;
StorablePicture **listX[6];
StorablePicture *no_reference_picture; //!< dummy storable picture for recovery point
ColocatedParams *Co_located = NULL;
ColocatedParams *Co_located_JV[MAX_PLANE] = { NULL, NULL, NULL }; //!< Co_located to be used during 4:4:4 independent mode decoding
extern StorablePicture *dec_picture;
int listXsize[6];
#define MAX_LIST_SIZE 33
/*!
************************************************************************
* \brief
* Print out list of pictures in DPB. Used for debug purposes.
************************************************************************
*/
void dump_dpb(void)
{
#if DUMP_DPB
unsigned i;
for (i=0; i<dpb.used_size;i++)
{
printf("(");
printf("fn=%d ", dpb.fs[i]->frame_num);
if (dpb.fs[i]->is_used & 1)
{
if (dpb.fs[i]->top_field)
printf("T: poc=%d ", dpb.fs[i]->top_field->poc);
else
printf("T: poc=%d ", dpb.fs[i]->frame->top_poc);
}
if (dpb.fs[i]->is_used & 2)
{
if (dpb.fs[i]->bottom_field)
printf("B: poc=%d ", dpb.fs[i]->bottom_field->poc);
else
printf("B: poc=%d ", dpb.fs[i]->frame->bottom_poc);
}
if (dpb.fs[i]->is_used == 3)
printf("F: poc=%d ", dpb.fs[i]->frame->poc);
printf("G: poc=%d) ", dpb.fs[i]->poc);
if (dpb.fs[i]->is_reference) printf ("ref (%d) ", dpb.fs[i]->is_reference);
if (dpb.fs[i]->is_long_term) printf ("lt_ref (%d) ", dpb.fs[i]->is_reference);
if (dpb.fs[i]->is_output) printf ("out ");
if (dpb.fs[i]->is_used == 3)
{
if (dpb.fs[i]->frame->non_existing) printf ("ne ");
}
printf ("\n");
}
#endif
}
/*!
************************************************************************
* \brief
* Returns the size of the dpb depending on level and picture size
*
*
************************************************************************
*/
int getDpbSize(void)
{
int pic_size = (active_sps->pic_width_in_mbs_minus1 + 1) * (active_sps->pic_height_in_map_units_minus1 + 1) * (active_sps->frame_mbs_only_flag?1:2) * 384;
int size = 0;
switch (active_sps->level_idc)
{
case 9:
size = 152064;
break;
case 10:
size = 152064;
break;
case 11:
if (!IS_FREXT_PROFILE(active_sps->profile_idc) && (active_sps->constrained_set3_flag == 1))
size = 152064;
else
size = 345600;
break;
case 12:
size = 912384;
break;
case 13:
size = 912384;
break;
case 20:
size = 912384;
break;
case 21:
size = 1824768;
break;
case 22:
size = 3110400;
break;
case 30:
size = 3110400;
break;
case 31:
size = 6912000;
break;
case 32:
size = 7864320;
break;
case 40:
size = 12582912;
break;
case 41:
size = 12582912;
break;
case 42:
size = 13369344;
break;
case 50:
size = 42393600;
break;
case 51:
size = 70778880;
break;
default:
error ("undefined level", 500);
break;
}
size /= pic_size;
size = imin( size, 16);
if (active_sps->vui_parameters_present_flag && active_sps->vui_seq_parameters.bitstream_restriction_flag)
{
if ((int)active_sps->vui_seq_parameters.max_dec_frame_buffering > size)
{
error ("max_dec_frame_buffering larger than MaxDpbSize", 500);
}
size = imax (1, active_sps->vui_seq_parameters.max_dec_frame_buffering);
}
return size;
}
/*!
************************************************************************
* \brief
* Check then number of frames marked "used for reference" and break
* if maximum is exceeded
*
************************************************************************
*/
void check_num_ref(void)
{
if ((int)(dpb.ltref_frames_in_buffer + dpb.ref_frames_in_buffer ) > (imax(1,dpb.num_ref_frames)))
{
error ("Max. number of reference frames exceeded. Invalid stream.", 500);
}
}
/*!
************************************************************************
* \brief
* Allocate memory for decoded picture buffer and initialize with sane values.
*
************************************************************************
*/
void init_dpb(void)
{
unsigned i,j;
if (dpb.init_done)
{
free_dpb();
}
dpb.size = getDpbSize();
dpb.num_ref_frames = active_sps->num_ref_frames;
if (dpb.size < active_sps->num_ref_frames)
{
error ("DPB size at specified level is smaller than the specified number of reference frames. This is not allowed.\n", 1000);
}
dpb.used_size = 0;
dpb.last_picture = NULL;
dpb.ref_frames_in_buffer = 0;
dpb.ltref_frames_in_buffer = 0;
dpb.fs = calloc(dpb.size, sizeof (FrameStore*));
if (NULL==dpb.fs)
no_mem_exit("init_dpb: dpb->fs");
dpb.fs_ref = calloc(dpb.size, sizeof (FrameStore*));
if (NULL==dpb.fs_ref)
no_mem_exit("init_dpb: dpb->fs_ref");
dpb.fs_ltref = calloc(dpb.size, sizeof (FrameStore*));
if (NULL==dpb.fs_ltref)
no_mem_exit("init_dpb: dpb->fs_ltref");
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<6; i++)
{
listX[i] = calloc(MAX_LIST_SIZE, sizeof (StorablePicture*)); // +1 for reordering
if (NULL==listX[i])
no_mem_exit("init_dpb: listX[i]");
}
/* allocate a dummy storable picture */
no_reference_picture = alloc_storable_picture (FRAME, img->width, img->height, img->width_cr, img->height_cr);
no_reference_picture->top_field = no_reference_picture;
no_reference_picture->bottom_field = no_reference_picture;
no_reference_picture->frame = no_reference_picture;
for (j=0;j<6;j++)
{
for (i=0; i<MAX_LIST_SIZE; i++)
{
listX[j][i] = NULL;
}
listXsize[j]=0;
}
dpb.last_output_poc = INT_MIN;
img->last_has_mmco_5 = 0;
dpb.init_done = 1;
// picture error concealment
if(img->conceal_mode !=0)
last_out_fs = alloc_frame_store();
}
/*!
************************************************************************
* \brief
* Free memory for decoded picture buffer.
************************************************************************
*/
void free_dpb(void)
{
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<6; i++)
if (listX[i])
{
free (listX[i]);
listX[i] = NULL;
}
dpb.init_done = 0;
// picture error concealment
if(img->conceal_mode != 0)
free_frame_store(last_out_fs);
free_storable_picture(no_reference_picture);
}
/*!
************************************************************************
* \brief
* Allocate memory for decoded picture buffer frame stores an initialize with sane values.
*
* \return
* the allocated FrameStore structure
************************************************************************
*/
FrameStore* alloc_frame_store(void)
{
FrameStore *f;
f = calloc (1, sizeof(FrameStore));
if (NULL==f)
no_mem_exit("alloc_frame_store: f");
f->is_used = 0;
f->is_reference = 0;
f->is_long_term = 0;
f->is_orig_reference = 0;
f->is_output = 0;
f->frame = NULL;;
f->top_field = NULL;
f->bottom_field = NULL;
return f;
}
void alloc_pic_motion(PicMotionParams *motion, int size_y, int size_x)
{
get_mem3Dint64 (&(motion->ref_pic_id), 6, size_y, size_x);
get_mem3Dint64 (&(motion->ref_id), 6, size_y, size_x);
get_mem4Dshort (&(motion->mv), 2, size_y, size_x, 2);
get_mem3D ((byte****)(&(motion->ref_idx)), 2, size_y , size_x);
motion->mb_field = calloc (size_y * size_x, sizeof(byte));
if (motion->mb_field == NULL)
no_mem_exit("alloc_storable_picture: motion->mb_field");
get_mem2D (&(motion->field_frame), size_y, size_x);
}
/*!
************************************************************************
* \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 nplane;
//printf ("Allocating (%s) picture (x=%d, y=%d, x_cr=%d, y_cr=%d)\n", (type == FRAME)?"FRAME":(type == TOP_FIELD)?"TOP_FIELD":"BOTTOM_FIELD", size_x, size_y, size_x_cr, size_y_cr);
s = calloc (1, sizeof(StorablePicture));
if (NULL==s)
no_mem_exit("alloc_storable_picture: s");
if (structure!=FRAME)
{
size_y /= 2;
size_y_cr /= 2;
}
s->PicSizeInMbs = (size_x*size_y)/256;
s->imgUV = NULL;
get_mem2Dpel (&(s->imgY), size_y, size_x);
if (active_sps->chroma_format_idc != YUV400)
get_mem3Dpel (&(s->imgUV), 2, size_y_cr, size_x_cr);
get_mem2Dshort (&(s->slice_id), size_y / MB_BLOCK_SIZE, size_x / MB_BLOCK_SIZE);
alloc_pic_motion(&s->motion, size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
if( IS_INDEPENDENT(img) )
{
for( nplane=0; nplane<MAX_PLANE; nplane++ )
{
alloc_pic_motion(&s->JVmotion[nplane], size_y / BLOCK_SIZE, size_x / BLOCK_SIZE);
}
}
s->pic_num=0;
s->frame_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->non_existing=0;
s->is_output = 0;
s->max_slice_id = 0;
s->structure=structure;
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->size_x_m1 = size_x - 1;
s->size_y_m1 = size_y - 1;
s->size_x_cr_m1 = size_x_cr - 1;
s->size_y_cr_m1 = size_y_cr - 1;
s->top_field = no_reference_picture;
s->bottom_field = no_reference_picture;
s->frame = no_reference_picture;
s->dec_ref_pic_marking_buffer = NULL;
s->coded_frame = 0;
s->MbaffFrameFlag = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -