标签:
(8)计算最优的代价,记录相关信息
Void TEncSearch::encodeResAndCalcRdInterCU( TComDataCU* pcCU, TComYuv* pcYuvOrg, TComYuv* pcYuvPred, TComYuv*& rpcYuvResi, TComYuv*& rpcYuvResiBest, TComYuv*& rpcYuvRec, Bool bSkipRes ) { // 如果它居然是进行帧内预测的,那么直接返回 if ( pcCU->isIntra(0) ) { return; } Bool bHighPass = pcCU->getSlice()->getDepth() ? true : false; UInt uiBits = 0, uiBitsBest = 0; UInt uiDistortion = 0, uiDistortionBest = 0; UInt uiWidth = pcCU->getWidth ( 0 ); UInt uiHeight = pcCU->getHeight( 0 ); // No residual coding : SKIP mode // 使用了skip模式 if ( bSkipRes ) { pcCU->setSkipFlagSubParts( true, 0, pcCU->getDepth(0) ); // 清空残差 rpcYuvResi->clear(); pcYuvPred->copyToPartYuv( rpcYuvRec, 0 ); uiDistortion = m_pcRdCost->getDistPart(g_bitDepthY, rpcYuvRec->getLumaAddr(), rpcYuvRec->getStride(), pcYuvOrg->getLumaAddr(), pcYuvOrg->getStride(), uiWidth, uiHeight ) + m_pcRdCost->getDistPart(g_bitDepthC, rpcYuvRec->getCbAddr(), rpcYuvRec->getCStride(), pcYuvOrg->getCbAddr(), pcYuvOrg->getCStride(), uiWidth >> 1, uiHeight >> 1, TEXT_CHROMA_U ) + m_pcRdCost->getDistPart(g_bitDepthC, rpcYuvRec->getCrAddr(), rpcYuvRec->getCStride(), pcYuvOrg->getCrAddr(), pcYuvOrg->getCStride(), uiWidth >> 1, uiHeight >> 1, TEXT_CHROMA_V ); m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[pcCU->getDepth(0)][CI_CURR_BEST]); m_pcEntropyCoder->resetBits(); // 使用了跳过变换量化的标志 if (pcCU->getSlice()->getPPS()->getTransquantBypassEnableFlag()) { m_pcEntropyCoder->encodeCUTransquantBypassFlag(pcCU, 0, true); } // 对跳过标志进行编码 m_pcEntropyCoder->encodeSkipFlag(pcCU, 0, true); // 对merge索引进行编码 m_pcEntropyCoder->encodeMergeIndex( pcCU, 0, true ); // 得到已经写入的比特数 uiBits = m_pcEntropyCoder->getNumberOfWrittenBits(); pcCU->getTotalBits() = uiBits; pcCU->getTotalDistortion() = uiDistortion; pcCU->getTotalCost() = m_pcRdCost->calcRdCost( uiBits, uiDistortion ); m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[pcCU->getDepth(0)][CI_TEMP_BEST]); pcCU->setCbfSubParts( 0, 0, 0, 0, pcCU->getDepth( 0 ) ); pcCU->setTrIdxSubParts( 0, 0, pcCU->getDepth(0) ); return; } // 没有使用skip模式,那么就要对残差进行编码(变换量化) // Residual coding. Int qp, qpBest = 0, qpMin, qpMax; Double dCost, dCostBest = MAX_DOUBLE; UInt uiTrLevel = 0; if( (pcCU->getWidth(0) > pcCU->getSlice()->getSPS()->getMaxTrSize()) ) { while( pcCU->getWidth(0) > (pcCU->getSlice()->getSPS()->getMaxTrSize()<<uiTrLevel) ) uiTrLevel++; } UInt uiMaxTrMode = 1 + uiTrLevel; while((uiWidth>>uiMaxTrMode) < (g_uiMaxCUWidth>>g_uiMaxCUDepth)) uiMaxTrMode--; qpMin = bHighPass ? Clip3( -pcCU->getSlice()->getSPS()->getQpBDOffsetY(), MAX_QP, pcCU->getQP(0) - m_iMaxDeltaQP ) : pcCU->getQP( 0 ); qpMax = bHighPass ? Clip3( -pcCU->getSlice()->getSPS()->getQpBDOffsetY(), MAX_QP, pcCU->getQP(0) + m_iMaxDeltaQP ) : pcCU->getQP( 0 ); rpcYuvResi->subtract( pcYuvOrg, pcYuvPred, 0, uiWidth ); for ( qp = qpMin; qp <= qpMax; qp++ ) { dCost = 0.; uiBits = 0; uiDistortion = 0; m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ pcCU->getDepth( 0 ) ][ CI_CURR_BEST ] ); UInt uiZeroDistortion = 0; // 对残差进行计算 xEstimateResidualQT( pcCU, 0, 0, 0, rpcYuvResi, pcCU->getDepth(0), dCost, uiBits, uiDistortion, &uiZeroDistortion ); m_pcEntropyCoder->resetBits(); // 进行熵编码 m_pcEntropyCoder->encodeQtRootCbfZero( pcCU ); UInt zeroResiBits = m_pcEntropyCoder->getNumberOfWrittenBits(); // 计算率失真代价 Double dZeroCost = m_pcRdCost->calcRdCost( zeroResiBits, uiZeroDistortion ); if(pcCU->isLosslessCoded( 0 )) { dZeroCost = dCost + 1; } if ( dZeroCost < dCost ) { dCost = dZeroCost; uiBits = 0; uiDistortion = uiZeroDistortion; const UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> (pcCU->getDepth(0) << 1); ::memset( pcCU->getTransformIdx() , 0, uiQPartNum * sizeof(UChar) ); ::memset( pcCU->getCbf( TEXT_LUMA ) , 0, uiQPartNum * sizeof(UChar) ); ::memset( pcCU->getCbf( TEXT_CHROMA_U ), 0, uiQPartNum * sizeof(UChar) ); ::memset( pcCU->getCbf( TEXT_CHROMA_V ), 0, uiQPartNum * sizeof(UChar) ); ::memset( pcCU->getCoeffY() , 0, uiWidth * uiHeight * sizeof( TCoeff ) ); ::memset( pcCU->getCoeffCb() , 0, uiWidth * uiHeight * sizeof( TCoeff ) >> 2 ); ::memset( pcCU->getCoeffCr() , 0, uiWidth * uiHeight * sizeof( TCoeff ) >> 2 ); pcCU->setTransformSkipSubParts ( 0, 0, 0, 0, pcCU->getDepth(0) ); } else { // 设置残差四叉树的数据 xSetResidualQTData( pcCU, 0, 0, 0, NULL, pcCU->getDepth(0), false ); } m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[pcCU->getDepth(0)][CI_CURR_BEST] ); uiBits = 0; { TComYuv *pDummy = NULL; xAddSymbolBitsInter( pcCU, 0, 0, uiBits, pDummy, NULL, pDummy ); } // 计算率失真代价 Double dExactCost = m_pcRdCost->calcRdCost( uiBits, uiDistortion ); dCost = dExactCost; // 更新最优值 if ( dCost < dCostBest ) { if ( !pcCU->getQtRootCbf( 0 ) ) { rpcYuvResiBest->clear(); } else { xSetResidualQTData( pcCU, 0, 0, 0, rpcYuvResiBest, pcCU->getDepth(0), true ); } if( qpMin != qpMax && qp != qpMax ) { const UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> (pcCU->getDepth(0) << 1); ::memcpy( m_puhQTTempTrIdx, pcCU->getTransformIdx(), uiQPartNum * sizeof(UChar) ); ::memcpy( m_puhQTTempCbf[0], pcCU->getCbf( TEXT_LUMA ), uiQPartNum * sizeof(UChar) ); ::memcpy( m_puhQTTempCbf[1], pcCU->getCbf( TEXT_CHROMA_U ), uiQPartNum * sizeof(UChar) ); ::memcpy( m_puhQTTempCbf[2], pcCU->getCbf( TEXT_CHROMA_V ), uiQPartNum * sizeof(UChar) ); ::memcpy( m_pcQTTempCoeffY, pcCU->getCoeffY(), uiWidth * uiHeight * sizeof( TCoeff ) ); ::memcpy( m_pcQTTempCoeffCb, pcCU->getCoeffCb(), uiWidth * uiHeight * sizeof( TCoeff ) >> 2 ); ::memcpy( m_pcQTTempCoeffCr, pcCU->getCoeffCr(), uiWidth * uiHeight * sizeof( TCoeff ) >> 2 ); #if ADAPTIVE_QP_SELECTION ::memcpy( m_pcQTTempArlCoeffY, pcCU->getArlCoeffY(), uiWidth * uiHeight * sizeof( Int ) ); ::memcpy( m_pcQTTempArlCoeffCb, pcCU->getArlCoeffCb(), uiWidth * uiHeight * sizeof( Int ) >> 2 ); ::memcpy( m_pcQTTempArlCoeffCr, pcCU->getArlCoeffCr(), uiWidth * uiHeight * sizeof( Int ) >> 2 ); #endif ::memcpy( m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA), uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U), uiQPartNum * sizeof( UChar ) ); ::memcpy( m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V), uiQPartNum * sizeof( UChar ) ); } uiBitsBest = uiBits; uiDistortionBest = uiDistortion; dCostBest = dCost; qpBest = qp; m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ pcCU->getDepth( 0 ) ][ CI_TEMP_BEST ] ); } } assert ( dCostBest != MAX_DOUBLE ); if( qpMin != qpMax && qpBest != qpMax ) { assert( 0 ); // check m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ pcCU->getDepth( 0 ) ][ CI_TEMP_BEST ] ); // copy best cbf and trIdx to pcCU const UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> (pcCU->getDepth(0) << 1); ::memcpy( pcCU->getTransformIdx(), m_puhQTTempTrIdx, uiQPartNum * sizeof(UChar) ); ::memcpy( pcCU->getCbf( TEXT_LUMA ), m_puhQTTempCbf[0], uiQPartNum * sizeof(UChar) ); ::memcpy( pcCU->getCbf( TEXT_CHROMA_U ), m_puhQTTempCbf[1], uiQPartNum * sizeof(UChar) ); ::memcpy( pcCU->getCbf( TEXT_CHROMA_V ), m_puhQTTempCbf[2], uiQPartNum * sizeof(UChar) ); ::memcpy( pcCU->getCoeffY(), m_pcQTTempCoeffY, uiWidth * uiHeight * sizeof( TCoeff ) ); ::memcpy( pcCU->getCoeffCb(), m_pcQTTempCoeffCb, uiWidth * uiHeight * sizeof( TCoeff ) >> 2 ); ::memcpy( pcCU->getCoeffCr(), m_pcQTTempCoeffCr, uiWidth * uiHeight * sizeof( TCoeff ) >> 2 ); #if ADAPTIVE_QP_SELECTION ::memcpy( pcCU->getArlCoeffY(), m_pcQTTempArlCoeffY, uiWidth * uiHeight * sizeof( Int ) ); ::memcpy( pcCU->getArlCoeffCb(), m_pcQTTempArlCoeffCb, uiWidth * uiHeight * sizeof( Int ) >> 2 ); ::memcpy( pcCU->getArlCoeffCr(), m_pcQTTempArlCoeffCr, uiWidth * uiHeight * sizeof( Int ) >> 2 ); #endif ::memcpy( pcCU->getTransformSkip(TEXT_LUMA), m_puhQTTempTransformSkipFlag[0], uiQPartNum * sizeof( UChar ) ); ::memcpy( pcCU->getTransformSkip(TEXT_CHROMA_U), m_puhQTTempTransformSkipFlag[1], uiQPartNum * sizeof( UChar ) ); ::memcpy( pcCU->getTransformSkip(TEXT_CHROMA_V), m_puhQTTempTransformSkipFlag[2], uiQPartNum * sizeof( UChar ) ); } rpcYuvRec->addClip ( pcYuvPred, rpcYuvResiBest, 0, uiWidth ); // update with clipped distortion and cost (qp estimation loop uses unclipped values) uiDistortionBest = m_pcRdCost->getDistPart(g_bitDepthY, rpcYuvRec->getLumaAddr(), rpcYuvRec->getStride(), pcYuvOrg->getLumaAddr(), pcYuvOrg->getStride(), uiWidth, uiHeight ) + m_pcRdCost->getDistPart(g_bitDepthC, rpcYuvRec->getCbAddr(), rpcYuvRec->getCStride(), pcYuvOrg->getCbAddr(), pcYuvOrg->getCStride(), uiWidth >> 1, uiHeight >> 1, TEXT_CHROMA_U ) + m_pcRdCost->getDistPart(g_bitDepthC, rpcYuvRec->getCrAddr(), rpcYuvRec->getCStride(), pcYuvOrg->getCrAddr(), pcYuvOrg->getCStride(), uiWidth >> 1, uiHeight >> 1, TEXT_CHROMA_V ); dCostBest = m_pcRdCost->calcRdCost( uiBitsBest, uiDistortionBest ); pcCU->getTotalBits() = uiBitsBest; pcCU->getTotalDistortion() = uiDistortionBest; pcCU->getTotalCost() = dCostBest; if ( pcCU->isSkipped(0) ) { pcCU->setCbfSubParts( 0, 0, 0, 0, pcCU->getDepth( 0 ) ); } pcCU->setQPSubParts( qpBest, 0, pcCU->getDepth(0) ); }根据预测帧和原始帧计算残差:
Void TComYuv::subtract( TComYuv* pcYuvSrc0, TComYuv* pcYuvSrc1, UInt uiTrUnitIdx, UInt uiPartSize ) { subtractLuma ( pcYuvSrc0, pcYuvSrc1, uiTrUnitIdx, uiPartSize ); subtractChroma( pcYuvSrc0, pcYuvSrc1, uiTrUnitIdx, uiPartSize>>1 ); }TEncSearch::xEstimateResidualQT函数详解:
Void TEncSearch::xEstimateResidualQT( TComDataCU* pcCU, UInt uiQuadrant, UInt uiAbsPartIdx, UInt absTUPartIdx, TComYuv* pcResi, const UInt uiDepth, Double &rdCost, UInt &ruiBits, UInt &ruiDist, UInt *puiZeroDist ) { // 四叉树的分割模式 const UInt uiTrMode = uiDepth - pcCU->getDepth( 0 ); assert( pcCU->getDepth( 0 ) == pcCU->getDepth( uiAbsPartIdx ) ); // 计算尺寸 const UInt uiLog2TrSize = g_aucConvertToBit[pcCU->getSlice()->getSPS()->getMaxCUWidth() >> uiDepth]+2; // split标志 UInt SplitFlag = ((pcCU->getSlice()->getSPS()->getQuadtreeTUMaxDepthInter() == 1) && pcCU->getPredictionMode(uiAbsPartIdx) == MODE_INTER && ( pcCU->getPartitionSize(uiAbsPartIdx) != SIZE_2Nx2N )); // 完整检查的标志 Bool bCheckFull; if ( SplitFlag && uiDepth == pcCU->getDepth(uiAbsPartIdx) && ( uiLog2TrSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) ) { bCheckFull = false; } else { bCheckFull = ( uiLog2TrSize <= pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() ); } // 是否检查split标志 const Bool bCheckSplit = ( uiLog2TrSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ); assert( bCheckFull || bCheckSplit ); // 是否对色度分量进行编码 Bool bCodeChroma = true; // 色度分量的模式 UInt uiTrModeC = uiTrMode; // 色度分量的尺寸 UInt uiLog2TrSizeC = uiLog2TrSize-1; // 对大小是4x4的TU进行特殊处理 if( uiLog2TrSize == 2 ) { uiLog2TrSizeC++; uiTrModeC --; UInt uiQPDiv = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth( 0 ) + uiTrModeC ) << 1 ); bCodeChroma = ( ( uiAbsPartIdx % uiQPDiv ) == 0 ); } // 设置CBF(编码块标志) const UInt uiSetCbf = 1 << uiTrMode; // code full block // 单独一整块的代价 Double dSingleCost = MAX_DOUBLE; // 单独一整块的比特数 UInt uiSingleBits = 0; // 歹毒一整块的失真 UInt uiSingleDist = 0; UInt uiAbsSumY = 0, uiAbsSumU = 0, uiAbsSumV = 0; // 最优的变换模式 UInt uiBestTransformMode[3] = {0}; m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); // 完整检查模式 if( bCheckFull ) { const UInt uiNumCoeffPerAbsPartIdxIncrement = pcCU->getSlice()->getSPS()->getMaxCUWidth() * pcCU->getSlice()->getSPS()->getMaxCUHeight() >> ( pcCU->getSlice()->getSPS()->getMaxCUDepth() << 1 ); const UInt uiQTTempAccessLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize; // 取得Y、U、V三个部分的残差系数 TCoeff *pcCoeffCurrY = m_ppcQTTempCoeffY [uiQTTempAccessLayer] + uiNumCoeffPerAbsPartIdxIncrement * uiAbsPartIdx; TCoeff *pcCoeffCurrU = m_ppcQTTempCoeffCb[uiQTTempAccessLayer] + (uiNumCoeffPerAbsPartIdxIncrement * uiAbsPartIdx>>2); TCoeff *pcCoeffCurrV = m_ppcQTTempCoeffCr[uiQTTempAccessLayer] + (uiNumCoeffPerAbsPartIdxIncrement * uiAbsPartIdx>>2); #if ADAPTIVE_QP_SELECTION Int *pcArlCoeffCurrY = m_ppcQTTempArlCoeffY [uiQTTempAccessLayer] + uiNumCoeffPerAbsPartIdxIncrement * uiAbsPartIdx; Int *pcArlCoeffCurrU = m_ppcQTTempArlCoeffCb[uiQTTempAccessLayer] + (uiNumCoeffPerAbsPartIdxIncrement * uiAbsPartIdx>>2); Int *pcArlCoeffCurrV = m_ppcQTTempArlCoeffCr[uiQTTempAccessLayer] + (uiNumCoeffPerAbsPartIdxIncrement * uiAbsPartIdx>>2); #endif Int trWidth = 0, trHeight = 0, trWidthC = 0, trHeightC = 0; UInt absTUPartIdxC = uiAbsPartIdx; // TU的宽度 trWidth = trHeight = 1 << uiLog2TrSize; trWidthC = trHeightC = 1 <<uiLog2TrSizeC; pcCU->setTrIdxSubParts( uiDepth - pcCU->getDepth( 0 ), uiAbsPartIdx, uiDepth ); // 三个分量的编码代价 Double minCostY = MAX_DOUBLE; Double minCostU = MAX_DOUBLE; Double minCostV = MAX_DOUBLE; // 是否跳过Y、U、V Bool checkTransformSkipY = pcCU->getSlice()->getPPS()->getUseTransformSkip() && trWidth == 4 && trHeight == 4; Bool checkTransformSkipUV = pcCU->getSlice()->getPPS()->getUseTransformSkip() && trWidthC == 4 && trHeightC == 4; checkTransformSkipY &= (!pcCU->isLosslessCoded(0)); checkTransformSkipUV &= (!pcCU->isLosslessCoded(0)); pcCU->setTransformSkipSubParts ( 0, TEXT_LUMA, uiAbsPartIdx, uiDepth ); if( bCodeChroma ) { pcCU->setTransformSkipSubParts ( 0, TEXT_CHROMA_U, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); pcCU->setTransformSkipSubParts ( 0, TEXT_CHROMA_V, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); } // 是否使用了率失真优化的量化 if (m_pcEncCfg->getUseRDOQ()) { // 估算比特数 m_pcEntropyCoder->estimateBit(m_pcTrQuant->m_pcEstBitsSbac, trWidth, trHeight, TEXT_LUMA ); } m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_LUMA, pcCU->getSlice()->getSPS()->getQpBDOffsetY(), 0 ); #if RDOQ_CHROMA_LAMBDA m_pcTrQuant->selectLambda(TEXT_LUMA); #endif // DCT变换和量化(Y分量),非常重要的函数 m_pcTrQuant->transformNxN( pcCU, pcResi->getLumaAddr( absTUPartIdx ), pcResi->getStride (), pcCoeffCurrY, #if ADAPTIVE_QP_SELECTION pcArlCoeffCurrY, #endif trWidth, trHeight, uiAbsSumY, TEXT_LUMA, uiAbsPartIdx ); pcCU->setCbfSubParts( uiAbsSumY ? uiSetCbf : 0, TEXT_LUMA, uiAbsPartIdx, uiDepth ); // 对色度部分信息编码 if( bCodeChroma ) { if (m_pcEncCfg->getUseRDOQ()) { m_pcEntropyCoder->estimateBit(m_pcTrQuant->m_pcEstBitsSbac, trWidthC, trHeightC, TEXT_CHROMA ); } Int curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCbQpOffset() + pcCU->getSlice()->getSliceQpDeltaCb(); m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); #if RDOQ_CHROMA_LAMBDA m_pcTrQuant->selectLambda(TEXT_CHROMA_U); #endif // 变换和量化(U分量) m_pcTrQuant->transformNxN( pcCU, pcResi->getCbAddr(absTUPartIdxC), pcResi->getCStride(), pcCoeffCurrU, #if ADAPTIVE_QP_SELECTION pcArlCoeffCurrU, #endif trWidthC, trHeightC, uiAbsSumU, TEXT_CHROMA_U, uiAbsPartIdx ); curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCrQpOffset() + pcCU->getSlice()->getSliceQpDeltaCr(); m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); #if RDOQ_CHROMA_LAMBDA m_pcTrQuant->selectLambda(TEXT_CHROMA_V); #endif // 变换和量化(V分量) m_pcTrQuant->transformNxN( pcCU, pcResi->getCrAddr(absTUPartIdxC), pcResi->getCStride(), pcCoeffCurrV, #if ADAPTIVE_QP_SELECTION pcArlCoeffCurrV, #endif trWidthC, trHeightC, uiAbsSumV, TEXT_CHROMA_V, uiAbsPartIdx ); pcCU->setCbfSubParts( uiAbsSumU ? uiSetCbf : 0, TEXT_CHROMA_U, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); pcCU->setCbfSubParts( uiAbsSumV ? uiSetCbf : 0, TEXT_CHROMA_V, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); } m_pcEntropyCoder->resetBits(); // 对CBF进行编码(Y分量) m_pcEntropyCoder->encodeQtCbf( pcCU, uiAbsPartIdx, TEXT_LUMA, uiTrMode ); // 对残差系数进行编码(Y分量) m_pcEntropyCoder->encodeCoeffNxN( pcCU, pcCoeffCurrY, uiAbsPartIdx, trWidth, trHeight, uiDepth, TEXT_LUMA ); const UInt uiSingleBitsY = m_pcEntropyCoder->getNumberOfWrittenBits(); UInt uiSingleBitsU = 0; UInt uiSingleBitsV = 0; // 对色度部分进行编码 if( bCodeChroma ) { m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); // 对CBF进行编码(U分量) m_pcEntropyCoder->encodeQtCbf ( pcCU, uiAbsPartIdx, TEXT_CHROMA_U, uiTrMode ); // 对系数进行编码(U分量) m_pcEntropyCoder->encodeCoeffNxN( pcCU, pcCoeffCurrU, uiAbsPartIdx, trWidthC, trHeightC, uiDepth, TEXT_CHROMA_U ); uiSingleBitsU = m_pcEntropyCoder->getNumberOfWrittenBits(); m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); // 对CBF进行编码(V分量) m_pcEntropyCoder->encodeQtCbf ( pcCU, uiAbsPartIdx, TEXT_CHROMA_V, uiTrMode ); // 对系数进行编码(V分量) m_pcEntropyCoder->encodeCoeffNxN( pcCU, pcCoeffCurrV, uiAbsPartIdx, trWidthC, trHeightC, uiDepth, TEXT_CHROMA_V ); uiSingleBitsV = m_pcEntropyCoder->getNumberOfWrittenBits(); } const UInt uiNumSamplesLuma = 1 << (uiLog2TrSize<<1); const UInt uiNumSamplesChro = 1 << (uiLog2TrSizeC<<1); ::memset( m_pTempPel, 0, sizeof( Pel ) * uiNumSamplesLuma ); // not necessary needed for inside of recursion (only at the beginning) UInt uiDistY = m_pcRdCost->getDistPart(g_bitDepthY, m_pTempPel, trWidth, pcResi->getLumaAddr( absTUPartIdx ), pcResi->getStride(), trWidth, trHeight ); // initialized with zero residual destortion if ( puiZeroDist ) { *puiZeroDist += uiDistY; } // 如果Y分量绝对系数和?(不是知道是不是这个意思,反正就是如果变换量化有效果就执行下面的步骤)大于0 // 开始执行反量化、反变换 if( uiAbsSumY ) { Pel *pcResiCurrY = m_pcQTTempTComYuv[ uiQTTempAccessLayer ].getLumaAddr( absTUPartIdx ); m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_LUMA, pcCU->getSlice()->getSPS()->getQpBDOffsetY(), 0 ); Int scalingListType = 3 + g_eTTable[(Int)TEXT_LUMA]; assert(scalingListType < SCALING_LIST_NUM); // 反变换、反量化(Y分量) m_pcTrQuant->invtransformNxN( pcCU->getCUTransquantBypass(uiAbsPartIdx), TEXT_LUMA,REG_DCT, pcResiCurrY, m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(), pcCoeffCurrY, trWidth, trHeight, scalingListType );//this is for inter mode only const UInt uiNonzeroDistY = m_pcRdCost->getDistPart(g_bitDepthY, m_pcQTTempTComYuv[uiQTTempAccessLayer].getLumaAddr( absTUPartIdx ), m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(), pcResi->getLumaAddr( absTUPartIdx ), pcResi->getStride(), trWidth,trHeight ); if (pcCU->isLosslessCoded(0)) { uiDistY = uiNonzeroDistY; } else { const Double singleCostY = m_pcRdCost->calcRdCost( uiSingleBitsY, uiNonzeroDistY ); m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeQtCbfZero( pcCU, TEXT_LUMA, uiTrMode ); const UInt uiNullBitsY = m_pcEntropyCoder->getNumberOfWrittenBits(); const Double nullCostY = m_pcRdCost->calcRdCost( uiNullBitsY, uiDistY ); if( nullCostY < singleCostY ) { uiAbsSumY = 0; ::memset( pcCoeffCurrY, 0, sizeof( TCoeff ) * uiNumSamplesLuma ); if( checkTransformSkipY ) { minCostY = nullCostY; } } else { uiDistY = uiNonzeroDistY; if( checkTransformSkipY ) { minCostY = singleCostY; } } } } // 否则(没有进行变换量化或者变换量化了没有效果?),如果是跳过Y分量 else if( checkTransformSkipY ) { m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); // 编码Y分量的CBF的0系数 m_pcEntropyCoder->encodeQtCbfZero( pcCU, TEXT_LUMA, uiTrMode ); const UInt uiNullBitsY = m_pcEntropyCoder->getNumberOfWrittenBits(); // 计算率失真 minCostY = m_pcRdCost->calcRdCost( uiNullBitsY, uiDistY ); } if( !uiAbsSumY ) { Pel *pcPtr = m_pcQTTempTComYuv[uiQTTempAccessLayer].getLumaAddr( absTUPartIdx ); const UInt uiStride = m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(); for( UInt uiY = 0; uiY < trHeight; ++uiY ) { ::memset( pcPtr, 0, sizeof( Pel ) * trWidth ); pcPtr += uiStride; } } UInt uiDistU = 0; UInt uiDistV = 0; // 如果对色度部分进行了变换量化,那么需要对色度部分进行反变换反量化 if( bCodeChroma ) { uiDistU = m_pcRdCost->getDistPart(g_bitDepthC, m_pTempPel, trWidthC, pcResi->getCbAddr( absTUPartIdxC ), pcResi->getCStride(), trWidthC, trHeightC , TEXT_CHROMA_U ); // initialized with zero residual destortion if ( puiZeroDist ) { *puiZeroDist += uiDistU; } // 如果对U分量进行了变换量化 if( uiAbsSumU ) { Pel *pcResiCurrU = m_pcQTTempTComYuv[uiQTTempAccessLayer].getCbAddr( absTUPartIdxC ); Int curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCbQpOffset() + pcCU->getSlice()->getSliceQpDeltaCb(); m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); Int scalingListType = 3 + g_eTTable[(Int)TEXT_CHROMA_U]; assert(scalingListType < SCALING_LIST_NUM); // 反变换、反量化(U分量) m_pcTrQuant->invtransformNxN( pcCU->getCUTransquantBypass(uiAbsPartIdx), TEXT_CHROMA,REG_DCT, pcResiCurrU, m_pcQTTempTComYuv[uiQTTempAccessLayer].getCStride(), pcCoeffCurrU, trWidthC, trHeightC, scalingListType ); const UInt uiNonzeroDistU = m_pcRdCost->getDistPart(g_bitDepthC, m_pcQTTempTComYuv[uiQTTempAccessLayer].getCbAddr( absTUPartIdxC), m_pcQTTempTComYuv[uiQTTempAccessLayer].getCStride(), pcResi->getCbAddr( absTUPartIdxC), pcResi->getCStride(), trWidthC, trHeightC , TEXT_CHROMA_U ); if(pcCU->isLosslessCoded(0)) { uiDistU = uiNonzeroDistU; } else { const Double dSingleCostU = m_pcRdCost->calcRdCost( uiSingleBitsU, uiNonzeroDistU ); m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeQtCbfZero( pcCU, TEXT_CHROMA_U, uiTrMode ); const UInt uiNullBitsU = m_pcEntropyCoder->getNumberOfWrittenBits(); const Double dNullCostU = m_pcRdCost->calcRdCost( uiNullBitsU, uiDistU ); if( dNullCostU < dSingleCostU ) { uiAbsSumU = 0; ::memset( pcCoeffCurrU, 0, sizeof( TCoeff ) * uiNumSamplesChro ); if( checkTransformSkipUV ) { minCostU = dNullCostU; } } else { uiDistU = uiNonzeroDistU; if( checkTransformSkipUV ) { minCostU = dSingleCostU; } } } } // 否则(即变换量化没有效果或者不够优?) else if( checkTransformSkipUV ) { m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); // 编码CBF的0系数 m_pcEntropyCoder->encodeQtCbfZero( pcCU, TEXT_CHROMA_U, uiTrMode ); const UInt uiNullBitsU = m_pcEntropyCoder->getNumberOfWrittenBits(); minCostU = m_pcRdCost->calcRdCost( uiNullBitsU, uiDistU ); } if( !uiAbsSumU ) { Pel *pcPtr = m_pcQTTempTComYuv[uiQTTempAccessLayer].getCbAddr( absTUPartIdxC ); const UInt uiStride = m_pcQTTempTComYuv[uiQTTempAccessLayer].getCStride(); for( UInt uiY = 0; uiY < trHeightC; ++uiY ) { ::memset( pcPtr, 0, sizeof(Pel) * trWidthC ); pcPtr += uiStride; } } uiDistV = m_pcRdCost->getDistPart(g_bitDepthC, m_pTempPel, trWidthC, pcResi->getCrAddr( absTUPartIdxC), pcResi->getCStride(), trWidthC, trHeightC , TEXT_CHROMA_V ); // initialized with zero residual destortion if ( puiZeroDist ) { *puiZeroDist += uiDistV; } // 对V分量进行处理(过程同U分量) if( uiAbsSumV ) { Pel *pcResiCurrV = m_pcQTTempTComYuv[uiQTTempAccessLayer].getCrAddr( absTUPartIdxC ); Int curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCrQpOffset() + pcCU->getSlice()->getSliceQpDeltaCr(); m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); Int scalingListType = 3 + g_eTTable[(Int)TEXT_CHROMA_V]; assert(scalingListType < SCALING_LIST_NUM); // 反变换反量化(V分量) m_pcTrQuant->invtransformNxN( pcCU->getCUTransquantBypass(uiAbsPartIdx), TEXT_CHROMA,REG_DCT, pcResiCurrV, m_pcQTTempTComYuv[uiQTTempAccessLayer].getCStride(), pcCoeffCurrV, trWidthC, trHeightC, scalingListType ); const UInt uiNonzeroDistV = m_pcRdCost->getDistPart(g_bitDepthC, m_pcQTTempTComYuv[uiQTTempAccessLayer].getCrAddr( absTUPartIdxC ), m_pcQTTempTComYuv[uiQTTempAccessLayer].getCStride(), pcResi->getCrAddr( absTUPartIdxC ), pcResi->getCStride(), trWidthC, trHeightC , TEXT_CHROMA_V ); if (pcCU->isLosslessCoded(0)) { uiDistV = uiNonzeroDistV; } else { const Double dSingleCostV = m_pcRdCost->calcRdCost( uiSingleBitsV, uiNonzeroDistV ); m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); // 对CBF的0系数进行编码 m_pcEntropyCoder->encodeQtCbfZero( pcCU, TEXT_CHROMA_V, uiTrMode ); const UInt uiNullBitsV = m_pcEntropyCoder->getNumberOfWrittenBits(); const Double dNullCostV = m_pcRdCost->calcRdCost( uiNullBitsV, uiDistV ); if( dNullCostV < dSingleCostV ) { uiAbsSumV = 0; ::memset( pcCoeffCurrV, 0, sizeof( TCoeff ) * uiNumSamplesChro ); if( checkTransformSkipUV ) { minCostV = dNullCostV; } } else { uiDistV = uiNonzeroDistV; if( checkTransformSkipUV ) { minCostV = dSingleCostV; } } } } // 如果跳过了UV分量 else if( checkTransformSkipUV ) { m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); // 对CBF的0系数进行编码 m_pcEntropyCoder->encodeQtCbfZero( pcCU, TEXT_CHROMA_V, uiTrMode ); const UInt uiNullBitsV = m_pcEntropyCoder->getNumberOfWrittenBits(); // 计算率失真代价 minCostV = m_pcRdCost->calcRdCost( uiNullBitsV, uiDistV ); } if( !uiAbsSumV ) { Pel *pcPtr = m_pcQTTempTComYuv[uiQTTempAccessLayer].getCrAddr( absTUPartIdxC ); const UInt uiStride = m_pcQTTempTComYuv[uiQTTempAccessLayer].getCStride(); for( UInt uiY = 0; uiY < trHeightC; ++uiY ) { ::memset( pcPtr, 0, sizeof(Pel) * trWidthC ); pcPtr += uiStride; } } } pcCU->setCbfSubParts( uiAbsSumY ? uiSetCbf : 0, TEXT_LUMA, uiAbsPartIdx, uiDepth ); if( bCodeChroma ) { pcCU->setCbfSubParts( uiAbsSumU ? uiSetCbf : 0, TEXT_CHROMA_U, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); pcCU->setCbfSubParts( uiAbsSumV ? uiSetCbf : 0, TEXT_CHROMA_V, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); } // 如果跳过了Y分量 if( checkTransformSkipY ) { UInt uiNonzeroDistY, uiAbsSumTransformSkipY; Double dSingleCostY; Pel *pcResiCurrY = m_pcQTTempTComYuv[ uiQTTempAccessLayer ].getLumaAddr( absTUPartIdx ); UInt resiYStride = m_pcQTTempTComYuv[ uiQTTempAccessLayer ].getStride(); TCoeff bestCoeffY[32*32]; memcpy( bestCoeffY, pcCoeffCurrY, sizeof(TCoeff) * uiNumSamplesLuma ); #if ADAPTIVE_QP_SELECTION TCoeff bestArlCoeffY[32*32]; memcpy( bestArlCoeffY, pcArlCoeffCurrY, sizeof(TCoeff) * uiNumSamplesLuma ); #endif Pel bestResiY[32*32]; for ( Int i = 0; i < trHeight; ++i ) { memcpy( &bestResiY[i*trWidth], pcResiCurrY+i*resiYStride, sizeof(Pel) * trWidth ); } m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); pcCU->setTransformSkipSubParts ( 1, TEXT_LUMA, uiAbsPartIdx, uiDepth ); if (m_pcEncCfg->getUseRDOQTS()) { // 估算比特数 m_pcEntropyCoder->estimateBit( m_pcTrQuant->m_pcEstBitsSbac, trWidth, trHeight, TEXT_LUMA ); } m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_LUMA, pcCU->getSlice()->getSPS()->getQpBDOffsetY(), 0 ); #if RDOQ_CHROMA_LAMBDA m_pcTrQuant->selectLambda(TEXT_LUMA); #endif // 变换和量化 m_pcTrQuant->transformNxN( pcCU, pcResi->getLumaAddr( absTUPartIdx ), pcResi->getStride (), pcCoeffCurrY, #if ADAPTIVE_QP_SELECTION pcArlCoeffCurrY, #endif trWidth, trHeight, uiAbsSumTransformSkipY, TEXT_LUMA, uiAbsPartIdx, true ); pcCU->setCbfSubParts( uiAbsSumTransformSkipY ? uiSetCbf : 0, TEXT_LUMA, uiAbsPartIdx, uiDepth ); if( uiAbsSumTransformSkipY != 0 ) { m_pcEntropyCoder->resetBits(); // 对CBF的0系数进行编码 m_pcEntropyCoder->encodeQtCbf( pcCU, uiAbsPartIdx, TEXT_LUMA, uiTrMode ); // 对残差系数进行编码 m_pcEntropyCoder->encodeCoeffNxN( pcCU, pcCoeffCurrY, uiAbsPartIdx, trWidth, trHeight, uiDepth, TEXT_LUMA ); const UInt uiTsSingleBitsY = m_pcEntropyCoder->getNumberOfWrittenBits(); m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_LUMA, pcCU->getSlice()->getSPS()->getQpBDOffsetY(), 0 ); Int scalingListType = 3 + g_eTTable[(Int)TEXT_LUMA]; assert(scalingListType < SCALING_LIST_NUM); // 反变换、反量化 m_pcTrQuant->invtransformNxN( pcCU->getCUTransquantBypass(uiAbsPartIdx), TEXT_LUMA,REG_DCT, pcResiCurrY, m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(), pcCoeffCurrY, trWidth, trHeight, scalingListType, true ); uiNonzeroDistY = m_pcRdCost->getDistPart(g_bitDepthY, m_pcQTTempTComYuv[uiQTTempAccessLayer].getLumaAddr( absTUPartIdx ), m_pcQTTempTComYuv[uiQTTempAccessLayer].getStride(), pcResi->getLumaAddr( absTUPartIdx ), pcResi->getStride(), trWidth, trHeight ); // 计算率失真 dSingleCostY = m_pcRdCost->calcRdCost( uiTsSingleBitsY, uiNonzeroDistY ); } if( !uiAbsSumTransformSkipY || minCostY < dSingleCostY ) { pcCU->setTransformSkipSubParts ( 0, TEXT_LUMA, uiAbsPartIdx, uiDepth ); memcpy( pcCoeffCurrY, bestCoeffY, sizeof(TCoeff) * uiNumSamplesLuma ); #if ADAPTIVE_QP_SELECTION memcpy( pcArlCoeffCurrY, bestArlCoeffY, sizeof(TCoeff) * uiNumSamplesLuma ); #endif for( Int i = 0; i < trHeight; ++i ) { memcpy( pcResiCurrY+i*resiYStride, &bestResiY[i*trWidth], sizeof(Pel) * trWidth ); } } else { uiDistY = uiNonzeroDistY; uiAbsSumY = uiAbsSumTransformSkipY; uiBestTransformMode[0] = 1; } pcCU->setCbfSubParts( uiAbsSumY ? uiSetCbf : 0, TEXT_LUMA, uiAbsPartIdx, uiDepth ); } // 如果对色度部分进行编码,但是跳过了UV分量(这是什么情况?) if( bCodeChroma && checkTransformSkipUV ) { UInt uiNonzeroDistU, uiNonzeroDistV, uiAbsSumTransformSkipU, uiAbsSumTransformSkipV; Double dSingleCostU, dSingleCostV; Pel *pcResiCurrU = m_pcQTTempTComYuv[uiQTTempAccessLayer].getCbAddr( absTUPartIdxC ); Pel *pcResiCurrV = m_pcQTTempTComYuv[uiQTTempAccessLayer].getCrAddr( absTUPartIdxC ); UInt resiCStride = m_pcQTTempTComYuv[uiQTTempAccessLayer].getCStride(); TCoeff bestCoeffU[32*32], bestCoeffV[32*32]; memcpy( bestCoeffU, pcCoeffCurrU, sizeof(TCoeff) * uiNumSamplesChro ); memcpy( bestCoeffV, pcCoeffCurrV, sizeof(TCoeff) * uiNumSamplesChro ); #if ADAPTIVE_QP_SELECTION TCoeff bestArlCoeffU[32*32], bestArlCoeffV[32*32]; memcpy( bestArlCoeffU, pcArlCoeffCurrU, sizeof(TCoeff) * uiNumSamplesChro ); memcpy( bestArlCoeffV, pcArlCoeffCurrV, sizeof(TCoeff) * uiNumSamplesChro ); #endif Pel bestResiU[32*32], bestResiV[32*32]; for (Int i = 0; i < trHeightC; ++i ) { memcpy( &bestResiU[i*trWidthC], pcResiCurrU+i*resiCStride, sizeof(Pel) * trWidthC ); memcpy( &bestResiV[i*trWidthC], pcResiCurrV+i*resiCStride, sizeof(Pel) * trWidthC ); } m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); pcCU->setTransformSkipSubParts ( 1, TEXT_CHROMA_U, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); pcCU->setTransformSkipSubParts ( 1, TEXT_CHROMA_V, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); if (m_pcEncCfg->getUseRDOQTS()) { // 比特数估算 m_pcEntropyCoder->estimateBit(m_pcTrQuant->m_pcEstBitsSbac, trWidthC, trHeightC, TEXT_CHROMA ); } Int curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCbQpOffset() + pcCU->getSlice()->getSliceQpDeltaCb(); m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); #if RDOQ_CHROMA_LAMBDA m_pcTrQuant->selectLambda(TEXT_CHROMA_U); #endif // 变换量化(U分量) m_pcTrQuant->transformNxN( pcCU, pcResi->getCbAddr(absTUPartIdxC), pcResi->getCStride(), pcCoeffCurrU, #if ADAPTIVE_QP_SELECTION pcArlCoeffCurrU, #endif trWidthC, trHeightC, uiAbsSumTransformSkipU, TEXT_CHROMA_U, uiAbsPartIdx, true ); curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCrQpOffset() + pcCU->getSlice()->getSliceQpDeltaCr(); m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); #if RDOQ_CHROMA_LAMBDA m_pcTrQuant->selectLambda(TEXT_CHROMA_V); #endif // 变换量化(V分量) m_pcTrQuant->transformNxN( pcCU, pcResi->getCrAddr(absTUPartIdxC), pcResi->getCStride(), pcCoeffCurrV, #if ADAPTIVE_QP_SELECTION pcArlCoeffCurrV, #endif trWidthC, trHeightC, uiAbsSumTransformSkipV, TEXT_CHROMA_V, uiAbsPartIdx, true ); pcCU->setCbfSubParts( uiAbsSumTransformSkipU ? uiSetCbf : 0, TEXT_CHROMA_U, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); pcCU->setCbfSubParts( uiAbsSumTransformSkipV ? uiSetCbf : 0, TEXT_CHROMA_V, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); uiSingleBitsU = 0; uiSingleBitsV = 0; // 如果跳过了U分量 if( uiAbsSumTransformSkipU ) { m_pcEntropyCoder->resetBits(); // 对系数进行编码 m_pcEntropyCoder->encodeQtCbf ( pcCU, uiAbsPartIdx, TEXT_CHROMA_U, uiTrMode ); m_pcEntropyCoder->encodeCoeffNxN( pcCU, pcCoeffCurrU, uiAbsPartIdx, trWidthC, trHeightC, uiDepth, TEXT_CHROMA_U ); uiSingleBitsU = m_pcEntropyCoder->getNumberOfWrittenBits(); curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCbQpOffset() + pcCU->getSlice()->getSliceQpDeltaCb(); m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); Int scalingListType = 3 + g_eTTable[(Int)TEXT_CHROMA_U]; assert(scalingListType < SCALING_LIST_NUM); // 反变换反量化 m_pcTrQuant->invtransformNxN( pcCU->getCUTransquantBypass(uiAbsPartIdx), TEXT_CHROMA,REG_DCT, pcResiCurrU, m_pcQTTempTComYuv[uiQTTempAccessLayer].getCStride(), pcCoeffCurrU, trWidthC, trHeightC, scalingListType, true ); uiNonzeroDistU = m_pcRdCost->getDistPart(g_bitDepthC, m_pcQTTempTComYuv[uiQTTempAccessLayer].getCbAddr( absTUPartIdxC), m_pcQTTempTComYuv[uiQTTempAccessLayer].getCStride(), pcResi->getCbAddr( absTUPartIdxC), pcResi->getCStride(), trWidthC, trHeightC , TEXT_CHROMA_U ); dSingleCostU = m_pcRdCost->calcRdCost( uiSingleBitsU, uiNonzeroDistU ); } if( !uiAbsSumTransformSkipU || minCostU < dSingleCostU ) { pcCU->setTransformSkipSubParts ( 0, TEXT_CHROMA_U, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); memcpy( pcCoeffCurrU, bestCoeffU, sizeof (TCoeff) * uiNumSamplesChro ); #if ADAPTIVE_QP_SELECTION memcpy( pcArlCoeffCurrU, bestArlCoeffU, sizeof (TCoeff) * uiNumSamplesChro ); #endif for( Int i = 0; i < trHeightC; ++i ) { memcpy( pcResiCurrU+i*resiCStride, &bestResiU[i*trWidthC], sizeof(Pel) * trWidthC ); } } else { uiDistU = uiNonzeroDistU; uiAbsSumU = uiAbsSumTransformSkipU; uiBestTransformMode[1] = 1; } // 如果跳过了V分量 if( uiAbsSumTransformSkipV ) { m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); // 对系数进行编码 m_pcEntropyCoder->encodeQtCbf ( pcCU, uiAbsPartIdx, TEXT_CHROMA_V, uiTrMode ); m_pcEntropyCoder->encodeCoeffNxN( pcCU, pcCoeffCurrV, uiAbsPartIdx, trWidthC, trHeightC, uiDepth, TEXT_CHROMA_V ); uiSingleBitsV = m_pcEntropyCoder->getNumberOfWrittenBits(); curChromaQpOffset = pcCU->getSlice()->getPPS()->getChromaCrQpOffset() + pcCU->getSlice()->getSliceQpDeltaCr(); m_pcTrQuant->setQPforQuant( pcCU->getQP( 0 ), TEXT_CHROMA, pcCU->getSlice()->getSPS()->getQpBDOffsetC(), curChromaQpOffset ); Int scalingListType = 3 + g_eTTable[(Int)TEXT_CHROMA_V]; assert(scalingListType < SCALING_LIST_NUM); // 反变换反量化 m_pcTrQuant->invtransformNxN( pcCU->getCUTransquantBypass(uiAbsPartIdx), TEXT_CHROMA,REG_DCT, pcResiCurrV, m_pcQTTempTComYuv[uiQTTempAccessLayer].getCStride(), pcCoeffCurrV, trWidthC, trHeightC, scalingListType, true ); uiNonzeroDistV = m_pcRdCost->getDistPart(g_bitDepthC, m_pcQTTempTComYuv[uiQTTempAccessLayer].getCrAddr( absTUPartIdxC ), m_pcQTTempTComYuv[uiQTTempAccessLayer].getCStride(), pcResi->getCrAddr( absTUPartIdxC ), pcResi->getCStride(), trWidthC, trHeightC , TEXT_CHROMA_V ); dSingleCostV = m_pcRdCost->calcRdCost( uiSingleBitsV, uiNonzeroDistV ); } if( !uiAbsSumTransformSkipV || minCostV < dSingleCostV ) { pcCU->setTransformSkipSubParts ( 0, TEXT_CHROMA_V, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); memcpy( pcCoeffCurrV, bestCoeffV, sizeof(TCoeff) * uiNumSamplesChro ); #if ADAPTIVE_QP_SELECTION memcpy( pcArlCoeffCurrV, bestArlCoeffV, sizeof(TCoeff) * uiNumSamplesChro ); #endif for( Int i = 0; i < trHeightC; ++i ) { memcpy( pcResiCurrV+i*resiCStride, &bestResiV[i*trWidthC], sizeof(Pel) * trWidthC ); } } else { uiDistV = uiNonzeroDistV; uiAbsSumV = uiAbsSumTransformSkipV; uiBestTransformMode[2] = 1; } pcCU->setCbfSubParts( uiAbsSumU ? uiSetCbf : 0, TEXT_CHROMA_U, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); pcCU->setCbfSubParts( uiAbsSumV ? uiSetCbf : 0, TEXT_CHROMA_V, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); } m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); if( uiLog2TrSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) { // 编码分割标志? m_pcEntropyCoder->encodeTransformSubdivFlag( 0, 5 - uiLog2TrSize ); } // 前面的是为了选出最优模式,下面对系数进行编码 // 对色度部分CBF进行编码 if( bCodeChroma ) { m_pcEntropyCoder->encodeQtCbf( pcCU, uiAbsPartIdx, TEXT_CHROMA_U, uiTrMode ); m_pcEntropyCoder->encodeQtCbf( pcCU, uiAbsPartIdx, TEXT_CHROMA_V, uiTrMode ); } // 对亮度的CBF进行编码 m_pcEntropyCoder->encodeQtCbf( pcCU, uiAbsPartIdx, TEXT_LUMA, uiTrMode ); // 编码亮度部分的系数 m_pcEntropyCoder->encodeCoeffNxN( pcCU, pcCoeffCurrY, uiAbsPartIdx, trWidth, trHeight, uiDepth, TEXT_LUMA ); // 对色度部分的系数进行编码 if( bCodeChroma ) { m_pcEntropyCoder->encodeCoeffNxN( pcCU, pcCoeffCurrU, uiAbsPartIdx, trWidthC, trHeightC, uiDepth, TEXT_CHROMA_U ); m_pcEntropyCoder->encodeCoeffNxN( pcCU, pcCoeffCurrV, uiAbsPartIdx, trWidthC, trHeightC, uiDepth, TEXT_CHROMA_V ); } uiSingleBits = m_pcEntropyCoder->getNumberOfWrittenBits(); uiSingleDist = uiDistY + uiDistU + uiDistV; // 计算率失真代价 dSingleCost = m_pcRdCost->calcRdCost( uiSingleBits, uiSingleDist ); } // code sub-blocks // 对TU的四个子TU进行计算(使用递归的方式) if( bCheckSplit ) { if( bCheckFull ) { m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_TEST ] ); m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); } UInt uiSubdivDist = 0; UInt uiSubdivBits = 0; Double dSubdivCost = 0.0; const UInt uiQPartNumSubdiv = pcCU->getPic()->getNumPartInCU() >> ((uiDepth + 1 ) << 1); for( UInt ui = 0; ui < 4; ++ui ) { UInt nsAddr = uiAbsPartIdx + ui * uiQPartNumSubdiv; // 递归调用 xEstimateResidualQT( pcCU, ui, uiAbsPartIdx + ui * uiQPartNumSubdiv, nsAddr, pcResi, uiDepth + 1, dSubdivCost, uiSubdivBits, uiSubdivDist, bCheckFull ? NULL : puiZeroDist ); } UInt uiYCbf = 0; UInt uiUCbf = 0; UInt uiVCbf = 0; for( UInt ui = 0; ui < 4; ++ui ) { uiYCbf |= pcCU->getCbf( uiAbsPartIdx + ui * uiQPartNumSubdiv, TEXT_LUMA, uiTrMode + 1 ); uiUCbf |= pcCU->getCbf( uiAbsPartIdx + ui * uiQPartNumSubdiv, TEXT_CHROMA_U, uiTrMode + 1 ); uiVCbf |= pcCU->getCbf( uiAbsPartIdx + ui * uiQPartNumSubdiv, TEXT_CHROMA_V, uiTrMode + 1 ); } for( UInt ui = 0; ui < 4 * uiQPartNumSubdiv; ++ui ) { pcCU->getCbf( TEXT_LUMA )[uiAbsPartIdx + ui] |= uiYCbf << uiTrMode; pcCU->getCbf( TEXT_CHROMA_U )[uiAbsPartIdx + ui] |= uiUCbf << uiTrMode; pcCU->getCbf( TEXT_CHROMA_V )[uiAbsPartIdx + ui] |= uiVCbf << uiTrMode; } m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] ); m_pcEntropyCoder->resetBits(); // 对残差四叉树进行编码(目前不知道这样调用的目的是什么) xEncodeResidualQT( pcCU, uiAbsPartIdx, uiDepth, true, TEXT_LUMA ); xEncodeResidualQT( pcCU, uiAbsPartIdx, uiDepth, false, TEXT_LUMA ); xEncodeResidualQT( pcCU, uiAbsPartIdx, uiDepth, false, TEXT_CHROMA_U ); xEncodeResidualQT( pcCU, uiAbsPartIdx, uiDepth, false, TEXT_CHROMA_V ); uiSubdivBits = m_pcEntropyCoder->getNumberOfWrittenBits(); // 计算率失真代价 dSubdivCost = m_pcRdCost->calcRdCost( uiSubdivBits, uiSubdivDist ); if( uiYCbf || uiUCbf || uiVCbf || !bCheckFull ) { if( dSubdivCost < dSingleCost ) { rdCost += dSubdivCost; ruiBits += uiSubdivBits; ruiDist += uiSubdivDist; return; } } pcCU->setTransformSkipSubParts ( uiBestTransformMode[0], TEXT_LUMA, uiAbsPartIdx, uiDepth ); if(bCodeChroma) { pcCU->setTransformSkipSubParts ( uiBestTransformMode[1], TEXT_CHROMA_U, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); pcCU->setTransformSkipSubParts ( uiBestTransformMode[2], TEXT_CHROMA_V, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); } assert( bCheckFull ); m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_TEST ] ); } rdCost += dSingleCost; ruiBits += uiSingleBits; ruiDist += uiSingleDist; pcCU->setTrIdxSubParts( uiTrMode, uiAbsPartIdx, uiDepth ); pcCU->setCbfSubParts( uiAbsSumY ? uiSetCbf : 0, TEXT_LUMA, uiAbsPartIdx, uiDepth ); if( bCodeChroma ) { pcCU->setCbfSubParts( uiAbsSumU ? uiSetCbf : 0, TEXT_CHROMA_U, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); pcCU->setCbfSubParts( uiAbsSumV ? uiSetCbf : 0, TEXT_CHROMA_V, uiAbsPartIdx, pcCU->getDepth(0)+uiTrModeC ); } }对残差四叉树进行编码:
Void TEncSearch::xEncodeResidualQT( TComDataCU* pcCU, UInt uiAbsPartIdx, const UInt uiDepth, Bool bSubdivAndCbf, TextType eType ) { assert( pcCU->getDepth( 0 ) == pcCU->getDepth( uiAbsPartIdx ) ); // 模式 const UInt uiCurrTrMode = uiDepth - pcCU->getDepth( 0 ); const UInt uiTrMode = pcCU->getTransformIdx( uiAbsPartIdx ); // 对当前TU是否会继续向下分割 const Bool bSubdiv = uiCurrTrMode != uiTrMode; const UInt uiLog2TrSize = g_aucConvertToBit[pcCU->getSlice()->getSPS()->getMaxCUWidth() >> uiDepth]+2; if( bSubdivAndCbf && uiLog2TrSize <= pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() && uiLog2TrSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) ) { // 编码向下分割的标志 m_pcEntropyCoder->encodeTransformSubdivFlag( bSubdiv, 5 - uiLog2TrSize ); } assert( pcCU->getPredictionMode(uiAbsPartIdx) != MODE_INTRA ); // if( bSubdivAndCbf ) { const Bool bFirstCbfOfCU = uiCurrTrMode == 0; // 编码UV分量的CBF(Y分量已经在调用这个函数之前处理完了) if( bFirstCbfOfCU || uiLog2TrSize > 2 ) { if( bFirstCbfOfCU || pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_U, uiCurrTrMode - 1 ) ) { m_pcEntropyCoder->encodeQtCbf( pcCU, uiAbsPartIdx, TEXT_CHROMA_U, uiCurrTrMode ); } if( bFirstCbfOfCU || pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_V, uiCurrTrMode - 1 ) ) { m_pcEntropyCoder->encodeQtCbf( pcCU, uiAbsPartIdx, TEXT_CHROMA_V, uiCurrTrMode ); } } else if( uiLog2TrSize == 2 ) { assert( pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_U, uiCurrTrMode ) == pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_U, uiCurrTrMode - 1 ) ); assert( pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_V, uiCurrTrMode ) == pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_V, uiCurrTrMode - 1 ) ); } } // 如果不在继续向下分割,那么直接编码YUV三个分量的系数,否则需要对子TU递归调用 if( !bSubdiv ) { const UInt uiNumCoeffPerAbsPartIdxIncrement = pcCU->getSlice()->getSPS()->getMaxCUWidth() * pcCU->getSlice()->getSPS()->getMaxCUHeight() >> ( pcCU->getSlice()->getSPS()->getMaxCUDepth() << 1 ); //assert( 16 == uiNumCoeffPerAbsPartIdxIncrement ); // check const UInt uiQTTempAccessLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize; TCoeff *pcCoeffCurrY = m_ppcQTTempCoeffY [uiQTTempAccessLayer] + uiNumCoeffPerAbsPartIdxIncrement * uiAbsPartIdx; TCoeff *pcCoeffCurrU = m_ppcQTTempCoeffCb[uiQTTempAccessLayer] + (uiNumCoeffPerAbsPartIdxIncrement * uiAbsPartIdx>>2); TCoeff *pcCoeffCurrV = m_ppcQTTempCoeffCr[uiQTTempAccessLayer] + (uiNumCoeffPerAbsPartIdxIncrement * uiAbsPartIdx>>2); Bool bCodeChroma = true; UInt uiTrModeC = uiTrMode; UInt uiLog2TrSizeC = uiLog2TrSize-1; if( uiLog2TrSize == 2 ) { uiLog2TrSizeC++; uiTrModeC --; UInt uiQPDiv = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth( 0 ) + uiTrModeC ) << 1 ); bCodeChroma = ( ( uiAbsPartIdx % uiQPDiv ) == 0 ); } if( bSubdivAndCbf ) { m_pcEntropyCoder->encodeQtCbf( pcCU, uiAbsPartIdx, TEXT_LUMA, uiTrMode ); } else { if( eType == TEXT_LUMA && pcCU->getCbf( uiAbsPartIdx, TEXT_LUMA, uiTrMode ) ) { Int trWidth = 1 << uiLog2TrSize; Int trHeight = 1 << uiLog2TrSize; // 对Y分量的系数进行编码 m_pcEntropyCoder->encodeCoeffNxN( pcCU, pcCoeffCurrY, uiAbsPartIdx, trWidth, trHeight, uiDepth, TEXT_LUMA ); } if( bCodeChroma ) { Int trWidth = 1 << uiLog2TrSizeC; Int trHeight = 1 << uiLog2TrSizeC; // 对U分量的系数进行编码 if( eType == TEXT_CHROMA_U && pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_U, uiTrMode ) ) { m_pcEntropyCoder->encodeCoeffNxN( pcCU, pcCoeffCurrU, uiAbsPartIdx, trWidth, trHeight, uiDepth, TEXT_CHROMA_U ); } // 对V分量的系数进行编码 if( eType == TEXT_CHROMA_V && pcCU->getCbf( uiAbsPartIdx, TEXT_CHROMA_V, uiTrMode ) ) { m_pcEntropyCoder->encodeCoeffNxN( pcCU, pcCoeffCurrV, uiAbsPartIdx, trWidth, trHeight, uiDepth, TEXT_CHROMA_V ); } } } } else { if( bSubdivAndCbf || pcCU->getCbf( uiAbsPartIdx, eType, uiCurrTrMode ) ) { const UInt uiQPartNumSubdiv = pcCU->getPic()->getNumPartInCU() >> ((uiDepth + 1 ) << 1); // 对子TU递归调用该函数 for( UInt ui = 0; ui < 4; ++ui ) { xEncodeResidualQT( pcCU, uiAbsPartIdx + ui * uiQPartNumSubdiv, uiDepth + 1, bSubdivAndCbf, eType ); } } } }
标签:
原文地址:http://blog.csdn.net/nb_vol_1/article/details/51190324