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

📄 mv-search.c

📁 H.264编码实现
💻 C
📖 第 1 页 / 共 5 页
字号:

  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*    pred_mv = img->pred_mv[list][ref][blocktype][block_y][block_x];
  short***   all_mv = &img->all_mv[list][ref][blocktype][block_y];
  int list_offset = ((img->MbaffFrameFlag) && (currMB->mb_field)) ? img->current_mb_nr % 2 ? 4 : 2 : 0;
  int *prevSad = (params->SearchMode == EPZS)? EPZSDistortion[list + list_offset][blocktype - 1]: NULL;

#if GET_METIME
  static TIME_T me_time_start;
  static TIME_T me_time_end;
  time_t me_tmp_time;
  gettime( &me_time_start );    // start time ms
#endif
  PrepareMEParams(apply_weights, params->ChromaMEEnable, list + 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 );
  }

  // Set if 8x8 transform will be used if SATD is used
  test8x8transform = params->Transform8x8Mode && blocktype <= 4;

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

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


  //==================================
  //=====   INTEGER-PEL SEARCH   =====
  //==================================
  if (params->EPZSSubPelGrid)
  {
    mv[0] = pred_mv[0];
    mv[1] = pred_mv[1];
  }
  else
  {
    mv[0] = (pred_mv[0] + 2)>> 2;
    mv[1] = (pred_mv[1] + 2)>> 2;
  }

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

  // 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, list_offset,
    enc_picture->motion.ref_idx, enc_picture->motion.mv, pic_pix_x, pic_pix_y, blocktype,
    pred_mv, 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[0] <<= 2;
    mv[1] <<= 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, list_offset, pic_pix_x, pic_pix_y, blocktype,
        pred_mv, mv, 9, 9, min_mcost, lambda_factor, apply_weights);
    }
  }

  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[0]      = img->all_mv [0][0][0][0][0][0];
        mv[1]      = 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[0];
    all_mv[0][i][1] = mv[1];
  }

  // 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_mv, ref, list, mb_x, mb_y, blocktype, search_range, apply_bi_weights, lambda_factor);
  }

#if GET_METIME
  gettime(&me_time_end);   // end time ms
  me_tmp_time = timediff (&me_time_start, &me_time_end);
  me_tot_time += me_tmp_time;
  me_time += me_tmp_time;
#endif
  return min_mcost;
}


/*!
 ***********************************************************************
 * \brief
 *    Block bi-prediction motion search
 ***********************************************************************
 */
int BiPredBlockMotionSearch(Macroblock *currMB,      //!< Current Macroblock
                   short     mv[2],           //!< current list motion vector
                   short*    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;
  short       bimv[2] = {0, 0}, tempmv[2] = {0, 0};
  short*      pred_mv1 = NULL;
  short*      pred_mv2 = NULL;
  short*      bi_mv1 = NULL, *bi_mv2 = NULL;
  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;
  int         list_offset = ((img->MbaffFrameFlag) && (currMB->mb_field)) ? img->current_mb_nr % 2 ? 4 : 2 : 0;

  if (params->SearchMode == UM_HEX)
  {
    bipred_flag = 1;
    UMHEXSetMotionVectorPredictor(currMB, pred_mv_bi, enc_picture->motion.ref_idx[list ^ 1], enc_picture->motion.mv[(list == LIST_0? LIST_1: LIST_0)], 0, (list == LIST_0? LIST_1: LIST_0), mb_x, mb_y, bsx, bsy, &search_range);
  }
  else
    SetMotionVectorPredictor     (currMB, pred_mv_bi, enc_picture->motion.ref_idx[list ^ 1], enc_picture->motion.mv[(list == LIST_0? LIST_1: LIST_0)], 0, (list == LIST_0? LIST_1: LIST_0), mb_x, mb_y, bsx, bsy);

  if ((params->SearchMode != EPZS) || (params->EPZSSubPelGrid == 0))
  {
    mv[0] = (mv[0] + 2) >> 2;
    mv[1] = (mv[1] + 2) >> 2;
    bimv[0] = (pred_mv_bi[0] + 2)>>2;
    bimv[1] = (pred_mv_bi[1] + 2)>>2;
  }
  else
  {
    bimv[0] = pred_mv_bi[0];
    bimv[1] = pred_mv_bi[1];
  }

  //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_mv_bi;
      bi_mv1    = mv;
      bi_mv2    = bimv;
      iterlist  = list;
    }
    else
    {
      pred_mv1  = pred_mv_bi;
      pred_mv2  = pred_mv;
      bi_mv1    = bimv;
      bi_mv2    = mv;
      iterlist = list ^ 1;
    }

    tempmv[0] = bi_mv1[0];
    tempmv[1] = bi_mv1[1];

    PrepareBiPredMEParams(apply_bi_weights, ChromaMEEnable, iterlist, list_offset, ref);
    // Get bipred mvs for list iterlist given previously computed mvs from other list
    min_mcostbi = BiPredME (currMB, orig_pic, ref, iterlist, list_offset, enc_picture->motion.ref_idx, enc_picture->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[0] == bi_mv1[0]) && (tempmv[1] == bi_mv1[1]))
    {
      break;
    }
  }

  if ((params->SearchMode != EPZS) || (params->EPZSSubPelGrid == 0))
  {
    bi_mv2[0] = (bi_mv2[0] << 2);
    bi_mv2[1] = (bi_mv2[1] << 2);
    bi_mv1[0] = (bi_mv1[0] << 2);
    bi_mv1[1] = (bi_mv1[1] << 2);
  }

  if (!params->DisableSubpelME)
  {
    if (params->BiPredMESubPel)
    {
      min_mcostbi = INT_MAX;
      PrepareBiPredMEParams(apply_bi_weights, ChromaMEEnable, iterlist, 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, 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);
    }
  }

  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[0];
      bipred_mv[iterlist    ][ref][blocktype][j][i][1] = bi_mv1[1];
      bipred_mv[iterlist ^ 1][ref][blocktype][j][i][0] = bi_mv2[0];
      bipred_mv[iterlist ^ 1][ref][blocktype][j][i][1] = bi_mv2[1];
    }
  }
  return min_mcostbi;
}

/*!
 ***********************************************************************
 * \brief
 *    Motion Cost for Bidirectional modes
 ***********************************************************************
 */
int BIDPartitionCost (Macroblock *currMB, 
                      int   blocktype,
                      int   block8x8,
                      char  cur_ref[2],
                      int   lambda_factor)
{
  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}};

  int   curr_blk[MB_BLOCK_SIZE][MB_BLOCK_SIZE]; // ABT pred.error buffer
  int   bsx       = imin(params->blc_size[blocktype][0],8);
  int   bsy       = imin(params->blc_size[blocktype][1],8);

  int   pic_pix_x, pic_pix_y, block_x, block_y;
  int   v, h, mcost, i, j, k;
  int   mvd_bits  = 0;
  int   parttype  = (blocktype<4?blocktype:4);
  int   step_h0   = (params->part_size[ parttype][0]);
  int   step_v0   = (params->part_size[ parttype][1]);
  int   step_h    = (params->part_size[blocktype][0]);
  int   step_v    = (params->part_size[blocktype][1]);
  int   bxx, byy;                               // indexing curr_blk
  int   bx = bx0[parttype][block8x8];
  int   by = by0[parttype][block8x8];
  short   ***   p_mv_l0 = img->pred_mv[LIST_0][(int) cur_ref[LIST_0]][blocktype];
  short   ***   p_mv_l1 = img->pred_mv[LIST_1][(int) cur_ref[LIST_1]][blocktype];
  short   *** all_mv_l0 = img->all_mv [LIST_0][(int) cur_ref[LIST_0]][blocktype];
  short   *** all_mv_l1 = img->all_mv [LIST_1][(int) cur_ref[LIST_1]][blocktype];
  short bipred_me =  0; //no bipred for this case 
  imgpel  (*mb_pred)[16] = img->mb_pred[0];

  //----- cost for motion vector bits -----
  // Should write a separate, small function to do this processing
  // List0 
  mvd_bits = mv_bits_cost(all_mv_l0, p_mv_l0, by, bx, step_v0, step_v, step_h0, step_h, mvd_bits);
  // List1
  mvd_bits = mv_bits_cost(all_mv_l1, p_mv_l1, by, bx, step_v0, step_v, step_h0, step_h, mvd_bits);

  mcost = WEIGHTED_COST (lambda_factor, mvd_bits);

  //----- cost of residual signal -----
  for (byy=0, v=by; v<by + step_v0; byy+=4, v++)
  {
    pic_pix_y = img->opix_y + (block_y = (v<<2));
    for (bxx=0, h=bx; h<bx + step_h0; bxx+=4, h++)
    {

⌨️ 快捷键说明

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