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

📄 macroblock.c

📁 H.264编码实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  int    mb_y, mb_x, block8x8;  
  int    list_mode[2];
  short  list_ref_idx[2], p_dir;
  int    num_blks;
  int    cost8x8=0, cost4x4=0;
  int    *diff_ptr;
  short bipred_me;
  imgpel (*mb_pred)[16] = img->mb_pred[0];

  if(block_check==-1)
  {
    block8x8 = 0;
    num_blks = 4;
  }
  else
  {
    block8x8 = block_check;
    num_blks = block_check + 1;
  }
  
  for (; block8x8<num_blks; block8x8++)
  {
    SetModesAndRefframe (currMB, block8x8, &p_dir, list_mode, list_ref_idx);
    bipred_me = currMB->bipred_me[block8x8]; 
    mb_y = (block8x8 >> 1) << 3;
    mb_x = (block8x8 & 0x01) << 3;
        
    //===== prediction of 8x8 block =====
    LumaPrediction (currMB, mb_x, mb_y, 8, 8, p_dir, list_mode[0], list_mode[1], list_ref_idx[0], list_ref_idx[1], bipred_me);

    //===== loop over 4x4 blocks =====
    for (k=0, block_y=mb_y; block_y<mb_y+8; block_y+=4)
    {     
      for (block_x=mb_x; block_x<mb_x+8; block_x+=4)
      {
        //===== get displaced frame difference ======
        diff_ptr=&diff64[k];
        for (j=block_y; j<block_y + 4; j++)
        {
          for (i = block_x; i < block_x + 4; i++, k++)
            diff64[k] = pCurImg[img->opix_y+j][img->opix_x + i] - mb_pred[j][i];
        }
        cost4x4 += distortion4x4 (diff_ptr);
      }
    }
    cost8x8 += distortion8x8 (diff64);
  }

  if(params->Transform8x8Mode==2) //always allow 8x8 transform
    return 1;
  else if(cost8x8 < cost4x4)
    return 1;
  else
  {
    *cost += (cost4x4 - cost8x8);
    return 0;
  }
}



/*!
 ************************************************************************
 * \brief
 *    Chroma residual coding for an macroblock
 ************************************************************************
 */
void ChromaResidualCoding (Macroblock *currMB, int is_cavlc)
{
  int chroma_cbp;
  static int   uv, block8, block_y, block_x, j, i;
  static int   list_mode[2];
  static short p_dir, list_ref_idx[2];
  int   skipped = (currMB->mb_type == 0 && (img->type == P_SLICE || img->type == SP_SLICE));
  int   yuv = img->yuv_format - 1; 
  short bipred_me;
  imgpel (*mb_pred)[16] = NULL;
  
  for (chroma_cbp = 0, uv=0; uv<2; uv++)
  {
    mb_pred = img->mb_pred[ uv + 1];
    //===== prediction of chrominance blocks ===d==
    block8 = 0;
    for (block_y=0; block_y < img->mb_cr_size_y; block_y+=4)
    for (block_x=0; block_x < img->mb_cr_size_x; block_x+=4)
    {
      block8 = block8x8_idx[yuv][block_y>>2][block_x>>2];
      bipred_me = currMB->bipred_me[block8];
      SetModesAndRefframe (currMB, block8, &p_dir, list_mode, list_ref_idx);

      ChromaPrediction4x4 (currMB, uv, block_x, block_y, p_dir, list_mode[0], list_mode[1], list_ref_idx[0], list_ref_idx[1], bipred_me);
      //ChromaPrediction    (currMB, uv, block_x, block_y, 4, 4, p_dir, l0_mode, l1_mode, l0_ref_idx, l1_ref_idx);
    }

    // ==== set chroma residue to zero for skip Mode in SP frames
    if (img->NoResidueDirect)
    {
      for (j=0; j<img->mb_cr_size_y; j++)
        memcpy(&enc_picture->imgUV[uv][img->pix_c_y+j][img->pix_c_x], mb_pred[j], img->mb_cr_size_x * sizeof(imgpel));
    }
    else if (skipped && img->type==SP_SLICE)
    {
      for (j=0; j<img->mb_cr_size_y; j++)
        memset(img->mb_ores[uv + 1][j], 0 , img->mb_cr_size_x * sizeof(int));
      for (j=0; j<img->mb_cr_size_y; j++)
        memset(img->mb_rres[uv + 1][j], 0 , img->mb_cr_size_x * sizeof(int));
    }
    else if (skipped)
    {
      for (j=0; j<img->mb_cr_size_y; j++)
        memcpy(&enc_picture->imgUV[uv][img->pix_c_y+j][img->pix_c_x], mb_pred[j], img->mb_cr_size_x * sizeof(imgpel));
    }
    else
    {
      for (j=0; j<img->mb_cr_size_y; j++)
        for (i=0; i<img->mb_cr_size_x; i++)
        {
          img->mb_ores[uv + 1][j][i] = pImgOrg[uv + 1][img->opix_c_y+j][img->opix_c_x+i] - mb_pred[j][i];
        }
    }

    //===== DCT, Quantization, inverse Quantization, IDCT, and Reconstruction =====
    //===== Call function for skip mode in SP frames to properly process frame ====

    if (skipped && img->type==SP_SLICE)
    {
      if(si_frame_indicator || sp2_frame_indicator)
        chroma_cbp = dct_chroma_sp2(currMB, uv,chroma_cbp, is_cavlc);
      else
        chroma_cbp = dct_chroma_sp(currMB, uv,chroma_cbp, is_cavlc);
    }
    else
    {
      if (!img->NoResidueDirect && !skipped)
      {
        if (img->type!=SP_SLICE || (currMB->mb_type==I16MB ))
        {
          //even if the block is intra it should still be treated as SP
          chroma_cbp = dct_cr_4x4[uv] (currMB, uv,chroma_cbp, is_cavlc);
        }
        else
        {
          if(si_frame_indicator||sp2_frame_indicator)
            chroma_cbp=dct_chroma_sp2(currMB, uv,chroma_cbp, is_cavlc);// SI frames or switching SP frames
          else
            chroma_cbp=dct_chroma_sp(currMB, uv,chroma_cbp, is_cavlc);
        }
      }
    }
  }

  //===== update currMB->cbp =====
  currMB->cbp += ((chroma_cbp)<<4);

}


/*!
 **************************************************************************************
 * \brief
 *    RD Decision for Intra prediction mode of the chrominance layers of one macroblock
 **************************************************************************************
 */
void IntraChromaRDDecision (Macroblock *currMB, RD_PARAMS enc_mb)
{
  int      i, j, k;
  imgpel** image;
  int      block_x, block_y;  
  int      mb_available_up;
  int      mb_available_left[2];
  int      mb_available_up_left;
  int      uv;
  int      mode;
  int      best_mode = DC_PRED_8;  //just an initialization here, should always be overwritten
  int      cost;
  int      min_cost;
  PixelPos up;        //!< pixel position  p(0,-1)
  PixelPos left[17];  //!< pixel positions p(-1, -1..15)
  int      cr_MB_x = img->mb_cr_size_x;
  int      cr_MB_y = img->mb_cr_size_y;
  static imgpel *img_org, *img_prd;
  static imgpel (*curr_mpr_16x16)[16][16];

  for (i=0;i<cr_MB_y+1;i++)
  {
    getNeighbour(currMB, -1 , i-1 , img->mb_size[IS_CHROMA], &left[i]);
  }
  getNeighbour(currMB, 0 , -1 , img->mb_size[IS_CHROMA], &up);

  mb_available_up                             = up.available;
  mb_available_up_left                        = left[0].available;
  mb_available_left[0] = mb_available_left[1] = left[1].available;

  if(params->UseConstrainedIntraPred)
  {
    mb_available_up = up.available ? img->intra_block[up.mb_addr] : 0;
    for (i=1, mb_available_left[0] = 1; i < (cr_MB_y>>1) + 1; i++)
      mb_available_left[0]  &= left[i].available ? img->intra_block[left[i].mb_addr]: 0;

    for (i=(cr_MB_y>>1) + 1, mb_available_left[1]=1; i < cr_MB_y + 1;i++)
      mb_available_left[1] &= left[i].available ? img->intra_block[left[i].mb_addr]: 0;

    mb_available_up_left = left[0].available ? img->intra_block[left[0].mb_addr]: 0;
  }

  // pick lowest cost prediction mode
  min_cost = INT_MAX;
  for (i=0;i<cr_MB_y;i++)
  {
    getNeighbour(currMB, 0, i, img->mb_size[IS_CHROMA], &left[i]);
  }
  if ( img->MbaffFrameFlag && img->field_mode )
  {
    for (i=0;i<cr_MB_y;i++)
    {
      left[i].pos_y = left[i].pos_y >> 1;
    }
  }

  for (mode=DC_PRED_8; mode<=PLANE_8; mode++)
  {
    if ((mode==VERT_PRED_8 && !mb_available_up) ||
      (mode==HOR_PRED_8 && (!mb_available_left[0] || !mb_available_left[1])) ||
      (mode==PLANE_8 && (!mb_available_left[0] || !mb_available_left[1] || !mb_available_up || !mb_available_up_left)))
      continue;

    cost = 0;
    for (uv = 1; uv < 3; uv++)
    {
      image = pImgOrg[uv];
      curr_mpr_16x16 = img->mpr_16x16[uv];
      for (block_y=0; block_y<cr_MB_y; block_y+=4)
      {
        for (block_x=0; block_x<cr_MB_x; block_x+=4)
        {
          for (k=0,j=block_y; j<block_y+4; j++)
          {
            img_prd = curr_mpr_16x16[mode][j];
            img_org = &image[left[j].pos_y][left[j].pos_x];

            for (i = block_x; i < block_x + 4; i++)
              diff[k++] = img_org[i] - img_prd[i];
          }

          cost += distortion4x4(diff);
        }
        if (cost > min_cost) break;
      }
      if (cost > min_cost) break;
    }

    cost += (int) (enc_mb.lambda_me[Q_PEL] * mvbits[ mode ]); // exp golomb coding cost for mode signaling

    if (cost < min_cost)
    {
      best_mode = mode;
      min_cost = cost;
    }
  }
  currMB->c_ipred_mode = best_mode;
}


/*!
 ************************************************************************
 * \brief
 *    Check if all reference frames for a macroblock are zero
 ************************************************************************
 */
int ZeroRef (Macroblock* currMB)
{
  int i,j;

  for (j=img->block_y; j<img->block_y + BLOCK_MULTIPLE; j++)
  {
    for (i=img->block_x; i<img->block_x + BLOCK_MULTIPLE; i++)
    {
      if (enc_picture->motion.ref_idx[LIST_0][j][i]!=0)
        return 0;
    }
  }
  return 1;
}


/*!
 ************************************************************************
 * \brief
 *    Converts macroblock type to coding value
 ************************************************************************
 */
int MBType2Value (Macroblock* currMB)
{
  static const int dir1offset[3]    =  { 1,  2, 3};
  static const int dir2offset[3][3] = {{ 0,  4,  8},   // 1. block forward
                                       { 6,  2, 10},   // 1. block backward
                                       {12, 14, 16}};  // 1. block bi-directional

  int mbtype, pdir0, pdir1;

  if (img->type!=B_SLICE)
  {
    if      (currMB->mb_type==I8MB ||currMB->mb_type==I4MB)
      return (img->type==I_SLICE ? 0 : 6);
    else if (currMB->mb_type==I16MB) return (img->type==I_SLICE ? 0 : 6) + img->i16offset;
    else if (currMB->mb_type==IPCM)  return (img->type==I_SLICE ? 25 : 31);
    else if (currMB->mb_type==P8x8)
    {
      if (img->currentSlice->symbol_mode==CAVLC
        && ZeroRef (currMB))         return 5;
      else                           return 4;
    }
    else                             return currMB->mb_type;
  }
  else
  {
    mbtype = currMB->mb_type;
    pdir0  = currMB->b8pdir[0];
    pdir1  = currMB->b8pdir[3];

    if      (mbtype==0)                    return 0;
    else if (mbtype==I4MB || mbtype==I8MB) return 23;
    else if (mbtype==I16MB)                return 23 + img->i16offset;
    else if (mbtype==IPCM)                 return 48;
    else if (mbtype==P8x8)                 return 22;
    else if (mbtype==1)                    return dir1offset[pdir0];
    else if (mbtype==2)                    return 4 + dir2offset[pdir0][pdir1];
    else                                   return 5 + dir2offset[pdir0][pdir1];
  }
}


/*!
************************************************************************
* \brief
*    Writes 4x4 intra prediction modes for a macroblock
************************************************************************
*/
int writeIntra4x4Modes(Macroblock *currMB)
{
  int i;
  SyntaxElement se;
  int           *bitCount   = currMB->bitcounter;
  Slice         *currSlice  = img->currentSlice;
  const int     *partMap    = assignSE2partition[params->partition_mode];
  DataPartition *dataPart   = &(currSlice->partArr[partMap[SE_INTRAPREDMODE]]);

  int rate = 0;

  currMB->IntraChromaPredModeFlag = 1;

  for(i=0;i<16;i++)
  {
    se.context = i;
    se.value1  = currMB->intra_pred_modes[i];
    se.value2  = 0;

#if TRACE
    if (se.value1 < 0 )
      snprintf(se.tracestring, TRACESTRING_SIZE, "Intra 4x4 mode  = predicted (context: %d)",se.context);
    else
      snprintf(se.tracestring, TRACESTRING_SIZE, "Intra 4x4 mode  = %3d (context: %d)",se.value1,se.context);
#endif

    // set symbol type and function pointers
    se.type = SE_INTRAPREDMODE;

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

    bitCount[BITS_COEFF_Y_MB]+=se.len;
    rate += se.len;
  }

  return rate;
}

/*!
************************************************************************
* \brief
*    Writes 8x8 intra prediction modes for a macroblock
************************************************************************
*/
int writeIntra8x8Modes(Macroblock *currMB)
{
  int block8x8;
  SyntaxElement se;
  int           *bitCount   = currMB->bitcounter;
  Slice         *currSlice  = img->currentSlice;
  const int     *partMap    = assignSE2partition[params->partition_mode];
  DataPartition *dataPart   = &(currSlice->partArr[partMap[SE_INTRAPREDMODE]]);

  int rate = 0;

  currMB->IntraChromaPredModeFlag = 1;

  for(block8x8 = 0;block8x8 < 16; block8x8 += 4)
  {

    se.context = block8x8;
    se.value1  = currMB->intra_pred_modes8x8[block8x8];

⌨️ 快捷键说明

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