📄 mbuffer.c
字号:
}
/*!
************************************************************************
* \brief
* Returns short term pic with given LongtermPicNum
*
************************************************************************
*/
static StorablePicture* get_long_term_pic(int LongtermPicNum)
{
unsigned i;
for (i=0; i<dpb.ltref_frames_in_buffer; i++)
{
if (img->structure==FRAME)
{
if (dpb.fs_ltref[i]->is_reference == 3)
if ((dpb.fs_ltref[i]->frame->is_long_term)&&(dpb.fs_ltref[i]->frame->long_term_pic_num == LongtermPicNum))
return dpb.fs_ltref[i]->frame;
}
else
{
if (dpb.fs_ltref[i]->is_reference & 1)
if ((dpb.fs_ltref[i]->top_field->is_long_term)&&(dpb.fs_ltref[i]->top_field->long_term_pic_num == LongtermPicNum))
return dpb.fs_ltref[i]->top_field;
if (dpb.fs_ltref[i]->is_reference & 2)
if ((dpb.fs_ltref[i]->bottom_field->is_long_term)&&(dpb.fs_ltref[i]->bottom_field->long_term_pic_num == LongtermPicNum))
return dpb.fs_ltref[i]->bottom_field;
}
}
return NULL;
}
/*!
************************************************************************
* \brief
* Reordering process for short-term reference pictures
*
************************************************************************
*/
static void reorder_short_term(StorablePicture **RefPicListX, int num_ref_idx_lX_active_minus1, int picNumLX, int *refIdxLX)
{
int cIdx, nIdx;
StorablePicture *picLX;
picLX = get_short_term_pic(picNumLX);
for( cIdx = num_ref_idx_lX_active_minus1+1; cIdx > *refIdxLX; cIdx-- )
RefPicListX[ cIdx ] = RefPicListX[ cIdx - 1];
RefPicListX[ (*refIdxLX)++ ] = picLX;
nIdx = *refIdxLX;
for( cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1+1; cIdx++ )
if (RefPicListX[ cIdx ])
if( (RefPicListX[ cIdx ]->is_long_term ) || (RefPicListX[ cIdx ]->pic_num != picNumLX ))
RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ];
}
/*!
************************************************************************
* \brief
* Reordering process for short-term reference pictures
*
************************************************************************
*/
static void reorder_long_term(StorablePicture **RefPicListX, int num_ref_idx_lX_active_minus1, int LongTermPicNum, int *refIdxLX)
{
int cIdx, nIdx;
StorablePicture *picLX;
picLX = get_long_term_pic(LongTermPicNum);
for( cIdx = num_ref_idx_lX_active_minus1+1; cIdx > *refIdxLX; cIdx-- )
RefPicListX[ cIdx ] = RefPicListX[ cIdx - 1];
RefPicListX[ (*refIdxLX)++ ] = picLX;
nIdx = *refIdxLX;
for( cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1+1; cIdx++ )
if (RefPicListX[ cIdx ])
if( (!RefPicListX[ cIdx ]->is_long_term ) || (RefPicListX[ cIdx ]->long_term_pic_num != LongTermPicNum ))
RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ];
}
/*!
************************************************************************
* \brief
* Reordering process for reference picture lists
*
************************************************************************
*/
void reorder_ref_pic_list(StorablePicture **list, int *list_size, int num_ref_idx_lX_active_minus1, int *reordering_of_pic_nums_idc, int *abs_diff_pic_num_minus1, int *long_term_pic_idx)
{
int i;
int maxPicNum, currPicNum, picNumLXNoWrap, picNumLXPred, picNumLX;
int refIdxLX = 0;
if (img->structure==FRAME)
{
maxPicNum = img->MaxFrameNum;
currPicNum = img->frame_num;
}
else
{
maxPicNum = 2 * img->MaxFrameNum;
currPicNum = 2 * img->frame_num + 1;
}
picNumLXPred = currPicNum;
for (i=0; reordering_of_pic_nums_idc[i]!=3; i++)
{
if (reordering_of_pic_nums_idc[i]>3)
error ("Invalid remapping_of_pic_nums_idc command", 500);
if (reordering_of_pic_nums_idc[i] < 2)
{
if (reordering_of_pic_nums_idc[i] == 0)
{
if( picNumLXPred - ( abs_diff_pic_num_minus1[i] + 1 ) < 0 )
picNumLXNoWrap = picNumLXPred - ( abs_diff_pic_num_minus1[i] + 1 ) + maxPicNum;
else
picNumLXNoWrap = picNumLXPred - ( abs_diff_pic_num_minus1[i] + 1 );
}
else // (remapping_of_pic_nums_idc[i] == 1)
{
if( picNumLXPred + ( abs_diff_pic_num_minus1[i] + 1 ) >= maxPicNum )
picNumLXNoWrap = picNumLXPred + ( abs_diff_pic_num_minus1[i] + 1 ) - maxPicNum;
else
picNumLXNoWrap = picNumLXPred + ( abs_diff_pic_num_minus1[i] + 1 );
}
picNumLXPred = picNumLXNoWrap;
if( picNumLXNoWrap > currPicNum )
picNumLX = picNumLXNoWrap - maxPicNum;
else
picNumLX = picNumLXNoWrap;
reorder_short_term(list, num_ref_idx_lX_active_minus1, picNumLX, &refIdxLX);
}
else //(remapping_of_pic_nums_idc[i] == 2)
{
reorder_long_term(list, num_ref_idx_lX_active_minus1, long_term_pic_idx[i], &refIdxLX);
}
}
// that's a definition
*list_size = num_ref_idx_lX_active_minus1 + 1;
}
/*!
************************************************************************
* \brief
* Update the list of frame stores that contain reference frames/fields
*
************************************************************************
*/
void update_ref_list(void)
{
unsigned i, j;
for (i=0, j=0; i<dpb.used_size; i++)
{
if (is_short_term_reference(dpb.fs[i]))
{
dpb.fs_ref[j++]=dpb.fs[i];
}
}
dpb.ref_frames_in_buffer = j;
while (j<dpb.size)
{
dpb.fs_ref[j++]=NULL;
}
}
/*!
************************************************************************
* \brief
* Update the list of frame stores that contain long-term reference
* frames/fields
*
************************************************************************
*/
void update_ltref_list(void)
{
unsigned i, j;
for (i=0, j=0; i<dpb.used_size; i++)
{
if (is_long_term_reference(dpb.fs[i]))
{
dpb.fs_ltref[j++]=dpb.fs[i];
}
}
dpb.ltref_frames_in_buffer=j;
while (j<dpb.size)
{
dpb.fs_ltref[j++]=NULL;
}
}
/*!
************************************************************************
* \brief
* Perform Memory management for idr pictures
*
************************************************************************
*/
static void idr_memory_management(StorablePicture* p)
{
unsigned i;
assert (p->idr_flag);
if (p->no_output_of_prior_pics_flag)
{
// free all stored pictures
for (i=0; i<dpb.used_size; i++)
{
// reset all reference settings
free_frame_store(dpb.fs[i]);
dpb.fs[i] = alloc_frame_store();
}
for (i=0; i<dpb.ref_frames_in_buffer; i++)
{
dpb.fs_ref[i]=NULL;
}
for (i=0; i<dpb.ltref_frames_in_buffer; i++)
{
dpb.fs_ltref[i]=NULL;
}
dpb.used_size=0;
}
else
{
flush_dpb();
}
dpb.last_picture = NULL;
update_ref_list();
update_ltref_list();
dpb.last_output_poc = INT_MIN;
if (p->long_term_reference_flag)
{
dpb.max_long_term_pic_idx = 0;
p->is_long_term = 1;
p->long_term_frame_idx = 0;
}
else
{
dpb.max_long_term_pic_idx = -1;
p->is_long_term = 0;
}
}
/*!
************************************************************************
* \brief
* Perform Sliding window decoded reference picture marking process
*
************************************************************************
*/
static void sliding_window_memory_management(StorablePicture* p)
{
unsigned i;
assert (!p->idr_flag);
// if this is a reference pic with sliding sliding window, unmark first ref frame
if (dpb.ref_frames_in_buffer==dpb.num_ref_frames - dpb.ltref_frames_in_buffer)
{
for (i=0; i<dpb.used_size;i++)
{
if (dpb.fs[i]->is_reference && (!(dpb.fs[i]->is_long_term)))
{
unmark_for_reference(dpb.fs[i]);
update_ref_list();
break;
}
}
}
p->is_long_term = 0;
}
/*!
************************************************************************
* \brief
* Calculate picNumX
************************************************************************
*/
static int get_pic_num_x (StorablePicture *p, int difference_of_pic_nums_minus1)
{
int currPicNum;
if (p->structure == FRAME)
currPicNum = p->frame_num;
else
currPicNum = 2 * p->frame_num + 1;
return currPicNum - (difference_of_pic_nums_minus1 + 1);
}
/*!
************************************************************************
* \brief
* Adaptive Memory Management: Mark short term picture unused
************************************************************************
*/
static void mm_unmark_short_term_for_reference(StorablePicture *p, int difference_of_pic_nums_minus1)
{
int picNumX;
unsigned i;
picNumX = get_pic_num_x(p, difference_of_pic_nums_minus1);
for (i=0; i<dpb.ref_frames_in_buffer; i++)
{
if (p->structure == FRAME)
{
if ((dpb.fs_ref[i]->is_reference==3) && (dpb.fs_ref[i]->is_long_term==0))
{
if (dpb.fs_ref[i]->frame->pic_num == picNumX)
{
unmark_for_reference(dpb.fs_ref[i]);
return;
}
}
}
else
{
if ((dpb.fs_ref[i]->is_reference & 1) && (!(dpb.fs_ref[i]->is_long_term & 1)))
{
if (dpb.fs_ref[i]->top_field->pic_num == picNumX)
{
dpb.fs_ref[i]->top_field->used_for_reference = 0;
dpb.fs_ref[i]->is_reference &= 2;
if (dpb.fs_ref[i]->is_used == 3)
{
dpb.fs_ref[i]->frame->used_for_reference = 0;
}
return;
}
}
if ((dpb.fs_ref[i]->is_reference & 2) && (!(dpb.fs_ref[i]->is_long_term & 2)))
{
if (dpb.fs_ref[i]->bottom_field->pic_num == picNumX)
{
dpb.fs_ref[i]->bottom_field->used_for_reference = 0;
dpb.fs_ref[i]->is_reference &= 1;
if (dpb.fs_ref[i]->is_used == 3)
{
dpb.fs_ref[i]->frame->used_for_reference = 0;
}
return;
}
}
}
}
}
/*!
************************************************************************
* \brief
* Adaptive Memory Management: Mark long term picture unused
************************************************************************
*/
static void mm_unmark_long_term_for_reference(StorablePicture *p, int long_term_pic_num)
{
unsigned i;
for (i=0; i<dpb.ltref_frames_in_buffer; i++)
{
if (p->structure == FRAME)
{
if ((dpb.fs_ltref[i]->is_reference==3) && (dpb.fs_ltref[i]->is_long_term==3))
{
if (dpb.fs_ltref[i]->frame->long_term_pic_num == long_term_pic_num)
{
unmark_for_long_term_reference(dpb.fs_ltref[i]);
}
}
}
else
{
if ((dpb.fs_ltref[i]->is_reference & 1) && ((dpb.fs_ltref[i]->is_long_term & 1)))
{
if (dpb.fs_ltref[i]->top_field->long_term_pic_num == long_term_pic_num)
{
dpb.fs_ltref[i]->top_field->used_for_reference = 0;
dpb.fs_ltref[i]->top_field->is_long_term = 0;
dpb.fs_ltref[i]->is_reference &= 2;
dpb.fs_ltref[i]->is_long_term &= 2;
if (dpb.fs_ltref[i]->is_used == 3)
{
dpb.fs_ltref[i]->frame->used_for_reference = 0;
dpb.fs_ltref[i]->frame->is_long_term = 0;
}
return;
}
}
if ((dpb.fs_ltref[i]->is_reference & 2) && ((dpb.fs_ltref[i]->is_long_term & 2)))
{
if (dpb.fs_ltref[i]->bottom_field->long_term_pic_num == long_term_pic_num)
{
dpb.fs_ltref[i]->bottom_field->used_for_reference = 0;
dpb.fs_ltref[i]->bottom_field->is_long_term = 0;
dpb.fs_ltref[i]->is_reference &= 1;
dpb.fs_ltref[i]->is_long_term &= 1;
if (dpb.fs_ltref[i]->is_used == 3)
{
dpb.fs_ltref[i]->frame->used_for_reference = 0;
dpb.fs_ltref[i]->frame->is_long_term = 0;
}
return;
}
}
}
}
}
/*!
************************************************************************
* \brief
* Mark a long-term reference frame or complementary field pair unused for referemce
************************************************************************
*/
static void unmark_long_term_frame_for_reference_by_frame_idx(int long_term_frame_idx)
{
unsigned i;
for(i=0; i<dpb.ltref_frames_in_buffer; i++)
{
if (dpb.fs_ltref[i]->long_term_frame_idx == long_term_frame_idx)
unmark_for_long_term_reference(dpb.fs_ltref[i]);
}
}
/*!
************************************************************************
* \brief
* Mark a long-term reference field unused for reference only if it's not
* the complementary field of the picture indicated by picNumX
************************************************************************
*/
static void unmark_long_term_field_for_reference_by_frame_idx(PictureStructure structure, int long_term_frame_idx, int mark_current, unsigned curr_frame_num, int curr_pic_num)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -