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

📄 rdopt.c

📁 h.264/avc 视频编码程序,实现分数像素匹配功能,非原创.
💻 C
📖 第 1 页 / 共 5 页
字号:
 *************************************************************************************
 * \brief
 *    Store macroblock parameters
 *************************************************************************************
 */
void
store_macroblock_parameters (int mode)
{
  int  i, j, k, ****i4p, ***i3p;
  Macroblock *currMB  = &img->mb_data[img->current_mb_nr];
  int        bframe   = (img->type==B_IMG);
  int        **frefar = (img->type==B_IMG ? fw_refFrArr : refFrArr);
  int        **brefar = bw_refFrArr;

  //--- store best mode ---
  best_mode = mode;
  for (i=0; i<4; i++)
  {
    b8mode[i] = currMB->b8mode[i];
    b8pdir[i] = currMB->b8pdir[i];
  }

  //--- reconstructed blocks ----
  if (!bframe && mode==0)
  {
    for (j=0; j<16; j++)
    for (i=0; i<16; i++)
    {
      rec_mbY[j][i] = FastPelY_14 (mref[0], (img->pix_y+j)<<2, (img->pix_x+i)<<2);
    }
    for (j=0; j<8; j++)
    for (i=0; i<8; i++)
    {
      rec_mbU[j][i] = mcef[0][0][img->pix_c_y+j][img->pix_c_x+i];
      rec_mbV[j][i] = mcef[0][1][img->pix_c_y+j][img->pix_c_x+i];
    }
  }
  else
  {
    for (j=0; j<16; j++)
    for (i=0; i<16; i++)
    {
      rec_mbY[j][i] = imgY[img->pix_y+j][img->pix_x+i];
    }
    for (j=0; j<8; j++)
    for (i=0; i<8; i++)
    {
      rec_mbU[j][i] = imgUV[0][img->pix_c_y+j][img->pix_c_x+i];
      rec_mbV[j][i] = imgUV[1][img->pix_c_y+j][img->pix_c_x+i];
    }
  }

  //--- store results of decoders ---
  if (input->rdopt==2 && !bframe)
  {
    for (k=0; k<input->NoOfDecoders; k++)
    {
      for (j=img->pix_y; j<img->pix_y+16; j++)
      for (i=img->pix_x; i<img->pix_x+16; i++)
      {
        // Keep the decoded values of each MB for updating the ref frames
        decs->decY_best[k][j][i] = decs->decY[k][j][i];
      }
    }
  }

  //--- coeff, cbp, kac ---
  if (mode || bframe)
  {
    i4p=cofAC; cofAC=img->cofAC; img->cofAC=i4p;
    i3p=cofDC; cofDC=img->cofDC; img->cofDC=i3p;
    cbp     = currMB->cbp;
    cbp_blk = currMB->cbp_blk;
  }
  else
  {
    cbp = cbp_blk = 0;
  }

  //--- references ---
  frefframe[0] = frefar[img->block_y  ][img->block_x  ];
  frefframe[1] = frefar[img->block_y  ][img->block_x+2];
  frefframe[2] = frefar[img->block_y+2][img->block_x  ];
  frefframe[3] = frefar[img->block_y+2][img->block_x+2];
  if (bframe)
  {
    brefframe[0] = brefar[img->block_y  ][img->block_x  ]; 
    brefframe[1] = brefar[img->block_y  ][img->block_x+2];
    brefframe[2] = brefar[img->block_y+2][img->block_x  ];
    brefframe[3] = brefar[img->block_y+2][img->block_x+2];
  }
}


/*! 
 *************************************************************************************
 * \brief
 *    Set stored macroblock parameters
 *************************************************************************************
 */
void
set_stored_macroblock_parameters ()
{
  int  i, j, k, ****i4p, ***i3p;
  Macroblock  *currMB  = &img->mb_data[img->current_mb_nr];
  int         mode     = best_mode;
  int         bframe   = (img->type==B_IMG);
  int         **frefar = (img->type==B_IMG ? fw_refFrArr : refFrArr);
  int         **brefar = bw_refFrArr;

  //===== reconstruction values =====
  for (j=0; j<16; j++)
  for (i=0; i<16; i++)
  {
    imgY[img->pix_y+j][img->pix_x+i] = rec_mbY[j][i];
  }
  for (j=0; j<8; j++)
  for (i=0; i<8; i++)
  {
    imgUV[0][img->pix_c_y+j][img->pix_c_x+i] = rec_mbU[j][i];
    imgUV[1][img->pix_c_y+j][img->pix_c_x+i] = rec_mbV[j][i];
  }

  //===== coefficients and cbp =====
  i4p=cofAC; cofAC=img->cofAC; img->cofAC=i4p;
  i3p=cofDC; cofDC=img->cofDC; img->cofDC=i3p;
  currMB->cbp      = cbp;
  currMB->cbp_blk = cbp_blk;

  //==== macroblock type ====
  currMB->mb_type = mode;
  for (i=0; i<4; i++)
  {
    currMB->b8mode[i] = b8mode[i];
    currMB->b8pdir[i] = b8pdir[i];
  }
  if (input->rdopt==2 && !bframe)
  {
    //! save the MB Mode of every macroblock
    decs->dec_mb_mode[img->mb_x][img->mb_y] = mode;
  }

  //==== reference frames =====
  for (j=0; j<4; j++)
  for (i=0; i<4; i++)
  {
    frefar[img->block_y+j][img->block_x+i] = frefframe[2*(j/2) + (i/2)];
  }
  if (bframe)
  {
    for (j=0; j<4; j++)
    for (i=0; i<4; i++)
    {
      brefar[img->block_y+j][img->block_x+i] = brefframe[2*(j/2) + (i/2)];
    }
  }

  //==== intra prediction modes ====
  if (mode==P8x8)
  {
    for (k=0, j=img->block_y+1; j<img->block_y+5; j++)
    for (     i=img->block_x+1; i<img->block_x+5; i++, k++)
    {
      img   ->ipredmode    [i][j] = b8_ipredmode       [k];
      currMB->intra_pred_modes[k] = b8_intra_pred_modes[k];
    }
  }
  else if (mode!=I4MB)
  {
    for (k=0, j=img->block_y+1; j<img->block_y+5; j++)
    for (     i=img->block_x+1; i<img->block_x+5; i++, k++)
    {
      img   ->ipredmode    [i][j] = 0;
      currMB->intra_pred_modes[k] = 0;
    }
  }

  //==== motion vectors =====
  SetMotionVectorsMB (currMB, bframe);
}



/*! 
 *************************************************************************************
 * \brief
 *    Set reference frames and motion vectors
 *************************************************************************************
 */
void
SetRefAndMotionVectors (int block, int mode, int ref, int pdir)
{
  int i, j;
  int     bframe  = (img->type==B_IMG);
  int     pmode   = (mode==1||mode==2||mode==3?mode:4);
  int     j0      = ((block/2)<<1);
  int     i0      = ((block%2)<<1);
  int     j1      = j0 + (input->blc_size[pmode][1]>>2);
  int     i1      = i0 + (input->blc_size[pmode][0]>>2);
  int**   frefArr = (bframe ? fw_refFrArr : refFrArr);
  int**   brefArr = bw_refFrArr;
  int***  fmvArr  = (bframe ? tmp_fwMV    : tmp_mv);
  int***  bmvArr  = tmp_bwMV;

  if ((pdir==0 || pdir==2) && (mode!=IBLOCK && mode!=0))
  {
    for (j=j0; j<j1; j++)
    for (i=i0; i<i1; i++)
    {
      fmvArr[0][img->block_y+j][img->block_x+i+4] = img->all_mv[i][j][ref][mode][0];
      fmvArr[1][img->block_y+j][img->block_x+i+4] = img->all_mv[i][j][ref][mode][1];
      frefArr  [img->block_y+j][img->block_x+i  ] = ref;
    }
  }
  else
  {
    for (j=j0; j<j0+2; j++)
    for (i=i0; i<i0+2; i++)
    {
      fmvArr[0][img->block_y+j][img->block_x+i+4] = 0;
      fmvArr[1][img->block_y+j][img->block_x+i+4] = 0;
      frefArr  [img->block_y+j][img->block_x+i  ] = -1;
    }
  }
  if ((pdir==1 || pdir==2) && (mode!=IBLOCK && mode!=0))
  {
    for (j=j0; j<j0+2; j++)
    for (i=i0; i<i0+2; i++)
    {
      bmvArr[0][img->block_y+j][img->block_x+i+4] = img->all_bmv[i][j][0][mode][0];
      bmvArr[1][img->block_y+j][img->block_x+i+4] = img->all_bmv[i][j][0][mode][1];
      brefArr  [img->block_y+j][img->block_x+i  ] = 0;
    }
  }
  else if (bframe)
  {
    for (j=j0; j<j0+2; j++)
    for (i=i0; i<i0+2; i++)
    {
      bmvArr[0][img->block_y+j][img->block_x+i+4] = 0;
      bmvArr[1][img->block_y+j][img->block_x+i+4] = 0;
      brefArr  [img->block_y+j][img->block_x+i  ] = -1;
    }
  }
}




/*! 
 *************************************************************************************
 * \brief
 *    Mode Decision for a macroblock
 *************************************************************************************
 */
void
encode_one_macroblock ()
{
  static const int  b8_mode_table[6] = {0, 4, 5, 6, 7, IBLOCK};         // DO NOT CHANGE ORDER !!!
  static const int  mb_mode_table[7] = {0, 1, 2, 3, P8x8, I16MB, I4MB}; // DO NOT CHANGE ORDER !!!

  int         valid[MAXMODE];
  int         rerun, block, index, mode, i0, i1, j0, j1, pdir, ref, i, j, k, ctr16x16, dummy;
  double      qp, lambda_mode, lambda_motion, min_rdcost, rdcost, max_rdcost=1e30;
  int         lambda_motion_factor;
  int         fw_mcost, bw_mcost, bid_mcost, mcost, max_mcost=(1<<30);
  int         curr_cbp_blk, cnt_nonz, best_cnt_nonz, best_fw_ref, best_pdir;
  int         cost, min_cost, cost8x8, cost_direct=0, have_direct=0, i16mode;
  int         intra1[4];

  int         intra       = ((img->type==INTER_IMG && img->mb_y==img->mb_y_upd && img->mb_y_upd!=img->mb_y_intra) || img->type==INTRA_IMG);
  int         spframe     = (img->type==INTER_IMG && img->types==SP_IMG);
  int         bframe      = (img->type==B_IMG);
  int         write_ref   = (input->no_multpred>1 || input->add_ref_frame>0);
  int         runs        = (input->RestrictRef==1 && input->rdopt==2 && img->type==INTER_IMG ? 2 : 1);
  int         max_ref     = img->nb_references;
  int         checkref    = (input->rdopt && input->RestrictRef && img->type==INTER_IMG);
  Macroblock* currMB      = &img->mb_data[img->current_mb_nr];


  //===== SET VALID MODES =====
  valid[I4MB]   = 1;
  valid[I16MB]  = 1;
  // HS: I'm not sure when the Intra Mode on 8x8 basis should be unvalid
  //     Is it o.k. to have intra and inter 8x8 block inside one macroblock for SP-frame (especially for chroma)?
  //     Is it o.k. for data partitioning? (where the syntax elements have to written to?)
  valid[IBLOCK] = 1;
  valid[0]      = (!intra && !spframe);
  valid[1]      = (!intra && input->InterSearch16x16);
  valid[2]      = (!intra && input->InterSearch16x8);
  valid[3]      = (!intra && input->InterSearch8x16);
  valid[4]      = (!intra && input->InterSearch8x8);
  valid[5]      = (!intra && input->InterSearch8x4);
  valid[6]      = (!intra && input->InterSearch4x8);
  valid[7]      = (!intra && input->InterSearch4x4);
  valid[P8x8]   = (valid[4] || valid[5] || valid[6] || valid[7] || (bframe && valid[0] && valid[IBLOCK]));



  //===== SET LAGRANGE PARAMETERS =====
  if (input->rdopt)
  {
    qp            = (double)img->qp;
    lambda_mode   = 0.85 * pow (2, qp/3.0) * (bframe||spframe?4:1);  // ????? WHY FACTOR 4 FOR SP-FRAME ?????
    lambda_motion = sqrt (lambda_mode);
  }
  else
  {
    lambda_mode = lambda_motion = QP2QUANT[max(0,img->qp)];
  }
  lambda_motion_factor = LAMBDA_FACTOR (lambda_motion);


  for (rerun=0; rerun<runs; rerun++)
  {
    if (runs==2)
    {
      if (rerun==0)   input->rdopt=1;
      else            input->rdopt=2;
    }

    if (!intra)
    {
      //----- set search range ---
      #if(Range_Decision)
		new_search_range_x=Determine_Range(input->search_range,0);
		new_search_range_y=Determine_Range(input->search_range,1);
      #else
		new_search_range_x=input->search_range;
		new_search_range_y=input->search_range;
      #endif
      //===== set direct motion vectors =====
      if (bframe)
      {
        Get_Direct_Motion_Vectors ();
      }

      if (valid[P8x8])
      {
        cost8x8 = 0;

        //===== store coding state of macroblock =====
        store_coding_state (cs_mb);

        //=====  LOOP OVER 8x8 SUB-PARTITIONS  (Motion Estimation & Mode Decision) =====
        for (cbp8x8=cbp_blk8x8=cnt_nonz_8x8=0, block=0; block<4; block++)
        {
          //--- set coordinates ---
          j0 = ((block/2)<<3);    j1 = (j0>>2);
          i0 = ((block%2)<<3);    i1 = (i0>>2);

          //=====  LOOP OVER POSSIBLE CODING MODES FOR 8x8 SUB-PARTITION  =====
          for (min_cost=(1<<20), min_rdcost=1e30, index=(bframe?0:1); index<6; index++)
          {
            if (valid[mode=b8_mode_table[index]])
            {
              curr_cbp_blk = 0;

              if (mode==IBLOCK)
              {
                //--- Intra4x4 mode decision for 8x8 block ---
                cnt_nonz    = Mode_Decision_for_8x8IntraBlocks (block, lambda_mode, &cost);
                best_fw_ref = -1;
                best_pdir   = -1;
              } // if (mode==IBLOCK)
              else if (mode==0)
              {
                //--- Direct Mode ---
                if (!input->rdopt)
                {
                  cost_direct += (cost = Get_Direct_Cost8x8 (block, lambda_mode));
                  have_direct ++;
                }
                best_fw_ref = -1;
                best_pdir   =  2;
              } // if (mode==0)
              else
              {
                //--- motion estimation for all reference frames ---
                PartitionMotionSearch (mode, block, lambda_motion);

                //--- get cost and reference frame for forward prediction ---
                for (fw_mcost=max_mcost, ref=0; ref<max_ref; ref++)
                {
                  if (!checkref || ref==0 || CheckReliabilityOfRef (block, ref, mode))
                  {
                    mcost  = (input->rdopt ? write_ref ? REF_COST (lambda_motion_factor, ref) : 0 : (int)(2*lambda_motion*min(ref,1)));
                    mcost += motion_cost[mode][ref+1][block];
                    if (mcost < fw_mcost)
                    {
                      fw_mcost    = mcost;
                      best_fw_ref = ref;
                    }
                  }
                }

                if (bframe)
                {

⌨️ 快捷键说明

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