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 ×××××
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_papcFrame从m_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()
AU的NalUnit队列
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
//由BaseLayer的Size信息更新本层的ESS信息
m_pcResizeParameters->updatePicParameters( m_papcFrame[ uiFrameIdInGOP ]->getPicParameters( ePicType ) );
设置Inter-layer 预测的参数 (BaseMode、Motion、Residual)
检查Level的约束
rcControlData.setBaseLayer( uiBaseLayerId ); //最后才确定BaseLayer的Id
设置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 )
//对LayerEncoder的m_acRefPicListFrameId_LX[ uiFrameIdInGOP ]队列每一帧
pcFrame = xGetRefFrame( uiFrmId, eRefListUsage ); //获得对应index的参考帧
//如果是RefBasePic:m_apcBaseFrame[ 0/1 ] ,否则m_papcELFrame(MGS)或m_papcFrame
//如果没有extend,还要xFillAndUpsampleFrame() / xFillAndExtendFrame()
rcRefListX.add( pcFrame->getPic( FRAME ) //加入队列
pcFrame->setLongTerm( m_bUseLongTermPics );
// uiFrameIdCol是最后加入RCList1的FrameId,即List1的第一帧(因为是栈)
如果是KeyPicture或者使用Std(MGScontrol=0):ME和MC队列都用RC队列------同层的参考帧
MGScontrol=1:ME用EL的队列,MC用RC(std)的队列
MGScontrol=2:ME和MC都用EL的队列
SliceHeader写的是Std的RC队列
//当是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_pcBaseLayerSbb、m_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 ); //同分辨率的EL,TCoeff=FALSE则为真
m_pcBaseLayerCtrl->initSlice( *pcSliceHeader, PRE_PROCESS, false, NULL )
把当前SliceHeader给了m_pcBaseLayerCtrl的m_pcSliceHeader
m_pcBaseLayerCtrl->upsampleMotion(…)
//对BaseLayer每个宏块
cMotionUpsampling.resample( iMbX, iMbY ) MotionUpsampling
xInitMb ( iMbXCurr, iMbYCurr ) //设置宏块大小、块模式、每块ref_idx等信息
xSetPartIdcArray()
//对16个4x4块
xGetRefLayerPartIdc( ( iX << 2 ) + 1, ( iY << 2 ) + 1, m_aaiPartIdc[iX][iY] ) //得到该块在参考层的4x4块id
xGetRefLayerMb(iXInsideCurrMb,iYInsideCurrMb,iBaseMbIdx,iXInsideBaseMb, iYInsideBaseMb )
//标准G6.1过程 得到该4x4块在参考层的宏块id和在宏块内的坐标
//如果是InCropWindow且不是INTRA_BL,对每个List
xGetRefIdxAndInitialMvPred( ListIdx( iListIdx ) )
//对每个4x4块
xGetInitialBaseRefIdxAndMv() //获得BaseLayer的MotionData和Mv,修正Mv
//ref_idx和Mv保存在m_aaaiRefIdx / m_aaacMv
//对每个8x8块
xDeriveBlockModeAndUpdateMv( iB8x8Idx ) //根据宏块分区更新Mv
xDeriveMbMode () //由BaseMbMode检查ref_idx和Mv,并得到MbMode
xDeriveFwdBwd ()
xSetInterIntraIdc () //设置m_aabBaseIntra[][]
//如果是InCropWindow,则检查分区方式、ref_idx和Mv是否正确,设置m_bResPredSafe
xSetResPredSafeFlag ()
//从BaseLayer得到MbMode、分区方式、ref_idx和Mv
xSetPredMbData()
//如果是INTRA_BL或非InCropWindow,则不得到Motion信息
//否则拷贝每个List的每个8x8块的ref_idx和每个4x4块的Mv
InCropWindow的话,MbMode、FwdBwd等等也拷贝
//SNR伸缩------SCoeff/TCoeff 且是InCropWindow
rcMbData.copyTCoeffs ( rcMbDataBase ); //拷贝BL的变换系数、CBP、QP、TransformSize
拷贝BLSkipFlag
IntraBL
TCoeffPred
拷贝BL的MbMode
拷贝IntraPredMode
CBP、QP、TransformSize
//如果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
//BL的LayerEncoder的m_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 pcTempBaseFrame和pcTempFrame辅助采样
rcControlData保存了m_pcBaseLayerResidual和m_pcBaseLayerFrame
//如果是EL,用BaseLayer的加权预测:
pcSliceHeader->setBasePredWeightTableFlag( true );
//否则,自己计算
m_pcSliceEncoder->xSetPredWeights( *pcSliceHeader, m_papcFrame[uiFrameIdInGOP], rcControlData.getRefListStruct() );
pcSliceHeader->setBasePredWeightTableFlag( false );
//SEI、HRD、RedundantPicture、LARDO、SIP,未关注
xEncodeLayerRepresentation( rcOutputList, rcControlData, pcOrgFrame, pcFrame, pcResidualLF, pcResidualILPred, pcPredSignal,
uiBits, cPicOutputDataList, uiFrameIdInGOP, ePicType ) //后面分析
m_pcSubband->copy( pcFrame, ePicType ) ) //保存去块滤波之前的重建帧
//SEI、RateControl、RedPic相关,未关注
//如果是增强层
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宏块 (rcControl的m_pcBaseLayerSbb,即LayerEncoder的m_pcBaseLayerResidual)
//去块滤波
m_pcLoopFilter->process( *pcSliceHeader, pcFrame, pcResidualLF, pcMbDataCtrl, 0, rcControlData.getSpatialScalability() )
注意:滤波的仍然是pcFrame,pcResidualLF只是用来计算CBP!!!!
输出PSNR等信息
xClearBufferExtensions() //清除m_papcFrame[]、m_papcELFrame[]、m_pcSubband、m_pcResidualLF、
//m_pcResidualILPred和m_apcBaseFrame[X]的1/2像素缓存 ,注意,是整个GOP的
更新m_uiLastCodedFrameIdInGOP = uiFrameIdInGOP和 m_uiLastCodedTemporalId = uiTemporalId;
//如果是GOP最后一帧
m_pcAnchorFrameReconstructed拷贝该帧内容èm_papcFrame[ m_uiGOPSize ]