JM-对整象素搜索的一些理解

整象素搜索主要包括3个函数SetupFastFullPelSearch,SetMotionVectorPredictor,SetupLargerBlocks,都位于文件mv_search.c中间。

1)该函数对参考帧ref,实现list0(前向),list1(后向)全局整象素搜索,并统计各种分块模式下的SAD值(整象素只计算SAD值,见蓝风车FAQ语录),因此一个宏块只需要计算一次,是整个宏块计算复杂度最大的一个函数,通过这个函数,可以明白,所谓搜索半径只是对整象素搜索而言,下面我对该函数步逐作详细注解。

void SetupFastFullPelSearch (short ref, int list) // <-- reference frame parameter, list0 or 1
{
short   pmv[2];//预测向量X,Y两个方向
pel_t   orig_blocks[256], *orgptr=orig_blocks, *refptr;//对宏块分配地址,static值系统当然只分配一次.
int   offset_x, offset_y, x, y, range_partly_outside, ref_x, ref_y, pos, abs_x, abs_y, bindex, blky;
int   LineSadBlk0, LineSadBlk1, LineSadBlk2, LineSadBlk3;
//为4X4块计算SAD分配空间,注意该4个4X4块为一个宏块内同一行内4个子块
int   max_width, max_height;
int   img_width, img_height;
 
StorablePicture *ref_picture;//参考帧
pel_t   *ref_pic;//参考象素
 
distpel**   block_sad = BlockSAD[ list ][ref][7];
//[7]为4X4子块模式SAD值下标
int   search_range = max_search_range[ list ][ref];
//获得当前帧对ref参考帧list方向预测搜索半径,有点疑问,难道可以有不同的搜索半径
int   max_pos     = (2*search_range+1) * (2*search_range+1);
//计算最大搜索点
int   list_offset   = img->mb_data[img->current_mb_nr].list_offset;
//list方向偏移,个人认为该值和field编码有关,当帧编码时为0  
int   apply_weights = ( (active_pps->weighted_pred_flag && (img->type == P_SLICE || img->type == SP_SLICE)) ||
  (active_pps->weighted_bipred_idc && (img->type == B_SLICE)));
//是否权重预测  
 
ref_picture   = listX[list+list_offset][ref];
//获得参考帧,为计算SAD准备.
//===== Use weighted Reference for ME ====
if (apply_weights && input->UseWeightedReferenceME)
  ref_pic     = ref_picture->imgY_11_w;
else
  ref_pic     = ref_picture->imgY_11;
//是否使用权重预测,使用不同的参考象素值
max_width   = ref_picture->size_x - 17;
max_height   = ref_picture->size_y - 17;
 
img_width   = ref_picture->size_x;
img_height   = ref_picture->size_y;
 
//===== get search center: predictor of 16x16 block =====
SetMotionVectorPredictor (pmv, enc_picture->ref_idx[ list ], enc_picture->mv[ list ], ref, list, 0, 0, 16, 16);
//以上预测MV,该MV为1/4象素为单位向量值,下次再讲这个函数。
search_center_x[ list ][ref] = pmv[0] / 4;
search_center_y[ list ][ref] = pmv[1] / 4;
//ref帧对当前帧预测偏移(整象素值)

if (!input->rdopt)
{
  //--- correct center so that (0,0) vector is inside ---
  search_center_x[ list ][ref] = max(-search_range, min(search_range, search_center_x[ list ][ref]));
  search_center_y[ list ][ref] = max(-search_range, min(search_range, search_center_y[ list ][ref]));
}
search_center_x[ list ][ref] = Clip3(-2047 + search_range, 2047 - search_range, search_center_x[ list ][ref]);
search_center_y[ list ][ref] = Clip3(LEVELMVLIMIT[img->LevelIndex][0] + search_range, LEVELMVLIMIT[img->LevelIndex][1] - search_range, search_center_y[ list ][ref]);
//对上下方向饱和
search_center_x[ list ][ref] += img->opix_x;
search_center_y[ list ][ref] += img->opix_y;

offset_x = search_center_x[ list ][ref];
offset_y = search_center_y[ list ][ref];
//计算绝对偏移(对整幅图像左上角(0,0)位置)
 
//===== copy original block for fast access =====
for   (y = img->opix_y; y < img->opix_y+16; y++)
  for (x = img->opix_x; x < img->opix_x+16; x++)
    *orgptr++ = imgY_org [y][x];
//拷贝原始象素放入数组,一维数组比较快,所以叫做fast access
//===== check if whole search range is inside image =====
if (offset_x >= search_range && offset_x <= max_width - search_range &&
    offset_y >= search_range && offset_y <= max_height - search_range   )
{
  range_partly_outside = 0; PelYline_11 = FastLine16Y_11;
}
else
{
  range_partly_outside = 1;
}
//检查是否越界,第1个宏块16搜索半径当然越界


//===== determine position of (0,0)-vector =====
if (!input->rdopt)
{
  ref_x = img->opix_x - offset_x;
  ref_y = img->opix_y - offset_y;
  for (pos = 0; pos < max_pos; pos++)
  {
    if (ref_x == spiral_search_x[pos] &&
      ref_y == spiral_search_y[pos])
 

阅读更多
个人分类: 音视频编解码
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭