HEVC代码学习35:xEncodeCU函数

45 篇文章 189 订阅
44 篇文章 15 订阅

xEncodeCU是由encodeCtu调用,其作用是从CTU开始迭代对每个CU进行编码。注意,xEncodeCU是在最优分块已经划分完成后进行编码时使用的,在xCompressCU中没有使用。

xEncodeCU会调用以下函数来完成各部分的编码:
encodeSplitFlag编码块是否划分
encodeSkipFlag编码是否是skip模式
encodeMergeIndex如果是skip模式,编码merge索引
encodePredMode编码CU的模式,是intra还是inter
encodePartSize编码CU中的PU的类型
encodeIPCMInfo 如果选用了PCM模式会编码PCM模式的信息
encodePredInfo编码预测的信息,如果是帧内,编码预测方向,如果是帧间,编码MV和参考索引
encodeCoeff编码残差系数
encodeCoeff中会编码TU的分割标志位,cbf和残差系数的信息

/** encode a CU block recursively
 * \param pcCU
 * \param uiAbsPartIdx
 * \param uiDepth
 * \returns Void
 */
//迭代对CU编码
Void TEncCu::xEncodeCU( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth )
{
        TComPic   *const pcPic   = pcCU->getPic();      //当前图像
        TComSlice *const pcSlice = pcCU->getSlice();        //当前Slice
  const TComSPS   &sps =*(pcSlice->getSPS());       //SPS
  const TComPPS   &pps =*(pcSlice->getPPS());   //PPS

  const UInt maxCUWidth  = sps.getMaxCUWidth();     //最大CU宽度
  const UInt maxCUHeight = sps.getMaxCUHeight();        //最大CU高度

        Bool bBoundary = false;     //边界
        UInt uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ]; //起始x坐标
  const UInt uiRPelX   = uiLPelX + (maxCUWidth>>uiDepth)  - 1;      //结束x坐标
        UInt uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];     //起始y坐标
  const UInt uiBPelY   = uiTPelY + (maxCUHeight>>uiDepth) - 1;      //结束y坐标

  if( ( uiRPelX < sps.getPicWidthInLumaSamples() ) && ( uiBPelY < sps.getPicHeightInLumaSamples() ) )
  {
    m_pcEntropyCoder->encodeSplitFlag( pcCU, uiAbsPartIdx, uiDepth );       //编码划分Flag
  }
  else
  {
    bBoundary = true;
  }

  if( ( ( uiDepth < pcCU->getDepth( uiAbsPartIdx ) ) && ( uiDepth < sps.getLog2DiffMaxMinCodingBlockSize() ) ) || bBoundary )
  {
    UInt uiQNumParts = ( pcPic->getNumPartitionsInCtu() >> (uiDepth<<1) )>>2;
    if( uiDepth == pps.getMaxCuDQPDepth() && pps.getUseDQP())       //如果使用DQP,置flag
    {
      setdQPFlag(true);
    }

    if( uiDepth == pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() && pcSlice->getUseChromaQpAdj())       //色度QP自适应
    {
      setCodeChromaQpAdjFlag(true);
    }

    for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++, uiAbsPartIdx+=uiQNumParts )       //遍历四个分块编码
    {
      uiLPelX   = pcCU->getCUPelX() + g_auiRasterToPelX[ g_auiZscanToRaster[uiAbsPartIdx] ];        //块的起始x坐标
      uiTPelY   = pcCU->getCUPelY() + g_auiRasterToPelY[ g_auiZscanToRaster[uiAbsPartIdx] ];        //块的起始y坐标
      if( ( uiLPelX < sps.getPicWidthInLumaSamples() ) && ( uiTPelY < sps.getPicHeightInLumaSamples() ) )
      {
        xEncodeCU( pcCU, uiAbsPartIdx, uiDepth+1 );
      }
    }
    return;
  }

  if( uiDepth <= pps.getMaxCuDQPDepth() && pps.getUseDQP())     //如果使用DQP,置flag
  {
    setdQPFlag(true);
  }

  if( uiDepth <= pps.getPpsRangeExtension().getDiffCuChromaQpOffsetDepth() && pcSlice->getUseChromaQpAdj())
  {
    setCodeChromaQpAdjFlag(true);
  }

  if (pps.getTransquantBypassEnabledFlag())     //默认false
  {
    m_pcEntropyCoder->encodeCUTransquantBypassFlag( pcCU, uiAbsPartIdx );
  }

  if( !pcSlice->isIntra() )     //帧间编码编码skip flag
  {
    m_pcEntropyCoder->encodeSkipFlag( pcCU, uiAbsPartIdx );
  }

  if( pcCU->isSkipped( uiAbsPartIdx ) )     //编码merge索引
  {
    m_pcEntropyCoder->encodeMergeIndex( pcCU, uiAbsPartIdx );
    finishCU(pcCU,uiAbsPartIdx);
    return;
  }

  m_pcEntropyCoder->encodePredMode( pcCU, uiAbsPartIdx );       //编码预测模式
  m_pcEntropyCoder->encodePartSize( pcCU, uiAbsPartIdx, uiDepth );          //编码PU类型

  if (pcCU->isIntra( uiAbsPartIdx ) && pcCU->getPartitionSize( uiAbsPartIdx ) == SIZE_2Nx2N )       //帧内SIZE_2Nx2N时,需要判断是否编码PCM信息
  {
    m_pcEntropyCoder->encodeIPCMInfo( pcCU, uiAbsPartIdx );

    if(pcCU->getIPCMFlag(uiAbsPartIdx))
    {
      // Encode slice finish
      finishCU(pcCU,uiAbsPartIdx);
      return;
    }
  }

  // prediction Info ( Intra : direction mode, Inter : Mv, reference idx )
  m_pcEntropyCoder->encodePredInfo( pcCU, uiAbsPartIdx );       //编码预测信息:帧内为预测方向,帧间为MV和参考索引

  // Encode Coefficients    
  //编码系数
  Bool bCodeDQP = getdQPFlag();
  Bool codeChromaQpAdj = getCodeChromaQpAdjFlag();
  m_pcEntropyCoder->encodeCoeff( pcCU, uiAbsPartIdx, uiDepth, bCodeDQP, codeChromaQpAdj );
  setCodeChromaQpAdjFlag( codeChromaQpAdj );
  setdQPFlag( bCodeDQP );

  // --- write terminating bit ---
  finishCU(pcCU,uiAbsPartIdx);
}
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值