📄 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 <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"
#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();
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);
// 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;
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()
{
#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
#if 0
unsigned i;
//fprintf(img->fdump, "#\n");
for (i=0; i<dpb.used_size;i++)
{
//fprintf(img->fdump, "(");
//fprintf(img->fdump, "fn=%d ", dpb.fs[i]->frame_num);
if (dpb.fs[i]->is_used & 1)
{
if (dpb.fs[i]->top_field)
fprintf(img->fdump, "T: poc=%d ", dpb.fs[i]->top_field->poc);
else
fprintf(img->fdump, "T: poc=%d ", dpb.fs[i]->frame->top_poc);
}
if (dpb.fs[i]->is_used & 2)
{
if (dpb.fs[i]->bottom_field)
fprintf(img->fdump, "B: poc=%d ", dpb.fs[i]->bottom_field->poc);
else
fprintf(img->fdump, "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) fprintf(img->fdump, "ref (%d) ", dpb.fs[i]->is_reference);
if (dpb.fs[i]->is_long_term) fprintf(img->fdump, "lt_ref (%d) ", dpb.fs[i]->is_reference);
if (dpb.fs[i]->is_output) fprintf(img->fdump, "out ");
if (dpb.fs[i]->is_used == 3)
{
if (dpb.fs[i]->frame->non_existing) fprintf(img->fdump, "ne ");
}
fprintf(img->fdump, "\n");
}
fprintf(img->fdump, "\n");
#endif
}
/*!
************************************************************************
* \brief
* Returns the size of the dpb depending on level and picture size
*
*
************************************************************************
*/
int getDpbSize()
{
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 ((active_sps->profile_idc < FREXT_HP)&&(active_sps->constrained_set3_flag == 0))
size = 345600;
else
size = 152064;
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:
if( (active_sps->profile_idc==FREXT_HP ) || (active_sps->profile_idc==FREXT_Hi10P)
|| (active_sps->profile_idc==FREXT_Hi422) || (active_sps->profile_idc==FREXT_Hi444))
size = 13369344;
else
size = 12582912;
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()
{
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()
{
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.memory_used = calloc(2*(dpb.size + 1), sizeof(unsigned int *));
dpb.memory_used_poc = calloc(2*(dpb.size + 1), sizeof(int *));
for(i=0; i<2*(dpb.size + 1); i++)
{
dpb.memory_used_poc[i] = -1;
}
dpb.got_first_field = 0;
dpb.last_pic_mem_idx = -1;
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;
no_reference_picture = NULL;
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()
{
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.memory_used)
{
free(dpb.memory_used);
dpb.memory_used = NULL;
}
if (dpb.memory_used_poc)
{
free(dpb.memory_used_poc);
dpb.memory_used_poc = 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()
{
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;
}
extern FILE *fpic_mem;
int take_idle_mem(PictureStructure structure)
{
unsigned int index;
int pic_mem_idx;
if (dpb.got_first_field == 0) // frame or first field.
{
for (index=0; index<(dpb.size+1); index++)
{
if ((!dpb.memory_used[2*index]) && (!dpb.memory_used[2*index+1])) // both fields are empty.
{
pic_mem_idx = 2*index;
break;
}
}
}
else // second field.
{
pic_mem_idx = (dpb.last_pic_mem_idx>>1)*2;
}
if (structure == BOTTOM_FIELD)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -