📄 mbuffer.c
字号:
{
unmark_long_term_frame_for_reference_by_frame_idx(long_term_frame_idx);
}
else
{
unmark_long_term_field_for_reference_by_frame_idx(p, long_term_frame_idx, 2 * p->pic_num + 1);
}
p->is_long_term = 1;
p->long_term_frame_idx = long_term_frame_idx;
}
/*!
************************************************************************
* \brief
* Perform Adaptive memory control decoded reference picture marking process
************************************************************************
*/
static void adaptive_memory_management(StorablePicture* p)
{
DecRefPicMarking_t *tmp_drpm;
img->last_has_mmco_5 = 0;
assert (!img->currentPicture->idr_flag);
assert (img->adaptive_ref_pic_buffering_flag);
while (img->dec_ref_pic_marking_buffer)
{
tmp_drpm = img->dec_ref_pic_marking_buffer;
switch (tmp_drpm->memory_management_control_operation)
{
case 0:
if (tmp_drpm->Next != NULL)
{
error ("memory_management_control_operation = 0 not last operation in buffer", 500);
}
break;
case 1:
mm_unmark_short_term_for_reference(p, tmp_drpm->difference_of_pic_nums_minus1);
update_ref_list();
break;
case 2:
mm_unmark_long_term_for_reference(p, tmp_drpm->long_term_pic_num);
update_ltref_list();
break;
case 3:
mm_assign_long_term_frame_idx(p, tmp_drpm->difference_of_pic_nums_minus1, tmp_drpm->long_term_frame_idx);
update_ref_list();
update_ltref_list();
break;
case 4:
mm_update_max_long_term_frame_idx (tmp_drpm->max_long_term_frame_idx_plus1);
update_ltref_list();
break;
case 5:
mm_unmark_all_short_term_for_reference();
mm_unmark_all_long_term_for_reference();
img->last_has_mmco_5 = 1;
break;
case 6:
mm_mark_current_picture_long_term(p, tmp_drpm->long_term_frame_idx);
break;
default:
error ("invalid memory_management_control_operation in buffer", 500);
}
img->dec_ref_pic_marking_buffer = tmp_drpm->Next;
free (tmp_drpm);
}
if ( img->last_has_mmco_5 )
{
img->frame_num = p->pic_num = 0;
p->poc = 0;
flush_dpb();
}
}
/*!
************************************************************************
* \brief
* Store a picture in DPB. This includes cheking for space in DPB and
* flushing frames.
* If we received a frame, we need to check for a new store, if we
* got a field, check if it's the second field of an already allocated
* store.
*
* \param p
* Picture to be stored
*
************************************************************************
*/
void store_picture_in_dpb(StorablePicture* p)
{
unsigned i;
int found;
int poc, pos;
// diagnostics
//printf ("Storing (%s) non-ref pic with frame_num #%d\n", (p->type == FRAME)?"FRAME":(p->type == TOP_FIELD)?"TOP_FIELD":"BOTTOM_FIELD", img->frame_num);
// if frame, check for new store,
assert (p!=NULL);
p->used_for_reference = (img->nal_reference_idc != 0);
img->last_has_mmco_5=0;
img->last_pic_bottom_field = (img->structure == BOTTOM_FIELD);
if (img->currentPicture->idr_flag)
idr_memory_management(p);
else
{
// adaptive memory management
if (p->used_for_reference && (img->adaptive_ref_pic_buffering_flag))
adaptive_memory_management(p);
}
if ((p->structure==TOP_FIELD)||(p->structure==BOTTOM_FIELD))
{
// check for frame store with same pic_number
found = 0;
for (i=0;i<dpb.used_size;i++)
{
if((dpb.fs[i]->frame_num == img->frame_num)&&(dpb.fs[i]->is_used<3))
{
found=1;
break;
}
}
if (found)
{
if (!(((p->structure==TOP_FIELD)&&(dpb.fs[i]->is_used&1))||((p->structure==BOTTOM_FIELD)&&(dpb.fs[i]->is_used&2))))
{
// printf ("store second field at pos %d\n",i);
insert_picture_in_dpb(dpb.fs[i], p);
update_ref_list();
update_ltref_list();
dump_dpb();
return;
}
}
}
// this is a frame or a field which has no stored complementatry field
// sliding window, if necessary
if ((!img->currentPicture->idr_flag)&&(p->used_for_reference && (!img->adaptive_ref_pic_buffering_flag)))
{
sliding_window_memory_management(p);
}
// first try to remove unused frames
if (dpb.used_size==dpb.size)
{
remove_unused_frame_from_dpb();
}
// then output frames until one can be removed
while (dpb.used_size==dpb.size)
{
// non-reference frames may be output directly
if (!p->used_for_reference)
{
get_smallest_poc(&poc, &pos);
if ((-1==pos) || (p->poc < poc))
{
direct_output(p, p_dec);
return;
}
}
// flush a frame
output_one_frame_from_dpb();
}
// check for duplicate frame number in short term reference buffer
if ((p->used_for_reference)&&(!p->is_long_term))
{
for (i=0; i<dpb.ref_frames_in_buffer; i++)
{
if (dpb.fs_ref[i]->frame_num == img->frame_num)
{
error("duplicate frame_num im short-term reference picture buffer", 500);
}
}
}
// store at end of buffer
// printf ("store frame/field at pos %d\n",dpb.used_size);
insert_picture_in_dpb(dpb.fs[dpb.used_size],p);
dpb.used_size++;
update_ref_list();
update_ltref_list();
dump_dpb();
}
/*!
************************************************************************
* \brief
* Insert the frame picture into the if the top field has already
* been stored for the coding decision
*
* \param p
* StorablePicture to be inserted
*
************************************************************************
*/
void replace_top_pic_with_frame(StorablePicture* p)
{
FrameStore* fs = NULL;
unsigned i, found;
assert (p!=NULL);
assert (p->structure==FRAME);
p->used_for_reference = (img->nal_reference_idc != 0);
// upsample a reference picture
if (p->used_for_reference)
{
UnifiedOneForthPix(p);
}
found=0;
for (i=0;i<dpb.used_size;i++)
{
if((dpb.fs[i]->frame_num == img->frame_num)&&(dpb.fs[i]->is_used==1))
{
found=1;
fs = dpb.fs[i];
break;
}
}
if (!found)
{
error("replace_top_pic_with_frame: error storing reference frame (top field not found)",500);
}
free_storable_picture(fs->top_field);
fs->top_field=NULL;
fs->frame=p;
fs->is_used = 3;
if (p->used_for_reference)
{
fs->is_reference = 3;
if (p->is_long_term)
{
fs->is_long_term = 3;
}
}
// generate field views
dpb_split_field(fs);
update_ref_list();
update_ltref_list();
}
/*!
************************************************************************
* \brief
* Insert the picture into the DPB. A free DPB position is necessary
* for frames, .
*
* \param fs
* FrameStore into which the picture will be inserted
* \param p
* StorablePicture to be inserted
*
************************************************************************
*/
static void insert_picture_in_dpb(FrameStore* fs, StorablePicture* p)
{
// printf ("insert (%s) pic with frame_num #%d, poc %d\n", (p->structure == FRAME)?"FRAME":(p->structure == TOP_FIELD)?"TOP_FIELD":"BOTTOM_FIELD", img->frame_num, p->poc);
assert (p!=NULL);
assert (fs!=NULL);
// upsample a reference picture
if (p->used_for_reference)
{
UnifiedOneForthPix(p);
}
switch (p->structure)
{
case FRAME:
fs->frame = p;
fs->is_used = 3;
if (p->used_for_reference)
{
fs->is_reference = 3;
if (p->is_long_term)
{
fs->is_long_term = 3;
}
}
if (active_sps->frame_mbs_only_flag)
{
int i,j;
fs->poc = fs->frame->poc;
fs->long_term_frame_idx = fs->frame->long_term_frame_idx;
for (j=0 ; j<fs->frame->size_y/4 ; j++)
{
for (i=0 ; i<fs->frame->size_x/4 ; i++)
{
if (!active_sps->frame_mbs_only_flag || active_sps->direct_8x8_inference_flag)
{
#define RSD(x) ((x&2)?(x|1):(x&(~1)))
//! Use inference flag to remap mvs/references
fs->frame->mv[LIST_0][i][j][0]=fs->frame->mv[LIST_0][RSD(i)][RSD(j)][0];
fs->frame->mv[LIST_0][i][j][1]=fs->frame->mv[LIST_0][RSD(i)][RSD(j)][1];
fs->frame->mv[LIST_1][i][j][0]=fs->frame->mv[LIST_1][RSD(i)][RSD(j)][0];
fs->frame->mv[LIST_1][i][j][1]=fs->frame->mv[LIST_1][RSD(i)][RSD(j)][1];
fs->frame->ref_idx[LIST_0][i][j]=fs->frame->ref_idx[LIST_0][RSD(i)][RSD(j)] ;
fs->frame->ref_idx[LIST_1][i][j]=fs->frame->ref_idx[LIST_1][RSD(i)][RSD(j)] ;
#undef RSD
}
fs->frame->moving_block[i][j]=
!(((fs->frame->ref_idx[LIST_0][i][j] == 0) &&
(abs(fs->frame->mv[LIST_0][i][j][0])>>1 == 0) &&
(abs(fs->frame->mv[LIST_0][i][j][1])>>1 == 0)) ||
((fs->frame->ref_idx[LIST_0][i][j] == -1) &&
(fs->frame->ref_idx[LIST_1][i][j] == 0) &&
(abs(fs->frame->mv[LIST_1][i][j][0])>>1 == 0) &&
(abs(fs->frame->mv[LIST_1][i][j][1])>>1 == 0)));
}
}
}
else
dpb_split_field(fs); // generate field views
break;
case TOP_FIELD:
fs->top_field = p;
fs->is_used |= 1;
if (p->used_for_reference)
{
fs->is_reference |= 1;
if (p->is_long_term)
{
fs->is_long_term |= 1;
fs->long_term_frame_idx = p->long_term_frame_idx;
}
}
if (fs->is_used == 3)
{
// generate frame view
dpb_combine_field(fs);
} else
{
fs->poc = p->poc;
}
break;
case BOTTOM_FIELD:
fs->bottom_field = p;
fs->is_used |= 2;
if (p->used_for_reference)
{
fs->is_reference |= 2;
if (p->is_long_term)
{
fs->is_long_term |= 2;
fs->long_term_frame_idx = p->long_term_frame_idx;
}
}
if (fs->is_used == 3)
{
// generate frame view
dpb_combine_field(fs);
} else
{
fs->poc = p->poc;
}
break;
}
fs->frame_num = p->pic_num;
fs->is_output = p->is_output;
}
/*!
************************************************************************
* \brief
* Check if one of the frames/fields in frame store is used for reference
************************************************************************
*/
static int is_used_for_reference(FrameStore* fs)
{
if (fs->is_reference)
{
return 1;
}
if (fs->is_used==3) // frame
{
if (fs->frame->used_for_reference)
{
return 1;
}
}
if (!active_sps->frame_mbs_only_flag)
{
if (fs->is_used&1) // top field
{
if (fs->top_field->used_for_reference)
{
return 1;
}
}
if (fs->is_used&2) // bottom field
{
if (fs->bottom_field->used_for_reference)
{
return 1;
}
}
}
return 0;
}
/*!
************************************************************************
* \brief
* Check if one of the frames/fields in frame store is used for short-term reference
************************************************************************
*/
static int is_short_term_reference(FrameStore* fs)
{
if (fs->is_used==3) // frame
{
if ((fs->frame->used_for_reference)&&(!fs->frame->is_long_term))
{
return 1;
}
}
if (!active_sps->frame_mbs_only_flag)
{
if (fs->is_used&1) // top field
{
if ((fs->top_field->used_for_reference)&&(!fs->top_field->is_long_term))
{
return 1;
}
}
if (fs->is_used&2) // bottom field
{
if ((fs->bottom_field->used_for_reference)&&(!fs->bottom_field->is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -