三坐标测量仪使用:PartitionMotionSearch()函数流程-H264读书笔记-搜狐空间

来源:百度文库 编辑:偶看新闻 时间:2024/04/28 16:45:17

PartitionMotionSearch()函数流程

标签: 搜索  矢量  预测  编码  运动  分类: PartitionMotionSearch()函数流程 2007-01-08 16:20


PartitionMotionSearch (int blocktype, int block8x8,  double lambda)
{
//各种宏块模式下的子块的起始偏移量,相对4*4块来讲,这有利于运动矢量的存放
//[5]表示宏块的类型,[4]表示各种类型下的子块序号,最多子块情况为P8X8模式下有4个
  static int  bx0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,2,0,2}};
  static int  by0[5][4] = {{0,0,0,0}, {0,0,0,0}, {0,2,0,0}, {0,0,0,0}, {0,0,2,2}};
 …………
if (img->mb_data[img->current_mb_nr].mb_field)
{
 …………//设置list_offset,对于场编码的宏块的情况
}
else
{
 ……//设置list_offset,对于非自适应帧/场编码的宏块的情况或者宏块帧编码情况
}
numlists=bslice?2:1;/*bslice对应img->type,如果img->type==B_SLICE,那么参考序列就要参考listX[0],listX[1],这时

numlists就应该等于2,by the way,JM86采用的遍历的方法在参考列表中搜索。*/

  for (list=0; list  {
    for (ref=0; ref < listXsize[list+list_offset]; ref++)//list_offset和场模式有关,对于
    {
 …………
        for (v=by0[parttype][block8x8]; v        {
          ……
          for (h=bx0[parttype][block8x8]; h          {
            …………
           
            //--- motion search for block ---//
       mcost = BlockMotionSearch(ref, list, h<<2, v<<2, blocktype, search_range, lambda)
               {
/*
BlockMotionSearch(),该函数的具体流程如下:
a、  获取当前块的数据
b、  运动矢量预测
c、  整象素点搜索
d、  亚象素点搜索
e、  保存MV并返回SAD值
*/
                 static pel_t   orig_val [256];//16*16宏块的象素个数就是16*16=256个
     static pel_t  *orig_pic  [16] =
      {orig_val,     orig_val+ 16, orig_val+ 32, orig_val+ 48,
                                     orig_val+ 64, orig_val+ 80, orig_val+ 96, orig_val+112,
                                     orig_val+128, orig_val+144, orig_val+160, orig_val+176,
                                     orig_val+192, orig_val+208, orig_val+224, orig_val+240};
……………………………………………………………………
  int       bsx       = input->blc_size[blocktype][0];//mode1就是等于16,mode2时等于16,mode3时等于8
  int       bsy       = input->blc_size[blocktype][1];//mode1就是等于16,mode2时等于8 ,mode3时等于16


  int       pic_pix_x = img->opix_x + mb_x;//!< current original picture pixel horizontal
  int       pic_pix_y = img->opix_y + mb_y;//!< current original picture pixel vertical

  int****** all_mv    = img->all_mv;
/*六重指针all_mv的含义:
对应的是一个六维数组如下:
all_mv[block_x][block_y][list][ref][blocktype][direction]
其中block_x, block_y分别表示4*4块在整个宏块16*16内的水平和垂直位置,
同时也说明所保存的运动矢量都是以4*4为单位的,假如有一个8*4的块,其运动矢量会保存成相同的两份。
List表示的是哪个参考帧列表
Ref表示的是参考帧序号
Blocktype表示的是宏块的类型,有16×16,16×8。。。4×4
Direction表示水平或垂直方向,其值分别是0和1
*/

  if(input->FMEnable)  // FastME enable,可通过配置文件中的参数UseFME 将其关掉# Use fast motion estimation   

        (0=disable, 1=enable)

  {
  …………
  }

  //==================================
  //=====   GET ORIGINAL BLOCK   =====
  //==================================
  for (j = 0; j < bsy; j++)//获得宏块YUV数据
  {
    for (i = 0; i < bsx; i++)
    {
    }
  }
  //===========================================
  //=====   GET MOTION VECTOR PREDICTOR   =====
  //===========================================

  SetMotionVectorPredictor (pred_mv, enc_picture->ref_idx, enc_picture->mv, ref, list, block_x, block_y, bsx, bsy);
void SetMotionVectorPredictor (int  pmv[2],
                               int  ***refPic,
                               int  ****tmp_mv,
                               int  ref_frame,
                               int  list,
                               int  block_x,
                               int  block_y,
                               int  blockshape_x,
                               int  blockshape_y)
{
/*block_x:X方向的坐标
block_y:Y方向的坐标
blockshape_x:该子块X方向的尺寸,MbPartWidth,
blockshape_y:该子块Y方向的尺寸  MbPartHeight
*/

/*
pmv:将要获得的预测向量.
ref_frame:当前参考帧序号,refIdxLX
rFrameL:相邻块A的参考帧序号,即标准中的refIdxLXA
rFrameU:refIdxLXB
rFrameUR:refIdxLXC
refPic:当前编码帧每个4X4子块的参考帧索引.
tmp_mv:当前编码帧每个4X4子块的运动MV包括X,Y两个方向.
(已经运动估计过的的子块,当前编码块相邻的A,B,C,D子块都是已经运动估计了,所以refPic,tmp_mv可以用来参考)
ref_frame:参考帧索引号,不是frame_num,也不是POC号,是位于list中的序号.
block_x:X方向的坐标
block_y:Y方向的坐标
blockshape_x:该子块X方向的尺寸,MbPartWidth,
blockshape_y:该子块Y方向的尺寸  MbPartHeight
*/

  getLuma4x4Neighbour(mb_nr, block_x, block_y,           -1,  0, &block_a);
  getLuma4x4Neighbour(mb_nr, block_x, block_y,            0, -1, &block_b);
  getLuma4x4Neighbour(mb_nr, block_x, block_y, blockshape_x, -1, &block_c);
  getLuma4x4Neighbour(mb_nr, block_x, block_y,           -1, -1, &block_d);

/////////////////////block_c和block_d是什么关系//////////////////////
  if (!block_c.available)
  {
    block_c=block_d;//当C块不存在时就参考D块,C块时再当前块的右上角,D块是在当前块的左上角
  }

  if (!img->MbaffFrameFlag)//>MbaffFrameFlag表明编码器是否支持自适应帧/场编码,这个选项可通过配置文件的参数

PicInterlace设置
  {/*
rFrameL是相邻块A的参考帧序号,即标准中的refIdxLXA
rFrameU:refIdxLXB
rFrameUR:refIdxLXC*/
    rFrameL    = block_a.available    ? refPic[list][block_a.pos_x][block_a.pos_y] : -1;//
    rFrameU    = block_b.available    ? refPic[list][block_b.pos_x][block_b.pos_y] : -1;
    rFrameUR   = block_c.available    ? refPic[list][block_c.pos_x][block_c.pos_y] : -1;
  }
  else/////////////////////////////////////我不支持自适应帧场编码模式,所以这段程序无效
  {
  }

  //中间这些语句是在确定预测方向,即确定rFrameL,rFrameU,rFrameUR等的值
  for (hv=0; hv < 2; hv++)
  {
    if (!img->MbaffFrameFlag || hv==0)//获得候选预测块的矢量,也就是取得abc三块的矢量
    {
      mv_a = block_a.available  ? tmp_mv[list][block_a.pos_x][block_a.pos_y][hv] : 0;
      mv_b = block_b.available  ? tmp_mv[list][block_b.pos_x][block_b.pos_y][hv] : 0;
      mv_c = block_c.available  ? tmp_mv[list][block_c.pos_x][block_c.pos_y][hv] : 0;
    }

    switch (mvPredType)//根据预测方向,确定最后的预测矢量
    {
    case MVPRED_MEDIAN:
    case MVPRED_L:
    case MVPRED_UR:
    default:
      break;
    }
    pmv[hv] = pred_vec;
 }
//*********************以上是SetMotionVectorPredictor 的流程

  //==================================
  //=====   INTEGER-PEL SEARCH   =====
  //==================================
  if(input->FMEnable)
  { 
   else
      {
    //--- perform motion search ---
     min_mcost = FullPelBlockMotionSearch (orig_pic, ref, list, pic_pix_x, pic_pix_y, blocktype,
                                              pred_mv_x, pred_mv_y, &mv_x, &mv_y, search_range,
                                              min_mcost, lambda);
 }
  }
 …………

  //==============================
  //=====   SUB-PEL SEARCH   =====
  //==============================
  if (input->hadamard)
  {
  }
  if(input->FMEnable)
  { 
  }
  else
  {
    min_mcost =  SubPelBlockMotionSearch (orig_pic, ref, list, pic_pix_x, pic_pix_y, blocktype,
                                          pred_mv_x, pred_mv_y, &mv_x, &mv_y, 9, 9,
                                          min_mcost, lambda);
  }
  //===============================================
  //=====   SET MV'S AND RETURN MOTION COST   =====
  //===============================================
  if(input->FMEnable)
  { 
  }
  else
  {
    for (i=0; i < (bsx>>2); i++)
    {
      for (j=0; j < (bsy>>2); j++)
      {
        all_mv[block_x+i][block_y+j][list][ref][blocktype][0] = mv_x;
        all_mv[block_x+i][block_y+j][list][ref][blocktype][1] = mv_y;
      }
    }
  }
  return min_mcost;
}