H.264参考帧列表管理分析 ―― JM中相关函数解析(上)(二)

2014-11-24 08:53:03 · 作者: · 浏览: 1
// check if lists are identical, if yes swap first two elements of listX[1]
diff=0;
for (j = 0; j< listXsize[0]; j++) //!< 检查listX[0]和listX[1]是否相同
{
if (listX[0][j]!=listX[1][j])
diff=1;
}
if (!diff) //!< 如果两个列表相同,则交换listX[1]前两个元素的位置
{
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);
listXsize[1] = min (listXsize[1], img->num_ref_idx_l1_active);

// set the unused list entries to NULL
for (i=listXsize[0]; i< (MAX_LIST_SIZE) ; i++)
{
listX[0][i] = NULL;
}
for (i=listXsize[1]; i< (MAX_LIST_SIZE) ; i++)
{
listX[1][i] = NULL;
}
}
上述代码中,有个函数qsort,关于它的用法,在我的另一篇博客qsort 函数的使用 有简单的介绍。

(2)参考帧列表的重排序

主要在函数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)中实现,在编码端被 init_slice (int start_mb_addr)调用,在解码端被read_new_slice()中的子函数reorder_lists(int currSliceType, Slice * currSlice)调用。

[cpp]
/*!
************************************************************************
* \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; //!< frame_num的最大值
currPicNum = img->frame_num; //!< 当前帧的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) //!< 该句法元素取值范围为0~3,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) //!< 当前帧的PicNum减去(abs_diff_pic_num_minus1[i] + 1)指明需要重排序的图像
{
if( picNumLXPred - ( abs_diff_pic_num_minus1[i] + 1 ) < 0 ) //!< 预测值小于实际值
picNumLXNoWrap = picNumLXPred - ( abs_diff_pic_num_minus1[i] + 1 ) + maxPicNum; //!< frame_num循环计数
else
picNumLXNoWrap = picNumLXPred - ( abs_diff_pic_num_minus1[i] + 1 );
}
else // (remapping_of_pic_nums_idc[i] == 1) //!< 当前帧的PicNum加上(abs_diff_pic_num_minus1[i] + 1)指明需要重排序的图像
{
if( picNumLXPred + ( abs_diff_pic_num_minus1[i] + 1 ) >= maxPicNum ) //!< 预测值大于实际值
picNumLXNoWrap = picNumLXPred + ( abs_diff_pic_num_minus1[i] + 1 ) - maxPicNum; //!< frame_num循环计数
else
picNumLXNoWrap = picNumLXPred + ( abs_diff_pic_num_minus1[i] + 1 );
}
picNumLXPred = picNumLXNoWrap;

if( picNumLXNoWrap > currPicNum )
picNumLX = picNumLXNoWrap - maxPicNum;
else
picNumLX = picNumLXNoWrap;
//!< picNumLX存放的是需要移至refIdxLX位置的短期参考图像的PicNum
reorder_short_term(list, num_ref_idx_lX_active_minus1, picNumLX, &refIdxLX); //!< 调用该函数实现短期参考帧的重排序
}
else //(remapping_of_pic_nums_idc[i] == 2) //!< 长期参考帧重排序
{//!< long_term_pic_idx[i]存放的是需要移至refIdxLX位置的短期参考图像的序号
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;
}

(3)参考图像的标记

主要由两种,一种是滑窗标记即FIFO,另一种是自适应标记。

前者由函数sliding_window_memory_management(StorablePicture* p)实现,后者由函数adapt