HEVC-HM16.9源码学习(1)TEncCu::xCompressCU

HEVC-HM16.9源码学习(1)TEncCu::xCompressCU

通过划分结构关系,一个Slice划分成的SS可以包含若干个CTU。因此,在一个slice中,枚举每个CTU进入编码过程:
从slice进入CU编码
函数入口: TEncSlice::compressSlicem_pcCuEncoder->compressCtu( pCtu );
在这里插入图片描述
调用 xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], 0 );


从CTU开始以四叉树的结构划分CU,递归的每次尝试各种模式和划分方法,记录一个最佳的方案并保存参数。

xCompressCU做的工作:

  1. 对当前CU计算最好代价;
  2. 对当前CU的子块继续递归调用xCompressCU;xCompressCU过程
    源码以及注释:
Void TEncCu::xCompressCU( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, const UInt uiDepth DEBUG_STRING_FN_DECLARE(sDebug_), PartSize eParentPartSize )
{
   
   
    TComPic* pcPic = rpcBestCU->getPic(); // 获取当前CU的图像
    const TComPPS &pps=*(rpcTempCU->getSlice()->getPPS()); // 获取图像参数集
    const TComSPS &sps=*(rpcTempCU->getSlice()->getSPS()); // 获取序列参数集
    
    m_ppcOrigYuv[uiDepth]->copyFromPicYuv( pcPic->getPicYuvOrg(), rpcBestCU->getCtuRsAddr(), rpcBestCU->getZorderIdxInCtu() ); // 从图像中获取原始YUV数据
    
    Bool    doNotBlockPu = true; // 快速cbf标识(cbf模式见术语表)
    Bool    earlyDetectionSkipMode = false; //early skip早期跳出标识(early skip模式见术语表)
    
    const UInt uiLPelX   = rpcBestCU->getCUPelX(); // 最左端点x坐标
    const UInt uiRPelX   = uiLPelX + rpcBestCU->getWidth(0)  - 1; // 最右端点x坐标
    const UInt uiTPelY   = rpcBestCU->getCUPelY(); // 最上端点y坐标
    const UInt uiBPelY   = uiTPelY + rpcBestCU->getHeight(0) - 1; // 最下端点y坐标
    const UInt uiWidth   = rpcBestCU->getWidth(0); // 当前CU块宽度
    
    Int iBaseQP = xComputeQP( rpcBestCU, uiDepth );
    // 传入当前CU和深度,计算对当前CU的QP;如果不是对每个CU自适应的改变QP,则直接用之前slice算出的QP
    
    const UInt numberValidComponents = rpcBestCU->getPic()->getNumberValidComponents();
    // 获取成分数量,如果色度格式是CHROMA_400,数量为1,反之为3(最大)
    
    /* 【省略代码】根据当前深度、是否使用码率控制、是否使用TQB(TransquantBypass模式,见术语表)调整QP最大和最小的范围(iMinQP-iMaxQP) */
    
    TComSlice * pcSlice = rpcTempCU->getPic()->getSlice(rpcTempCU->getPic()->getCurrSliceIdx()); // 获取当前所在slice
    
    const Bool bBoundary = !( uiRPelX < sps.getPicWidthInLumaSamples() && uiBPelY < sps.getPicHeightInLumaSamples() ); // 当前CU块的右边界在整个图像的最右边 或者 下边界在整个图像最下边 则为TRUE(即在边界)
    
    if ( !bBoundary ) // 如果不在边界
    {
   
   
        for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) // 在之前确定的QP范围中枚举QP
        {
   
   
            /* 【省略代码】如果是TransquantBypass模式(这里用bIsLosslessMode布尔型标识)且如果当前枚举到最小QP,将其改为lowestQP */
            /* 【省略代码】如果是自适应改变QP,设置相关的对最小编码块大小取Log的值、色度QP偏移量索引*/
            
            rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode );
            // 使用CTU四叉树子层的deltaQP初始化预测数据,根据深度设置CU的宽度和高度,对QP赋值
            
            /* {做帧间预测, SKIP和2Nx2N} */
            if( rpcBestCU->getSlice()->getSliceType() != I_SLICE )
            {
   
   
                /* {2Nx2N} */
                if(m_pcEncCfg->getUseEarlySkipDetection()) // 使用early skip早期跳出模式
                {
   
   
                    xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N DEBUG_STRING_PASS_INTO(sDebug) ); // 尝试用普通模式进行预测
                    rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); // rpcBestCU保存性能最优的预测方式下的参数,rpcTempCU是每次用于尝试划分预测的CU,每次做完后重新恢复初始化
                }
                /* {SKIP} */
                xCheckRDCostMerge2Nx2N( rpcBestCU, rpcTempCU DEBUG_STRING_PASS_INTO(sDebug), &earlyDetectionSkipMode ); // 尝试用Merge模式进行预测,传入早期跳出标识,如果模式为skip则修改该布尔值
                rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode );
                
                if(!m_pcEncCfg->getUseEarlySkipDetection())
                {
   
   
                    /* {2Nx2N, NxN(?讲道理,真没找到这个NxN哪里做了)} */
                    xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N DEBUG_STRING_PASS_INTO(sDebug) );
                    rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode );
                    if(m_pcEncCfg->getUseCbfFastMode()) // 使用快速cbf模式
                    {
   
   
                        doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; // 判断四叉树根节点的CBFlag如果为true,则不需要后续继续划分
                    }
                }
            }
        }
        
        
        if(!earlyDetectionSkipMode) // 如果之前没有设置提前跳出,继续尝试所有的划分方式
        {
   
   
            for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) // 枚举QP
            {
   
   
                /* 【省略代码】如果是TransquantBypass模式同上处理 */
                rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); // CU恢复初始化
                
                /* {帧间预测, NxN, 2NxN, Nx2N} */
        
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值