标签:
(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