mv-search.c

来自「the newest JM software by h.264 JVT offi」· C语言 代码 · 共 1,857 行 · 第 1/5 页

C
1,857
字号
      {
        mcost += distortion4x4 (diff64);
      }
    }
  }
  if (params->Transform8x8Mode && (blocktype<=4))  // tchen 4-29-04
  {
    for (byy=0; byy < params->blc_size[parttype][1]; byy += bsy)
      for (bxx=0; bxx < params->blc_size[parttype][0]; bxx += bsx)
      {
        for (k=0, j = byy; j < byy + 8; j++, k += 8)
          memcpy(&diff64[k], &(curr_blk[j][bxx]), 8 * sizeof(int));

        mcost += distortion8x8(diff64);
      }
  }
  return mcost;
}


/*!
 ***********************************************************************
 * \brief
 *    Block motion search
 ***********************************************************************
 */
int                                         //!< minimum motion cost after search
BlockMotionSearch (Macroblock *currMB,      //!< Current Macroblock
                   short     ref,           //!< reference idx
                   int       list,          //!< reference picture list
                   int       mb_x,          //!< x-coordinate inside macroblock
                   int       mb_y,          //!< y-coordinate inside macroblock
                   int       blocktype,     //!< block type (1-16x16 ... 7-4x4)
                   int       search_range,  //!< 1-d search range for integer-position search
                   int*      lambda_factor) //!< lagrangian parameter for determining motion cost
{
  // each 48-pel line stores the 16 luma pels (at 0) followed by 8 or 16 crcb[0] (at 16) and crcb[1] (at 32) pels
  // depending on the type of chroma subsampling used: YUV 4:4:4, 4:2:2, and 4:2:0
  static PixelPos block_a, block_b, block_c, block_d;  // neighbor blocks

  imgpel *orig_pic_tmp = orig_pic;

  int   apply_bi_weights = params->UseWeightedReferenceME && ((img->type == B_SLICE) && active_pps->weighted_bipred_idc != 0);
  int   apply_weights    = params->UseWeightedReferenceME &&
                           ((active_pps->weighted_pred_flag  && (img->type == P_SLICE || img->type == SP_SLICE)) || apply_bi_weights);

  short pred_mv[2];
  MotionVector mv, pred;
  int       i, j;

  int       max_value = INT_MAX;
  int       min_mcost = max_value;

  int       block_x   = (mb_x>>2);
  int       block_y   = (mb_y>>2);

  int       bsx       = params->blc_size[blocktype][0];
  int       bsy       = params->blc_size[blocktype][1];

  int       pic_pix_x = img->opix_x + mb_x;
  int       pic_pix_y = img->opix_y + mb_y;

  int pic_pix_x_c = pic_pix_x >> (shift_cr_x);
  int pic_pix_y_c = pic_pix_y >> (shift_cr_y);
  int bsx_c = bsx >> (shift_cr_x);
  int bsy_c = bsy >> (shift_cr_y);
  
  short***   all_mv = &img->all_mv[list][ref][blocktype][block_y];
  PicMotionParams *motion = &enc_picture->motion;
  int *prevSad = (params->SearchMode == EPZS)? EPZSDistortion[list + currMB->list_offset][blocktype - 1]: NULL;


  get_neighbors(currMB, &block_a, &block_b, &block_c, &block_d, mb_x, mb_y, bsx);
  PrepareMEParams(apply_weights, params->ChromaMEEnable, list + currMB->list_offset, ref);

  //==================================
  //=====   GET ORIGINAL BLOCK   =====
  //==================================
  for (j = pic_pix_y; j < pic_pix_y + bsy; j++)
  {
    memcpy(orig_pic_tmp,&pCurImg[j][pic_pix_x], bsx * sizeof(imgpel));
    orig_pic_tmp += bsx;
  }

  ChromaMEEnable = params->ChromaMEEnable;
  if ( ChromaMEEnable )
  {
    // copy the original cmp1 and cmp2 data to the orig_pic matrix
    for ( i = 1; i<=2; i++)
    {
      orig_pic_tmp = orig_pic + (256 << (i - 1));
      for (j = pic_pix_y_c; j < pic_pix_y_c + bsy_c; j++)
      {
        memcpy(orig_pic_tmp, &(pImgOrg[i][j][pic_pix_x_c]), bsx_c * sizeof(imgpel));
        orig_pic_tmp += bsx_c;
      }
    }
  }

  if (params->SearchMode == UM_HEX)
  {
    UMHEX_blocktype = blocktype;
    bipred_flag = 0;
  }
  else if (params->SearchMode == UM_HEX_SIMPLE)
  {
    smpUMHEX_setup(ref, list, block_y, block_x, blocktype, img->all_mv );
  }

  //===========================================
  //=====   GET MOTION VECTOR PREDICTOR   =====
  //===========================================

  if (params->SearchMode == UM_HEX)
    UMHEXSetMotionVectorPredictor(currMB, pred_mv, motion->ref_idx[list], motion->mv[list], ref, list, mb_x, mb_y, bsx, bsy, &search_range);
  else
    GetMotionVectorPredictor (currMB, &block_a, &block_b, &block_c, pred_mv, motion->ref_idx[list], motion->mv[list], ref, mb_x, mb_y, bsx, bsy);

  pred.mv_x = pred_mv[0];
  pred.mv_y = pred_mv[1];

  //==================================
  //=====   INTEGER-PEL SEARCH   =====
  //==================================
  if (params->EPZSSubPelGrid)
  {
    mv = pred;
  }
  else
  {
    mv.mv_x = (pred.mv_x + 2)>> 2;
    mv.mv_y = (pred.mv_y + 2)>> 2;
  }

  if (!params->rdopt)
  {
    //--- adjust search center so that the (0,0)-vector is inside ---
    mv.mv_x = iClip3 (-search_range<<(params->EPZSGrid), search_range<<(params->EPZSGrid), mv.mv_x);
    mv.mv_y = iClip3 (-search_range<<(params->EPZSGrid), search_range<<(params->EPZSGrid), mv.mv_y);
  }

  // valid search range limits could be precomputed once during the initialization process
   clip_mv_range(img, search_range, &mv, params->EPZSGrid);

  //--- perform motion search ---
    min_mcost = IntPelME (currMB, orig_pic, ref, list,
    motion->ref_idx, motion->mv, pic_pix_x, pic_pix_y, blocktype,
    &pred, &mv, search_range<<(params->EPZSGrid), min_mcost, lambda_factor[F_PEL], apply_weights);
  
  //===== convert search center to quarter-pel units =====
  if (params->EPZSSubPelGrid == 0 || params->SearchMode != EPZS)
  {
    mv.mv_x <<= 2;
    mv.mv_y <<= 2;
  }

  //==============================
  //=====   SUB-PEL SEARCH   =====
  //============================== 
  ChromaMEEnable = (params->ChromaMEEnable == ME_YUV_FP_SP ) ? 1 : 0; // set it externally

  if (!params->DisableSubpelME)
  {
    if (params->SearchMode != EPZS || (ref == 0 || img->structure != FRAME || (ref > 0 && min_mcost < 3.5 * prevSad[pic_pix_x >> 2])))
    {
      if ( !start_me_refinement_hp )
      {
        min_mcost = max_value;
      }
      min_mcost =  SubPelME (orig_pic, ref, list, currMB->list_offset, pic_pix_x, pic_pix_y, blocktype,
        &pred, &mv, 9, 9, min_mcost, lambda_factor, apply_weights);
    }
  }

  // clip mvs after me is performed (is not exactly the best)
  // better solution is to modify search window appropriately
  clip_mv_range(img, 0, &mv, Q_PEL);

  if (!params->rdopt)
  {
    // Get the skip mode cost
    if (blocktype == 1 && (img->type == P_SLICE||img->type == SP_SLICE))
    {
      int cost;

      FindSkipModeMotionVector (currMB);

      cost  = GetSkipCostMB (currMB);
      cost -= ((lambda_factor[Q_PEL] + 4096) >> 13);
      if (cost < min_mcost)
      {
        min_mcost = cost;
        mv.mv_x = img->all_mv [0][0][0][0][0][0];
        mv.mv_y = img->all_mv [0][0][0][0][0][1];
      }
    } 
  }

  //===============================================
  //=====   SET MV'S AND RETURN MOTION COST   =====
  //===============================================

  // Set first line
  for (i=block_x; i < block_x + (bsx>>2); i++)
  {
    all_mv[0][i][0] = mv.mv_x;
    all_mv[0][i][1] = mv.mv_y;
  }

  // set all other lines
  for (j=1; j < (bsy>>2); j++)
  {
    memcpy(all_mv[j][block_x], all_mv[0][block_x], (bsx>>2) * 2 * sizeof(short));
  }


  // Bipred ME consideration: returns minimum bipred cost
  if (img->type == B_SLICE && is_bipred_enabled(blocktype) && (ref == 0)) 
  {
    BiPredBlockMotionSearch(currMB, &mv, &pred, ref, list, mb_x, mb_y, blocktype, search_range, apply_bi_weights, lambda_factor);
  }

  return min_mcost;
}


/*!
 ***********************************************************************
 * \brief
 *    Bi-predictive motion search
 ***********************************************************************
 */
int BiPredBlockMotionSearch(Macroblock *currMB,      //!< Current Macroblock
                   MotionVector *mv,           //!< current list motion vector
                   MotionVector *pred_mv,         //!< current list motion vector predictor
                   short     ref,             //!< reference idx
                   int       list,            //!< reference picture list
                   int       mb_x,            //!< x-coordinate inside macroblock
                   int       mb_y,            //!< y-coordinate inside macroblock
                   int       blocktype,       //!< block type (1-16x16 ... 7-4x4)
                   int       search_range,    //!< 1-d search range for integer-position search
                   int       apply_bi_weights, //!< apply bipred weights
                   int*      lambda_factor)   //!< lagrangian parameter for determining motion cost
{
  int         iteration_no, i, j;
  short       bipred_type = list ? 0 : 1;
  short****** bipred_mv = img->bipred_mv[bipred_type];
  int         min_mcostbi = INT_MAX;
  MotionVector bimv, tempmv;
  MotionVector pred_mv1, pred_mv2, pred_bi;
  MotionVector bi_mv1, bi_mv2;
  short       iterlist=list;
  short       pred_mv_bi[2];
  int         block_x   = (mb_x>>2);
  int         block_y   = (mb_y>>2);
  int         bsx       = params->blc_size[blocktype][0];
  int         bsy       = params->blc_size[blocktype][1];
  int         pic_pix_x = img->opix_x + mb_x;
  int         pic_pix_y = img->opix_y + mb_y;  
  static      PixelPos block_a, block_b, block_c, block_d;  // neighbor blocks
  PicMotionParams *motion = &enc_picture->motion;
  
  get_neighbors(currMB, &block_a, &block_b, &block_c, &block_d, mb_x, mb_y, bsx);

  if (params->SearchMode == UM_HEX)
  {
    bipred_flag = 1;
    UMHEXSetMotionVectorPredictor(currMB, pred_mv_bi, motion->ref_idx[list ^ 1], motion->mv[list ^ 1], 0, list ^ 1, mb_x, mb_y, bsx, bsy, &search_range);
  }
  else
    GetMotionVectorPredictor (currMB, &block_a, &block_b, &block_c, pred_mv_bi, motion->ref_idx[list ^ 1], motion->mv[list ^ 1], 0, mb_x, mb_y, bsx, bsy);

  pred_bi.mv_x = pred_mv_bi[0];
  pred_bi.mv_y = pred_mv_bi[1];

  if ((params->SearchMode != EPZS) || (params->EPZSSubPelGrid == 0))
  {
    mv->mv_x  = (mv->mv_x + 2) >> 2;
    mv->mv_y  = (mv->mv_y + 2) >> 2;
    bimv.mv_x = (pred_bi.mv_x + 2)>>2;
    bimv.mv_y = (pred_bi.mv_y + 2)>>2;
  }
  else
  {
    bimv = pred_bi;
  }

  //Bi-predictive motion Refinements
  for (iteration_no = 0; iteration_no <= params->BiPredMERefinements; iteration_no++)
  {
    if (iteration_no & 0x01)
    {
      pred_mv1  = *pred_mv;
      pred_mv2  = pred_bi;
      bi_mv1    = *mv;
      bi_mv2    = bimv;
      iterlist  = list;
    }
    else
    {
      pred_mv1  = pred_bi;
      pred_mv2  = *pred_mv;
      bi_mv1    = bimv;
      bi_mv2    = *mv;
      iterlist = list ^ 1;
    }

    tempmv = bi_mv1;

    PrepareBiPredMEParams(apply_bi_weights, ChromaMEEnable, iterlist, currMB->list_offset, ref);
    // Get bipred mvs for list iterlist given previously computed mvs from other list
    min_mcostbi = BiPredME (currMB, orig_pic, ref, iterlist, motion->ref_idx, motion->mv,
      pic_pix_x, pic_pix_y, blocktype, &pred_mv1, &pred_mv2, &bi_mv1, &bi_mv2,
      (params->BiPredMESearchRange <<(params->EPZSGrid))>>iteration_no, min_mcostbi, iteration_no, lambda_factor[F_PEL], apply_bi_weights);

    if (iteration_no > 0 && (tempmv.mv_x == bi_mv1.mv_x) && (tempmv.mv_y == bi_mv1.mv_y))
    {
      break;
    }
  }

  if ((params->SearchMode != EPZS) || (params->EPZSSubPelGrid == 0))
  {
    bi_mv2.mv_x = (bi_mv2.mv_x << 2);
    bi_mv2.mv_y = (bi_mv2.mv_y << 2);
    bi_mv1.mv_x = (bi_mv1.mv_x << 2);
    bi_mv1.mv_y = (bi_mv1.mv_y << 2);
  }

  if (!params->DisableSubpelME)
  {
    if (params->BiPredMESubPel)
    {
      min_mcostbi = INT_MAX;
      PrepareBiPredMEParams(apply_bi_weights, ChromaMEEnable, iterlist, currMB->list_offset, ref);

      min_mcostbi =  SubPelBiPredME (orig_pic, ref, iterlist, pic_pix_x, pic_pix_y, blocktype,
        &pred_mv1, &pred_mv2, &bi_mv1, &bi_mv2, 9, 9, min_mcostbi, lambda_factor, apply_bi_weights);
    }

    if (params->BiPredMESubPel==2)
    {
      min_mcostbi = INT_MAX;
      PrepareBiPredMEParams(apply_bi_weights, ChromaMEEnable, iterlist ^ 1, currMB->list_offset, ref);

      min_mcostbi =  SubPelBiPredME (orig_pic, ref, iterlist ^ 1, pic_pix_x, pic_pix_y, blocktype,
        &pred_mv2, &pred_mv1, &bi_mv2, &bi_mv1, 9, 9, min_mcostbi, lambda_factor, apply_bi_weights);
    }
  }

  clip_mv_range(img, 0, &bi_mv1, Q_PEL);
  clip_mv_range(img, 0, &bi_mv2, Q_PEL);

  for (j=block_y; j < block_y + (bsy>>2); j++)
  {
    for (i=block_x ; i < block_x + (bsx>>2); i++)
    {
      bipred_mv[iterlist    ][ref][blocktype][j][i][0] = bi_mv1.mv_x;
      bipred_mv[iterlist    ][ref][blocktype][j][i][1] = bi_mv1.mv_y;
      bipred_mv[iterlist ^ 1][ref][blocktype][j][i][0] = bi_mv2.mv_x;
      bipred_mv[iterlist ^ 1][ref][blocktype][j][i][1] = bi_mv2.mv_y;
    }
  }
  return min_mcostbi;
}

/*!
 ***********************************************************************
 * \brief
 *    Motion Cost for Bidirectional modes
 ***********************************************************************
 */

⌨️ 快捷键说明

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