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

📄 block.c

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

  int nonzero = FALSE;

  int   pos_x   = block_x >> BLOCK_SHIFT;
  int   pos_y   = block_y >> BLOCK_SHIFT;
  int   b8      = 2*(pos_y >> 1) + (pos_x >> 1) + (pl<<2);
  int   b4      = 2*(pos_y & 0x01) + (pos_x & 0x01);
  int*  ACLevel = img->cofAC[b8][b4][0];
  int*  ACRun   = img->cofAC[b8][b4][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_SCAN : SNGL_SCAN;

  int qp_rem = qp_rem_matrix[qp];

  // select scaling parameters
  levelscale    = LevelScale4x4Comp[pl][intra][qp_rem];
  invlevelscale = InvLevelScale4x4Comp[pl][intra][qp_rem];
  leveloffset   = ptLevelOffset4x4[intra][qp];

  fadjust4x4    = img->AdaptiveRounding ? (pl ? &img->fadjust4x4Cr[pl-1][intra][block_y] : &img->fadjust4x4[intra][block_y]) : NULL;
  img->subblock_x = ((b8&0x1)==0) ? (((b4&0x1)==0)? 0: 1) : (((b4&0x1)==0)? 2: 3); // horiz. position for coeff_count context
  img->subblock_y = (b8<2)        ? ((b4<2)       ? 0: 1) : ((b4<2)       ? 2: 3); // vert.  position for coeff_count context

  //  Forward 4x4 transform
  forward4x4(mb_ores, M1, block_y, block_x);

  // Quantization process
  nonzero = quant_4x4(&M1[block_y], block_y, block_x, qp, ACLevel, ACRun, fadjust4x4, 
    levelscale, invlevelscale, leveloffset, coeff_cost, pos_scan, COEFF_COST4x4[params->disthres], is_cavlc);

  //  Decoded block moved to frame memory
  if (nonzero)
  {
    // Inverse 4x4 transform
    inverse4x4(M1, 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, BLOCK_SIZE, max_imgpel_value, DQ_BITS);
  }
  else // if (nonzero) => No transformed residual. Just use prediction.
  {
    for (j=block_y; j < block_y + BLOCK_SIZE; j++)
    {
      memcpy(&(img_enc[img->pix_y + j][img->pix_x + block_x]),&(mb_pred[j][block_x]), BLOCK_SIZE * sizeof(imgpel));
    }
  }

  return nonzero;
}



/*!
************************************************************************
* \brief
*    Process for lossless coding of coefficients.
*    The routine performs transform, quantization,inverse transform, 
*    adds the diff to the prediction and writes the result to the 
*    decoded luma frame. 
*
* \par Input:
*    currMB:          Current macroblock.
*    pl:              Color plane for 4:4:4 coding.
*    block_x,block_y: Block position inside a macro block (0,4,8,12).
*    intra:           Intra block indicator.
*
* \par Output_
*    nonzero:         0 if no levels are nonzero. \n
*                     1 if there are nonzero levels.\n
*    coeff_cost:      Coeff coding cost for thresholding consideration.\n
************************************************************************
*/
int dct_4x4_ls(Macroblock *currMB, ColorPlane pl, int block_x,int block_y,int *coeff_cost, int intra, int is_cavlc)
{
  int i,j, coeff_ctr;
  int run = -1;
  int nonzero = FALSE;  

  int   pos_x   = block_x >> BLOCK_SHIFT;
  int   pos_y   = block_y >> BLOCK_SHIFT;
  int   b8      = 2*(pos_y >> 1) + (pos_x >> 1) + (pl<<2);
  int   b4      = 2*(pos_y & 0x01) + (pos_x & 0x01);

  int*  ACL = &img->cofAC[b8][b4][0][0];
  int*  ACR = &img->cofAC[b8][b4][1][0];

  int   pix_y, pix_x;
  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   *m7;

  const byte *p_scan = currMB->is_field_mode ? &FIELD_SCAN[0][0] : &SNGL_SCAN[0][0];

  // select scaling parameters
  fadjust4x4 = img->AdaptiveRounding ? &img->fadjust4x4[intra][block_y] : NULL;

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

  for (coeff_ctr=0;coeff_ctr < 16;coeff_ctr++)
  {
    i = *p_scan++;
    j = *p_scan++;

    run++;

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

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

    if (*m7 != 0)
    {
      if (is_cavlc)
        *m7 = iClip3(-CAVLC_LEVEL_LIMIT, CAVLC_LEVEL_LIMIT, *m7);

      nonzero=TRUE;
      *coeff_cost += MAX_VALUE;
      *ACL++ = *m7;
      *ACR++ = run;
      run=-1;                     // reset zero level counter        
    }
  }
  *ACL = 0;

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

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

  return nonzero;
}

/*!
************************************************************************
* \brief
*    Residual DPCM for Intra lossless coding
*
* \par Input:
*    block_x,block_y: Block position inside a macro block (0,4,8,12).
************************************************************************
*/
static int Residual_DPCM_4x4(int ipmode, int mb_ores[16][16], int mb_rres[16][16], int block_y, int block_x)
{
  int i;
  int temp[4][4];

  if(ipmode==VERT_PRED)
  {
    temp[0][0] = mb_ores[block_y][block_x    ];
    temp[0][1] = mb_ores[block_y][block_x + 1];
    temp[0][2] = mb_ores[block_y][block_x + 2];
    temp[0][3] = mb_ores[block_y][block_x + 3];

    for (i=1; i<4; i++) 
    {
      temp[i][0] = mb_ores[block_y + i][block_x    ] - mb_ores[block_y + i - 1][block_x    ];
      temp[i][1] = mb_ores[block_y + i][block_x + 1] - mb_ores[block_y + i - 1][block_x + 1];
      temp[i][2] = mb_ores[block_y + i][block_x + 2] - mb_ores[block_y + i - 1][block_x + 2];
      temp[i][3] = mb_ores[block_y + i][block_x + 3] - mb_ores[block_y + i - 1][block_x + 3];
    }

    for (i = 0; i < 4; i++)
    {
      mb_ores[block_y+i][block_x    ] = temp[i][0];
      mb_ores[block_y+i][block_x + 1] = temp[i][1];
      mb_ores[block_y+i][block_x + 2] = temp[i][2];
      mb_ores[block_y+i][block_x + 3] = temp[i][3];
    }
  }
  else  //HOR_PRED
  {
    temp[0][0] = mb_ores[block_y    ][block_x];
    temp[1][0] = mb_ores[block_y + 1][block_x];
    temp[2][0] = mb_ores[block_y + 2][block_x];
    temp[3][0] = mb_ores[block_y + 3][block_x];

    for (i=0; i<4; i++)
    {
      temp[i][1] = mb_ores[block_y + i][block_x + 1] - mb_ores[block_y + i][block_x    ];
      temp[i][2] = mb_ores[block_y + i][block_x + 2] - mb_ores[block_y + i][block_x + 1];
      temp[i][3] = mb_ores[block_y + i][block_x + 3] - mb_ores[block_y + i][block_x + 2];
    }

    for (i=0; i<4; i++)
    {
      mb_ores[block_y + i][block_x + 0] = temp[i][0];
      mb_ores[block_y + i][block_x + 1] = temp[i][1];
      mb_ores[block_y + i][block_x + 2] = temp[i][2];
      mb_ores[block_y + i][block_x + 3] = temp[i][3];
    }
  }
  return 0;
}

/*!
************************************************************************
* \brief
*    Inverse residual DPCM for Intra lossless coding
*
* \par Input:
*    block_x,block_y: Block position inside a macro block (0,4,8,12).
************************************************************************
*/
//For residual DPCM
static int Inv_Residual_DPCM_4x4(int m7[16][16], int block_y, int block_x)  
{
  int i;
  int temp[4][4];

  if(ipmode_DPCM==VERT_PRED)
  {
    for(i=0; i<4; i++)
    {
      temp[0][i] = m7[block_y + 0][block_x + i];
      temp[1][i] = temp[0][i] + m7[block_y + 1][block_x + i];
      temp[2][i] = temp[1][i] + m7[block_y + 2][block_x + i];
      temp[3][i] = temp[2][i] + m7[block_y + 3][block_x + i];
    }
    for(i=0; i<4; i++)
    {      
      m7[block_y + i][block_x    ] = temp[i][0];
      m7[block_y + i][block_x + 1] = temp[i][1];
      m7[block_y + i][block_x + 2] = temp[i][2];
      m7[block_y + i][block_x + 3] = temp[i][3];
    }
  }
  else //HOR_PRED
  {
    for(i=0; i<4; i++)
    {
      temp[i][0] = m7[block_y+i][block_x+0];
      temp[i][1] = temp[i][0] + m7[block_y + i][block_x + 1];
      temp[i][2] = temp[i][1] + m7[block_y + i][block_x + 2];
      temp[i][3] = temp[i][2] + m7[block_y + i][block_x + 3];    
    }
    for(i=0; i<4; i++)
    {
      m7[block_y+i][block_x  ] = temp[i][0];
      m7[block_y+i][block_x+1] = temp[i][1];
      m7[block_y+i][block_x+2] = temp[i][2];
      m7[block_y+i][block_x+3] = temp[i][3];
    }
  }
  return 0;
}

/*!
************************************************************************
* \brief
*    Residual DPCM for Intra lossless coding
************************************************************************
*/
//For residual DPCM
static int Residual_DPCM_4x4_for_Intra16x16(int m7[4][4], int ipmode)  
{
  int i,j;
  int temp[4][4];

  if(ipmode==VERT_PRED)
  {   
    for (i=1; i<4; i++) 
      for (j=0; j<4; j++)
        temp[i][j] = m7[i][j] - m7[i-1][j];

    for (i=1; i<4; i++)
      for (j=0; j<4; j++)
        m7[i][j] = temp[i][j];
  }
  else  //HOR_PRED
  {
    for (i=0; i<4; i++)
      for (j=1; j<4; j++)
        temp[i][j] = m7[i][j] - m7[i][j-1];

    for (i=0; i<4; i++)
      for (j=1; j<4; j++)
        m7[i][j] = temp[i][j];
  }
  return 0;
}
/*!
************************************************************************
* \brief
*    Inverse residual DPCM for Intra lossless coding
************************************************************************
*/
//For residual DPCM
static int Inv_Residual_DPCM_4x4_for_Intra16x16(int m7[4][4], int ipmode)  
{
  int i;
  int temp[4][4];

  if(ipmode==VERT_PRED)
  {
    for (i=0; i<4; i++) 
    {
      temp[0][i] = m7[0][i];
      temp[1][i] = m7[1][i] + temp[0][i];
      temp[2][i] = m7[2][i] + temp[1][i];
      temp[3][i] = m7[3][i] + temp[2][i];
    }
    // These could now just use a memcpy
    for (i=0; i<4; i++)
    {
      m7[1][i] = temp[1][i];
      m7[2][i] = temp[2][i];
      m7[3][i] = temp[3][i];
    }
  }
  else  //HOR_PRED
  {
    for(i=0; i<4; i++)
    {
      temp[i][0] = m7[i][0];
      temp[i][1] = m7[i][1] + temp[i][0];
      temp[i][2] = m7[i][2] + temp[i][1];
      temp[i][3] = m7[i][3] + temp[i][2];
    }
    for (i=0; i<4; i++)
    {
      m7[i][1] = temp[i][1];
      m7[i][2] = temp[i][2];
      m7[i][3] = temp[i][3];
    }    
  }
  return 0;
}

/*!
 ************************************************************************
 * \brief
 *    Transform,quantization,inverse transform for chroma.
 *    The main reason why this is done in a separate routine is the
 *    additional 2x2 transform of DC-coeffs. This routine is called
 *    once for each of the chroma components.
 *
 * \par Input:
 *    uv    : Make difference between the U and V chroma component  \n
 *    cr_cbp: chroma coded block pattern
 *
 * \par Output:
 *    cr_cbp: Updated chroma coded block pattern.
 ************************************************************************
 */
int dct_chroma(Macroblock *currMB, int uv, int cr_cbp, int is_cavlc)
{
  int i, j, n2, n1, coeff_ctr;
  static int m1[BLOCK_SIZE];
  int coeff_cost = 0;
  int cr_cbp_tmp = 0;
  int DCzero = FALSE;
  int nonzero[4][4] = {{FALSE}};
  int nonezero = FALSE;

  const byte *c_cost = COEFF_COST4x4[params->disthres];

  int   b4;
  int*  DCLevel = img->cofDC[uv+1][0];
  int*  DCRun   = img->cofDC[uv+1][1];
  int*  ACLevel;
  int*  ACRun;
  int   intra = IS_INTRA (currMB);
  int   uv_scale = uv * (img->num_blk8x8_uv >> 1);

  //FRExt
  static const int64 cbpblk_pattern[4]={0, 0xf0000, 0xff0000, 0xffff0000};
  int yuv = img->yuv_format;
  int b8;  

  const byte (*pos_scan)[2] = currMB->is_field_mode ? FIELD_SCAN : SNGL_SCAN;
  int cur_qp = currMB->qpc[uv] + img->bitdepth_chroma_qp_scale;  

  int qp_rem = qp_rem_matrix[cur_qp];

  int max_imgpel_value_uv = img->max_imgpel_value_comp[uv + 1];

  int    (*mb_rres)[MB_BLOCK_SIZE] = img->mb_rres[uv + 1]; 
  int    (*mb_ores)[MB_BLOCK_SIZE] = img->mb_ores[uv + 1];
  imgpel (*mb_pred)[MB_BLOCK_SIZE] = img->mb_pred[uv + 1]; 

  levelscale    = LevelScale4x4Comp   [uv + 1][intra][qp_rem];
  leveloffset   = LevelOffset4x4Comp  [uv + 1][intra][cur_qp];
  invlevelscale = InvLevelScale4x4Comp[uv + 1][intra][qp_rem];
  fadjust4x4    = img->AdaptiveRounding ? img->fadjust4x4Cr[intra][uv] : NULL;
  img->is_v_block = uv;

  //============= dct transform ===============
  for (n2=0; n2 < img->mb_cr_size_y; n2 += BLOCK_SIZE)
  {
    for (n1=0; n1 < img->mb_cr_size_x; n1 += BLOCK_SIZE)
    {
      forward4x4(mb_ores, mb_rres, n2, n1);
    }
  }

  if (yuv == YUV420)
  {
    //================== CHROMA DC YUV420 ===================
  
    // forward 2x2 hadamard
    hadamard2x2(mb_rres, m1);

    // Quantization process of chroma 2X2 hadamard transformed DC coeffs.

⌨️ 快捷键说明

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