• HM16.0之帧内模式——xCheckRDCostIntra()函数


    参考:https://blog.csdn.net/nb_vol_1/article/category/6179825/1?

    1、源代码:

    Void TEncCu::xCheckRDCostIntra( TComDataCU *&rpcBestCU,
                                    TComDataCU *&rpcTempCU,
                                    Double      &cost,
                                    PartSize     eSize
                                    DEBUG_STRING_FN_DECLARE(sDebug) )
    {
      DEBUG_STRING_NEW(sTest)
    
      UInt uiDepth = rpcTempCU->getDepth( 0 );
    
      rpcTempCU->setSkipFlagSubParts( false, 0, uiDepth );
    
      rpcTempCU->setPartSizeSubParts( eSize, 0, uiDepth );
      rpcTempCU->setPredModeSubParts( MODE_INTRA, 0, uiDepth );
      rpcTempCU->setChromaQpAdjSubParts( rpcTempCU->getCUTransquantBypass(0) ? 0 : m_ChromaQpAdjIdc, 0, uiDepth );
    
      Bool bSeparateLumaChroma = true; // choose estimation mode
    
      Distortion uiPreCalcDistC = 0;
      if (rpcBestCU->getPic()->getChromaFormat()==CHROMA_400)
      {
        bSeparateLumaChroma=true;
      }
    
      Pel resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE];
    
      if( !bSeparateLumaChroma )
      {
        // after this function, the direction will be PLANAR, DC, HOR or VER
        // however, if Luma ends up being one of those, the chroma dir must be later changed to DM_CHROMA.
        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], resiLuma, uiPreCalcDistC, bSeparateLumaChroma DEBUG_STRING_PASS_INTO(sTest) ); m_ppcRecoYuvTemp[uiDepth]->copyToPicComponent(COMPONENT_Y, rpcTempCU->getPic()->getPicYuvRec(), rpcTempCU->getAddr(), rpcTempCU->getZorderIdxInCU() ); if (rpcBestCU->getPic()->getChromaFormat()!=CHROMA_400) {
      // 色度块的帧内预测 m_pcPredSearch
    ->estIntraPredChromaQT( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth], m_ppcResiYuvTemp[uiDepth], m_ppcRecoYuvTemp[uiDepth], resiLuma, uiPreCalcDistC DEBUG_STRING_PASS_INTO(sTest) ); } 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 ); m_pcEntropyCoder->encodeIPCMInfo(rpcTempCU, 0, true ); // Encode Coefficients Bool bCodeDQP = getdQPFlag(); Bool codeChromaQpAdjFlag = getCodeChromaQpAdjFlag(); m_pcEntropyCoder->encodeCoeff( rpcTempCU, 0, uiDepth, bCodeDQP, codeChromaQpAdjFlag ); setCodeChromaQpAdjFlag( codeChromaQpAdjFlag ); setdQPFlag( bCodeDQP ); m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]); rpcTempCU->getTotalBits() = m_pcEntropyCoder->getNumberOfWrittenBits(); rpcTempCU->getTotalBins() = ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() ); xCheckDQP( rpcTempCU ); cost = rpcTempCU->getTotalCost(); xCheckBestMode(rpcBestCU, rpcTempCU, uiDepth DEBUG_STRING_PASS_INTO(sDebug) DEBUG_STRING_PASS_INTO(sTest)); }

    2、estIntraPredQT(亮度块的帧内预测):

    Void
    TEncSearch::estIntraPredQT(TComDataCU* pcCU,
                               TComYuv*    pcOrgYuv,
                               TComYuv*    pcPredYuv,
                               TComYuv*    pcResiYuv,
                               TComYuv*    pcRecoYuv,
                               Pel         resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE],
                               Distortion& ruiDistC,
                               Bool        bLumaOnly
                               DEBUG_STRING_FN_DECLARE(sDebug))
    {
      const UInt         uiDepth               = pcCU->getDepth(0);
      const UInt         uiInitTrDepth         = pcCU->getPartitionSize(0) == SIZE_2Nx2N ? 0 : 1;
      const UInt         uiInitTrDepthC        = pcCU->getPartitionSize(0) != SIZE_2Nx2N && enable4ChromaPUsInIntraNxNCU(pcOrgYuv->getChromaFormat()) ? 1 : 0;
      const UInt         uiNumPU               = 1<<(2*uiInitTrDepth);
      const UInt         uiQNumParts           = pcCU->getTotalNumPart() >> 2;
      const UInt         uiWidthBit            = pcCU->getIntraSizeIdx(0);
      const ChromaFormat chFmt                 = pcCU->getPic()->getChromaFormat();
      const UInt         numberValidComponents = getNumberValidComponents(chFmt);
            Distortion   uiOverallDistY        = 0;
            Distortion   uiOverallDistC        = 0;
            UInt         CandNum;
            Double       CandCostList[ FAST_UDI_MAX_RDMODE_NUM ]; // 候选的Cost列表
            Pel          resiLumaPU[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE];
    
            Bool    bMaintainResidual[NUMBER_OF_STORED_RESIDUAL_TYPES];
            for (UInt residualTypeIndex = 0; residualTypeIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; residualTypeIndex++)
            {
              bMaintainResidual[residualTypeIndex] = true; //assume true unless specified otherwise
            }
    
            bMaintainResidual[RESIDUAL_ENCODER_SIDE] = !(m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate());
    
      //NOTE: RExt - Lambda calculation at equivalent Qp of 4 is recommended because at that Qp, the quantisation divisor is 1.
    #if FULL_NBIT
      const Double sqrtLambdaForFirstPass= (m_pcEncCfg->getCostMode()==COST_MIXED_LOSSLESS_LOSSY_CODING && pcCU->getCUTransquantBypass(0)) ?
                    sqrt(0.57 * pow(2.0, ((RExt__LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME - 12) / 3.0)))
                  : m_pcRdCost->getSqrtLambda();
    #else
      const Double sqrtLambdaForFirstPass= (m_pcEncCfg->getCostMode()==COST_MIXED_LOSSLESS_LOSSY_CODING && pcCU->getCUTransquantBypass(0)) ?
                    sqrt(0.57 * pow(2.0, ((RExt__LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP_PRIME - 12 - 6 * (g_bitDepth[CHANNEL_TYPE_LUMA] - 8)) / 3.0)))
                  : m_pcRdCost->getSqrtLambda();
    #endif
    
      //===== set QP and clear Cbf =====
    // 设置QP参数,清理Cbf
    if ( pcCU->getSlice()->getPPS()->getUseDQP() == true) { pcCU->setQPSubParts( pcCU->getQP(0), 0, uiDepth ); } else {
       // 进入此处 pcCU
    ->setQPSubParts( pcCU->getSlice()->getSliceQp(), 0, uiDepth ); } //===== loop over partitions ===== TComTURecurse tuRecurseCU(pcCU, 0); TComTURecurse tuRecurseWithPU(tuRecurseCU, false, (uiInitTrDepth==0)?TComTU::DONT_SPLIT : TComTU::QUAD_SPLIT); do { const UInt uiPartOffset=tuRecurseWithPU.GetAbsPartIdxTU(); // for( UInt uiPU = 0, uiPartOffset=0; uiPU < uiNumPU; uiPU++, uiPartOffset += uiQNumParts ) //{ //===== init pattern for luma prediction ===== Bool bAboveAvail = false; // 上面的块是否有效 Bool bLeftAvail = false; // 左边的块是否有效 DEBUG_STRING_NEW(sTemp2) //===== determine set of modes to be tested (using prediction signal only) =====
    // 35种帧内预测模式
    Int numModesAvailable = 35; //total number of Intra modes UInt uiRdModeList[FAST_UDI_MAX_RDMODE_NUM]; Int numModesForFullRD = g_aucIntraModeNumFast[ uiWidthBit ]; if (tuRecurseWithPU.ProcessComponentSection(COMPONENT_Y))
        // 使用重建后的YUV图像对当前PU的相邻样点进行滤波,提供参考样本值 initAdiPatternChType( tuRecurseWithPU, bAboveAvail, bLeftAvail, COMPONENT_Y,
    true DEBUG_STRING_PASS_INTO(sTemp2) ); Bool doFastSearch = (numModesForFullRD != numModesAvailable); if (doFastSearch) { assert(numModesForFullRD < numModesAvailable); for( Int i=0; i < numModesForFullRD; i++ ) {
    // 用于存储每一种模式的消耗 CandCostList[ i ]
    = MAX_DOUBLE; } CandNum = 0; const TComRectangle &puRect=tuRecurseWithPU.getRect(COMPONENT_Y); const UInt uiAbsPartIdx=tuRecurseWithPU.GetAbsPartIdxTU();
    // 在原始的YUV中获取亮度的地址 Pel
    * piOrg = pcOrgYuv ->getAddr( COMPONENT_Y, uiAbsPartIdx );
    // 在预测的YUV中获取亮度的地址 Pel
    * piPred = pcPredYuv->getAddr( COMPONENT_Y, uiAbsPartIdx ); UInt uiStride = pcPredYuv->getStride( COMPONENT_Y ); // 偏移 DistParam distParam; const Bool bUseHadamard=pcCU->getCUTransquantBypass(0) == 0; m_pcRdCost->setDistParam(distParam, g_bitDepth[CHANNEL_TYPE_LUMA], piOrg, uiStride, piPred, uiStride, puRect.width, puRect.height, bUseHadamard); distParam.bApplyWeight = false;
    // 遍历35种帧内预测模式,选取若干个代价比较小的模式作为后续处理的模式
    for( Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ ) { UInt uiMode = modeIdx; Distortion uiSad = 0; const Bool bUseFilter=TComPrediction::filteringIntraReferenceSamples(COMPONENT_Y, uiMode, puRect.width, puRect.height, chFmt, pcCU->getSlice()->getSPS()->getDisableIntraReferenceSmoothing());
    // 对亮度块进行预测 predIntraAng( COMPONENT_Y, uiMode, piOrg, uiStride, piPred, uiStride, tuRecurseWithPU, bAboveAvail, bLeftAvail, bUseFilter, TComPrediction::UseDPCMForFirstPassIntraEstimation(tuRecurseWithPU, uiMode) );
    // use hadamard transform here
    // 使用hadamard变换,计算SATD的值 uiSad+=distParam.DistFunc(&distParam); UInt iModeBits = 0; // NB xModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated. iModeBits+=xModeBitsIntra( pcCU, uiMode, uiPartOffset, uiDepth, uiInitTrDepth, CHANNEL_TYPE_LUMA );
    // 计算此种模式的代价 Double cost
    = (Double)uiSad + (Double)iModeBits * sqrtLambdaForFirstPass; #ifdef DEBUG_INTRA_SEARCH_COSTS std::cout << "1st pass mode " << uiMode << " SAD = " << uiSad << ", mode bits = " << iModeBits << ", cost = " << cost << " "; #endif // 更新候选列表 CandNum += xUpdateCandList( uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList ); } #if FAST_UDI_USE_MPM Int uiPreds[NUM_MOST_PROBABLE_MODES] = {-1, -1, -1}; Int iMode = -1;
    // 根据相邻块的预测模式来对当前块的模式进行预测,得到若干模式(称为预测模式),存放在uiPreds中 Int numCand
    = pcCU->getIntraDirPredictor( uiPartOffset, uiPreds, COMPONENT_Y, &iMode ); if( iMode >= 0 ) {
    // 将候选列表的索引设置为此模式 numCand
    = iMode; }
    // 遍历预测模式,如果它不在模式候选列表中,那么把它添加到其中
    for( Int j=0; j < numCand; j++) { Bool mostProbableModeIncluded = false; Int mostProbableMode = uiPreds[j]; for( Int i=0; i < numModesForFullRD; i++) { mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]); } if (!mostProbableModeIncluded) { uiRdModeList[numModesForFullRD++] = mostProbableMode; } } #endif // FAST_UDI_USE_MPM } else { for( Int i=0; i < numModesForFullRD; i++) { uiRdModeList[i] = i; } } //===== check modes (using r-d costs) ===== #if HHI_RQT_INTRA_SPEEDUP_MOD UInt uiSecondBestMode = MAX_UINT; Double dSecondBestPUCost = MAX_DOUBLE; #endif DEBUG_STRING_NEW(sPU) UInt uiBestPUMode = 0; Distortion uiBestPUDistY = 0; Distortion uiBestPUDistC = 0; Double dBestPUCost = MAX_DOUBLE; #if RExt__ENVIRONMENT_VARIABLE_DEBUG_AND_TEST UInt max=numModesForFullRD; if (DebugOptionList::ForceLumaMode.isSet()) max=0; // we are forcing a direction, so don't bother with mode check for ( UInt uiMode = 0; uiMode < max; uiMode++) #else
    // 遍历候选集中的模式 for( UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++ ) #endif { // set luma prediction mode UInt uiOrgMode = uiRdModeList[uiMode]; pcCU->setIntraDirSubParts ( CHANNEL_TYPE_LUMA, uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth ); DEBUG_STRING_NEW(sMode) // set context models
    // 设置上下文模型 m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] ); // determine residual for partition Distortion uiPUDistY = 0; Distortion uiPUDistC = 0; Double dPUCost = 0.0; #if HHI_RQT_INTRA_SPEEDUP
    // 通过多候选模式进行预测、变换、量化等操作来计算代价
    // 注意倒数第三个参数bCheckFirst是true,表示会继续按照四叉树的方式向下划分 xRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, uiPUDistC,
    true, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) ); #else xRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, uiPUDistC, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) ); #endif #ifdef DEBUG_INTRA_SEARCH_COSTS std::cout << "2nd pass [luma,chroma] mode [" << Int(pcCU->getIntraDir(CHANNEL_TYPE_LUMA, uiPartOffset)) << "," << Int(pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, uiPartOffset)) << "] cost = " << dPUCost << " "; #endif // check r-d cost
    // 从候选列表中选取最优的模式 if( dPUCost < dBestPUCost ) { DEBUG_STRING_SWAP(sPU, sMode) #if HHI_RQT_INTRA_SPEEDUP_MOD uiSecondBestMode = uiBestPUMode; dSecondBestPUCost = dBestPUCost; #endif uiBestPUMode = uiOrgMode; uiBestPUDistY = uiPUDistY; uiBestPUDistC = uiPUDistC; dBestPUCost = dPUCost; xSetIntraResultQT( bLumaOnly, pcRecoYuv, tuRecurseWithPU ); if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()) { const Int xOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).x0; const Int yOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).y0; for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++) { if (bMaintainResidual[storedResidualIndex]) { xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaPU[storedResidualIndex], tuRecurseWithPU, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE ); } } } UInt uiQPartNum = tuRecurseWithPU.GetAbsPartIdxNumParts(); ::memcpy( m_puhQTTempTrIdx, pcCU->getTransformIdx() + uiPartOffset, uiQPartNum * sizeof( UChar ) ); for (UInt component = 0; component < numberValidComponents; component++) { const ComponentID compID = ComponentID(component); ::memcpy( m_puhQTTempCbf[compID], pcCU->getCbf( compID ) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[compID], pcCU->getTransformSkip(compID) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); } } #if HHI_RQT_INTRA_SPEEDUP_MOD else if( dPUCost < dSecondBestPUCost ) { uiSecondBestMode = uiOrgMode; dSecondBestPUCost = dPUCost; } #endif } // Mode loop #if HHI_RQT_INTRA_SPEEDUP #if HHI_RQT_INTRA_SPEEDUP_MOD for( UInt ui =0; ui < 2; ++ui ) #endif { #if HHI_RQT_INTRA_SPEEDUP_MOD UInt uiOrgMode = ui ? uiSecondBestMode : uiBestPUMode; if( uiOrgMode == MAX_UINT ) { break; } #else UInt uiOrgMode = uiBestPUMode; #endif #if RExt__ENVIRONMENT_VARIABLE_DEBUG_AND_TEST if (DebugOptionList::ForceLumaMode.isSet()) uiOrgMode = DebugOptionList::ForceLumaMode.getInt(); #endif pcCU->setIntraDirSubParts ( CHANNEL_TYPE_LUMA, uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth ); DEBUG_STRING_NEW(sModeTree) // set context models m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] ); // determine residual for partition Distortion uiPUDistY = 0; Distortion uiPUDistC = 0; Double dPUCost = 0.0;
    // 使用最优模式对PU进行预测,然后变换量化等,计算代价
    // 注意倒数第三个参数bCheckFirst是false,表示当前PU不再进行划分,即只处理当前深度的PU xRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaPU, uiPUDistY, uiPUDistC,
    false, dPUCost, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sModeTree)); // check r-d cost
    // 检测同一种模式下,bCheckFirst为true和false的情况下,哪个的代价更低 if( dPUCost < dBestPUCost ) { DEBUG_STRING_SWAP(sPU, sModeTree) uiBestPUMode = uiOrgMode; uiBestPUDistY = uiPUDistY; uiBestPUDistC = uiPUDistC; dBestPUCost = dPUCost; xSetIntraResultQT( bLumaOnly, pcRecoYuv, tuRecurseWithPU ); if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()) { const Int xOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).x0; const Int yOffset = tuRecurseWithPU.getRect( COMPONENT_Y ).y0; for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++) { if (bMaintainResidual[storedResidualIndex]) { xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaPU[storedResidualIndex], tuRecurseWithPU, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE ); } } } const UInt uiQPartNum = tuRecurseWithPU.GetAbsPartIdxNumParts(); ::memcpy( m_puhQTTempTrIdx, pcCU->getTransformIdx() + uiPartOffset, uiQPartNum * sizeof( UChar ) ); for (UInt component = 0; component < numberValidComponents; component++) { const ComponentID compID = ComponentID(component); ::memcpy( m_puhQTTempCbf[compID], pcCU->getCbf( compID ) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[compID], pcCU->getTransformSkip(compID) + uiPartOffset, uiQPartNum * sizeof( UChar ) ); } } } // Mode loop #endif DEBUG_STRING_APPEND(sDebug, sPU) //--- update overall distortion --- uiOverallDistY += uiBestPUDistY; uiOverallDistC += uiBestPUDistC; //--- update transform index and cbf --- const UInt uiQPartNum = tuRecurseWithPU.GetAbsPartIdxNumParts(); ::memcpy( pcCU->getTransformIdx() + uiPartOffset, m_puhQTTempTrIdx, uiQPartNum * sizeof( UChar ) ); for (UInt component = 0; component < numberValidComponents; component++) { const ComponentID compID = ComponentID(component); ::memcpy( pcCU->getCbf( compID ) + uiPartOffset, m_puhQTTempCbf[compID], uiQPartNum * sizeof( UChar ) ); ::memcpy( pcCU->getTransformSkip( compID ) + uiPartOffset, m_puhQTTempTransformSkipFlag[compID ], uiQPartNum * sizeof( UChar ) ); } //--- set reconstruction for next intra prediction blocks ---
    // 变换量化/反变换反量化都已经处理完成了,那么设置重建块 if( !tuRecurseWithPU.IsLastSection() ) { const Bool bSkipChroma = tuRecurseWithPU.ProcessChannelSection(CHANNEL_TYPE_CHROMA); const UInt numChannelToProcess = (bLumaOnly || bSkipChroma) ? 1 : getNumberValidComponents(pcCU->getPic()->getChromaFormat()); for (UInt ch=0; ch<numChannelToProcess; ch++) { const ComponentID compID = ComponentID(ch); const TComRectangle &puRect=tuRecurseWithPU.getRect(compID); const UInt uiCompWidth = puRect.width; const UInt uiCompHeight = puRect.height; const UInt uiZOrder = pcCU->getZorderIdxInCU() + uiPartOffset; Pel* piDes = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getAddr(), uiZOrder ); const UInt uiDesStride = pcCU->getPic()->getPicYuvRec()->getStride( compID); const Pel* piSrc = pcRecoYuv->getAddr( compID, uiPartOffset ); const UInt uiSrcStride = pcRecoYuv->getStride( compID); for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride ) { for( UInt uiX = 0; uiX < uiCompWidth; uiX++ ) { piDes[ uiX ] = piSrc[ uiX ]; } } } } //=== update PU data ==== pcCU->setIntraDirSubParts ( CHANNEL_TYPE_LUMA, uiBestPUMode, uiPartOffset, uiDepth + uiInitTrDepth ); if (!bLumaOnly && getChromasCorrespondingPULumaIdx(uiPartOffset, chFmt)==uiPartOffset) { UInt chromaDir=pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, getChromasCorrespondingPULumaIdx(uiPartOffset, chFmt)); if (chromaDir == uiBestPUMode && tuRecurseWithPU.ProcessChannelSection(CHANNEL_TYPE_CHROMA)) { pcCU->setIntraDirSubParts ( CHANNEL_TYPE_CHROMA, DM_CHROMA_IDX, getChromasCorrespondingPULumaIdx(uiPartOffset, chFmt), uiDepth + uiInitTrDepthC ); } } //pcCU->copyToPic ( uiDepth, uiPU, uiInitTrDepth ); // Unnecessary copy? } while (tuRecurseWithPU.nextSection(tuRecurseCU)); if( uiNumPU > 1 ) { // set Cbf for all blocks UInt uiCombCbfY = 0; UInt uiCombCbfU = 0; UInt uiCombCbfV = 0; UInt uiPartIdx = 0; for( UInt uiPart = 0; uiPart < 4; uiPart++, uiPartIdx += uiQNumParts ) { uiCombCbfY |= pcCU->getCbf( uiPartIdx, COMPONENT_Y, 1 ); uiCombCbfU |= pcCU->getCbf( uiPartIdx, COMPONENT_Cb, 1 ); uiCombCbfV |= pcCU->getCbf( uiPartIdx, COMPONENT_Cr, 1 ); } for( UInt uiOffs = 0; uiOffs < 4 * uiQNumParts; uiOffs++ ) { pcCU->getCbf( COMPONENT_Y )[ uiOffs ] |= uiCombCbfY; pcCU->getCbf( COMPONENT_Cb )[ uiOffs ] |= uiCombCbfU; pcCU->getCbf( COMPONENT_Cr )[ uiOffs ] |= uiCombCbfV; } } //===== reset context models ===== m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); //===== set distortion (rate and r-d costs are determined later) ===== ruiDistC = uiOverallDistC; pcCU->getTotalDistortion() = uiOverallDistY + uiOverallDistC; }
    Void
    TEncSearch::xRecurIntraCodingQT(Bool        bLumaOnly,
                                    TComYuv*    pcOrgYuv,
                                    TComYuv*    pcPredYuv,
                                    TComYuv*    pcResiYuv,
                                    Pel         resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE],
                                    Distortion& ruiDistY,
                                    Distortion& ruiDistC,
    #if HHI_RQT_INTRA_SPEEDUP
                                    Bool        bCheckFirst,
    #endif
                                    Double&     dRDCost,
                                    TComTU&     rTu
                                    DEBUG_STRING_FN_DECLARE(sDebug))
    {
      TComDataCU   *pcCU          = rTu.getCU();
      const UInt    uiAbsPartIdx  = rTu.GetAbsPartIdxTU();
      const UInt    uiFullDepth   = rTu.GetTransformDepthTotal();
      const UInt    uiTrDepth     = rTu.GetTransformDepthRel();
      const UInt    uiLog2TrSize  = rTu.GetLog2LumaTrSize();
            Bool    bCheckFull    = ( uiLog2TrSize  <= pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() );
            Bool    bCheckSplit   = ( uiLog2TrSize  >  pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) );
      const UInt    numValidComp  = (bLumaOnly) ? 1 : pcOrgYuv->getNumberValidComponents();
    
            Pel     resiLumaSplit [NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE];
            Pel     resiLumaSingle[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE];
    
            Bool    bMaintainResidual[NUMBER_OF_STORED_RESIDUAL_TYPES];
            for (UInt residualTypeIndex = 0; residualTypeIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; residualTypeIndex++)
            {
              bMaintainResidual[residualTypeIndex] = true; //assume true unless specified otherwise
            }
    
            bMaintainResidual[RESIDUAL_ENCODER_SIDE] = !(m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate());
    
    #if HHI_RQT_INTRA_SPEEDUP
      Int maxTuSize = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize();
      Int isIntraSlice = (pcCU->getSlice()->getSliceType() == I_SLICE);
      // don't check split if TU size is less or equal to max TU size
      Bool noSplitIntraMaxTuSize = bCheckFull;
      if(m_pcEncCfg->getRDpenalty() && ! isIntraSlice)
      {
        // in addition don't check split if TU size is less or equal to 16x16 TU size for non-intra slice
        noSplitIntraMaxTuSize = ( uiLog2TrSize  <= min(maxTuSize,4) );
    
        // if maximum RD-penalty don't check TU size 32x32
        if(m_pcEncCfg->getRDpenalty()==2)
        {
          bCheckFull    = ( uiLog2TrSize  <= min(maxTuSize,4));
        }
      }
      if( bCheckFirst && noSplitIntraMaxTuSize )
    
      {
        bCheckSplit = false;
      }
    #else
      Int maxTuSize = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize();
      Int isIntraSlice = (pcCU->getSlice()->getSliceType() == I_SLICE);
      // if maximum RD-penalty don't check TU size 32x32
      if((m_pcEncCfg->getRDpenalty()==2)  && !isIntraSlice)
      {
        bCheckFull    = ( uiLog2TrSize  <= min(maxTuSize,4));
      }
    #endif
      Double     dSingleCost                        = MAX_DOUBLE;
      Distortion uiSingleDist[MAX_NUM_CHANNEL_TYPE] = {0,0};
      UInt       uiSingleCbf[MAX_NUM_COMPONENT]     = {0,0,0};
      Bool       checkTransformSkip  = pcCU->getSlice()->getPPS()->getUseTransformSkip();
      Int        bestModeId[MAX_NUM_COMPONENT] = { 0, 0, 0};
      checkTransformSkip           &= TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(COMPONENT_Y), pcCU->getSlice()->getPPS()->getTransformSkipLog2MaxSize());
      checkTransformSkip           &= (!pcCU->getCUTransquantBypass(0));
    
      if ( m_pcEncCfg->getUseTransformSkipFast() )
      {
        checkTransformSkip       &= (pcCU->getPartitionSize(uiAbsPartIdx)==SIZE_NxN);
      }
    
      if( bCheckFull )
      {
    // TransformSkip模式为true,表示将会跳过变换步骤
    if(checkTransformSkip == true) { //----- store original entropy coding status ----- m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); Distortion singleDistTmp[MAX_NUM_CHANNEL_TYPE] = { 0, 0 }; UInt singleCbfTmp[MAX_NUM_COMPONENT] = { 0, 0, 0 }; Double singleCostTmp = 0; Int firstCheckId = 0;
    // 遍历两次是为了选取最优模式,modeId能够决定xIntraCodingTUBlock的最后一个参数,该参数控制了预测像素如何生成
    for(Int modeId = firstCheckId; modeId < 2; modeId ++) { DEBUG_STRING_NEW(sModeString) Int default0Save1Load2 = 0; singleDistTmp[0]=singleDistTmp[1]=0; if(modeId == firstCheckId) { default0Save1Load2 = 1; } else { default0Save1Load2 = 2; } for(UInt ch=COMPONENT_Y; ch<numValidComp; ch++) { const ComponentID compID = ComponentID(ch); if (rTu.ProcessComponentSection(compID)) { const UInt totalAdjustedDepthChan = rTu.GetTransformDepthTotalAdj(compID); pcCU->setTransformSkipSubParts ( modeId, compID, uiAbsPartIdx, totalAdjustedDepthChan );
    // 亮度块的预测和量化 xIntraCodingTUBlock( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSingle,
    false, singleDistTmp[toChannelType(compID)], compID, rTu DEBUG_STRING_PASS_INTO(sModeString), default0Save1Load2 ); } singleCbfTmp[compID] = pcCU->getCbf( uiAbsPartIdx, compID, uiTrDepth ); } //----- determine rate and r-d cost ----- if(modeId == 1 && singleCbfTmp[COMPONENT_Y] == 0) { //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden. singleCostTmp = MAX_DOUBLE; } else { UInt uiSingleBits = xGetIntraBitsQT( rTu, true, !bLumaOnly, false ); singleCostTmp = m_pcRdCost->calcRdCost( uiSingleBits, singleDistTmp[CHANNEL_TYPE_LUMA] + singleDistTmp[CHANNEL_TYPE_CHROMA] ); }
    // 代价更新
    if(singleCostTmp < dSingleCost) { DEBUG_STRING_SWAP(sDebug, sModeString) dSingleCost = singleCostTmp; uiSingleDist[CHANNEL_TYPE_LUMA] = singleDistTmp[CHANNEL_TYPE_LUMA]; uiSingleDist[CHANNEL_TYPE_CHROMA] = singleDistTmp[CHANNEL_TYPE_CHROMA]; for (UInt ch=0; ch<MAX_NUM_COMPONENT; ch++) uiSingleCbf[ch] = singleCbfTmp[ch]; bestModeId[COMPONENT_Y] = modeId; if(bestModeId[COMPONENT_Y] == firstCheckId) { xStoreIntraResultQT(COMPONENT_Y, bLumaOnly?COMPONENT_Y:COMPONENT_Cr, rTu ); m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] ); } if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()) { const Int xOffset = rTu.getRect( COMPONENT_Y ).x0; const Int yOffset = rTu.getRect( COMPONENT_Y ).y0; for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++) { if (bMaintainResidual[storedResidualIndex]) { xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaSingle[storedResidualIndex], rTu, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE); } } } } if (modeId == firstCheckId) { m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); } } for(UInt ch=COMPONENT_Y; ch<numValidComp; ch++) { const ComponentID compID=ComponentID(ch); if (rTu.ProcessComponentSection(compID)) { const UInt totalAdjustedDepthChan = rTu.GetTransformDepthTotalAdj(compID); pcCU ->setTransformSkipSubParts ( bestModeId[COMPONENT_Y], compID, uiAbsPartIdx, totalAdjustedDepthChan ); } } if(bestModeId[COMPONENT_Y] == firstCheckId) { xLoadIntraResultQT(COMPONENT_Y, bLumaOnly?COMPONENT_Y:COMPONENT_Cr, rTu ); for(UInt ch=COMPONENT_Y; ch< numValidComp; ch++) { const ComponentID compID=ComponentID(ch); if (rTu.ProcessComponentSection(compID)) pcCU->setCbfSubParts ( uiSingleCbf[compID] << uiTrDepth, compID, uiAbsPartIdx, rTu.GetTransformDepthTotalAdj(compID) ); } m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] ); } if( !bLumaOnly ) { bestModeId[COMPONENT_Cb] = bestModeId[COMPONENT_Cr] = bestModeId[COMPONENT_Y]; if (rTu.ProcessComponentSection(COMPONENT_Cb) && bestModeId[COMPONENT_Y] == 1) { //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden. for (UInt ch=COMPONENT_Cb; ch<numValidComp; ch++) { if (uiSingleCbf[ch] == 0) { const ComponentID compID=ComponentID(ch); const UInt totalAdjustedDepthChan = rTu.GetTransformDepthTotalAdj(compID); pcCU ->setTransformSkipSubParts ( 0, compID, uiAbsPartIdx, totalAdjustedDepthChan); bestModeId[ch] = 0; } } } } }
    // TransformSkip模式为false,表示不会跳过变换步骤
    else { //----- store original entropy coding status ----- if( bCheckSplit ) { m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); } //----- code luma/chroma block with given intra prediction mode and store Cbf----- dSingleCost = 0.0; for (UInt ch=COMPONENT_Y; ch<numValidComp; ch++) { const ComponentID compID = ComponentID(ch); if (rTu.ProcessComponentSection(compID)) { const UInt totalAdjustedDepthChan = rTu.GetTransformDepthTotalAdj(compID); pcCU ->setTransformSkipSubParts ( 0, compID, uiAbsPartIdx, totalAdjustedDepthChan ); }
    // 亮度块的预测、变换和量化 xIntraCodingTUBlock( pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSingle,
    false, uiSingleDist[toChannelType(compID)], compID, rTu DEBUG_STRING_PASS_INTO(sDebug)); if( bCheckSplit ) { uiSingleCbf[compID] = pcCU->getCbf( uiAbsPartIdx, compID, uiTrDepth ); } } //----- determine rate and r-d cost ----- UInt uiSingleBits = xGetIntraBitsQT( rTu, true, !bLumaOnly, false ); if(m_pcEncCfg->getRDpenalty() && (uiLog2TrSize==5) && !isIntraSlice) { uiSingleBits=uiSingleBits*4; } dSingleCost = m_pcRdCost->calcRdCost( uiSingleBits, uiSingleDist[CHANNEL_TYPE_LUMA] + uiSingleDist[CHANNEL_TYPE_CHROMA] ); if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()) { const Int xOffset = rTu.getRect( COMPONENT_Y ).x0; const Int yOffset = rTu.getRect( COMPONENT_Y ).y0; for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++) { if (bMaintainResidual[storedResidualIndex]) { xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaSingle[storedResidualIndex], rTu, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE); } } } } }
    // 当前块是否向下继续划分为4个子块,如果是,那么就递归处理
    if( bCheckSplit ) { //----- store full entropy coding status, load original entropy coding status ----- if( bCheckFull ) { m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_TEST ] ); m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); } else { m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); } //----- code splitted block ----- Double dSplitCost = 0.0; Distortion uiSplitDist[MAX_NUM_CHANNEL_TYPE] = {0,0}; UInt uiSplitCbf[MAX_NUM_COMPONENT] = {0,0,0}; TComTURecurse tuRecurseChild(rTu, false); DEBUG_STRING_NEW(sSplit) do { DEBUG_STRING_NEW(sChild) #if HHI_RQT_INTRA_SPEEDUP
    // 递归调用 xRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSplit, uiSplitDist[0], uiSplitDist[1], bCheckFirst, dSplitCost, tuRecurseChild DEBUG_STRING_PASS_INTO(sChild) ); #else xRecurIntraCodingQT( bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, resiLumaSplit, uiSplitDist[0], uiSplitDist[1], dSplitCost, tuRecurseChild DEBUG_STRING_PASS_INTO(sChild) ); #endif DEBUG_STRING_APPEND(sSplit, sChild) for(UInt ch=0; ch<numValidComp; ch++) { uiSplitCbf[ch] |= pcCU->getCbf( tuRecurseChild.GetAbsPartIdxTU(), ComponentID(ch), tuRecurseChild.GetTransformDepthRel() ); } } while (tuRecurseChild.nextSection(rTu) ); UInt uiPartsDiv = rTu.GetAbsPartIdxNumParts(); for(UInt ch=COMPONENT_Y; ch<numValidComp; ch++) { if (uiSplitCbf[ch]) { const UInt flag=1<<uiTrDepth; const ComponentID compID=ComponentID(ch); UChar *pBase=pcCU->getCbf( compID ); for( UInt uiOffs = 0; uiOffs < uiPartsDiv; uiOffs++ ) { pBase[ uiAbsPartIdx + uiOffs ] |= flag; } } } //----- restore context states ----- m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] ); //----- determine rate and r-d cost ----- UInt uiSplitBits = xGetIntraBitsQT( rTu, true, !bLumaOnly, false ); dSplitCost = m_pcRdCost->calcRdCost( uiSplitBits, uiSplitDist[CHANNEL_TYPE_LUMA] + uiSplitDist[CHANNEL_TYPE_CHROMA] ); //===== compare and set best ===== if( dSplitCost < dSingleCost ) { //--- update cost --- DEBUG_STRING_SWAP(sSplit, sDebug) ruiDistY += uiSplitDist[CHANNEL_TYPE_LUMA]; ruiDistC += uiSplitDist[CHANNEL_TYPE_CHROMA]; dRDCost += dSplitCost; if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()) { const Int xOffset = rTu.getRect( COMPONENT_Y ).x0; const Int yOffset = rTu.getRect( COMPONENT_Y ).y0; for (UInt storedResidualIndex = 0; storedResidualIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; storedResidualIndex++) { if (bMaintainResidual[storedResidualIndex]) { xStoreCrossComponentPredictionResult(resiLuma[storedResidualIndex], resiLumaSplit[storedResidualIndex], rTu, xOffset, yOffset, MAX_CU_SIZE, MAX_CU_SIZE); } } } return; } //----- set entropy coding status ----- m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_TEST ] ); //--- set transform index and Cbf values --- pcCU->setTrIdxSubParts( uiTrDepth, uiAbsPartIdx, uiFullDepth ); for(UInt ch=0; ch<numValidComp; ch++) { const ComponentID compID=ComponentID(ch); const TComRectangle &tuRect=rTu.getRect(compID); const UInt totalAdjustedDepthChan = rTu.GetTransformDepthTotalAdj(compID); pcCU->setCbfSubParts ( uiSingleCbf[compID] << uiTrDepth, compID, uiAbsPartIdx, totalAdjustedDepthChan ); pcCU ->setTransformSkipSubParts ( bestModeId[compID], compID, uiAbsPartIdx, totalAdjustedDepthChan ); //--- set reconstruction for next intra prediction blocks ---
    // 执行像素块的重建操作 const UInt uiQTLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize; const UInt uiZOrder = pcCU->getZorderIdxInCU() + uiAbsPartIdx; const UInt uiWidth = tuRect.width; const UInt uiHeight = tuRect.height; Pel* piSrc = m_pcQTTempTComYuv[ uiQTLayer ].getAddr( compID, uiAbsPartIdx ); UInt uiSrcStride = m_pcQTTempTComYuv[ uiQTLayer ].getStride ( compID ); Pel* piDes = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getAddr(), uiZOrder ); UInt uiDesStride = pcCU->getPic()->getPicYuvRec()->getStride ( compID ); for( UInt uiY = 0; uiY < uiHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride ) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { piDes[ uiX ] = piSrc[ uiX ]; } } } } ruiDistY += uiSingleDist[CHANNEL_TYPE_LUMA]; ruiDistC += uiSingleDist[CHANNEL_TYPE_CHROMA]; dRDCost += dSingleCost; }
    // 帧内预测的一整套流程:预测+变换量化+反变换反量化+重建像素
    Void TEncSearch::xIntraCodingTUBlock( TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, Pel resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE], const Bool checkCrossCPrediction, Distortion& ruiDist, const ComponentID compID, TComTU& rTu DEBUG_STRING_FN_DECLARE(sDebug) ,Int default0Save1Load2 ) { if (!rTu.ProcessComponentSection(compID)) return; const Bool bIsLuma = isLuma(compID); const TComRectangle &rect= rTu.getRect(compID); TComDataCU *pcCU=rTu.getCU(); const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(); const UInt uiTrDepth=rTu.GetTransformDepthRelAdj(compID);
    const UInt uiFullDepth = rTu.GetTransformDepthTotal(); // 获取深度 const UInt uiLog2TrSize = rTu.GetLog2LumaTrSize(); const ChromaFormat chFmt = pcOrgYuv->getChromaFormat(); const ChannelType chType = toChannelType(compID); const UInt uiWidth = rect.width; // 获取宽度 const UInt uiHeight = rect.height; // 获取高度 const UInt uiStride = pcOrgYuv ->getStride (compID); // 获取偏移 Pel* piOrg = pcOrgYuv ->getAddr( compID, uiAbsPartIdx ); // 原始的像素地址 Pel* piPred = pcPredYuv->getAddr( compID, uiAbsPartIdx ); // 预测的像素地址 Pel* piResi = pcResiYuv->getAddr( compID, uiAbsPartIdx ); // 残差的像素地址 Pel* piReco = pcPredYuv->getAddr( compID, uiAbsPartIdx ); // 重建的像素地址 const UInt uiQTLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize; Pel* piRecQt = m_pcQTTempTComYuv[ uiQTLayer ].getAddr( compID, uiAbsPartIdx ); const UInt uiRecQtStride = m_pcQTTempTComYuv[ uiQTLayer ].getStride(compID); const UInt uiZOrder = pcCU->getZorderIdxInCU() + uiAbsPartIdx; // Z扫描的顺序 Pel* piRecIPred = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getAddr(), uiZOrder ); UInt uiRecIPredStride = pcCU->getPic()->getPicYuvRec()->getStride ( compID ); TCoeff* pcCoeff = m_ppcQTTempCoeff[compID][uiQTLayer] + rTu.getCoefficientOffset(compID); // 系数 Bool useTransformSkip = pcCU->getTransformSkip(uiAbsPartIdx, compID); #if ADAPTIVE_QP_SELECTION TCoeff* pcArlCoeff = m_ppcQTTempArlCoeff[compID][ uiQTLayer ] + rTu.getCoefficientOffset(compID); #endif const UInt uiChPredMode = pcCU->getIntraDir( chType, uiAbsPartIdx ); // 获取预测模式 const UInt uiChCodedMode = (uiChPredMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, chFmt)) : uiChPredMode; const UInt uiChFinalMode = ((chFmt == CHROMA_422) && !bIsLuma) ? g_chroma422IntraAngleMappingTable[uiChCodedMode] : uiChCodedMode; const Int blkX = g_auiRasterToPelX[ g_auiZscanToRaster[ uiAbsPartIdx ] ]; const Int blkY = g_auiRasterToPelY[ g_auiZscanToRaster[ uiAbsPartIdx ] ]; const Int bufferOffset = blkX + (blkY * MAX_CU_SIZE); Pel *const encoderLumaResidual = resiLuma[RESIDUAL_ENCODER_SIDE ] + bufferOffset; Pel *const reconstructedLumaResidual = resiLuma[RESDIUAL_RECONSTRUCTED] + bufferOffset; const Bool bUseCrossCPrediction = isChroma(compID) && (uiChPredMode == DM_CHROMA_IDX) && checkCrossCPrediction; const Bool bUseReconstructedResidualForEstimate = m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate(); Pel *const lumaResidualForEstimate = bUseReconstructedResidualForEstimate ? reconstructedLumaResidual : encoderLumaResidual; #ifdef DEBUG_STRING const Int debugPredModeMask=DebugStringGetPredModeMask(MODE_INTRA); #endif //===== init availability pattern ===== Bool bAboveAvail = false; // 上方是否有效 Bool bLeftAvail = false; // 左侧是否有效 DEBUG_STRING_NEW(sTemp) #ifndef DEBUG_STRING
    // default0Save1Load2参数控制了预测像素的生成方式
    if( default0Save1Load2 != 2 ) #endif { const Bool bUseFilteredPredictions=TComPrediction::filteringIntraReferenceSamples(compID, uiChFinalMode, uiWidth, uiHeight, chFmt, pcCU->getSlice()->getSPS()->getDisableIntraReferenceSmoothing()); initAdiPatternChType( rTu, bAboveAvail, bLeftAvail, compID, bUseFilteredPredictions DEBUG_STRING_PASS_INTO(sDebug) ); //===== get prediction signal =====
    // 预测操作 predIntraAng( compID, uiChFinalMode, piOrg, uiStride, piPred, uiStride, rTu, bAboveAvail, bLeftAvail, bUseFilteredPredictions ); // save prediction
    // 保存预测信息 if( default0Save1Load2 == 1 ) { Pel* pPred = piPred; Pel* pPredBuf = m_pSharedPredTransformSkip[compID]; Int k = 0; for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { pPredBuf[ k ++ ] = pPred[ uiX ]; } pPred += uiStride; } } } #ifndef DEBUG_STRING else { // load prediction
    // 直接计算预测值 Pel* pPred = piPred; Pel* pPredBuf = m_pSharedPredTransformSkip[compID]; Int k = 0; for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { pPred[ uiX ] = pPredBuf[ k ++ ]; } pPred += uiStride; } } #endif //===== get residual signal ===== { // get residual
    // 计算残差 Pel* pOrg = piOrg; Pel* pPred = piPred; Pel* pResi = piResi; for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) {
    // 此处计算残差数据 pResi[ uiX ]
    = pOrg[ uiX ] - pPred[ uiX ]; } pOrg += uiStride; pResi += uiStride; pPred += uiStride; } } if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()) { if (bUseCrossCPrediction) { if (xCalcCrossComponentPredictionAlpha( rTu, compID, lumaResidualForEstimate, piResi, uiWidth, uiHeight, MAX_CU_SIZE, uiStride ) == 0) return; TComTrQuant::crossComponentPrediction ( rTu, compID, reconstructedLumaResidual, piResi, piResi, uiWidth, uiHeight, MAX_CU_SIZE, uiStride, uiStride, false ); } else if (isLuma(compID) && !bUseReconstructedResidualForEstimate) { xStoreCrossComponentPredictionResult( encoderLumaResidual, piResi, rTu, 0, 0, MAX_CU_SIZE, uiStride ); } } //===== transform and quantization =====
    // 变换和量化
    //--- init rate estimation arrays for RDOQ ---
    // 是否跳过变换操作 if( useTransformSkip ? m_pcEncCfg->getUseRDOQTS() : m_pcEncCfg->getUseRDOQ() ) {
    // 比特数估计 m_pcEntropyCoder
    ->estimateBit( m_pcTrQuant->m_pcEstBitsSbac, uiWidth, uiHeight, chType ); } //--- transform and quantization --- TCoeff uiAbsSum = 0; if (bIsLuma) { pcCU ->setTrIdxSubParts ( uiTrDepth, uiAbsPartIdx, uiFullDepth ); } const QpParam cQP(*pcCU, compID); #if RDOQ_CHROMA_LAMBDA m_pcTrQuant->selectLambda (compID); #endif
    // 变换(连同量化一起) m_pcTrQuant
    ->transformNxN ( rTu, compID, piResi, uiStride, pcCoeff, #if ADAPTIVE_QP_SELECTION pcArlCoeff, #endif uiAbsSum, cQP ); //--- inverse transform --- // uiAbsSum表示变换系数的绝对值之和 #ifdef DEBUG_STRING if ( (uiAbsSum > 0) || (DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask) ) #else if ( uiAbsSum > 0 ) #endif {
    // 反变换 m_pcTrQuant
    ->invTransformNxN ( rTu, compID, piResi, uiStride, pcCoeff, cQP DEBUG_STRING_PASS_INTO_OPTIONAL(&sDebug, (DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask)) ); } else { Pel* pResi = piResi; memset( pcCoeff, 0, sizeof( TCoeff ) * uiWidth * uiHeight ); for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { memset( pResi, 0, sizeof( Pel ) * uiWidth ); pResi += uiStride; } } //===== reconstruction =====
    // 图像重建 { Pel* pPred = piPred; Pel* pResi = piResi; Pel* pReco = piReco; Pel* pRecQt = piRecQt; Pel* pRecIPred = piRecIPred; const UInt clipbd=g_bitDepth[chType]; if (pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()) { if (bUseCrossCPrediction) { TComTrQuant::crossComponentPrediction( rTu, compID, reconstructedLumaResidual, piResi, piResi, uiWidth, uiHeight, MAX_CU_SIZE, uiStride, uiStride, true ); } else if (isLuma(compID)) { xStoreCrossComponentPredictionResult( reconstructedLumaResidual, piResi, rTu, 0, 0, MAX_CU_SIZE, uiStride ); } } #ifdef DEBUG_STRING std::stringstream ss(stringstream::out); const Bool bDebugPred=((DebugOptionList::DebugString_Pred.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID)); const Bool bDebugResi=((DebugOptionList::DebugString_Resi.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID)); const Bool bDebugReco=((DebugOptionList::DebugString_Reco.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID)); if (bDebugPred || bDebugResi || bDebugReco) { ss << "###: " << "CompID: " << compID << " pred mode (ch/fin): " << uiChPredMode << "/" << uiChFinalMode << " absPartIdx: " << rTu.GetAbsPartIdxTU() << " "; for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { ss << "###: "; if (bDebugPred) { ss << " - pred: "; for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { ss << pPred[ uiX ] << ", "; } } if (bDebugResi) ss << " - resi: "; for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { if (bDebugResi) ss << pResi[ uiX ] << ", "; pReco [ uiX ] = Pel(ClipBD<Int>( Int(pPred[uiX]) + Int(pResi[uiX]), clipbd )); pRecQt [ uiX ] = pReco[ uiX ]; pRecIPred[ uiX ] = pReco[ uiX ]; } if (bDebugReco) { ss << " - reco: "; for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { ss << pReco[ uiX ] << ", "; } } pPred += uiStride; pResi += uiStride; pReco += uiStride; pRecQt += uiRecQtStride; pRecIPred += uiRecIPredStride; ss << " "; } DEBUG_STRING_APPEND(sDebug, ss.str()) } else #endif { for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { pReco [ uiX ] = Pel(ClipBD<Int>( Int(pPred[uiX]) + Int(pResi[uiX]), clipbd )); pRecQt [ uiX ] = pReco[ uiX ]; pRecIPred[ uiX ] = pReco[ uiX ]; } pPred += uiStride; pResi += uiStride; pReco += uiStride; pRecQt += uiRecQtStride; pRecIPred += uiRecIPredStride; } } } //===== update distortion =====
    // 失真代价更新 ruiDist += m_pcRdCost->getDistPart( g_bitDepth[chType], piReco, uiStride, piOrg, uiStride, uiWidth, uiHeight, compID ); }
    Void TComPrediction::predIntraAng( const ComponentID compID, UInt uiDirMode, Pel* piOrg /* Will be null for decoding */, UInt uiOrgStride, Pel* piPred, UInt uiStride, TComTU &rTu, Bool bAbove, Bool bLeft, const Bool bUseFilteredPredSamples, const Bool bUseLosslessDPCM )
    {
      const ChromaFormat   format      = rTu.GetChromaFormat(); // 获得图片格式,一般为YUV420
      const ChannelType    channelType = toChannelType(compID);
      const TComRectangle &rect        = rTu.getRect(isLuma(compID) ? COMPONENT_Y : COMPONENT_Cb);
      const Int            iWidth      = rect.width;  // TU的宽
      const Int            iHeight     = rect.height; // TU的高
    
      assert( g_aucConvertToBit[ iWidth ] >= 0 ); //   4x  4
      assert( g_aucConvertToBit[ iWidth ] <= 5 ); // 128x128
      //assert( iWidth == iHeight  );
    
            Pel *pDst = piPred; // 预测值的首地址
    
      // get starting pixel in block
    // 获取块中的开始像素
    const Int sw = (2 * iWidth + 1);
    // 如果预测方式为垂直或水平,则bUseLosslessDPCM为true
    if ( bUseLosslessDPCM ) {
    // 得到参考块的左上方地址(不在参考块内)
    const Pel *ptrSrc = getPredictorPtr( compID, false ); // Sample Adaptive intra-Prediction (SAP)
    // 水平模式预测 if (uiDirMode==HOR_IDX) { // left column filled with reference samples // remaining columns filled with piOrg data (if available). for(Int y=0; y<iHeight; y++) { piPred[y*uiStride+0] = ptrSrc[(y+1)*sw]; } if (piOrg!=0) { piPred+=1; // miss off first column for(Int y=0; y<iHeight; y++, piPred+=uiStride, piOrg+=uiOrgStride) { memcpy(piPred, piOrg, (iWidth-1)*sizeof(Pel)); } } }
    // 垂直模式预测
    else // VER_IDX { // top row filled with reference samples // remaining rows filled with piOrd data (if available) for(Int x=0; x<iWidth; x++) { piPred[x] = ptrSrc[x+1]; } if (piOrg!=0) { piPred+=uiStride; // miss off the first row for(Int y=1; y<iHeight; y++, piPred+=uiStride, piOrg+=uiOrgStride) { memcpy(piPred, piOrg, iWidth*sizeof(Pel)); } } } } else { const Pel *ptrSrc = getPredictorPtr( compID, bUseFilteredPredSamples ); if ( uiDirMode == PLANAR_IDX ) {
    // Planar模式 xPredIntraPlanar( ptrSrc
    +sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType, format ); } else { // Create the prediction TComDataCU *const pcCU = rTu.getCU(); const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU(); const Bool enableEdgeFilters = !(pcCU->isRDPCMEnabled(uiAbsPartIdx) && pcCU->getCUTransquantBypass(uiAbsPartIdx)); #if RExt__O0043_BEST_EFFORT_DECODING
    // 角度模式 xPredIntraAng( g_bitDepthInStream[channelType], ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType, format, uiDirMode, bAbove, bLeft, enableEdgeFilters ); #else xPredIntraAng( g_bitDepth[channelType], ptrSrc+sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType, format, uiDirMode, bAbove, bLeft, enableEdgeFilters ); #endif if(( uiDirMode == DC_IDX ) && bAbove && bLeft ) {
    // DC模式 xDCPredFiltering( ptrSrc
    +sw+1, sw, pDst, uiStride, iWidth, iHeight, channelType ); } } } }

    3、estIntraPredChromaQT(色度块的帧内预测):

    Void
    TEncSearch::estIntraPredChromaQT(TComDataCU* pcCU,
                                     TComYuv*    pcOrgYuv,
                                     TComYuv*    pcPredYuv,
                                     TComYuv*    pcResiYuv,
                                     TComYuv*    pcRecoYuv,
                                     Pel         resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE],
                                     Distortion  uiPreCalcDistC
                                     DEBUG_STRING_FN_DECLARE(sDebug))
    {
      pcCU->getTotalDistortion      () -= uiPreCalcDistC;
    
      //const UInt    uiDepthCU     = pcCU->getDepth(0);
      const UInt    uiInitTrDepth  = pcCU->getPartitionSize(0) != SIZE_2Nx2N && enable4ChromaPUsInIntraNxNCU(pcOrgYuv->getChromaFormat()) ? 1 : 0;
    //  const UInt    uiNumPU        = 1<<(2*uiInitTrDepth);
    
      TComTURecurse tuRecurseCU(pcCU, 0);
      TComTURecurse tuRecurseWithPU(tuRecurseCU, false, (uiInitTrDepth==0)?TComTU::DONT_SPLIT : TComTU::QUAD_SPLIT);
      const UInt    uiQNumParts    = tuRecurseWithPU.GetAbsPartIdxNumParts();
      const UInt    uiDepthCU=tuRecurseWithPU.getCUDepth();
      const UInt    numberValidComponents = pcCU->getPic()->getNumberValidComponents();
    
      do
      {
        UInt       uiBestMode  = 0;
        Distortion uiBestDist  = 0;
        Double     dBestCost   = MAX_DOUBLE;
    
        //----- init mode list -----
        if (tuRecurseWithPU.ProcessChannelSection(CHANNEL_TYPE_CHROMA))
        {
          UInt uiModeList[FAST_UDI_MAX_RDMODE_NUM];
          const UInt  uiQPartNum     = uiQNumParts;
          const UInt  uiPartOffset   = tuRecurseWithPU.GetAbsPartIdxTU();
          {
            UInt  uiMinMode = 0;
            UInt  uiMaxMode = NUM_CHROMA_MODE;
    
            //----- check chroma modes -----
            pcCU->getAllowedChromaDir( uiPartOffset, uiModeList );
    
    #if RExt__ENVIRONMENT_VARIABLE_DEBUG_AND_TEST
            if (DebugOptionList::ForceChromaMode.isSet())
            {
              uiMinMode=DebugOptionList::ForceChromaMode.getInt();
              if (uiModeList[uiMinMode]==34) uiMinMode=5; // if the fixed mode has been renumbered because DM_CHROMA covers it, use DM_CHROMA.
              uiMaxMode=uiMinMode+1;
            }
    #endif
    
            DEBUG_STRING_NEW(sPU)
    
            for( UInt uiMode = uiMinMode; uiMode < uiMaxMode; uiMode++ )
            {
              //----- restore context models -----
              m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepthCU][CI_CURR_BEST] );
              
              DEBUG_STRING_NEW(sMode)
              //----- chroma coding -----
              Distortion uiDist = 0;
              pcCU->setIntraDirSubParts  ( CHANNEL_TYPE_CHROMA, uiModeList[uiMode], uiPartOffset, uiDepthCU+uiInitTrDepth );
              xRecurIntraChromaCodingQT       ( pcOrgYuv, pcPredYuv, pcResiYuv, resiLuma, uiDist, tuRecurseWithPU DEBUG_STRING_PASS_INTO(sMode) );
    
              if( pcCU->getSlice()->getPPS()->getUseTransformSkip() )
              {
                m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepthCU][CI_CURR_BEST] );
              }
    
              UInt    uiBits = xGetIntraBitsQT( tuRecurseWithPU, false, true, false );
              Double  dCost  = m_pcRdCost->calcRdCost( uiBits, uiDist );
    
              //----- compare -----
              if( dCost < dBestCost )
              {
                DEBUG_STRING_SWAP(sPU, sMode);
                dBestCost   = dCost;
                uiBestDist  = uiDist;
                uiBestMode  = uiModeList[uiMode];
    
                xSetIntraResultChromaQT( pcRecoYuv, tuRecurseWithPU );
                for (UInt componentIndex = COMPONENT_Cb; componentIndex < numberValidComponents; componentIndex++)
                {
                  const ComponentID compID = ComponentID(componentIndex);
                  ::memcpy( m_puhQTTempCbf[compID], pcCU->getCbf( compID )+uiPartOffset, uiQPartNum * sizeof( UChar ) );
                  ::memcpy( m_puhQTTempTransformSkipFlag[compID], pcCU->getTransformSkip( compID )+uiPartOffset, uiQPartNum * sizeof( UChar ) );
                  ::memcpy( m_phQTTempCrossComponentPredictionAlpha[compID], pcCU->getCrossComponentPredictionAlpha(compID)+uiPartOffset, uiQPartNum * sizeof( Char ) );
                }
              }
            }
    
            DEBUG_STRING_APPEND(sDebug, sPU)
    
            //----- set data -----
            for (UInt componentIndex = COMPONENT_Cb; componentIndex < numberValidComponents; componentIndex++)
            {
              const ComponentID compID = ComponentID(componentIndex);
              ::memcpy( pcCU->getCbf( compID )+uiPartOffset, m_puhQTTempCbf[compID], uiQPartNum * sizeof( UChar ) );
              ::memcpy( pcCU->getTransformSkip( compID )+uiPartOffset, m_puhQTTempTransformSkipFlag[compID], uiQPartNum * sizeof( UChar ) );
              ::memcpy( pcCU->getCrossComponentPredictionAlpha(compID)+uiPartOffset, m_phQTTempCrossComponentPredictionAlpha[compID], uiQPartNum * sizeof( Char ) );
            }
          }
    
          if( ! tuRecurseWithPU.IsLastSection() )
          {
            for (UInt ch=COMPONENT_Cb; ch<numberValidComponents; ch++)
            {
              const ComponentID compID    = ComponentID(ch);
              const TComRectangle &tuRect = tuRecurseWithPU.getRect(compID);
              const UInt  uiCompWidth     = tuRect.width;
              const UInt  uiCompHeight    = tuRect.height;
              const UInt  uiZOrder        = pcCU->getZorderIdxInCU() + tuRecurseWithPU.GetAbsPartIdxTU();
                    Pel*  piDes           = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getAddr(), uiZOrder );
              const UInt  uiDesStride     = pcCU->getPic()->getPicYuvRec()->getStride( compID);
              const Pel*  piSrc           = pcRecoYuv->getAddr( compID, uiPartOffset );
              const UInt  uiSrcStride     = pcRecoYuv->getStride( compID);
    
              for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )
              {
                for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )
                {
                  piDes[ uiX ] = piSrc[ uiX ];
                }
              }
            }
          }
    
          pcCU->setIntraDirSubParts( CHANNEL_TYPE_CHROMA, uiBestMode, uiPartOffset, uiDepthCU+uiInitTrDepth );
          pcCU->getTotalDistortion      () += uiBestDist;
        }
    
      } while (tuRecurseWithPU.nextSection(tuRecurseCU));
    
      //----- restore context models -----
    
      if( uiInitTrDepth != 0 )
      { // set Cbf for all blocks
        UInt uiCombCbfU = 0;
        UInt uiCombCbfV = 0;
        UInt uiPartIdx  = 0;
        for( UInt uiPart = 0; uiPart < 4; uiPart++, uiPartIdx += uiQNumParts )
        {
          uiCombCbfU |= pcCU->getCbf( uiPartIdx, COMPONENT_Cb, 1 );
          uiCombCbfV |= pcCU->getCbf( uiPartIdx, COMPONENT_Cr, 1 );
        }
        for( UInt uiOffs = 0; uiOffs < 4 * uiQNumParts; uiOffs++ )
        {
          pcCU->getCbf( COMPONENT_Cb )[ uiOffs ] |= uiCombCbfU;
          pcCU->getCbf( COMPONENT_Cr )[ uiOffs ] |= uiCombCbfV;
        }
      }
    
      m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepthCU][CI_CURR_BEST] );
    }
    Void
    TEncSearch::xRecurIntraChromaCodingQT(TComYuv*    pcOrgYuv,
                                          TComYuv*    pcPredYuv,
                                          TComYuv*    pcResiYuv,
                                          Pel         resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE],
                                          Distortion& ruiDist,
                                          TComTU&     rTu
                                          DEBUG_STRING_FN_DECLARE(sDebug))
    {
      TComDataCU         *pcCU                  = rTu.getCU();
      const UInt          uiTrDepth             = rTu.GetTransformDepthRel();
      const UInt          uiAbsPartIdx          = rTu.GetAbsPartIdxTU();
      const ChromaFormat  format                = rTu.GetChromaFormat();
      UInt                uiTrMode              = pcCU->getTransformIdx( uiAbsPartIdx );
      const UInt          numberValidComponents = getNumberValidComponents(format);
    
      if(  uiTrMode == uiTrDepth )
      {
        if (!rTu.ProcessChannelSection(CHANNEL_TYPE_CHROMA)) return;
    
        const UInt uiFullDepth = rTu.GetTransformDepthTotal();
    
        Bool checkTransformSkip = pcCU->getSlice()->getPPS()->getUseTransformSkip();
        checkTransformSkip &= TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(COMPONENT_Cb), pcCU->getSlice()->getPPS()->getTransformSkipLog2MaxSize());
    
        if ( m_pcEncCfg->getUseTransformSkipFast() )
        {
          checkTransformSkip &= TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(COMPONENT_Y), pcCU->getSlice()->getPPS()->getTransformSkipLog2MaxSize());
    
          if (checkTransformSkip)
          {
            Int nbLumaSkip = 0;
            const UInt maxAbsPartIdxSub=uiAbsPartIdx + (rTu.ProcessingAllQuadrants(COMPONENT_Cb)?1:4);
            for(UInt absPartIdxSub = uiAbsPartIdx; absPartIdxSub < maxAbsPartIdxSub; absPartIdxSub ++)
            {
              nbLumaSkip += pcCU->getTransformSkip(absPartIdxSub, COMPONENT_Y);
            }
            checkTransformSkip &= (nbLumaSkip > 0);
          }
        }
    
    
        for (UInt ch=COMPONENT_Cb; ch<numberValidComponents; ch++)
        {
          const ComponentID compID = ComponentID(ch);
          DEBUG_STRING_NEW(sDebugBestMode)
    
          //use RDO to decide whether Cr/Cb takes TS
          m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[uiFullDepth][CI_QT_TRAFO_ROOT] );
    
          const Bool splitIntoSubTUs = rTu.getRect(compID).width != rTu.getRect(compID).height;
    
          TComTURecurse TUIterator(rTu, false, (splitIntoSubTUs ? TComTU::VERTICAL_SPLIT : TComTU::DONT_SPLIT), true, compID);
    
          const UInt partIdxesPerSubTU = TUIterator.GetAbsPartIdxNumParts(compID);
    
          do
          {
            const UInt subTUAbsPartIdx   = TUIterator.GetAbsPartIdxTU(compID);
    
            Double     dSingleCost               = MAX_DOUBLE;
            Int        bestModeId                = 0;
            Distortion singleDistC               = 0;
            UInt       singleCbfC                = 0;
            Distortion singleDistCTmp            = 0;
            Double     singleCostTmp             = 0;
            UInt       singleCbfCTmp             = 0;
            Char       bestCrossCPredictionAlpha = 0;
            Int        bestTransformSkipMode     = 0;
    
            const Bool checkCrossComponentPrediction =    (pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, subTUAbsPartIdx) == DM_CHROMA_IDX)
                                                       &&  pcCU->getSlice()->getPPS()->getUseCrossComponentPrediction()
                                                       && (pcCU->getCbf(subTUAbsPartIdx,  COMPONENT_Y, uiTrDepth) != 0);
    
            const Int  crossCPredictionModesToTest = checkCrossComponentPrediction ? 2 : 1;
            const Int  transformSkipModesToTest    = checkTransformSkip            ? 2 : 1;
            const Int  totalModesToTest            = crossCPredictionModesToTest * transformSkipModesToTest;
                  Int  currModeId                  = 0;
                  Int  default0Save1Load2          = 0;
    
            for(Int transformSkipModeId = 0; transformSkipModeId < transformSkipModesToTest; transformSkipModeId++)
            {
              for(Int crossCPredictionModeId = 0; crossCPredictionModeId < crossCPredictionModesToTest; crossCPredictionModeId++)
              {
                pcCU->setCrossComponentPredictionAlphaPartRange(0, compID, subTUAbsPartIdx, partIdxesPerSubTU);
                DEBUG_STRING_NEW(sDebugMode)
                pcCU->setTransformSkipPartRange( transformSkipModeId, compID, subTUAbsPartIdx, partIdxesPerSubTU );
                currModeId++;
    
                const Bool isOneMode  = (totalModesToTest == 1);
                const Bool isLastMode = (currModeId == totalModesToTest); //NOTE: RExt - currModeId is indexed from 1
    
                if (isOneMode)
                {
                  default0Save1Load2 = 0;
                }
                else if (!isOneMode && (transformSkipModeId == 0) && (crossCPredictionModeId == 0))
                {
                  default0Save1Load2 = 1; //save prediction on first mode
                }
                else
                {
                  default0Save1Load2 = 2; //load it on subsequent modes
                }
    
                singleDistCTmp = 0;
    
                xIntraCodingTUBlock( pcOrgYuv, pcPredYuv, pcResiYuv, resiLuma, (crossCPredictionModeId != 0), singleDistCTmp, compID, TUIterator DEBUG_STRING_PASS_INTO(sDebugMode), default0Save1Load2);
                singleCbfCTmp = pcCU->getCbf( subTUAbsPartIdx, compID, uiTrDepth);
    
                if (  ((crossCPredictionModeId == 1) && (pcCU->getCrossComponentPredictionAlpha(subTUAbsPartIdx, compID) == 0))
                   || ((transformSkipModeId    == 1) && (singleCbfCTmp == 0))) //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden.
                {
                  singleCostTmp = MAX_DOUBLE;
                }
                else if (!isOneMode)
                {
                  UInt bitsTmp = xGetIntraBitsQTChroma( TUIterator, compID, false );
                  singleCostTmp  = m_pcRdCost->calcRdCost( bitsTmp, singleDistCTmp);
                }
    
                if(singleCostTmp < dSingleCost)
                {
                  DEBUG_STRING_SWAP(sDebugBestMode, sDebugMode)
                  dSingleCost               = singleCostTmp;
                  singleDistC               = singleDistCTmp;
                  bestCrossCPredictionAlpha = (crossCPredictionModeId != 0) ? pcCU->getCrossComponentPredictionAlpha(subTUAbsPartIdx, compID) : 0;
                  bestTransformSkipMode     = transformSkipModeId;
                  bestModeId                = currModeId;
                  singleCbfC                = singleCbfCTmp;
    
                  if (!isOneMode && !isLastMode)
                  {
                    xStoreIntraResultQT(compID, compID, TUIterator);
                    m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] );
                  }
                }
    
                if (!isOneMode && !isLastMode)
                {
                  m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] );
                }
              }
            }
    
            if(bestModeId < totalModesToTest)
            {
              xLoadIntraResultQT(compID, compID, TUIterator);
              pcCU->setCbfPartRange( singleCbfC << uiTrDepth, compID, subTUAbsPartIdx, partIdxesPerSubTU );
    
              m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] );
            }
    
            DEBUG_STRING_APPEND(sDebug, sDebugBestMode)
            pcCU ->setTransformSkipPartRange                ( bestTransformSkipMode,     compID, subTUAbsPartIdx, partIdxesPerSubTU );
            pcCU ->setCrossComponentPredictionAlphaPartRange( bestCrossCPredictionAlpha, compID, subTUAbsPartIdx, partIdxesPerSubTU );
            ruiDist += singleDistC;
          }
          while (TUIterator.nextSection(rTu));
    
          if (splitIntoSubTUs) offsetSubTUCBFs(rTu, compID);
        }
      }
      else
      {
        UInt    uiSplitCbf[MAX_NUM_COMPONENT] = {0,0,0};
    
        TComTURecurse tuRecurseChild(rTu, false);
        const UInt uiTrDepthChild   = tuRecurseChild.GetTransformDepthRel();
        do
        {
          DEBUG_STRING_NEW(sChild)
    
          xRecurIntraChromaCodingQT( pcOrgYuv, pcPredYuv, pcResiYuv, resiLuma, ruiDist, tuRecurseChild DEBUG_STRING_PASS_INTO(sChild) );
    
          DEBUG_STRING_APPEND(sDebug, sChild)
          const UInt uiAbsPartIdxSub=tuRecurseChild.GetAbsPartIdxTU();
    
          for(UInt ch=COMPONENT_Cb; ch<numberValidComponents; ch++)
          {
            uiSplitCbf[ch] |= pcCU->getCbf( uiAbsPartIdxSub, ComponentID(ch), uiTrDepthChild );
          }
        } while ( tuRecurseChild.nextSection(rTu) );
    
    
        UInt uiPartsDiv = rTu.GetAbsPartIdxNumParts();
        for(UInt ch=COMPONENT_Cb; ch<numberValidComponents; ch++)
        {
          if (uiSplitCbf[ch])
          {
            const UInt flag=1<<uiTrDepth;
            ComponentID compID=ComponentID(ch);
            UChar *pBase=pcCU->getCbf( compID );
            for( UInt uiOffs = 0; uiOffs < uiPartsDiv; uiOffs++ )
            {
              pBase[ uiAbsPartIdx + uiOffs ] |= flag;
            }
          }
        }
      }
    }
  • 相关阅读:
    Unlicensed ARC session – terminating!
    ArcGIS读取dem格式数据
    OCIEnvCreate 失败,返回代码为 -1的解决方法
    PowerDesigner设计的数据库 ORA-0092
    Oracle空间查询 ORA-28595
    PowerDesigner添加表注释
    C# 动态解析表达式
    远程桌面不能交互复制粘贴
    ArcGIS10.4 Runtime Error R6034
    ArcGIS Add-in ValidateAddInXMLTask”任务意外失败
  • 原文地址:https://www.cnblogs.com/lucifer1997/p/10991046.html
Copyright © 2020-2023  润新知