ErrVal
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
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
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 ()
isSCoeffPred()
else
transform4x4BlkCGS ()
对当前4x4变换系数和baselayer反量化系数进行做差;对差值进行量化、反量化;得到的值加上baselayer反量化系数得到该层反量化值;最后进行反变换重建
transform4x4Blk ()
正常的4x4变换 重建
isTCoeffPred()
predict4x4Blk (当前系数,baselayer系数) ---------接着上面else继续的
当前块4x4变换量化后系数和baselayer量化后系数进行做差(直接在变换域预测)
用Uvlc编码计算bits
//对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
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
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块,进行变换
SCoeff
普通
transform4x4BlkCGS
1 (原始-MC预测)的差值进行变换
2 新变换系数 =前面的变换系数 – 参考层反量化后系数 就是变换系数差
3 新变换系数进行量化反量化
4 新反量化后的值 = 参考层反量化后 + 变换系数差量化反量化后
5 对新反量化后的值进行反变换
变换域—变换系数的差!!!!
传出去的是变换系数的差,重建的仍是完整的块
transform4x4Blk
1 (原始-MC预测)的差值进行变换
2 量化和反量化
3 反变换
TCoeff:SVC to AVC rewrite
反变换后的残差会与预测值相加进行重建!!!
CAVLC熵编码,计算Bits
//保存最佳重建的宏块
rcMbTempData.getMbTCoeffs ().copyFrom( cBestCoeffs );
rcMbTempData.loadLuma ( cBestRec );
rcMbTempData.loadChroma ( cBestRec );
//如果RC和MC队列不同 原来rcYuvMbBuffer是MC的,现在改成了RC的
rcYuvMbBuffer.subtract( cTempPredBuffer );
rcYuvMbBuffer.add ( rcTempYuvMbBuffer );