VVCJEM代码学习27:xIntraRecBlk

xiaoxiao2021-02-28  9

Void TDecCu::xIntraRecBlk( TComYuv* pcRecoYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, const ComponentID compID, TComTU &rTu) { if (!rTu.ProcessComponentSection(compID)) { return; } const Bool bIsLuma = isLuma(compID); TComDataCU *pcCU = rTu.getCU(); #if COM16_C983_RSAF || !JVET_D0033_ADAPTIVE_CLIPPING const TComSPS &sps=*(pcCU->getSlice()->getSPS()); #endif const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU(); const TComRectangle &tuRect =rTu.getRect(compID); const UInt uiWidth = tuRect.width; const UInt uiHeight = tuRect.height; const UInt uiStride = pcRecoYuv->getStride (compID); Pel* piPred = pcPredYuv->getAddr( compID, uiAbsPartIdx ); const ChromaFormat chFmt = rTu.GetChromaFormat(); #if !JVET_C0024_QTBT if (uiWidth != uiHeight) { //------------------------------------------------ //split at current level if dividing into square sub-TUs TComTURecurse subTURecurse(rTu, false, TComTU::VERTICAL_SPLIT, true, compID); //recurse further do { xIntraRecBlk(pcRecoYuv, pcPredYuv, pcResiYuv, compID, subTURecurse); } while (subTURecurse.nextSection(rTu)); //------------------------------------------------ return; } #endif const UInt uiChPredMode = pcCU->getIntraDir( toChannelType(compID), uiAbsPartIdx );//得到预测模式; #if JVET_C0024_QTBT #if JVET_E0062_MULTI_DMS const UInt uiChCodedMode = uiChPredMode; #else const UInt uiChCodedMode = (uiChPredMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, uiAbsPartIdx) : uiChPredMode; #endif #else const UInt partsPerMinCU = 1<<(2*(sps.getMaxTotalCUDepth() - sps.getLog2DiffMaxMinCodingBlockSize())); const UInt uiChCodedMode = (uiChPredMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, chFmt, partsPerMinCU)) : uiChPredMode; #endif const UInt uiChFinalMode = ((chFmt == CHROMA_422) && !bIsLuma) ? g_chroma422IntraAngleMappingTable[uiChCodedMode] : uiChCodedMode; //===== init availability pattern ,初始化可获得pattern===== #if !COM16_C983_RSAF const #endif //是否使用滤波的参考像素,与编码端一致 Bool bUseFilteredPredictions=TComPrediction::filteringIntraReferenceSamples(compID, uiChFinalMode, uiWidth, uiHeight, chFmt, pcCU->getSlice()->getSPS()->getSpsRangeExtension().getIntraSmoothingDisabledFlag() #if COM16_C983_RSAF_PREVENT_OVERSMOOTHING , sps.getUseRSAF() #endif ); #if DEBUG_STRING std::ostream &ss(std::cout); #endif #if COM16_C983_RSAF Bool bFilter = false; #if COM16_C1046_PDPC_RSAF_HARMONIZATION if (compID == COMPONENT_Y && sps.getUseRSAF() && pcCU->getPDPCIdx(uiAbsPartIdx) == 0) #else if (compID==COMPONENT_Y && sps.getUseRSAF()) #endif { bFilter = (pcCU->getLumaIntraFilter( uiAbsPartIdx )) != 0; #if JVET_C0024_QTBT bFilter &= !(pcCU->getWidth(0)*pcCU->getHeight(0)>1024); #else bFilter &= !(pcCU->getWidth(0)>32); #endif } #endif DEBUG_STRING_NEW(sTemp) m_pcPrediction->initIntraPatternChType( rTu, compID, bUseFilteredPredictions #if COM16_C983_RSAF , (compID==COMPONENT_Y) ? bFilter : false #endif DEBUG_STRING_PASS_INTO(sTemp) );//初始化参考像素 //===== get prediction signal,得到预测信号,过程跟编码端也一致===== #if COM16_C806_LMCHROMA if( uiChFinalMode == LM_CHROMA_IDX #if JVET_E0077_ENHANCED_LM || IsLMMode(uiChFinalMode) #endif )//是CCLM模式 { m_pcPrediction->getLumaRecPixels( rTu, uiWidth, uiHeight );//对相邻亮度色度和当前亮度进行下采样; #if JVET_E0077_ENHANCED_LM Int iLMType = uiChFinalMode; m_pcPrediction->predLMIntraChroma(rTu, compID, piPred, uiStride, uiWidth, uiHeight, iLMType);//用亮度预测色度 #else m_pcPrediction->predLMIntraChroma( rTu, compID, piPred, uiStride, uiWidth, uiHeight ); #endif } else//普通角度模式 { #endif #if COM16_C983_RSAF if (compID==COMPONENT_Y && sps.getUseRSAF()) { bUseFilteredPredictions = (bFilter != false); } #endif//这个也是和编码时一样的函数 m_pcPrediction->predIntraAng( compID, uiChFinalMode, 0 /* Decoder does not have an original image */, 0, piPred, uiStride, rTu, bUseFilteredPredictions ); #if COM16_C806_LMCHROMA if( compID == COMPONENT_Cr && pcCU->getSlice()->getSPS()->getUseLMChroma() ) { //std::cout << "传统预测模式是 " << uiChFinalMode << std::endl; m_pcPrediction->addCrossColorResi( rTu, compID, piPred, uiStride, uiWidth, uiHeight, pcResiYuv->getAddr( COMPONENT_Cb, uiAbsPartIdx ), pcResiYuv->getStride(COMPONENT_Cb) ); } } #endif #if DEBUG_STRING ss << sTemp; #endif //===== inverse transform ,反变换和反量化===== Pel* piResi = pcResiYuv->getAddr( compID, uiAbsPartIdx );//残差YUV TCoeff* pcCoeff = pcCU->getCoeff(compID) + rTu.getCoefficientOffset(compID);//( uiNumCoeffInc * uiAbsPartIdx ); const QpParam cQP(*pcCU, compID); DEBUG_STRING_NEW(sDebug); #if DEBUG_STRING const Int debugPredModeMask=DebugStringGetPredModeMask(MODE_INTRA); std::string *psDebug=(DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask) ? &sDebug : 0; #endif if (pcCU->getCbf(uiAbsPartIdx, compID, rTu.GetTransformDepthRel()) != 0)//如果cbf!=0,则对残差进行反量化和反变换 { m_pcTrQuant->invTransformNxN( rTu, compID, piResi, uiStride, pcCoeff, cQP DEBUG_STRING_PASS_INTO(psDebug) ); } else//如果cbf=0,则直接令残差数据为0 { for (UInt y = 0; y < uiHeight; y++) { for (UInt x = 0; x < uiWidth; x++) { piResi[(y * uiStride) + x] = 0; } } } #if DEBUG_STRING if (psDebug) { ss << (*psDebug); } #endif //===== reconstruction ,重建=预测加残差===== const UInt uiRecIPredStride = pcCU->getPic()->getPicYuvRec()->getStride(compID); const Bool useCrossComponentPrediction = isChroma(compID) && (pcCU->getCrossComponentPredictionAlpha(uiAbsPartIdx, compID) != 0); const Pel* pResiLuma = pcResiYuv->getAddr( COMPONENT_Y, uiAbsPartIdx ); const Int strideLuma = pcResiYuv->getStride( COMPONENT_Y ); Pel* pPred = piPred; Pel* pResi = piResi; Pel* pReco = pcRecoYuv->getAddr( compID, uiAbsPartIdx ); Pel* pRecIPred = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiAbsPartIdx ); #if DEBUG_STRING 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() << std::endl; } #endif #if !JVET_D0033_ADAPTIVE_CLIPPING const Int clipbd = sps.getBitDepth(toChannelType(compID)); #endif #if O0043_BEST_EFFORT_DECODING const Int bitDepthDelta = sps.getStreamBitDepth(toChannelType(compID)) - clipbd; #endif if( useCrossComponentPrediction ) { TComTrQuant::crossComponentPrediction( rTu, compID, pResiLuma, piResi, piResi, uiWidth, uiHeight, strideLuma, uiStride, uiStride, true ); } //if (compID == 2 && uiChFinalMode >= 0 && uiChFinalMode < 67) //{ // std::cout << "cr分量的重建残差: " << std::endl; //} for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { #if DEBUG_STRING if (bDebugPred || bDebugResi || bDebugReco) { ss << "###: "; } if (bDebugPred) { ss << " - pred: "; for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { ss << pPred[ uiX ] << ", "; } } if (bDebugResi) { ss << " - resi: "; } #endif for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { #if DEBUG_STRING if (bDebugResi) { ss << pResi[ uiX ] << ", "; } #endif #if O0043_BEST_EFFORT_DECODING #if JVET_D0033_ADAPTIVE_CLIPPING pReco [ uiX ] = ClipA( rightShiftEvenRounding<Pel>(pPred[ uiX ] + pResi[ uiX ], bitDepthDelta), compID); #else pReco [ uiX ] = ClipBD( rightShiftEvenRounding<Pel>(pPred[ uiX ] + pResi[ uiX ], bitDepthDelta), clipbd ); #endif #else #if JVET_D0033_ADAPTIVE_CLIPPING // decoder intra rec pReco [ uiX ] = ClipA(pPred[ uiX ] + pResi[ uiX ], compID);//重建值等于预测值加残差; #else pReco [ uiX ] = ClipBD( pPred[ uiX ] + pResi[ uiX ], clipbd ); #endif #endif pRecIPred[ uiX ] = pReco[ uiX ];//保存重建值,用于下一帧的预测; //if (compID == 2 && uiChFinalMode >= 0 && uiChFinalMode < 67) // printf("M", pResi[uiX]); } //if (compID == 2 && uiChFinalMode >= 0 && uiChFinalMode < 67) //std::cout << std::endl; #if DEBUG_STRING if (bDebugReco) { ss << " - reco: "; for( UInt uiX = 0; uiX < uiWidth; uiX++ ) { ss << pReco[ uiX ] << ", "; } } if (bDebugPred || bDebugResi || bDebugReco) { ss << "\n"; } #endif pPred += uiStride; pResi += uiStride; pReco += uiStride; pRecIPred += uiRecIPredStride; } //if (compID == 2 && uiChFinalMode >= 0 && uiChFinalMode < 67) //{ // std::cout << std::endl; // std::cout << std::endl; //} #if JVET_F0096_BILATERAL_FILTER if(pcCU->getSlice()->getSPS()->getUseBilateralFilter()) //重建完使用双边滤波,和编码端一致,只对亮度分量使用 { Pel* piReco = pcRecoYuv->getAddr( compID, uiAbsPartIdx ); Pel* piRecIPred = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiAbsPartIdx ); if (isLuma(compID)) { if ((pcCU->getCbf(uiAbsPartIdx, compID, rTu.GetTransformDepthRel()) != 0) && (pcCU->getQP(COMPONENT_Y) > 17)) {//双边滤波器即重建CU中的每一个亮度采样都用其自身及其邻近采样的加权平均替代 TComBilateralFilter::instance()->bilateralFilterIntra(pcCU, uiWidth, uiHeight, piReco, uiStride, pcCU->getQP(COMPONENT_Y)); for( UInt uiY = 0; uiY < uiHeight; uiY++ ) { memcpy(piRecIPred + uiY * uiRecIPredStride, piReco + uiY * uiStride , uiWidth * sizeof(Short)); uiY++; memcpy(piRecIPred + uiY * uiRecIPredStride, piReco + uiY * uiStride , uiWidth * sizeof(Short)); } } } } #endif }
转载请注明原文地址: https://www.6miu.com/read-2650345.html

最新回复(0)