视频编码SVC --- JSVM代码阅读笔记(五)

本文详细介绍了JSVM中MB编码器的16x16运动估计过程,包括MbEncoder类的xEstimateMb16x16、xEstimateMbIntra16、xEstimateMbIntraBL和xEstimateMbBLSkip方法,涉及运动预测、RdCost计算及最佳模式选择等关键步骤。同时,文中提到了BLSkip模式下的处理细节和INTRA_16x16预测模式的选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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     ();      // BLmv  作为EL运动估计的MVP

 

rpcMbTempData->clear();                       // 清空

//设置几个参数

rpcMbTempData->setMbMode( MODE_16x16 );    

rpcMbTempData->setBLSkipFlag( false );

rpcMbTempData->setResidualPredFlag( bResidualPred );

 

//List0List1每个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,也可能是BLmv(BLref_idx与当前的ref_idx相等时就以BLMv为搜索起点,但是MVP仍是周围块得到的)

 

//如果这个ref_idxBL的相同,则    MotionPrediction

m_pcMotionEstimation->estimateBlockWithStart(…)   // 运动估计出mv

//注意:这里MVPBLmv,搜索起点可能是BLmv

 

//如果cost比前面的最小cost(org-ref的失真 Mvref_idx的比特数)

选用该ref_idxmv

 

//如果是List1预测,还要补偿出双向预测用的块

m_pcMotionEstimation->compensateBlock ( &cYuvMbBuffer[1], PART_16x16, MODE_16x16 )

 

//如果是B帧,还要进行迭代的Bi-Pred,步骤与上面相同

//注意:MVP用对应LISTMVP,起始MV也用上次对应LIST运动估计出的MV,包括StdMEBLME

 

//保存ref_idxmvmvd

  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变换的RdCostBestDataRdCost大,则函数退出

 

  //交换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 );

 

如果是BLSkipavcRewrite:读取BaseLayer的预测模式,下面的遍历只用这一种模式

 

遍历四种INTRA16预测模式

//进行INTRA预测:

m_pcIntraPrediction->predictSLumaMb( rpcMbTempData, n, bValid )

 

//进行变换/量化/反量化/反变换:

m_pcTransform->transformMb16x16()

 

//计算distortion

m_pcXDistortion->getLum16x16( pPel, iStride );

 

如果是BLSkipavcRewritem_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()

 

如果是BLSkipavcRewritem_pcTransform->predictMb16x16()

                          计算新CBP

 

//计算LUMA RD

m_pcXDistortion->getLum16x16( pPel, iStride, rcDFunc );

m_pcMotionEstimation->getRateCost( uiBestBits + uiMBits, rcDFunc == DF_SAD )

 

//编码色度部分:

xEncodeChromaIntra()

 

如果是BLSkipavcRewriteMbMode = INTRA_BL

否则,是INTRA16 INTRA_4x4+1 +0/1/2/3代表四种INTRA预测还要加上CBP等构成MbMode

 

avcRewriteINTRA_BL或者普通INTRA)和不用avcRewriteCBP要计算

 

MotionPred = false    ResidualPred = false     BaseModeBLSkip有关

 

//计算总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 )      //只要BLintra

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 = 1SliceHeader)(MGS CGS

rcYuvMbBuffer拷贝BaseLayer的预测数据m_sPred

(就是BLintra预测样点====最底层BLintra重建)

Others Spatial

rcYuvMbBuffer拷贝pcBaseLayerRec->getFullPelYuvBuffer()

BLm_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 predictionmotion prediction

因此函数的bCheckWithResPred = 0SCoeff = 0(虽然SH里面为1

 

那么SHSCoeff = 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 copymbMode 和分区方式

rpcMbTempData->copyMotion ( pcMbDataAccessBase->getMbData() );

 

//设置BLSkipFlag = trueResidualPredFlag(truefalse

 

//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

读取MClist

compensateMb()/compensateSubMb()        //补偿出预测宏块

   xGetMbPredData()   //读取ref_idx/MV/MVD/参考帧buffer到变量cMC8x8D

   xPredLuma()   xPredChroma()  //根据mvref_idx得到预测的宏块è rcYuvMbBuffer

//BLintra预测,该层用base mode 进行补偿出预测宏块

m_pcMotionEstimation->compensateMbBLSkipIntra( rcMbDataAccess, &rcYuvMbBuffer, pcBaseLayerRec )

rcYuvMbBuffer(预测的宏块)赋值给cTempPredBufferMC的预测值

 

get prediction signal (for reconstruction)---------重建RC

如果RCMC队列不同,读取RClist

compensateMb()/compensateSubMb()/compensateMbBLSkipIntra()

预测值à rcTempYuvMbBufferRC的预测值

 

(如果MCRC队列相同,rcTempYuvMbBuffer== rcYuvMbBuffer

 

//BaseModeResidual Pred

   m_pcMotionEstimation->updateMbBLSkipResidual( rcMbDataAccess, rcTempBLSkipBaseRes )

     // rcTempBLSkipBaseRespcBaseLayerResidual,对该值进行更新

   rcYuvMbBuffer + =  rcTempBLSkipBaseRes   pcBaseLayerResidual 

 (如果BL是用的预测rcYuvMbBuffer=0;或者INTERBaseModecBaseLayerBuffer=0)

   cTempPredBufferrcTempYuvMbBuffer都是rcYuvMbBuffer(MC预测值)

 

注意:rcYuvMbBufferrpcMbTempData的宏块数据

 

对每个8x8块的每个4x4块,进行变换

SCoeff

普通

transform4x4BlkCGS

1 (原始-MC预测)的差值进行变换

2 新变换系数 =前面的变换系数 参考层反量化后系数 就是变换系数差

3 新变换系数进行量化反量化

4 新反量化后的值 = 参考层反量化后 + 变换系数差量化反量化后

5 新反量化后的值进行反变换

变换域变换系数的差!!!!

传出去的是变换系数的差,重建的仍是完整的块

transform4x4Blk

1 (原始-MC预测)的差值进行变换

2 量化和反量化

3 反变换

TCoeffSVC to AVC rewrite

反变换后的残差会与预测值相加进行重建!!!

 

CAVLC熵编码,计算Bits

 

//保存最佳重建的宏块

  rcMbTempData.getMbTCoeffs ().copyFrom( cBestCoeffs );

  rcMbTempData.loadLuma     ( cBestRec );

  rcMbTempData.loadChroma   ( cBestRec );

 

//如果RCMC队列不同   原来rcYuvMbBufferMC的,现在改成了RC

rcYuvMbBuffer.subtract( cTempPredBuffer );

rcYuvMbBuffer.add ( rcTempYuvMbBuffer );

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值