ErrVal
MbEncoder::xEstimateMb16x16( IntMbTempData*& rpcMbTempData,
IntMbTempData*& rpcMbBestData,
RefListStruct& rcRefListStruct,
UInt uiMinQP,
UInt uiMaxQP,
UInt uiMaxNumMv,
UInt uiNumMaxIter,
UInt uiIterSearchRange,
MbDataAccess* pcMbDataAccessBase,
Bool bResidualPred )
//运动估计队列用的是MEList
//如果允许MotionPred
iBLRefIdx [0] = pcMbDataAccessBase->getMbMotionData( LIST_0 ).getRefIdx (); //ref_idx
cBLMvPred [0] = pcMbDataAccessBase->getMbMotionData( LIST_0 ).getMv (); // BL的mv 作为EL运动估计的MVP
rpcMbTempData->clear(); // 清空
//设置几个参数
rpcMbTempData->setMbMode( MODE_16x16 );
rpcMbTempData->setBLSkipFlag( false );
rpcMbTempData->setResidualPredFlag( bResidualPred );
//对List0、List1中每个ref_idx,进行ME
pcRefFrame = rcRefFrameList0[iRefIdxTest]; //读取参考帧
// 根据当前块的ABC块得到MVP 存入cMvPred[0][iRefIdxTest] rpcMbTempData->getMbDataAccess().getMvPredictor ( cMvPred[0][iRefIdxTest], iRefIdxTest, LIST_0 );
m_pcMotionEstimation->estimateBlockWithStart(…) // 运动估计出mv //注意:这里MVP一定是周围块得到的MVP,搜索起点可能是MVP,也可能是BL的mv(当BL的ref_idx与当前的ref_idx相等时就以BL的Mv为搜索起点,但是MVP仍是周围块得到的)
//如果这个ref_idx与BL的相同,则 MotionPrediction m_pcMotionEstimation->estimateBlockWithStart(…) // 运动估计出mv //注意:这里MVP是BL的mv,搜索起点可能是BL的mv
//如果cost比前面的最小cost(org-ref的失真 和Mv与ref_idx的比特数) 选用该ref_idx和mv
//如果是List1预测,还要补偿出双向预测用的块 m_pcMotionEstimation->compensateBlock ( &cYuvMbBuffer[1], PART_16x16, MODE_16x16 ) |
//如果是B帧,还要进行迭代的Bi-Pred,步骤与上面相同
//注意:MVP用对应LIST的MVP,起始MV也用上次对应LIST运动估计出的MV,包括Std的ME和BL的ME
//保存ref_idx、mv和mvd
rpcMbTempData->getMbMotionData( LIST_0 ).setRefIdx ( iRefIdx [0] );
rpcMbTempData->getMbMotionData( LIST_0 ).setAllMv ( cMv [0] );
rpcMbTempData->getMbMvdData ( LIST_0 ).setAllMv ( cMvd [0] );
//设置每个4x4块的MotionPredFlag
rpcMbTempData->getMbMotionData( LIST_0 ).setMotPredFlag( bBLPred [0] );
rpcMbTempData->getMbMotionData( LIST_1 ).setMotPredFlag( bBLPred [1] );
//计算4x4变换的RDCost
xSetRdCostInterMb(*rpcMbTempData, pcMbDataAccessBase, rcRefListStruct, uiMinQP, uiMaxQP, bLowComplexMbEnable ) 后面分析
xCheckBestEstimation( rpcMbTempData, rpcMbBestData )
//如果当前4x4变换的RdCost比BestData的RdCost大,则函数退出
//交换rpcMbTempData和 rpcMbBestData
xCheckInterMbMode8x8( rpcMbTempData, rpcMbBestData, pcMbRefData, rcRefListStruct, uiMinQP, uiMaxQP,
false, pcMbDataAccessBase )
//计算当前8x8变换的RdCost
xSetRdCost8x8InterMb( *rpcMbTempData, pcMbDataAccessBaseMotion, rcRefListStruct,
uiMinQP, uiMaxQP, bBLSkip, 0, pcBaseLayerRec, pcBaseLayerResidual )
xCheckBestEstimation( rpcMbTempData, rpcMbBestData )
ErrVal
MbEncoder::xEstimateMbIntra16( IntMbTempData*& rpcMbTempData,
IntMbTempData*& rpcMbBestData,
UInt uiQp,
Bool bBSlice,
Bool bBLSkip
) 在xEstimateIntraBL()里会调用这个函数,且bBLSkip = true(只有这种情况为true,这个时候一定是TCoeff = 1,反过来不成立,因为可能TCoeff = 1,但是BLSkip不是true)
rpcMbTempData->clear(); //清空MbData 、YuvMbBuffer、 MbDataStruct 、CostData 、MbTransformCoeffs数据
//读取预测需要的样点 从m_pcIntPicBuffer (pic)= > rpcMbTempData (mb)
rpcMbTempData->loadIntraPredictors( m_pcIntPicBuffer );
如果是BLSkip且avcRewrite:读取BaseLayer的预测模式,下面的遍历只用这一种模式
遍历四种INTRA16预测模式
//进行INTRA预测:
m_pcIntraPrediction->predictSLumaMb( rpcMbTempData, n, bValid )
//进行变换/量化/反量化/反变换:
m_pcTransform->transformMb16x16()
//计算distortion:
m_pcXDistortion->getLum16x16( pPel, iStride );
如果是BLSkip且avcRewrite:m_pcTransform->predictMb16x16()
xScanLumaBlock()
//用Uvlc进行熵编码:
xScanLumaIntra16x16()
//计算RD:
m_pcRateDistortionIf->getCost( uiBits, uiDist )
//根据上面选择的模式进行INTRA16预测:
m_pcIntraPrediction->predictSLumaMb()
rpcMbTempData->getTempYuvMbBuffer().loadLuma( *rpcMbTempData ); //保存Intra预测值
//进行变换/量化/反量化/反变换:系数存在rpcMbTempData->get( B4x4Idx(0) ) (TCoeff m_aaiLevel)
m_pcTransform->transformMb16x16()
如果是BLSkip且avcRewrite:m_pcTransform->predictMb16x16()
计算新CBP
//计算LUMA 的 RD:
m_pcXDistortion->getLum16x16( pPel, iStride, rcDFunc );
m_pcMotionEstimation->getRateCost( uiBestBits + uiMBits, rcDFunc == DF_SAD )
//编码色度部分:
xEncodeChromaIntra()
如果是BLSkip且avcRewrite:MbMode = INTRA_BL
否则,是INTRA16, INTRA_4x4+1 +0/1/2/3代表四种INTRA预测还要加上CBP等构成MbMode
avcRewrite(INTRA_BL或者普通INTRA)和不用avcRewrite的CBP要计算
MotionPred = false ResidualPred = false BaseMode与BLSkip有关
//计算总RD :
xSetRdCostIntraMb()
xCheckBestEstimation( rpcMbTempData, rpcMbBestData )
ErrVal
MbEncoder::xEstimateMbIntraBL( IntMbTempData*& rpcMbTempData,
IntMbTempData*& rpcMbBestData,
UInt uiMinQP,
UInt uiMaxQP,
const Frame* pcBaseLayerRec,
Bool bBSlice,
MbDataAccess* pcMbDataAccessBase )
rpcMbTempData->clear(); // 清空数据
rpcMbTempData->setMbMode( INTRA_BL ); //MbMode
rpcMbTempData->setBLSkipFlag( bBLSkip ) //只要BL是intra
rpcMbTempData->setTransformSize8x8( false );
rpcMbTempData->setResidualPredFlag( false );
TCoeffLevelPredictionFlag = 1 (SliceHeader) Based on the MbMode of BL MODE_PCM --xEstimateMbPCMRewrite INTRA_4x4 (TransformSize8x8 decide INTRA_4x4 or INTRA_8x8) --xEstimateMbIntra4 | xEstimateMbIntra8 others( INTRA_16x16) --xEstimateMbIntra16
Return | |||||||||
SCoeffResidualPredFlag = 1(SliceHeader)(MGS CGS) rcYuvMbBuffer拷贝BaseLayer的预测数据m_sPred (就是BL的intra预测样点====最底层BL的intra重建) |
Others (Spatial) rcYuvMbBuffer拷贝pcBaseLayerRec->getFullPelYuvBuffer() BL的m_Subband | ||||||||
rcTempYuvMbBuffer.loadLuma = rcYuvMbBuffer 都是BL的样点值 | |||||||||
对每个luma 8x8块 的每个4x4块 --xEncode4x4InterBlock ()
//对chroma --xEncodeChromaTexture () 流程与Luma几乎相同
//计算RD --xSetRdCostIntraMb ()
xCheckBestEstimation ( rpcMbTempData, rpcMbBestData )
//用8x8变换再计算一次 --xEstimateMbIntraBL8x8 () |
INTRA_BL:在不rewrite的情况下
预测值拷贝BL的预测值(分辨率相同)/BL重建值(分辨率不同)
注意:
INTRA_BL不可能用residual prediction和motion prediction
因此函数的bCheckWithResPred = 0,SCoeff = 0(虽然SH里面为1)
那么SH的SCoeff = 1有什么作用呢?
---------作用是用BL的预测值作为该EL层的预测值!!否则用BL的重建值
进行变换时
EL transform4x4BlkCGS |
EL transform4x4BlkCGS |
EL transform4x4Blk |
BL transform4x4Blk |
ErrVal
MbEncoder::xEstimateMbBLSkip( IntMbTempData*& rpcMbTempData,
IntMbTempData*& rpcMbBestData,
RefListStruct& rcRefListStruct,
UInt uiMinQP,
UInt uiMaxQP,
const Frame* pcBaseLayerRec, // 参考层的重建(去块滤波之前)
UInt uiMaxNumMv,
Bool bBiPred8x8Disable,
Bool bBSlice,
MbDataAccess* pcMbDataAccessBase,
MbDataAccess& rcMbDataAccess,
Bool bResidualPred,
const YuvMbBuffer* pcBLResidual ) //传入cBaseLayerBuffer
参考层是INTER继续下去,否则,如果当前宏块是InCropWindow,进入xEstimateMbIntraBL()
rpcMbTempData->clear ();
// 直接copy motion (ref_idx) 也copy了mbMode 和分区方式
rpcMbTempData->copyMotion ( pcMbDataAccessBase->getMbData() );
//设置BLSkipFlag = true,ResidualPredFlag(可true可false
//Mvd清零
rpcMbTempData->getMbMvdData ( LIST_0 ).setAllMv( Mv::ZeroMv() );
//计算RD
xSetRdCostInterMb()
xCheckBestEstimation( rpcMbTempData, rpcMbBestData ) );
xCheckInterMbMode8x8( rpcMbTempData, rpcMbBestData, pcMbRefData, rcRefListStruct, uiMinQP, uiMaxQP, true,
pcMbDataAccessBase, (Frame*)pcBaseLayerRec, pcBLResidual )
计算RD的函数调用参数
xEstimateMbBLSkip |
xSetRdCostInterMb( *rpcMbTempData, pcMbDataAccessBase, rcRefListStruct, uiMinQP, uiMaxQP, bLowComplexMbEnable, true, 0, (Frame*)pcBaseLayerRec, pcBLResidual(就是cBaseLayerBuffer) ) |
xEstimateMb16x16 |
xSetRdCostInterMb( *rpcMbTempData, pcMbDataAccessBase, rcRefListStruct, uiMinQP, uiMaxQP, bLowComplexMbEnable ) |
xEstimateMbIntraBL |
xSetRdCostIntraMb ( *rpcMbTempData, uiCoeffBits, bBLSkip ) |
xEstimateMbIntra16 |
xSetRdCostIntraMb ( *rpcMbTempData, uiBestBits, false ) |
ErrVal
MbEncoder::xSetRdCostInterMb( IntMbTempData& rcMbTempData,
MbDataAccess* pcMbDataAccessBase,
RefListStruct& rcRefListStruct,
UInt uiMinQP,
UInt uiMaxQP,
Bool bLowComplexity, // JVT-V079
Bool bBLSkip,
UInt uiAdditionalBits,
Frame* pcBaseLayerRec,
const YuvMbBuffer* pcBaseLayerResidual ) // cBaseLayerBuffer
参数
cTempPredBuffer |
|
空->MC预测值 |
rcYuvMbBuffer |
rcMbTempData |
空àMC预测值àMC重建值 |
rcTempYuvMbBuffer |
rcMbTempData .getTempYuvMbBuffer (); |
RC的预测值 |
rcTempBLSkipBaseRes |
rcMbTempData .getTempBLSkipResBuffer () |
一开始为空,后来是cBaseLayerBuffer的更新后的值 |
设置FwdBwd----------每个8x8块的LIST0/1参考情况
get prediction signal (for residual coding)---------运动补偿MC 读取MC的list compensateMb()/compensateSubMb(): //补偿出预测宏块 xGetMbPredData() //读取ref_idx/MV/MVD/参考帧buffer到变量cMC8x8D中 xPredLuma() xPredChroma() //根据mv和ref_idx得到预测的宏块è rcYuvMbBuffer //BL的intra预测,该层用base mode 进行补偿出预测宏块 m_pcMotionEstimation->compensateMbBLSkipIntra( rcMbDataAccess, &rcYuvMbBuffer, pcBaseLayerRec ) rcYuvMbBuffer(预测的宏块)赋值给cTempPredBuffer(MC的预测值)
get prediction signal (for reconstruction)---------重建RC 如果RC和MC队列不同,读取RC的list compensateMb()/compensateSubMb()/compensateMbBLSkipIntra(), 预测值à rcTempYuvMbBuffer(RC的预测值)
(如果MC和RC队列相同,rcTempYuvMbBuffer== rcYuvMbBuffer)
//是BaseMode且Residual Pred m_pcMotionEstimation->updateMbBLSkipResidual( rcMbDataAccess, rcTempBLSkipBaseRes ) // rcTempBLSkipBaseRes是pcBaseLayerResidual,对该值进行更新 rcYuvMbBuffer + = rcTempBLSkipBaseRes – pcBaseLayerResidual (如果BL是用的预测rcYuvMbBuffer=0;或者INTER的BaseMode,cBaseLayerBuffer=0) cTempPredBuffer和rcTempYuvMbBuffer都是rcYuvMbBuffer(MC预测值)
注意:rcYuvMbBuffer是rpcMbTempData的宏块数据
对每个8x8块的每个4x4块,进行变换
反变换后的残差会与预测值相加进行重建!!!
CAVLC熵编码,计算Bits
//保存最佳重建的宏块 rcMbTempData.getMbTCoeffs ().copyFrom( cBestCoeffs ); rcMbTempData.loadLuma ( cBestRec ); rcMbTempData.loadChroma ( cBestRec );
//如果RC和MC队列不同 原来rcYuvMbBuffer是MC的,现在改成了RC的 rcYuvMbBuffer.subtract( cTempPredBuffer ); rcYuvMbBuffer.add ( rcTempYuvMbBuffer ); |