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_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的第一帧(因为是栈)
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信息
由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 ) ); //再设置一遍,觉得多余
//如果分辨率改变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
//如果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 ]