在执行完帧间和帧内模式的预测之后,如果,满足xCheckIntraPCM的执行条件,则会执行PCM模式的check.
// test PCM,最后尝试PCM模式;
if (sps.getUsePCM()//PCM模式,在该模式下,编码器直接传输一个CU的像素值,而不经过预测,变换等其他操作;
&& rpcTempCU->getWidth(0) <= (1 << sps.getPCMLog2MaxSize())
&& rpcTempCU->getWidth(0) >= (1 << sps.getPCMLog2MinSize()))
{
UInt uiRawBits = getTotalBits(rpcBestCU->getWidth(0), rpcBestCU->getHeight(0), rpcBestCU->getPic()->getChromaFormat(), sps.getBitDepths().recon);
UInt uiBestBits = rpcBestCU->getTotalBits();
if ((uiBestBits > uiRawBits) || (rpcBestCU->getTotalCost() > m_pcRdCost->calcRdCost(uiRawBits, 0)))
{//比较已有最佳模式与PCM算出的TempRDcost的大小;
xCheckIntraPCM(rpcBestCU, rpcTempCU);
rpcTempCU->initEstData(uiDepth, iQP, bIsLosslessMode);
}
}
*///PCM以一种无损的方式进行编码,没有预测,也没有残差,失真为0,如果最优的模式产生的比特数大于PCM模式的时候选择PCM模式;
Void TEncCu::xCheckIntraPCM( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU )
{
if(getFastDeltaQp())
{
const TComSPS &sps=*(rpcTempCU->getSlice()->getSPS());
const UInt fastDeltaQPCuMaxPCMSize = Clip3((UInt)1<<sps.getPCMLog2MinSize(), (UInt)1<<sps.getPCMLog2MaxSize(), 32u);
if (rpcTempCU->getWidth( 0 ) > fastDeltaQPCuMaxPCMSize)
{
return; // only check necessary PCM in fast deltaqp mode
}
}
UInt uiDepth = rpcTempCU->getDepth( 0 );
//设置各种参数
rpcTempCU->setSkipFlagSubParts( false, 0, uiDepth );
#if COM16_C806_OBMC
rpcTempCU->setOBMCFlagSubParts( false, 0, uiDepth );
#endif
rpcTempCU->setIPCMFlag(0, true);
rpcTempCU->setIPCMFlagSubParts (true, 0, rpcTempCU->getDepth(0));//将IPCM Flag设置为true;
#if !JVET_C0024_QTBT
rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uiDepth );
#endif
rpcTempCU->setPredModeSubParts( MODE_INTRA, 0, uiDepth );//设置预测模式为帧内模式,所以该模式属于帧内模式???
#if !JVET_C0024_QTBT
rpcTempCU->setTrIdxSubParts ( 0, 0, uiDepth );
#endif
rpcTempCU->setChromaQpAdjSubParts( rpcTempCU->getCUTransquantBypass(0) ? 0 : m_cuChromaQpOffsetIdxPlus1, 0, uiDepth );
#if JVET_C0024_QTBT
UInt uiWIdx = g_aucConvertToBit[rpcTempCU->getWidth(0)];
UInt uiHIdx = g_aucConvertToBit[rpcTempCU->getHeight(0)];
//执行PCM模式的估计
m_pcPredSearch->IPCMSearch( rpcTempCU, m_pppcOrigYuv[uiWIdx][uiHIdx], m_pppcPredYuvTemp[uiWIdx][uiHIdx], m_pppcResiYuvTemp[uiWIdx][uiHIdx], m_pppcRecoYuvTemp[uiWIdx][uiHIdx]);
m_pcRDGoOnSbacCoder->load(m_ppppcRDSbacCoder[uiWIdx][uiHIdx][CI_CURR_BEST]);
#else
m_pcPredSearch->IPCMSearch( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth], m_ppcResiYuvTemp[uiDepth], m_ppcRecoYuvTemp[uiDepth]);
m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);
#endif
m_pcEntropyCoder->resetBits();
if ( rpcTempCU->getSlice()->getPPS()->getTransquantBypassEnableFlag())
{
m_pcEntropyCoder->encodeCUTransquantBypassFlag( rpcTempCU, 0, true );
}
m_pcEntropyCoder->encodeSkipFlag ( rpcTempCU, 0, true );
m_pcEntropyCoder->encodePredMode ( rpcTempCU, 0, true );
#if !JVET_C0024_QTBT
m_pcEntropyCoder->encodePartSize ( rpcTempCU, 0, uiDepth, true );
#endif
m_pcEntropyCoder->encodeIPCMInfo ( rpcTempCU, 0, true );
#if JVET_C0024_QTBT
m_pcRDGoOnSbacCoder->store(m_ppppcRDSbacCoder[uiWIdx][uiHIdx][CI_TEMP_BEST]);
#else
m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]);
#endif
rpcTempCU->getTotalBits() = m_pcEntropyCoder->getNumberOfWrittenBits();
rpcTempCU->getTotalBins() = ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded();
rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() );//计算率失真代价
xCheckDQP( rpcTempCU );
DEBUG_STRING_NEW(a)
DEBUG_STRING_NEW(b)
xCheckBestMode(rpcBestCU, rpcTempCU, uiDepth DEBUG_STRING_PASS_INTO(a) DEBUG_STRING_PASS_INTO(b));
}