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

📄 transform8x8.c

📁 H.264编码实现
💻 C
📖 第 1 页 / 共 4 页
字号:
  memcpy(LoopArray,PredPel, 25 * sizeof(imgpel));

  if(block_up)
  {
    if(block_up_left)
    {
      LoopArray[1] = ((PredPel[0] + (PredPel[1]<<1) + PredPel[2] + 2)>>2);
    }
    else
      LoopArray[1] = ((PredPel[1] + (PredPel[1]<<1) + PredPel[2] + 2)>>2);


    for(i = 2; i <16; i++)
    {
      LoopArray[i] = ((PredPel[i-1] + (PredPel[i]<<1) + PredPel[i+1] + 2)>>2);
    }
    LoopArray[16] = ((P_P + (P_P<<1) + P_O + 2)>>2);
  }

  if(block_up_left)
  {
    if(block_up && block_left)
    {
      LoopArray[0] = ((P_Q + (P_Z<<1) + P_A +2)>>2);
    }
    else
    {
      if(block_up)
        LoopArray[0] = ((P_Z + (P_Z<<1) + P_A +2)>>2);
      else
        if(block_left)
          LoopArray[0] = ((P_Z + (P_Z<<1) + P_Q +2)>>2);
    }
  }

  if(block_left)
  {
    if(block_up_left)
      LoopArray[17] = ((P_Z + (P_Q<<1) + P_R + 2)>>2);
    else
      LoopArray[17] = ((P_Q + (P_Q<<1) + P_R + 2)>>2);

    for(i = 18; i <24; i++)
    {
      LoopArray[i] = ((PredPel[i-1] + (PredPel[i]<<1) + PredPel[i+1] + 2)>>2);
    }
    LoopArray[24] = ((P_W + (P_X<<1) + P_X + 2) >> 2);
  }

  memcpy(PredPel, LoopArray, 25 * sizeof(imgpel));
}


/*!
 *************************************************************************************
 * \brief
 *    R-D Cost for an 8x8 Intra block
 *************************************************************************************
 */

double RDCost_for_8x8IntraBlocks(Macroblock *currMB, int *nonzero, int b8, int ipmode, double lambda, double min_rdcost, int mostProbableMode, int c_nzCbCr[3])
{
  double  rdcost = 0.0;
  int     dummy;
  int     rate;
  int64   distortion  = 0;
  int     block_x     = (b8 & 0x01) << 3;
  int     block_y     = (b8 >> 1) << 3;
  int     pic_pix_x   = img->pix_x + block_x;
  int     pic_pix_y   = img->pix_y + block_y;
  int     pic_opix_y  = img->opix_y + block_y;

  Slice          *currSlice =  img->currentSlice;
  SyntaxElement  se;
  const int      *partMap   = assignSE2partition[params->partition_mode];
  DataPartition  *dataPart;

  //===== perform DCT, Q, IQ, IDCT, Reconstruction =====
  dummy = 0;

  *nonzero = pDCT_8x8 (currMB, PLANE_Y, b8, &dummy, 1);

  //===== get distortion (SSD) of 8x8 block =====
  distortion += compute_SSE(&pCurImg[pic_opix_y], &enc_picture->imgY[pic_pix_y], pic_pix_x, pic_pix_x, 8, 8);

  if(img->P444_joined) 
  {
    ColorPlane k;

    for (k = PLANE_U; k <= PLANE_V; k++)
    {
      select_plane(k);
      /*    for (j=0; j<8; j++)   //KHHan, I think these line are not necessary
      {
      for (i=0; i<8; i++)
      {         
      img->mb_pred[k][block_y+j][block_x+i]  = img->mpr_8x8[k][ipmode][j][i];
      img->mb_ores[k][j][i] = pImgOrg[k][img->pix_y+block_y+j][img->pix_x+block_x+i] - img->mpr_8x8[k][ipmode][j][i];
      }
      }*/
      c_nzCbCr[k ]= pDCT_8x8(currMB, k, b8, &dummy,1);
      distortion += compute_SSE(&pImgOrg[k][pic_opix_y], &enc_picture->p_curr_img[pic_pix_y], pic_pix_x, pic_pix_x, 8, 8);
    }
	  ipmode_DPCM = NO_INTRA_PMODE;
    select_plane(PLANE_Y);
  }
  else if( img->yuv_format==YUV444 && IS_INDEPENDENT(params) )  //For residual DPCM
  {
    ipmode_DPCM = NO_INTRA_PMODE;  
  }

  //===== RATE for INTRA PREDICTION MODE  (SYMBOL MODE MUST BE SET TO CAVLC) =====
  se.value1 = (mostProbableMode == ipmode) ? -1 : ipmode < mostProbableMode ? ipmode : ipmode-1;

  //--- set position and type ---
  se.context = b8;
  se.type    = SE_INTRAPREDMODE;

  //--- choose data partition ---
  if (img->type!=B_SLICE)
    dataPart = &(currSlice->partArr[partMap[SE_INTRAPREDMODE]]);
  else
    dataPart = &(currSlice->partArr[partMap[SE_BFRAME]]);

  //--- encode and update rate ---
  writeIntraPredMode (&se, dataPart);

  rate = se.len;

  //===== RATE for LUMINANCE COEFFICIENTS =====

  if (currSlice->symbol_mode == CAVLC)
  {      
    if (img->P444_joined)
    {
      int b4;
      for(b4=0; b4<4; b4++)
      {
        rate  += writeCoeff4x4_CAVLC (currMB, LUMA, b8, b4, 0);
        rate  += writeCoeff4x4_CAVLC (currMB, CB, b8, b4, 0);
        rate  += writeCoeff4x4_CAVLC (currMB, CR, b8, b4, 0);
      }
    }
    else
    {
      rate  += writeCoeff4x4_CAVLC (currMB, LUMA, b8, 0, 0);
      rate  += writeCoeff4x4_CAVLC (currMB, LUMA, b8, 1, 0);
      rate  += writeCoeff4x4_CAVLC (currMB, LUMA, b8, 2, 0);
      rate  += writeCoeff4x4_CAVLC (currMB, LUMA, b8, 3, 0);
    }
  }
  else
  {
    rate  += writeCoeff8x8_CABAC (currMB, PLANE_Y, b8, 1);
    if(img->P444_joined)
    {
      rate  += writeCoeff8x8_CABAC (currMB, PLANE_U, b8, 1);
      rate  += writeCoeff8x8_CABAC (currMB, PLANE_V, b8, 1);
    }
  }

  rdcost = (double)distortion + lambda*(double)rate;

  return rdcost;
}

/*!
 ************************************************************************
 * \brief
 *    The routine performs transform,quantization,inverse transform, adds the diff.
 *    to the prediction and writes the result to the decoded luma frame. Includes the
 *    RD constrained quantization also.
 *
 * \par Input:
 *    b8: Block position inside a macro block (0,1,2,3).
 *
 * \par Output:
 *    nonzero: 0 if no levels are nonzero.  1 if there are nonzero levels.
 *    coeff_cost: Counter for nonzero coefficients, used to discard expensive levels.
 ************************************************************************
 */
int dct_8x8(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int intra)
{
  int j;

  int nonzero = FALSE; 

  int block_x = 8*(b8 & 0x01);
  int block_y = 8*(b8 >> 1);
  int pl_off = b8+ (pl<<2);
  int*  ACLevel = img->cofAC[pl_off][0][0];
  int*  ACRun   = img->cofAC[pl_off][0][1];  
  imgpel **img_enc       = enc_picture->p_curr_img;
  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[pl];
  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[pl];
  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[pl];

  int max_imgpel_value   = img->max_imgpel_value;
  int qp = currMB->qp_scaled[pl];
  const byte (*pos_scan)[2] = currMB->is_field_mode ? FIELD_SCAN8x8 : SNGL_SCAN8x8;

  int qp_rem = qp_rem_matrix[qp];

  levelscale    = LevelScale8x8Comp   [pl][intra][qp_rem];
  invlevelscale = InvLevelScale8x8Comp[pl][intra][qp_rem];
  leveloffset   = LevelOffset8x8Comp  [pl][intra][qp];

  fadjust8x8 = img->AdaptiveRounding ? (pl ? &img->fadjust8x8Cr[pl-1][intra][block_y] : &img->fadjust8x8[intra][block_y]) :NULL;

  // Forward 8x8 transform
  forward8x8(mb_ores, mb_rres, block_y, block_x);

  // Quantization process
  nonzero = quant_8x8(&mb_rres[block_y], block_y, block_x, qp, ACLevel, ACRun, fadjust8x8, 
    levelscale, invlevelscale, leveloffset, coeff_cost, pos_scan, COEFF_COST8x8[params->disthres]);

  if (nonzero)
  {
    // Inverse 8x8 transform
    inverse8x8(mb_rres, mb_rres, block_y, block_x);

    // generate final block
    SampleReconstruct (img_enc, mb_pred, mb_rres, block_y, block_x, img->pix_y, img->pix_x + block_x, BLOCK_SIZE_8x8, BLOCK_SIZE_8x8, max_imgpel_value, DQ_BITS_8);
  }
  else // if (nonzero) => No transformed residual. Just use prediction.
  {      
    for( j=block_y; j< block_y + BLOCK_SIZE_8x8; j++)
    {
      memcpy(&(img_enc[img->pix_y + j][img->pix_x + block_x]),&(mb_pred[j][block_x]), BLOCK_SIZE_8x8 * sizeof(imgpel));
    }
  }  

  //  Decoded block moved to frame memory
  return nonzero;
}

/*!
 ************************************************************************
 * \brief
 *    The routine performs transform,quantization,inverse transform, adds the diff.
 *    to the prediction and writes the result to the decoded luma frame. Includes the
 *    RD constrained quantization also. Used for CAVLC.
 *
 * \par Input:
 *    b8: Block position inside a macro block (0,1,2,3).
 *
 * \par Output:
 *    nonzero: 0 if no levels are nonzero.  1 if there are nonzero levels.
 *    coeff_cost: Counter for nonzero coefficients, used to discard expensive levels.
 ************************************************************************
 */
int dct_8x8_cavlc(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int intra)
{
  int j;
  int nonzero = FALSE; 

  int block_x = 8*(b8 & 0x01);
  int block_y = 8*(b8 >> 1);
  int pl_off = b8+ (pl<<2);
  imgpel **img_enc = enc_picture->p_curr_img;
  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[pl];  
  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[pl];   
  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[pl];   

  int max_imgpel_value   = img->max_imgpel_value;

  int qp = currMB->qp_scaled[pl];
  const byte (*pos_scan)[2] = currMB->is_field_mode ? FIELD_SCAN8x8 : SNGL_SCAN8x8;

  int qp_rem = qp_rem_matrix[qp];

  levelscale    = LevelScale8x8Comp   [pl][intra][qp_rem];
  invlevelscale = InvLevelScale8x8Comp[pl][intra][qp_rem];
  leveloffset   = LevelOffset8x8Comp  [pl][intra][qp];

  fadjust8x8 = img->AdaptiveRounding ? (pl ? &img->fadjust8x8Cr[pl-1][intra][block_y] : &img->fadjust8x8[intra][block_y]) :NULL;

  // Forward 8x8 transform
  forward8x8(mb_ores, mb_rres, block_y, block_x);

  // Quantization process
  nonzero = quant_8x8cavlc(&mb_rres[block_y], block_y, block_x, qp, img->cofAC[pl_off], fadjust8x8, 
    levelscale, invlevelscale, leveloffset, coeff_cost, pos_scan, COEFF_COST8x8[params->disthres]);

  if (nonzero)
  {
    // Inverse 8x8 transform
    inverse8x8(mb_rres, mb_rres, block_y, block_x);

    // generate final block
    SampleReconstruct (img_enc, mb_pred, mb_rres, block_y, block_x, img->pix_y, img->pix_x + block_x, BLOCK_SIZE_8x8, BLOCK_SIZE_8x8, max_imgpel_value, DQ_BITS_8);
  }
  else // if (nonzero) => No transformed residual. Just use prediction.
  {      
    for( j=block_y; j< block_y + BLOCK_SIZE_8x8; j++)
    {
      memcpy(&(img_enc[img->pix_y + j][img->pix_x + block_x]),&(mb_pred[j][block_x]), BLOCK_SIZE_8x8 * sizeof(imgpel));
    }
  }  

  //  Decoded block moved to frame memory
  return nonzero;
}

int dct_8x8_ls(Macroblock *currMB, ColorPlane pl, int b8, int *coeff_cost, int intra)
{
  int i,j,coeff_ctr;
  int scan_pos = 0,run = -1;
  int nonzero = FALSE;  

  int block_x = 8*(b8 & 0x01);
  int block_y = 8*(b8 >> 1);
  int pl_off = b8 + (pl<<2);
  int*  ACLevel = img->cofAC[pl_off][0][0];
  int*  ACRun   = img->cofAC[pl_off][0][1];  
  imgpel **img_enc       = enc_picture->p_curr_img;
  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[pl];
  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[pl];
  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[pl];

  int scan_poss[4] = { 0 }, runs[4] = { -1, -1, -1, -1 };
  int MCcoeff = 0;
  int *m7;
  int is_cavlc = (img->currentSlice->symbol_mode == CAVLC);

  const byte (*pos_scan)[2] = currMB->is_field_mode ? FIELD_SCAN8x8 : SNGL_SCAN8x8;

  int **fadjust8x8 = img->AdaptiveRounding ? (pl ? &img->fadjust8x8Cr[pl-1][intra][block_y] : &img->fadjust8x8[intra][block_y]) :NULL;

  runs[0]=runs[1]=runs[2]=runs[3]=-1;
  scan_poss[0] = scan_poss[1] = scan_poss[2] = scan_poss[3] = 0;

  if( (ipmode_DPCM < 2)&&(intra))
  {
    Residual_DPCM_8x8(ipmode_DPCM, mb_ores, mb_rres, block_y, block_x);
  }

  for (coeff_ctr=0; coeff_ctr < 64; coeff_ctr++)
  {
    i=pos_scan[coeff_ctr][0];
    j=pos_scan[coeff_ctr][1];

    run++;

    if (currMB->luma_transform_size_8x8_flag && is_cavlc)
    {
      MCcoeff = (coeff_ctr & 3);
      runs[MCcoeff]++;
    }

    m7 = &mb_rres[block_y + j][block_x + i];

    if (img->AdaptiveRounding)
    {
      fadjust8x8[j][block_x+i] = 0;
    }

    if (*m7 != 0)
    {
      nonzero = TRUE;

      if (currMB->luma_transform_size_8x8_flag && is_cavlc)
      {
        *m7 = iClip3(-CAVLC_LEVEL_LIMIT, CAVLC_LEVEL_LIMIT, *m7);
        *coeff_cost += MAX_VALUE;

        img->cofAC[pl_off][MCcoeff][0][scan_poss[MCcoeff]  ] = *m7;
        img->cofAC[pl_off][MCcoeff][1][scan_poss[MCcoeff]++] = runs[MCcoeff];
        ++scan_pos;
        runs[MCcoeff]=-1;
      }
      else
      {
        *coeff_cost += MAX_VALUE;
        ACLevel[scan_pos  ] = *m7;
        ACRun  [scan_pos++] = run;
        run=-1;                     // reset zero level counter
      }
    }
  }

  if (!currMB->luma_transform_size_8x8_flag || !is_cavlc)
    ACLevel[scan_pos] = 0;
  else
  {
    for(i=0; i<4; i++)
      img->cofAC[pl_off][i][0][scan_poss[i]] = 0;
  }

  if( (ipmode_DPCM < 2) && (intra))
  {
    Inv_Residual_DPCM_8x8(mb_rres, block_y, block_x);
  }

  for( j=block_y; j<block_y + BLOCK_SIZE_8x8; j++)
  {            
    for( i=block_x; i< block_x + BLOCK_SIZE_8x8; i++)
    {
      mb_rres[j][i] += mb_pred[j][i];
      img_enc[img->pix_y + j][img->pix_x + i]= (imgpel) mb_rres[j][i];
    }
  }  

  //  Decoded block moved to frame memory
  return nonzero;
}


/*static inline void compute_diff(int *diff, imgpel *cimg, imgpel *cmpr, int width)
{
  int i;
  for (i = 0; i < width; i++)
  {
    *(diff++) = *(cimg++) - *(cmpr++);
  }
}*/
/*!
*************************************************************************************
* \brief
*     distortion for an 8x8 Intra block 
*************************************************************************************
*/
void compute_comp_cost8x8(imgpel **cur_img, imgpel mpr8x8[16][16], int pic_opix_x, double *cost)
{
  int i, j;
  int *diff = &diff64[0];
  imgpel *cimg, *cmpr;

  for (j=0; j<8; j++)
  {
  //  compute_diff(diff, &cur_img[j][pic_opix_x], &mpr8x8[j][0], BLOCK_SIZE_8x8);

    cimg = &cur_img[j][pic_opix_x];
    cmpr = &mpr8x8[j][0];
    for (i=0; i<8; i++)
    {
      *diff++ = *cimg++ - *cmpr++;
    }

  }
  *cost += distortion8x8 (diff64);
}

⌨️ 快捷键说明

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