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

📄 mv-search.c

📁 H.264编码实现
💻 C
📖 第 1 页 / 共 5 页
字号:
          ? tmp_mv[block_b.pos_y][block_b.pos_x][hv]
          : tmp_mv[block_b.pos_y][block_b.pos_x][hv] / 2
          : 0;
        mv_c = block_c.available  ? img->mb_data[block_c.mb_addr].mb_field
          ? tmp_mv[block_c.pos_y][block_c.pos_x][hv]
          : tmp_mv[block_c.pos_y][block_c.pos_x][hv] / 2
          : 0;
      }
      else
      {
        mv_a = block_a.available  ? img->mb_data[block_a.mb_addr].mb_field
          ? tmp_mv[block_a.pos_y][block_a.pos_x][hv] * 2
          : tmp_mv[block_a.pos_y][block_a.pos_x][hv]
          : 0;
        mv_b = block_b.available  ? img->mb_data[block_b.mb_addr].mb_field
          ? tmp_mv[block_b.pos_y][block_b.pos_x][hv] * 2
          : tmp_mv[block_b.pos_y][block_b.pos_x][hv]
          : 0;
        mv_c = block_c.available  ? img->mb_data[block_c.mb_addr].mb_field
          ? tmp_mv[block_c.pos_y][block_c.pos_x][hv] * 2
          : tmp_mv[block_c.pos_y][block_c.pos_x][hv]
          : 0;
      }
    }

    switch (mvPredType)
    {
    case MVPRED_MEDIAN:
      if(!(block_b.available || block_c.available))
      {
        pred_vec = mv_a;
      }
      else
      {
        pred_vec = mv_a+mv_b+mv_c-imin(mv_a,imin(mv_b,mv_c))-imax(mv_a,imax(mv_b,mv_c));
      }
      break;
    case MVPRED_L:
      pred_vec = mv_a;
      break;
    case MVPRED_U:
      pred_vec = mv_b;
      break;
    case MVPRED_UR:
      pred_vec = mv_c;
      break;
    default:
      break;
    }

    pmv[hv] = pred_vec;
  }
}

/*!
************************************************************************
* \brief
*    Initialize the motion search
************************************************************************
*/
void Init_Motion_Search_Module (void)
{
  int bits, i_min, i_max, k;
  int i, l;

  int search_range               = params->search_range;
  int max_search_points          = imax(9, (2*search_range+1)*(2*search_range+1));
  int max_ref_bits               = 1 + 2 * (int)floor(log(imax(16, img->max_num_references + 1)) / log(2) + 1e-10);
  int max_ref                    = (1<<((max_ref_bits>>1)+1))-1;
  int number_of_subpel_positions = 4 * (2*search_range+3);
  int max_mv_bits                = 3 + 2 * (int)ceil (log(number_of_subpel_positions+1) / log(2) + 1e-10);
  max_mvd                        = (1<<( max_mv_bits >>1)   )-1;
  byte_abs_range                 = (imax(img->max_imgpel_value_comp[0],img->max_imgpel_value_comp[1]) + 1) * 64;

  //=====   CREATE ARRAYS   =====
  //-----------------------------
  if ((spiral_search_x = (short*)calloc(max_search_points, sizeof(short))) == NULL)
    no_mem_exit("Init_Motion_Search_Module: spiral_search_x");
  if ((spiral_search_y = (short*)calloc(max_search_points, sizeof(short))) == NULL)
    no_mem_exit("Init_Motion_Search_Module: spiral_search_y");
  if ((spiral_hpel_search_x = (short*)calloc(max_search_points, sizeof(short))) == NULL)
    no_mem_exit("Init_Motion_Search_Module: spiral_hpel_search_x");
  if ((spiral_hpel_search_y = (short*)calloc(max_search_points, sizeof(short))) == NULL)
    no_mem_exit("Init_Motion_Search_Module: spiral_hpel_search_y");

  if ((mvbits = (int*)calloc(2 * max_mvd + 1, sizeof(int))) == NULL)
    no_mem_exit("Init_Motion_Search_Module: mvbits");

  if ((refbits = (int*)calloc(max_ref, sizeof(int))) == NULL)
    no_mem_exit("Init_Motion_Search_Module: refbits");
  if ((byte_abs = (int*)calloc(byte_abs_range, sizeof(int))) == NULL)
    no_mem_exit("Init_Motion_Search_Module: byte_abs");

  if (img->max_num_references)
    get_mem4Dint (&motion_cost, 8, 2, img->max_num_references, 4);

  //--- set array offsets ---
  mvbits   += max_mvd;
  byte_abs += byte_abs_range/2;

  //=====   INIT ARRAYS   =====
  //---------------------------
  //--- init array: motion vector bits ---
  mvbits[0] = 1;
  for (bits=3; bits<=max_mv_bits; bits+=2)
  {
    i_max = 1    << (bits >> 1);
    i_min = i_max >> 1;

    for (i = i_min; i < i_max; i++)
      mvbits[-i] = mvbits[i] = bits;
  }

  //--- init array: reference frame bits ---
  refbits[0] = 1;
  for (bits=3; bits<=max_ref_bits; bits+=2)
  {
    i_max = (1   << ((bits >> 1) + 1)) - 1;
    i_min = i_max >> 1;

    for (i = i_min; i < i_max; i++)
      refbits[i] = bits;
  }

  //--- init array: absolute value ---
  byte_abs[0] = 0;
  // Set scaler for integer/subpel motion refinement.
  // Currently only EPZS supports subpel positions


  for (i=1; i<byte_abs_range/2; i++)
  {
    byte_abs[i] = byte_abs[-i] = i;
  }

  //--- init array: search pattern ---
  spiral_search_x[0] = spiral_search_y[0] = 0;
  spiral_hpel_search_x[0] = spiral_hpel_search_y[0] = 0;

  for (k=1, l=1; l <= imax(1,search_range); l++)
  {
    for (i=-l+1; i< l; i++)
    {
      spiral_search_x[k] =  i;
      spiral_search_y[k] = -l;
      spiral_hpel_search_x[k] =  i<<1;
      spiral_hpel_search_y[k++] = -l<<1;
      spiral_search_x[k] =  i;
      spiral_search_y[k] =  l;
      spiral_hpel_search_x[k] =  i<<1;
      spiral_hpel_search_y[k++] =  l<<1;
    }
    for (i=-l;   i<=l; i++)
    {
      spiral_search_x[k] = -l;
      spiral_search_y[k] =  i;
      spiral_hpel_search_x[k] = -l<<1;
      spiral_hpel_search_y[k++] = i<<1;
      spiral_search_x[k] =  l;
      spiral_search_y[k] =  i;
      spiral_hpel_search_x[k] =  l<<1;
      spiral_hpel_search_y[k++] = i<<1;
    }
  }

  // set global variable prior to ME
  start_me_refinement_hp = (params->ChromaMEEnable == 1 || params->MEErrorMetric[F_PEL] != params->MEErrorMetric[H_PEL] ) ? 0 : 1;
  start_me_refinement_qp = (params->ChromaMEEnable == 1 || params->MEErrorMetric[H_PEL] != params->MEErrorMetric[Q_PEL] ) ? 0 : 1;

  // Setup Distortion Metrics depending on refinement level
  for (i=0; i<3; i++)
  {
    switch(params->MEErrorMetric[i])
    {
    case ERROR_SAD:
      computeUniPred[i] = computeSAD;
      computeUniPred[i + 3] = computeSADWP;
      computeBiPred1[i] = computeBiPredSAD1;
      computeBiPred2[i] = computeBiPredSAD2;
      break;
    case ERROR_SSE:
      computeUniPred[i] = computeSSE;
      computeUniPred[i + 3] = computeSSEWP;
      computeBiPred1[i] = computeBiPredSSE1;
      computeBiPred2[i] = computeBiPredSSE2;
      break;
    case ERROR_SATD :
    default:
      computeUniPred[i] = computeSATD;
      computeUniPred[i + 3] = computeSATDWP;
      computeBiPred1[i] = computeBiPredSATD1;
      computeBiPred2[i] = computeBiPredSATD2;
      break;
    }
  }
  // Setup buffer access methods
  get_line[0] = FastLine4X;
  get_line[1] = UMVLine4X;
  get_crline[0] = FastLine8X_chroma;
  get_crline[1] = UMVLine8X_chroma;

  if (!params->IntraProfile)
  {
    if(params->SearchMode == FAST_FULL_SEARCH)
      InitializeFastFullIntegerSearch ();

    init_ME_engine(params->SearchMode);

    if (params->SearchMode == UM_HEX)
      UMHEX_DefineThreshold();
  }
}

/*!
 ************************************************************************
 * \brief
 *    Free memory used by motion search
 ************************************************************************
 */
void
Clear_Motion_Search_Module ()
{
  //--- correct array offset ---
  mvbits   -= max_mvd;
  byte_abs -= byte_abs_range/2;

  //--- delete arrays ---
  free (spiral_search_x);
  free (spiral_search_y);
  free (spiral_hpel_search_x);
  free (spiral_hpel_search_y);
  free (mvbits);
  free (refbits);
  free (byte_abs);

  if (motion_cost)
    free_mem4Dint (motion_cost);

  if ((params->SearchMode == FAST_FULL_SEARCH) && (!params->IntraProfile) )
    ClearFastFullIntegerSearch ();
}

static inline int mv_bits_cost(short ***all_mv, short ***p_mv, int by, int bx, int step_v0, int step_v, int step_h0, int step_h, int mvd_bits)
{
  int v, h;
  for (v=by; v<by + step_v0; v+=step_v)
  {
    for (h=bx; h<bx + step_h0; h+=step_h)
    {
      mvd_bits += mvbits[ all_mv[v][h][0] - p_mv[v][h][0] ];
      mvd_bits += mvbits[ all_mv[v][h][1] - p_mv[v][h][1] ];
    }
  }
  return mvd_bits;
}

/*!
 ***********************************************************************
 * \brief
 *    Motion Cost for Bidirectional modes
 ***********************************************************************
 */
int BPredPartitionCost (Macroblock *currMB,
                        int   blocktype,
                        int   block8x8,
                        short ref_l0,
                        short ref_l1,
                        int   lambda_factor,
                        int   list)
{
  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   by0_part = by0[parttype][block8x8];
  int   bx0_part = bx0[parttype][block8x8];

  short   ***all_mv_l0 = img->bipred_mv[list][LIST_0][ref_l0][blocktype]; 
  short   ***all_mv_l1 = img->bipred_mv[list][LIST_1][ref_l1][blocktype]; 
  short   ***p_mv_l0   = img->pred_mv[LIST_0][ref_l0][blocktype];
  short   ***p_mv_l1   = img->pred_mv[LIST_1][ref_l1][blocktype];
  imgpel  (*mb_pred)[16] = img->mb_pred[0];

  // List0 
  mvd_bits = mv_bits_cost(all_mv_l0, p_mv_l0, by0_part, bx0_part, step_v0, step_v, step_h0, step_h, mvd_bits);
  // List1
  mvd_bits = mv_bits_cost(all_mv_l1, p_mv_l1, by0_part, bx0_part, 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=by0_part; v < by0_part + step_v0; byy += 4, v++)
  {

    pic_pix_y = img->opix_y + (block_y = (v<<2));
    for (bxx=0, h = bx0_part; h < bx0_part + step_h0; bxx += 4, h++)
    {
      pic_pix_x = img->opix_x + (block_x = (h<<2));
      LumaPredictionBi (currMB, block_x, block_y, 4, 4, blocktype, blocktype, ref_l0, ref_l1, list);

      for (k = j = 0; j < 4; j++)
      {
        for (i = 0; i < 4; i++)
          diff64[k++] = curr_blk[byy+j][bxx+i] =
          pCurImg[pic_pix_y+j][pic_pix_x+i] - mb_pred[j+block_y][i+block_x];
      }

      if ((!params->Transform8x8Mode) || (blocktype>4))
      {
        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
  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     mv[2];
  int       i, j;

  int       max_value = INT_MAX;
  int       min_mcost = max_value;

⌨️ 快捷键说明

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