【HEVC学习与研究】37、HM编码器的基本结构2:帧内编码部分的代码骨架

简介: 第31篇博文大体介绍了HEVC参考代码HM10的编码器结构,但仅仅停留在compressCU()以上的层次,并未对具体编码的结构做深入解析。在此篇博文中我们依据对视频YUV序列的帧内编码的流程,重新梳理HM编码器的代码结构。

第31篇博文大体介绍了HEVC参考代码HM10的编码器结构,但仅仅停留在compressCU()以上的层次,并未对具体编码的结构做深入解析。在此篇博文中我们依据对视频YUV序列的帧内编码的流程,重新梳理HM编码器的代码结构。

1、编码器的上层结构:

主要包括:

  1. 入口点函数main()【创建cTAppEncTop类,解析输入的配置函数,设定时间相关的参数
  2. cTAppEncTop.encode()【对编码器所使用的几个对象进行初始化,分配YUV数据缓存,循环读取YUV文件
  3. m_cTEncTop.encode(...)【调用m_cGOPEncoder.compressGOP()实现对一个GOP的实际编码
  4. m_cGOPEncoder.compressGOP()【调用initGOP设置GOP的参数;调用m_pcSliceEncoder->initEncSlice(),利用SPS和PPS中的信息创建编码的slice对象;调用m_pcSliceEncoder->compressSlice ( pcPic )对一个slice进行编码。
  5. m_pcSliceEncoder->compressSlice ( pcPic )【设置编码slice的参数,对slice的每一个cu进行处理
  6. TEncCu::compressCU()【编码一个CU】

以上各个函数分别在前一个函数中调用,形成类似一个反向的call stack的结构。

2、对一个CU进行编码的过程:

TEncCu::compressCU()函数的实现如下:

Void TEncCu::compressCU( TComDataCU*& rpcCU )
{
  // initialize CU data
  m_ppcBestCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );
  m_ppcTempCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );

#if RATE_CONTROL_LAMBDA_DOMAIN
  m_addSADDepth      = 0;
  m_LCUPredictionSAD = 0;
  m_temporalSAD      = 0;
#endif

  // analysis of CU
  xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], 0 );

#if ADAPTIVE_QP_SELECTION
  if( m_pcEncCfg->getUseAdaptQpSelect() )
  {
    if(rpcCU->getSlice()->getSliceType()!=I_SLICE) //IIII
    {
      xLcuCollectARLStats( rpcCU);
    }
  }
#endif
}

该函数的核心方法为xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], 0 )。该函数实现了编码一个CU的多种功能,首先判断尝试进行帧间预测,然后尝试进行帧内预测,另外还包括了PCM模式的编码以及一个CU的进一步划分等。这里主要关心的是intra模式,实现的代码为:

if ( !bEarlySkip )
{
// speedup for inter frames
        if( rpcBestCU->getSlice()->getSliceType() == I_SLICE || 
        rpcBestCU->getCbf( 0, TEXT_LUMA     ) != 0   ||
        rpcBestCU->getCbf( 0, TEXT_CHROMA_U ) != 0   ||
        rpcBestCU->getCbf( 0, TEXT_CHROMA_V ) != 0     ) // avoid very complex intra if it is unlikely
        {
        xCheckRDCostIntra( rpcBestCU, rpcTempCU, SIZE_2Nx2N );
           rpcTempCU->initEstData( uiDepth, iQP );
            if( uiDepth == g_uiMaxCUDepth - g_uiAddCUDepth )
            {
                      if( rpcTempCU->getWidth(0) > ( 1 << rpcTempCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) )
               {
                xCheckRDCostIntra( rpcBestCU, rpcTempCU, SIZE_NxN   );
                rpcTempCU->initEstData( uiDepth, iQP );
                }
        }
}
}

该函数调用的xCheckRDCostIntra实现了帧内预测的具体过程:
Void TEncCu::xCheckRDCostIntra( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, PartSize eSize )
{
  UInt uiDepth = rpcTempCU->getDepth( 0 );
  
  rpcTempCU->setSkipFlagSubParts( false, 0, uiDepth );

  rpcTempCU->setPartSizeSubParts( eSize, 0, uiDepth );
  rpcTempCU->setPredModeSubParts( MODE_INTRA, 0, uiDepth );
  rpcTempCU->setCUTransquantBypassSubParts( m_pcEncCfg->getCUTransquantBypassFlagValue(), 0, uiDepth );
  
  Bool bSeparateLumaChroma = true; // choose estimation mode
  UInt uiPreCalcDistC      = 0;
  if( !bSeparateLumaChroma )
  {
    m_pcPredSearch->preestChromaPredMode( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth] );
  }
  m_pcPredSearch  ->estIntraPredQT      ( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth], m_ppcResiYuvTemp[uiDepth], m_ppcRecoYuvTemp[uiDepth], uiPreCalcDistC, bSeparateLumaChroma );

  m_ppcRecoYuvTemp[uiDepth]->copyToPicLuma(rpcTempCU->getPic()->getPicYuvRec(), rpcTempCU->getAddr(), rpcTempCU->getZorderIdxInCU() );
  
  m_pcPredSearch  ->estIntraPredChromaQT( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth], m_ppcResiYuvTemp[uiDepth], m_ppcRecoYuvTemp[uiDepth], uiPreCalcDistC );
  
  m_pcEntropyCoder->resetBits();
  if ( rpcTempCU->getSlice()->getPPS()->getTransquantBypassEnableFlag())
  {
    m_pcEntropyCoder->encodeCUTransquantBypassFlag( rpcTempCU, 0,          true );
  }
  m_pcEntropyCoder->encodeSkipFlag ( rpcTempCU, 0,          true );
  m_pcEntropyCoder->encodePredMode( rpcTempCU, 0,          true );
  m_pcEntropyCoder->encodePartSize( rpcTempCU, 0, uiDepth, true );
  m_pcEntropyCoder->encodePredInfo( rpcTempCU, 0,          true );
  m_pcEntropyCoder->encodeIPCMInfo(rpcTempCU, 0, true );

  // Encode Coefficients
  Bool bCodeDQP = getdQPFlag();
  m_pcEntropyCoder->encodeCoeff( rpcTempCU, 0, uiDepth, rpcTempCU->getWidth (0), rpcTempCU->getHeight(0), bCodeDQP );
  setdQPFlag( bCodeDQP );
  
  if( m_bUseSBACRD ) m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]);
  
  rpcTempCU->getTotalBits() = m_pcEntropyCoder->getNumberOfWrittenBits();
  if(m_pcEncCfg->getUseSBACRD())
  {
    rpcTempCU->getTotalBins() = ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded();
  }
  rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() );
  
  xCheckDQP( rpcTempCU );
  xCheckBestMode(rpcBestCU, rpcTempCU, uiDepth);
}
该函数调用了estIntraPredQT和estIntraPredChromaQT分别实现亮度分量和色度分量的帧内估计,二者大同小异。这里重点观察亮度分量。estIntraPredQT执行了遍历各种intra模式的操作,调用了pcCU->getPattern()->initAdiPattern、predIntraLumaAng等函数。详情可见编号第 3336的博文。

目录
相关文章
|
3月前
|
机器学习/深度学习 测试技术 Ruby
YOLOv8改进 | 主干篇 | 反向残差块网络EMO一种轻量级的CNN架构(附完整代码 + 修改教程)
YOLOv8改进 | 主干篇 | 反向残差块网络EMO一种轻量级的CNN架构(附完整代码 + 修改教程)
105 0
|
3月前
|
机器学习/深度学习 测试技术 Ruby
YOLOv5改进 | 主干篇 | 反向残差块网络EMO一种轻量级的CNN架构(附完整代码 + 修改教程)
YOLOv5改进 | 主干篇 | 反向残差块网络EMO一种轻量级的CNN架构(附完整代码 + 修改教程)
138 2
|
2月前
|
机器学习/深度学习 自然语言处理 运维
大模型开发:解释自编码器以及它们在表示学习中的作用。
自编码器是一种神经网络,用于无监督学习中的数据降维和压缩,由编码器和解码器组成,学习低维稀疏表示。它们分为收缩、正则和变分类型,常用于图像重构、聚类、机器翻译等任务,能生成类似训练数据的新样本。自编码器在特征学习和多种任务中展现强大能力。
74 7
|
6月前
|
机器学习/深度学习 传感器 自动驾驶
视觉BEV基本原理和方案解析
视觉BEV在高德高精地图地面要素识别、车道线拓扑构建、车端融合定位等业务场景中都扮演了重要角色。
|
3月前
|
计算机视觉 网络架构
YOLOv5改进 | 2023主干篇 | 替换LSKNet遥感目标检测主干 (附代码+修改教程+结构讲解)
YOLOv5改进 | 2023主干篇 | 替换LSKNet遥感目标检测主干 (附代码+修改教程+结构讲解)
61 0
|
3月前
|
机器学习/深度学习 计算机视觉 网络架构
YOLOv8改进 | 2023主干篇 | 替换LSKNet遥感目标检测主干 (附代码+修改教程+结构讲解)
YOLOv8改进 | 2023主干篇 | 替换LSKNet遥感目标检测主干 (附代码+修改教程+结构讲解)
78 1
YOLOv8改进 | 2023主干篇 | 替换LSKNet遥感目标检测主干 (附代码+修改教程+结构讲解)
|
3月前
|
机器学习/深度学习 存储 计算机视觉
YOLOv5改进 | 2023主干篇 | EfficientViT替换Backbone(高效的视觉变换网络)
YOLOv5改进 | 2023主干篇 | EfficientViT替换Backbone(高效的视觉变换网络)
98 1
|
3月前
|
机器学习/深度学习 存储 计算机视觉
YOLOv8改进 | 2023主干篇 | EfficientViT替换Backbone(高效的视觉变换网络)
YOLOv8改进 | 2023主干篇 | EfficientViT替换Backbone(高效的视觉变换网络)
120 0
|
8月前
|
机器学习/深度学习 存储 人工智能
解码Transformer:自注意力机制与编解码器机制详述与代码实现
解码Transformer:自注意力机制与编解码器机制详述与代码实现
137 0
|
9月前
|
机器学习/深度学习 编解码 数据可视化
ConvNeXt V2:与屏蔽自动编码器共同设计和缩放ConvNets,论文+代码+实战
ConvNeXt V2:与屏蔽自动编码器共同设计和缩放ConvNets,论文+代码+实战