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

    技术2022-05-20  29

    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 );

     


    最新回复(0)