HEVC函式入門(16)——Slice編碼
阿新 • • 發佈:2019-01-28
( uiCUAddr == rpcPic->getPicSym()->getTComTile(rpcPic->getPicSym()->getTileIdxMap(uiCUAddr))->getFirstCUAddr() && // must be first CU of tile
uiCUAddr!=0 && // cannot be first CU of picture
uiCUAddr!=rpcPic->getPicSym()->getPicSCUAddr(rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getSliceSegmentCurStartCUAddr())/rpcPic->getNumPartInCU() &&
uiCUAddr!=rpcPic->getPicSym()->getPicSCUAddr(rpcPic->getSlice(rpcPic->getCurrSliceIdx())->getSliceCurStartCUAddr())/rpcPic->getNumPartInCU()) / / cannot be first CU of slice
{
SliceType sliceType = pcSlice->getSliceType();
if (!pcSlice->isIntra() && pcSlice->getPPS()->getCabacInitPresentFlag() && pcSlice->getPPS()->getEncCABACTableIdx()!=I_SLICE)
{
sliceType = (SliceType) pcSlice->getPPS()->getEncCABACTableIdx();
}
m_pcEntropyCoder->updateContextTables ( sliceType, pcSlice->getSliceQp(), false );
m_pcEntropyCoder->setEntropyCoder ( m_pppcRDSbacCoder[0][CI_CURR_BEST], pcSlice );
m_pcEntropyCoder->updateContextTables ( sliceType, pcSlice->getSliceQp() );
m_pcEntropyCoder->setEntropyCoder ( m_pcSbacCoder, pcSlice );
}
// set go-on entropy coder
m_pcEntropyCoder->setEntropyCoder ( m_pcRDGoOnSbacCoder, pcSlice );
m_pcEntropyCoder->setBitstream( &pcBitCounters[uiSubStrm] );
((TEncBinCABAC*)m_pcRDGoOnSbacCoder->getEncBinIf())->setBinCountingEnableFlag(true);
Double oldLambda = m_pcRdCost->getLambda();//57.9。。。
// 沒有使用位元速率控制
if ( m_pcCfg->getUseRateCtrl() )
{
Int estQP = pcSlice->getSliceQp();
Double estLambda = -1.0;
Double bpp = -1.0;
if ( ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE && m_pcCfg->getForceIntraQP() ) || !m_pcCfg->getLCULevelRC() )
{
estQP = pcSlice->getSliceQp();
}
else
{
bpp = m_pcRateCtrl->getRCPic()->getLCUTargetBpp(pcSlice->getSliceType());
if ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE)
{
estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambdaAndQP(bpp, pcSlice->getSliceQp(), &estQP);
}
else
{
estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambda( bpp );
estQP = m_pcRateCtrl->getRCPic()->getLCUEstQP ( estLambda, pcSlice->getSliceQp() );
}
estQP = Clip3( -pcSlice->getSPS()->getQpBDOffsetY(), MAX_QP, estQP );
m_pcRdCost->setLambda(estLambda);
#if RDOQ_CHROMA_LAMBDA
// set lambda for RDOQ
Double weight=m_pcRdCost->getChromaWeight();
const Double lambdaArray[3] = { estLambda, (estLambda / weight), (estLambda / weight) };
m_pcTrQuant->setLambdas( lambdaArray );
#else
m_pcTrQuant->setLambda( estLambda );
#endif
}
m_pcRateCtrl->setRCQP( estQP );
#if ADAPTIVE_QP_SELECTION
pcCU->getSlice()->setSliceQpBase( estQP );
#endif
}
// run CU encoder
// 對CU進行編碼(壓縮)
// 幀內預測,幀間預測編碼還有變換編碼
// 這裡很重要
// 編碼單元編碼
// 最重要的部分!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// 注意這個只是嘗試進行,然後選出最優熵編碼方案,下面的encodeCU才是真正進行熵編碼的地方
m_pcCuEncoder->compressCU( pcCU );
// 最重要的部分!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// restore entropy coder to an initial stage
// 熵編碼器設定為Sbac
m_pcEntropyCoder->setEntropyCoder ( m_pppcRDSbacCoder[0][CI_CURR_BEST], pcSlice );
// 設定需要寫入的位元流
m_pcEntropyCoder->setBitstream( &pcBitCounters[uiSubStrm] );
m_pcCuEncoder->setBitCounter( &pcBitCounters[uiSubStrm] );
// 位元計數器(用於統計熵編碼器寫入到位元流中的位元數)
m_pcBitCounter = &pcBitCounters[uiSubStrm];
pppcRDSbacCoder->setBinCountingEnableFlag( true );
m_pcBitCounter->resetBits();
pppcRDSbacCoder->setBinsCoded( 0 );
// 對CU進編碼
// 這裡是真正的進行熵編碼!!!!
// 重要!!!!!!!!!!!!!
m_pcCuEncoder->encodeCU( pcCU );
// 重要!!!!!!!!!!!!!
pppcRDSbacCoder->setBinCountingEnableFlag( false );
// 這兩個判斷,是為了判斷該CU是否為條帶中的最後一個CU,如果是則跳出迴圈
if (m_pcCfg->getSliceMode()==FIXED_NUMBER_OF_BYTES && ( ( pcSlice->getSliceBits() + m_pcEntropyCoder->getNumberOfWrittenBits() ) ) > m_pcCfg->getSliceArgument()<<3)
{
pcSlice->setNextSlice( true );
break;
}
if (m_pcCfg->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES && pcSlice->getSliceSegmentBits()+m_pcEntropyCoder->getNumberOfWrittenBits() > (m_pcCfg->getSliceSegmentArgument() << 3) &&pcSlice->getSliceCurEndCUAddr()!=pcSlice->getSliceSegmentCurEndCUAddr())
{
pcSlice->setNextSliceSegment( true );
break;
}
ppppcRDSbacCoders[uiSubStrm][0][CI_CURR_BEST]->load( m_pppcRDSbacCoder[0][CI_CURR_BEST] );
//Store probabilties of second LCU in line into buffer
if ( ( uiCol == uiTileLCUX+1) && (depSliceSegmentsEnabled || (pcSlice->getPPS()->getNumSubstreams() > 1)) && m_pcCfg->getWaveFrontsynchro())
{
m_pcBufferSbacCoders[uiTileCol].loadContexts(ppppcRDSbacCoders[uiSubStrm][0][CI_CURR_BEST]);
}
// 沒有使用位元速率控制
if ( m_pcCfg->getUseRateCtrl() )
{
Int actualQP = g_RCInvalidQPValue;
Double actualLambda = m_pcRdCost->getLambda();
Int actualBits = pcCU->getTotalBits();
Int numberOfEffectivePixels = 0;
for ( Int idx = 0; idx < rpcPic->getNumPartInCU(); idx++ )
{
if ( pcCU->getPredictionMode( idx ) != MODE_NONE && ( !pcCU->isSkipped( idx ) ) )
{
numberOfEffectivePixels = numberOfEffectivePixels + 16;
break;
}
}
if ( numberOfEffectivePixels == 0 )
{
actualQP = g_RCInvalidQPValue;
}
else
{
actualQP = pcCU->getQP( 0 );
}
m_pcRdCost->setLambda(oldLambda);
m_pcRateCtrl->getRCPic()->updateAfterLCU( m_pcRateCtrl->getRCPic()->getLCUCoded(), actualBits, actualQP, actualLambda,
pcCU->getSlice()->getSliceType() == I_SLICE ? 0 : m_pcCfg->getLCULevelRC() );
}
// 計算總的位元數
m_uiPicTotalBits += pcCU->getTotalBits();
// 計算執行代價
m_dPicRdCost += pcCU->getTotalCost();
// 計算失真率
m_uiPicDist += pcCU->getTotalDistortion();
} // for end
if ((pcSlice->getPPS()->getNumSubstreams() > 1) && !depSliceSegmentsEnabled)
{
pcSlice->setNextSlice( true );
}
if(m_pcCfg->getSliceMode()==FIXED_NUMBER_OF_BYTES || m_pcCfg->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES)
{
if(pcSlice->getSliceCurEndCUAddr()<=pcSlice->getSliceSegmentCurEndCUAddr())
{
pcSlice->setNextSlice( true );
}
else
{
pcSlice->setNextSliceSegment( true );
}
}
if( depSliceSegmentsEnabled )
{
if (m_pcCfg->getWaveFrontsynchro())
{
CTXMem[1]->loadContexts( &m_pcBufferSbacCoders[uiTileCol] );//ctx 2.LCU
}
CTXMem[0]->loadContexts( m_pppcRDSbacCoder[0][CI_CURR_BEST] );//ctx end of dep.slice
}
// 儲存WP引數
xRestoreWPparam( pcSlice );
}