⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mv-search.c

📁 h.264/avc 视频编码程序,实现分数像素匹配功能,非原创.
💻 C
📖 第 1 页 / 共 5 页
字号:
  //--- delete arrays ---
  free (spiral_search_x);
  free (spiral_search_y);
  free (mvbits);
  free (refbits);
  free (byte_abs);
  free_mem3Dint (motion_cost, 8);

#ifdef _FAST_FULL_ME_
  ClearFastFullIntegerSearch ();
#endif
}



/*!
 ***********************************************************************
 * \brief
 *    Full pixel block motion search
 ***********************************************************************
 */
int                                               //  ==> minimum motion cost after search
FullPelBlockMotionSearch (pel_t**   orig_pic,     // <--  original pixel values for the AxB block
                          int       ref,          // <--  reference frame (0... or -1 (backward))
                          int       pic_pix_x,    // <--  absolute x-coordinate of regarded AxB block
                          int       pic_pix_y,    // <--  absolute y-coordinate of regarded AxB block
                          int       blocktype,    // <--  block type (1-16x16 ... 7-4x4)
                          int       pred_mv_x,    // <--  motion vector predictor (x) in sub-pel units
                          int       pred_mv_y,    // <--  motion vector predictor (y) in sub-pel units
                          int*      mv_x,         // <--> in: search center (x) / out: motion vector (x) - in pel units
                          int*      mv_y,         // <--> in: search center (y) / out: motion vector (y) - in pel units
                          int       search_range_x, // <--  1-d search range in pel units (horizontal)
						  int       search_range_y, // <--  1-d search range in pel units (vertical) 
                          int       min_mcost,    // <--  minimum motion cost (cost for center or huge value)
                          double    lambda)       // <--  lagrangian parameter for determining motion cost
{
  int   pos, cand_x, cand_y, y, x4, mcost;
  pel_t *orig_line, *ref_line;
  pel_t *(*get_ref_line)(int, pel_t*, int, int);

  pel_t*ref_pic       = (ref==-1 ? Refbuf11_P : Refbuf11 [ref]);
  int   best_pos      = 0;                                        // position with minimum motion cost
  int   max_pos       = (2*search_range_x+1)*(2*search_range_y+1);    // number of search positions
  int   lambda_factor = LAMBDA_FACTOR (lambda);                   // factor for determining lagragian motion cost
  int   mvshift       = (input->mv_res ? 3 : 2);                  // motion vector shift for getting sub-pel units
  int   blocksize_y   = input->blc_size[blocktype][1];            // vertical block size
  int   blocksize_x   = input->blc_size[blocktype][0];            // horizontal block size
  int   blocksize_x4  = blocksize_x >> 2;                         // horizontal block size in 4-pel units
  int   pred_x        = (pic_pix_x << mvshift) + pred_mv_x;       // predicted position x (in sub-pel units)
  int   pred_y        = (pic_pix_y << mvshift) + pred_mv_y;       // predicted position y (in sub-pel units)
  int   center_x      = pic_pix_x + *mv_x;                        // center position x (in pel units)
  int   center_y      = pic_pix_y + *mv_y;                        // center position y (in pel units)
  int   check_for_00  = (blocktype==1 && !input->rdopt && img->type!=B_IMG && ref==0);

  //===== set function for getting reference picture lines =====
  if ((center_x > search_range_x) && (center_x < img->width -1-search_range_x-blocksize_x) &&
      (center_y > search_range_y) && (center_y < img->height-1-search_range_y-blocksize_y)   )
  {
     get_ref_line = FastLineX;
  }
  else
  {
     get_ref_line = UMVLineX;
  }


  //===== loop over all search positions =====
  for (pos=0; pos<max_pos; pos++)
  {
    //--- set candidate position (absolute position in pel units) ---
    cand_x = center_x + spiral_search_x[pos];
    cand_y = center_y + spiral_search_y[pos];

    //--- initialize motion cost (cost for motion vector) and check ---
    mcost = MV_COST (lambda_factor, mvshift, cand_x, cand_y, pred_x, pred_y);
    if (check_for_00 && cand_x==pic_pix_x && cand_y==pic_pix_y)
    {
      mcost -= WEIGHTED_COST (lambda_factor, 16);
    }
    if (mcost >= min_mcost)   continue;

    //--- add residual cost to motion cost ---
    for (y=0; y<blocksize_y; y++)
    {
      ref_line  = get_ref_line (blocksize_x, ref_pic, cand_y+y, cand_x);
      orig_line = orig_pic [y];

      for (x4=0; x4<blocksize_x4; x4++)
      {
        mcost += byte_abs[ *orig_line++ - *ref_line++ ];
        mcost += byte_abs[ *orig_line++ - *ref_line++ ];
        mcost += byte_abs[ *orig_line++ - *ref_line++ ];
        mcost += byte_abs[ *orig_line++ - *ref_line++ ];
      }

      if (mcost >= min_mcost)
      {
        break;
      }
    }

    //--- check if motion cost is less than minimum cost ---
    if (mcost < min_mcost)
    {
      best_pos  = pos;
      min_mcost = mcost;
    }
  }


  //===== set best motion vector and return minimum motion cost =====
  if (best_pos)
  {
    *mv_x += spiral_search_x[best_pos];
    *mv_y += spiral_search_y[best_pos];
  }
  return min_mcost;
}


#ifdef _FAST_FULL_ME_
/*!
 ***********************************************************************
 * \brief
 *    Fast Full pixel block motion search
 ***********************************************************************
 */
int                                                   //  ==> minimum motion cost after search
FastFullPelBlockMotionSearch (pel_t**   orig_pic,     // <--  not used
                              int       ref,          // <--  reference frame (0... or -1 (backward))
                              int       pic_pix_x,    // <--  absolute x-coordinate of regarded AxB block
                              int       pic_pix_y,    // <--  absolute y-coordinate of regarded AxB block
                              int       blocktype,    // <--  block type (1-16x16 ... 7-4x4)
                              int       pred_mv_x,    // <--  motion vector predictor (x) in sub-pel units
                              int       pred_mv_y,    // <--  motion vector predictor (y) in sub-pel units
                              int*      mv_x,         //  --> motion vector (x) - in pel units
                              int*      mv_y,         //  --> motion vector (y) - in pel units
                              int       search_range_x, // <--  1-d search range in pel units (horizontal)
							  int       search_range_y, // <--  1-d search range in pel units (vertical)
                              int       min_mcost,    // <--  minimum motion cost (cost for center or huge value)
                              double    lambda)       // <--  lagrangian parameter for determining motion cost
{
  int   pos, offset_x, offset_y, cand_x, cand_y, mcost;

  int   refindex      = (ref!=-1 ? ref : img->buf_cycle);                   // reference frame index (array entry)
  int   max_pos       = (2*search_range_x+1)*(2*search_range_y+1);          // number of search positions
  int   lambda_factor = LAMBDA_FACTOR (lambda);                             // factor for determining lagragian motion cost
  int   mvshift       = (input->mv_res ? 3 : 2);                            // motion vector shift for getting sub-pel units
  int   best_pos      = 0;                                                  // position with minimum motion cost
  int   block_index   = (pic_pix_y-img->pix_y)+((pic_pix_x-img->pix_x)>>2); // block index for indexing SAD array
  int*  block_sad     = BlockSAD[refindex][blocktype][block_index];         // pointer to SAD array


  //===== set up fast full integer search if needed / set search center =====
  if (!search_setup_done[refindex])
  {
    SetupFastFullPelSearch (ref);
  }
  offset_x = search_center_x[refindex] - img->pix_x;
  offset_y = search_center_y[refindex] - img->pix_y;


  //===== cost for (0,0)-vector: it is done before, because MVCost can be negative =====
  if (!input->rdopt)
  {
    mcost = block_sad[pos_00[refindex]] + MV_COST (lambda_factor, mvshift, 0, 0, pred_mv_x, pred_mv_y);
    if (img->type!=B_IMG && blocktype==1 && ref==0)
    {
      mcost -= WEIGHTED_COST (lambda_factor, 16);
    }

    if (mcost < min_mcost)
    {
      min_mcost = mcost;
      best_pos  = pos_00[refindex];
    }
  }

  //===== loop over all search positions =====
  for (pos=0; pos<max_pos; pos++, block_sad++)
  {
    //--- check residual cost ---
    if (*block_sad < min_mcost)
    {
      //--- get motion vector cost ---
      cand_x = offset_x + spiral_search_x[pos];
      cand_y = offset_y + spiral_search_y[pos];
      mcost  = *block_sad;
      mcost += MV_COST (lambda_factor, mvshift, cand_x, cand_y, pred_mv_x, pred_mv_y);

      //--- check motion cost ---
      if (mcost < min_mcost)
      {
        min_mcost = mcost;
        best_pos  = pos;
      }
    }
  }

  //===== set best motion vector and return minimum motion cost =====
  *mv_x = offset_x + spiral_search_x[best_pos];
  *mv_y = offset_y + spiral_search_y[best_pos];
  return min_mcost;
}
//***********************************************************************
//==============fast integer motion estimation algorithm by tsinghua univ., Zhibo Chen, July 22, 2002================
//***********************************************************************
int                                                   //  ==> minimum motion cost after search
FastFullPelBlockMotionSearch_chen (pel_t**   orig_pic,     // <--  not used
                              int       ref,          // <--  reference frame (0... or -1 (backward))
                              int       pic_pix_x,    // <--  absolute x-coordinate of regarded AxB block
                              int       pic_pix_y,    // <--  absolute y-coordinate of regarded AxB block
                              int       blocktype,    // <--  block type (1-16x16 ... 7-4x4)
                              int       pred_mv_x,    // <--  motion vector predictor (x) in sub-pel units
                              int       pred_mv_y,    // <--  motion vector predictor (y) in sub-pel units
                              int*      mv_x,         //  --> motion vector (x) - in pel units
                              int*      mv_y,         //  --> motion vector (y) - in pel units
                              int       search_range_x, // <--  1-d search range in pel units                         
                              int       search_range_y, // <--  1-d search range in pel units                         
                              int       min_mcost,    // <--  minimum motion cost (cost for center or huge value)
                              double    lambda)       // <--  lagrangian parameter for determining motion cost
{
  int   pos, offset_x, offset_y, cand_x, cand_y, mcost,mcost0;
  
  int   refindex      = (ref!=-1 ? ref : img->buf_cycle);                   // reference frame index (array entry)
  int     search_range_dynamic = max(search_range_x,search_range_y);  //add for Dynamic search
  int     search_range = input->search_range;  //add for Dynamic search 
  int   max_pos       = (2*search_range+1)*(2*search_range+1);              // number of search positions
  int   lambda_factor = LAMBDA_FACTOR (lambda);                             // factor for determining lagragian motion cost
  int   mvshift       = (input->mv_res ? 3 : 2);                            // motion vector shift for getting sub-pel units
  int   best_pos      = 0;                                                  // position with minimum motion cost
  int   block_index   = (pic_pix_y-img->pix_y)+((pic_pix_x-img->pix_x)>>2); // block index for indexing SAD array
  int*  block_sad     = BlockSAD[refindex][blocktype][block_index];         // pointer to SAD array
  char*  search_pos;
  
  int     predict_mv_x,predict_mv_y;
  int     center_x,center_y;
  pel_t   orig_blocks[256], *orgptr=orig_blocks,*refptr;
  pel_t*  ref_pic       = (ref>=0 ? Refbuf11[ref] : Refbuf11_P);
  int     y,x,iXMinNow, iYMinNow, i,iXMinNext,iYMinNext;
  int     iDistortion0,iDistortion1,iDistortion2,iSADLayer,m,pos_x,pos_y,iSAD,currmv_x,currmv_y;
  int     range_partly_outside;
  int     max_width     = img->width  - 17;
  int     max_height    = img->height - 17;
  int 	  search_step_orgin,search_step,search_index;
  
  int     iMinPred_x, iMinPred_y, iSadMinPred, iUsePred, iMvPred_x, iMvPred_y;
  
  
  predict_mv_x = ceil((float)pred_mv_x / (1 << mvshift));// 
  predict_mv_y = ceil((float)pred_mv_y / (1 << mvshift));// 
  
  ////////////////////////////////////////
  
  center_x = predict_mv_x + img->pix_x; 
  center_y = predict_mv_y + img->pix_y;
  offset_x = center_x - img->pix_x; 
  offset_y = center_y - img->pix_y;

  if(offset_x!= 0 || offset_y!=0)
    iUsePred = 1;
  else
    iUsePred = 0;

  if (center_x >= search_range && center_x <= max_width  - search_range &&
      center_y >= search_range && center_y <= max_height - search_range   )
  {
    range_partly_outside = 0; PelYline_11 = FastLine16Y_11;
  }
  else
  {
    range_partly_outside = 1;
  }
  
  for(y=0;y<2*search_range+1;y++)
    for(x=0;x<2*search_range+1;x++)
    {
      SearchState[y][x]=0;
      SearchStateMaD[y][x]=0;
    }
  
    for   (y = img->pix_y; y < img->pix_y+16; y++)
      for (x = img->pix_x; x < img->pix_x+16; x++)
      {
        *orgptr++ = imgY_org [y][x];
      }
    
    if(search_model == 0)
     	search_step_orgin  = 5;
    else  if(search_model == 1)
     	search_step_orgin  = 3;
    else
     	search_step_orgin  = 1;
     	 	
      orgptr = orig_blocks;
      mcost0 = CalMad(range_partly_outside,orgptr,ref_pic,16,16,center_x,center_y);
      SearchStateMaD[search_range][search_range] = mcost0; //(0,0)should be where predictor point
       mcost0 += MV_COST (lambda_factor, mvshift, offset_x, offset_y, pred_mv_x, pred_mv_y);
      SearchState[search_range][search_range] = mcost0; //(0,0)should be where predictor point
      if (mcost0 < min_mcost)
     {
        min_mcost = mcost0;
        iXMinNow = center_x;
        iYMinNow = center_y; 
        currmv_x = offset_x;
        currmv_y = offset_y;
      }
      
      search_step = search_step_orgin;
      iDistortion0 = iDistortion1 = iDistortion2 = 65536; 
      while(search_step>0)
      {
      search_index = 1;
       for(i=0;i<2*search_range_dynamic/search_step;i++)
      {
        iSADLayer = 65536;
        for (m = 0; m < 8; m++)
        {		
          orgptr = orig_blocks;	
          pos_x = iXMinNow + gpiHoriozntalPos[m]*search_step*search_index;
          pos_y = iYMinNow + gpiVerticalPos[m]*search_step*search_index;
          if(abs(pos_x - center_x) <32 && abs(pos_y - center_y)< 32)
          {
          if(SearchState[pos_y-center_y+search_range][pos_x-center_x+search_range])
            iSAD = SearchState[pos_y-center_y+search_range][pos_x-center_x+search_range];
          else
          {
            iSAD = CalMad(range_partly_outside,orgptr,ref_pic,16,16,pos_x,pos_y);
            SearchStateMaD[pos_y-center_y+search_range][pos_x-center_x+search_range] = iSAD;
            iSAD += MV_COST (lambda_factor, mvshift, pos_x-img->pix_x, pos_y-img->pix_y, pred_mv_x, pred_mv_y);//Mv_cost;
            SearchState[pos_y-center_y+search_range][pos_x-center_x+search_range] = iSAD;
          }
          if (iSAD < min_mcost)
          {
            currmv_x = pos_x - img->pix_x;
            currmv_y = pos_y - img->pix_y;
            min_mcost = iSAD;
          }
          if (iSAD < iSADLayer)
          {
            iSADLayer = iSAD;
            iXMinNext = pos_x;
            iYMinNext = pos_y;
          }
         }
        }
        iDistortion2 = iDistortion1;
        iDistortion1 = iDistortion0;
        iDistortion0 = iSADLayer;
        if (iDistortion1 <= iDistortion0 && iDistortion2 <= iDistortion0)
        {
          break;
        }
        search_index += 1;  
      }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -