- 转载https://blog.csdn.net/xidianliye/article/details/66968233
- 在compressGOP()函数中
compressGOP()
{
...
for (Int iGOPid=0;iGOPid<m_iGopSize;iGOPid++)
{
m_pcSliceEncoder->initEncSlice ( pcPic, iPOCLast, pocCurr, iGOPid, pcSlice, isField );//设置当前Slice的编码参数,如QP,lambda(基于QP)等
if ( m_pcCfg->getUseRateCtrl() ) //若开启码率控制,则会对当前帧进行码率分配,计算RDO的参数lambda和QP
{
if ( ( pcSlice->getPOC() == 0 && m_pcCfg->getInitialQP() > 0 ) || ( frameLevel == 0 && m_pcCfg->getForceIntraQP() ) ) // QP is specified
{
}
else if ( frameLevel == 0 ) // intra case, but use the model
{
m_pcSliceEncoder->calCostSliceI(pcPic);//计算intraCost,也就是与complexity相关的参数
...
m_pcRateCtrl->getRCPic()->getLCUInitTargetBits();//在intra情况下,初始LCU的成员变量m_targetBitsLeft
lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());
sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );
}
else //normal case
{
lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());//计算lambda
sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );//QP由lambda计算
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
对于intra的情况,在compressGOP()中,以CTU为单位,计算了每个CTU的intra cost.
Void TEncSlice::calCostSliceI(TComPic* pcPic) // TODO: this only analyses the first slice segment. What about the others?
{
Double iSumHadSlice = 0;
TComSlice * const pcSlice = pcPic->getSlice(getSliceIdx());
const TComSPS &sps = *(pcSlice->getSPS());
const Int shift = sps.getBitDepth(CHANNEL_TYPE_LUMA)-8;
const Int offset = (shift>0)?(1<<(shift-1)):0;
pcSlice->setSliceSegmentBits(0);
UInt startCtuTsAddr, boundingCtuTsAddr;
xDetermineStartAndBoundingCtuTsAddr ( startCtuTsAddr, boundingCtuTsAddr, pcPic );
for( UInt ctuTsAddr = startCtuTsAddr, ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap( startCtuTsAddr);
ctuTsAddr < boundingCtuTsAddr;
ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(++ctuTsAddr) )
{
// initialize CU encoder
TComDataCU* pCtu = pcPic->getCtu( ctuRsAddr );
pCtu->initCtu( pcPic, ctuRsAddr );
Int height = min( sps.getMaxCUHeight(),sps.getPicHeightInLumaSamples() - ctuRsAddr / pcPic->getFrameWidthInCtus() * sps.getMaxCUHeight() );
Int width = min( sps.getMaxCUWidth(), sps.getPicWidthInLumaSamples() - ctuRsAddr % pcPic->getFrameWidthInCtus() * sps.getMaxCUWidth() );
Int iSumHad = m_pcCuEncoder->updateCtuDataISlice(pCtu, width, height);//计算CTU的complexity
(m_pcRateCtrl->getRCPic()->getLCU(ctuRsAddr)).m_costIntra=(iSumHad+offset)>>shift;
iSumHadSlice += (m_pcRateCtrl->getRCPic()->getLCU(ctuRsAddr)).m_costIntra;
}
m_pcRateCtrl->getRCPic()->setTotalIntraCost(iSumHadSlice);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
updataCtuDataISlice(pCtu,width,height):是8*8的块为单位,取Y分量做Hadam变换,计算每个CTU的累计变换系数之和。TRCLCU有一个数据成员 m_costIntra.
struct TRCLCU
{
Int m_actualBits;
Int m_QP; // QP of skip mode is set to g_RCInvalidQPValue
Int m_targetBits;
Double m_lambda;
Double m_bitWeight;
Int m_numberOfPixel;
Double m_costIntra;
Int m_targetBitsLeft;
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
而pic level 的参数alpha和beta以及CTU的参数alpha和beta,都要通过TEncRCSeq来访问:
class TEncRCSeq
{
Void initPicPara( TRCParameter* picPara = NULL ); // NULL to initial with default value
Void initLCUPara( TRCParameter** LCUPara = NULL ); // NULL to initial with default value //经过统计规律,给两个参数一个初始值
TRCParameter* getPicPara() { return m_picPara; }
TRCParameter getPicPara( Int level ) { assert( level < m_numberOfLevel ); return m_picPara[level]; }
Void setPicPara( Int level, TRCParameter para ) { assert( level < m_numberOfLevel ); m_picPara[level] = para; }
TRCParameter** getLCUPara() { return m_LCUPara; }
TRCParameter* getLCUPara( Int level ) { assert( level < m_numberOfLevel ); return m_LCUPara[level]; }
TRCParameter getLCUPara( Int level, Int LCUIdx ) { assert( LCUIdx < m_numberOfLCU ); return getLCUPara(level)[LCUIdx]; }
Void setLCUPara( Int level, Int LCUIdx, TRCParameter para ) { assert( level < m_numberOfLevel ); assert( LCUIdx < m_numberOfLCU ); m_LCUPara[level][LCUIdx] = para; }
//对Pic和CTU的alpha和beta参数进行设置、访问
//类的数据成员定义
private:
TRCParameter* m_picPara;//一维数组,每种picture level对应的编码参数值
TRCParameter** m_LCUPara;//二维数组,每种picture level下、每个CTUIdx对应的编码参数
}