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

LayerEncoder::process( UInt             uiAUIndex,     //这是CodingIndex

                   AccessUnitData&  rcAccessUnitData,

                   PicBufferList&   rcPicBufferInputList,    // H264AVCEncoder::m_acOrgPicBufferList  [uiLayer],

                                        PicBufferList&   rcPicBufferOutputList,  // H264AVCEncoder::m_acRecPicBufferList  [uiLayer],

                   PicBufferList&   rcPicBufferUnusedList,  // H264AVCEncoder::apcPicBufferUnusedList[uiLayer],

                   ParameterSetMng* pcParameterSetMng )

xInitBitCounts()           //统计lower layer编码的比特数

xUpdateELPics()

   //GOP每一帧,如果m_papcELFrame[uiIndex]Unvalid

     m_pcH264AVCEncoder->getELRefPic( m_uiDependencyId, uiTemporalId, uiFIdInTId );

        m_apcLayerEncoder[uiELId]->getRefPic( uiTemporalId, uiFrameIdInTId );    //得到相同分辨率的最高EL层图像

 

     m_papcELFrame[uiIndex]->copy( const_cast<Frame*>( pcELPic ), FRAME )    //拷贝到m_papcELFrame

 

     xFillAndUpsampleFrame( m_papcELFrame[uiIndex], FRAME, m_bFrameMbsOnlyFlag )   //对最高层EL参考图像进行处理

       m_pcYuvFullPelBufferCtrl->initMb()    //初始化整像素的宏块大小

m_pcYuvHalfPelBufferCtrl->initMb()   //初始化1/2像素的宏块大小

pcFrame->initHalfPel( pHPData )        // Frame

           getHalfPelYuvBuffer()->init( rpucYuvBuffer )

              m_rcYuvBufferCtrl.initMb();    //进行1/2像素的扩充

       pcFrame->extendFrame( m_pcQuarterPelFilter, ePicType, bFrameMbsOnlyFlag )

           getFullPelYuvBuffer()->fillMargin( )      //边缘填充

              m_rcYuvBufferCtrl.initMb();

              xFillPlaneMargin()

           pcQuarterPelFilter->filterFrame(getFullPelYuvBuffer(), getHalfPelYuvBuffer() )   //进行int->1/2像素的插值滤波

 

xEncodePicture( bPicCoded, uiTemporalId, uiFrameIdInGOP, rcAccessUnitData, rcPicBufferInputList )   //后面分析

 

//当一个GOP编码完成

xStoreReconstruction( rcPicBufferOutputList )

   //GOP中每一帧,从输出队列H264AVCEncoder::m_acRecPicBufferList中取出一个PicBuffer

m_papcFrame[uiIndex<<m_uiNotCodedStages]->store( pcPicBuffer )

      getFullPelYuvBuffer()->storeToPicBuffer     ( pcPicBuffer )

 

xFinishGOP ( rcPicBufferInputList, rcPicBufferOutputList, rcPicBufferUnusedList) //output队列中过多的图像放到Unused队列

 


 

ErrVal                   // ×××××对每一个Layer GOP中的每一个AU ×××××

LayerEncoder::xEncodePicture( Bool&   rbPictureCoded,        //是否编码,输出用

                               UInt            uiTemporalId,            //时间层ID

                                UInt            uiFrameIdInGOP,       //GOP中播放顺序

                         AccessUnitData& rcAccessUnitData,       //该帧的AU

                                 PicBufferList&  rcPicBufferInputList )      // H264AVCEncoder::m_acOrgPicBufferList  [uiLayer],  

//如果是IDR

LayerEncoder的成员Bool  m_abCoded[(1<<MAX_DSTAGES)+1]全部置0 (用来指示GOP中对应帧是否编码)

 

//如果是非第一个GOP的第一个帧

当前帧m_papcFramem_pcAnchorFrameReconstructed拷贝而来

m_apcBaseFrame[0]m_apcBaseFrame[1]拷贝而来        //RefBasePic

 

重要参数

rcControlData

m_pacControlData[ uiFrameIdInGOP ]

帧控制类

pcMbDataCtrl

rcControlData.getMbDataCtrl()

宏块控制类

pcFrame

m_papcFrame [ uiFrameIdInGOP]

当前帧

pcResidualLF

m_pcResidualLF

xStoreEstimation 去块滤波计算CBP

pcResidualILPred

m_pcResidualILPred

xStoreEstimation

pcOrgFrame

m_apcFrameTemp  [ 2 ]

pcFrame的编码前内容,原始帧像素

pcPredSignal

m_apcFrameTemp  [ 3 ]

xStoreEstimation,没任何作用

rcOutputList

rcAccessUnitData.getNalUnitList()

AUNalUnit队列

 

m_pcSubband

一层编码完成后的重建帧(去块滤波之前)

 

m_apcBaseFrame[ 0/1 ]

GOP的两个RefBasePic

pcTempBaseFrame

m_apcFrameTemp[0]

辅助INTRA上采样用 (在xInitControlData里)

pcTempFrame

m_apcFrameTemp[1]

辅助INTRA上采样用 (在xInitControlData里)

 

//RateControl相关,未关注

 

xInitControlData( uiFrameIdInGOP, uiTemporalId, ePicType )

xSetBaseLayerData( uiFrameIdInGOP, ePicType )       //设置BaseLayer信息

  m_pcH264AVCEncoder->getBaseLayerStatus( uiBaseLayerId, m_uiDependencyId, ePicType, uiTemporalId )

m_apcLayerEncoder[ruiBaseLayerId]->getBaseLayerStatus( bExists, ePicType, uiTemporalId )  //检查BaseLayerId

  //BaseLayerSize信息更新本层的ESS信息

  m_pcResizeParameters->updatePicParameters( m_papcFrame[ uiFrameIdInGOP ]->getPicParameters( ePicType ) );

  设置Inter-layer 预测的参数 BaseModeMotionResidual

  检查Level的约束

  rcControlData.setBaseLayer( uiBaseLayerId );     //最后才确定BaseLayerId

 

设置QP & lambda

pcSliceHeader->setTCoeffLevelPredictionFlag( m_pcLayerParameters->getTCoeffLevelPredictionFlag() );

 

xGetAndSetPredictionLists( rcControlData, uiFrameIdInGOP, ePicType, true )   //设置参考帧队列

  //设置rcRefListStruct = rcControlData.getRefListStruct(); 

  //当前为RC队列:rcRefListStruct.acRefFrameListRC[ X ]

  获得当前帧状态eRLU RLU_REF_BASE_PIC (KeyPicture)或者 RLU_RECONSTRUCTION

  xGetPredictionLists( rcRefList0, rcRefList1, uiFrameIdCol, uiFrameIdInGOP, ePicType, eRLU, bHalfPel )

     //LayerEncoderm_acRefPicListFrameId_LX[ uiFrameIdInGOP ]队列每一帧

       pcFrame = xGetRefFrame( uiFrmId, eRefListUsage );       //获得对应index的参考帧

          //如果是RefBasePicm_apcBaseFrame[ 0/1 ] ,否则m_papcELFrameMGS)或m_papcFrame

       //如果没有extend,还要xFillAndUpsampleFrame() / xFillAndExtendFrame()

       rcRefListX.add( pcFrame->getPic( FRAME )   //加入队列

       pcFrame->setLongTerm( m_bUseLongTermPics );

     // uiFrameIdCol是最后加入RCList1FrameId,即List1的第一帧(因为是栈)

 

如果是KeyPicture或者使用Std(MGScontrol=0)MEMC队列都用RC队列------同层的参考帧

MGScontrol=1MEEL的队列,MCRC(std)的队列

MGScontrol=2MEMC都用EL的队列

 

  SliceHeader写的是StdRC队列

  //当是B片时pcMbDataCtrl0L1 = m_pacControlData[ rcRefListStruct.uiFrameIdCol ].getMbDataCtrl(),否则为空

  rcControlData.setMbDataCtrl0L1( pcMbDataCtrl0L1 );  //这个是co-located MB的控制类

 

//更新ESS信息

m_pcResizeParameters->updatePicParameters( m_papcFrame[ uiFrameIdInGOP ]->getPicParameters( ePicType ) );

 

xInitBaseLayerData( rcControlData, ePicType )

  先将m_pcBaseLayerRec m_pcBaseLayerSbbm_pcBaseLayerCtrl m_pcBaseLayerCtrlField 设置成0

  //如果BaseLayer存在

    m_pcH264AVCEncoder->getBaseLayerDataAvlb(pcBaseFrame, pcBaseResidual, pcBaseDataCtrl,

 rcControlData.getBaseLayerId(),bBaseDataAvailable,

                                           ePicType, pcSliceHeader->getTemporalId() )

       àm_apcLayerEncoder[uiBaseLayerId]->getBaseLayerDataAvlb(pcFrame,  pcResidual,  pcMbDataCtrl,

                                              ePicType, uiTemporalId ) //获得BaseLayer信息

LayerEncoder::xInitBaseLayerData()参数

BaseLayer  LayerEncoder

pcBaseFrame

m_pcSubband

pcBaseResidual

m_pcResidualILPred

pcBaseDataCtrl

m_pacControlData[m_uiLastCodedFrameIdInGOP].getMbDataCtrl()

BaseLayer的信息pcBaseDataCtrl更新ESS内容m_pcResizeParameters

//判断分辨率是否改变并设置

rcControlData.setSpatialScalability( m_pcResizeParameters->getSpatialResolutionChangeFlag() );

 

m_pcH264AVCEncoder->getBaseLayerData( *pcSliceHeader, pcBaseFrame, pcBaseResidual, pcBaseDataCtrl,

                                        m_pcResizeParameters->getSpatialResolutionChangeFlag(),

                                        rcControlData.getBaseLayerId(),ePicType, 

pcSliceHeader->getTemporalId() )

       à m_apcLayerEncoder[uiBaseLayerId]->getBaseLayerData( rcELSH, pcFrame, pcResidual, pcMbDataCtrl,

                                                       bSpatialScalability, ePicType, uiTemporalId ) );

         //再设置一遍,觉得多余

LayerEncoder::xInitBaseLayerData()参数

BaseLayer  LayerEncoder里,先复制给左边

pcBaseFrame

最后èm_pcBaseLayerFrame

m_pcSubband    去块滤波前的重建帧

pcBaseResidual

最后èm_pcBaseLayerResidual

m_pcResidualILPred

pcBaseDataCtrl

m_pacControlData[m_uiLastCodedFrameIdInGOP].getMbDataCtrl()

          //如果分辨率改变bSpatialScalability

           pcFrame = m_pcSubband = LayerEncoder::Frame m_apcFrameTemp[0] (数据一样,同一地址)

           m_pcLoopFilter->process(*pcSliceHeader, pcFrame, pcResidual, m_pacControlData[uiPos].getMbDataCtrl(),

                                 &rcELSH.getInterLayerDeblockingFilterParameter(),

                                 m_pacControlData[uiPos].getSpatialScalability() )  //因为是去块滤波前的

  //如果BaseLayer的控制器pcBaseDataCtrl存在

pcSliceHeader->setSCoeffResidualPredFlag( m_pcResizeParameters );  //同分辨率的ELTCoeff=FALSE则为真

m_pcBaseLayerCtrl->initSlice( *pcSliceHeader, PRE_PROCESS, false, NULL )

  把当前SliceHeader给了m_pcBaseLayerCtrlm_pcSliceHeader

      m_pcBaseLayerCtrl->upsampleMotion(…)

         //BaseLayer每个宏块

           cMotionUpsampling.resample( iMbX, iMbY )    MotionUpsampling

xInitMb ( iMbXCurr, iMbYCurr )  //设置宏块大小、块模式、每块ref_idx等信息

xSetPartIdcArray()

  //164x4

xGetRefLayerPartIdc( ( iX << 2 ) + 1, ( iY << 2 ) + 1, m_aaiPartIdc[iX][iY] ) //得到该块在参考层的4x4id

      xGetRefLayerMb(iXInsideCurrMb,iYInsideCurrMb,iBaseMbIdx,iXInsideBaseMb, iYInsideBaseMb )

        //标准G6.1过程  得到该4x4块在参考层的宏块id和在宏块内的坐标

 

//如果是InCropWindow且不是INTRA_BL对每个List

   xGetRefIdxAndInitialMvPred( ListIdx( iListIdx ) )

     //对每个4x4

       xGetInitialBaseRefIdxAndMv() //获得BaseLayerMotionDataMv,修正Mv

              //ref_idxMv保存在m_aaaiRefIdx / m_aaacMv

  

   //对每个8x8

     xDeriveBlockModeAndUpdateMv( iB8x8Idx )   //根据宏块分区更新Mv

   

   xDeriveMbMode ()   //BaseMbMode检查ref_idxMv,并得到MbMode

   xDeriveFwdBwd ()

   xSetInterIntraIdc ()    //设置m_aabBaseIntra[][]

 

//如果是InCropWindow,则检查分区方式、ref_idxMv是否正确,设置m_bResPredSafe

xSetResPredSafeFlag ()

 

//BaseLayer得到MbMode、分区方式、ref_idxMv

xSetPredMbData()

  //如果是INTRA_BL或非InCropWindow,则不得到Motion信息

  //否则拷贝每个List的每个8x8块的ref_idx和每个4x4块的Mv

 

  InCropWindow的话,MbModeFwdBwd等等也拷贝

 

  //SNR伸缩------SCoeff/TCoeff 且是InCropWindow

rcMbData.copyTCoeffs    ( rcMbDataBase );    //拷贝BL的变换系数、CBPQPTransformSize

拷贝BLSkipFlag

IntraBL

TCoeffPred

拷贝BLMbMode

拷贝IntraPredMode

CBPQPTransformSize

 

//如果BL有加权预测,直接拷贝BL的权值和加权表

pcSliceHeaderCurr->setLumaLog2WeightDenom( pcSliceHeaderBase->getLumaLog2WeightDenom() );

pcSliceHeaderCurr->setChromaLog2WeightDenom( pcSliceHeaderBase->getChromaLog2WeightDenom() );

pcSliceHeaderCurr->getPredWeightTable( LIST_0 ).copy( pcSliceHeaderBase->getPredWeightTable( LIST_0 ) )

pcSliceHeaderCurr->getPredWeightTable( LIST_1 ).copy( pcSliceHeaderBase->getPredWeightTable( LIST_1 ) );

//如果BaseLayer可用(bBaseDataAvailable)

    m_pcBaseLayerResidual->residualUpsampling( pcBaseResidual, m_cDownConvert, m_pcResizeParameters, pcBaseDataCtrl )

       rcDownConvert.residualUpsampling( this, pcBaseFrame, pcParameters, pcMbDataCtrlBase );  //像素帧Resize

     //BLLayerEncoderm_pcResidualILPred进过残差上采样赋值给了m_pcBaseLayerResidual

 

   rcControlData.setBaseLayerSbb( m_pcBaseLayerResidual );

//如果BaseLayer可用(bBaseDataAvailable)

m_pcBaseLayerFrame->intraUpsampling( pcBaseFrame, pcTempBaseFrame, pcTempFrame,m_cDownConvert,

 m_pcResizeParameters, pcBaseDataCtrl, m_pcBaseLayerCtrl,

m_pcBaseLayerCtrlField, m_pcReconstructionBypass, m_bCIUFlag,

 m_apabBaseModeFlagAllowedArrays[0], m_apabBaseModeFlagAllowedArrays[1] )

     //进行Intra上采样,从pcBaseFrame采样到m_pcBaseLayerFrame   pcTempBaseFramepcTempFrame辅助采样

rcControlData保存了m_pcBaseLayerResidualm_pcBaseLayerFrame

 

//如果是EL,用BaseLayer的加权预测:

pcSliceHeader->setBasePredWeightTableFlag( true );

//否则,自己计算

m_pcSliceEncoder->xSetPredWeights( *pcSliceHeader, m_papcFrame[uiFrameIdInGOP], rcControlData.getRefListStruct() );

pcSliceHeader->setBasePredWeightTableFlag( false );

 

 

//SEIHRDRedundantPictureLARDOSIP,未关注

 

xEncodeLayerRepresentation( rcOutputList, rcControlData,  pcOrgFrame, pcFrame, pcResidualLF, pcResidualILPred, pcPredSignal, 

                         uiBits, cPicOutputDataList, uiFrameIdInGOP, ePicType )        //后面分析

 

m_pcSubband->copy( pcFrame, ePicType ) )    //保存去块滤波之前的重建帧

 

//SEIRateControlRedPic相关,未关注

 

//如果是增强层

m_pcSliceEncoder->updateBaseLayerResidual( rcControlData, m_uiFrameWidthInMb );

    pcMbDataCtrl->initSlice( rcSliceHeader, DECODE_PROCESS, false, NULL )     //初始化宏块控制器

//对每个宏块

       pcMbDataCtrl ->initMb( pcMbDataAccess,     uiMbY, uiMbX )

       pcBaseLayerCtrl ->initMb ( pcMbDataAccessBase, uiMbY, uiMbX )

       //如果该宏块不用ResidualPred,清除该BL对应的Residual宏块 (rcControlm_pcBaseLayerSbb,即LayerEncoderm_pcBaseLayerResidual)

 

//去块滤波

m_pcLoopFilter->process( *pcSliceHeader, pcFrame, pcResidualLF, pcMbDataCtrl, 0, rcControlData.getSpatialScalability() )

注意:滤波的仍然是pcFramepcResidualLF只是用来计算CBP!!!!

 

输出PSNR等信息

xClearBufferExtensions()  //清除m_papcFrame[]m_papcELFrame[]m_pcSubbandm_pcResidualLF

//m_pcResidualILPredm_apcBaseFrame[X]1/2像素缓存 注意,是整个GOP

更新m_uiLastCodedFrameIdInGOP = uiFrameIdInGOP  m_uiLastCodedTemporalId   = uiTemporalId;

 

//如果是GOP最后一帧

m_pcAnchorFrameReconstructed拷贝该帧内容èm_papcFrame[ m_uiGOPSize ]

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值