文章目录
TEncTop.cpp
引言
TEncTop类是第二层编码类,也是执行实际编码计算工作的最顶层编码类。
Void TEncTop::encode是执行编码的入口函数,它主要实现为GOP压缩之前做一些准备工作,包括创建当前图像缓冲区、设定QP是否自适应、根据码率控制模式来确定是否需要先初始化GOP,然后调用TEncGop::compressGOP来压缩GOP。
Void TEncTop::encode
参数列表:
- flush:使编码器部分编码;
- pcPicYuvOrg、pcPicYuvTrueOrg:原始YUV图片;
- ipCS、snrCSC:色彩空间转换格式;
- rcListPicYuvRecOut:重建YUV图片列表;
- accessUnitOut:输出访问单元
- iNumEncoded:已编码图片数量
if (pcPicYuvOrg != NULL){//获取原始YUV图TComPic* pcPicCurr = NULL;//存放获取的图片缓存,主要用于更新缓存列表m_cListPicInt ppsID=-1; // 使用默认PPSidif (getWCGChromaQPControl().isEnabled())//如果启动宽色域色度QP控制{ppsID=getdQPs()[ m_iPOCLast+1 ];//设置PPSID}xGetNewPicBuffer( pcPicCurr, ppsID );//根据PPS获取新缓存pcPicYuvOrg->copyToPic( pcPicCurr->getPicYuvOrg() );//将原始未编码的YUV缓存赋值到pcPicCurr内部成员m_apcPicYuv[PIC_YUV_ORG]和m_apcPicYuv[PIC_YUV_TRUE_ORG]pcPicYuvTrueOrg->copyToPic( pcPicCurr->getPicYuvTrueOrg() );//是否自适应QP控制,默认不用,用时计算图像特征if ( getUseAdaptiveQP() ){m_cPreanalyzer.xPreanalyze( dynamic_cast<TEncPic*>( pcPicCurr ) );}}if ((m_iNumPicRcvd == 0) || (!flush && (m_iPOCLast != 0) && (m_iNumPicRcvd != m_iGOPSize) && (m_iGOPSize != 0)))//判断是否开始编码{iNumEncoded = 0;return;}//是否速率控制,默认不if ( m_RCEnableRateControl ){m_cRateCtrl.initRCGOP( m_iNumPicRcvd );}// 压缩GOP编码m_cGOPEncoder.compressGOP(m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut, accessUnitsOut, false, false, ipCSC, snrCSC, getOutputLogControl());if ( m_RCEnableRateControl ){m_cRateCtrl.destroyRCGOP();}iNumEncoded = m_iNumPicRcvd;m_iNumPicRcvd = 0;//接收图片数量m_uiNumAllPicCoded += iNumEncoded; //增加已编码数量
}
执行流程
实现细节
Class TEncTop
private:// pictureInt m_iPOCLast; ///< time index (POC)Int m_iNumPicRcvd; ///< number of received picturesUInt m_uiNumAllPicCoded; ///< number of coded picturesTComList<TComPic*> m_cListPic; ///< dynamic list of pictures// encoder searchTEncSearch m_cSearch; ///< 编码搜索类//TEncEntropy* m_pcEntropyCoder; ///< 熵编码TEncCavlc* m_pcCavlcCoder; ///< 变长编码// coding toolTComTrQuant m_cTrQuant; ///< 转换和量化类TComLoopFilter m_cLoopFilter; ///< 去方块滤波TEncSampleAdaptiveOffset m_cEncSAO; ///< SAOTEncEntropy m_cEntropyCoder; ///< 熵编码TEncCavlc m_cCavlcCoder; ///< 变长编码TEncSbac m_cSbacCoder; ///< 并行的CABAC编码TEncBinCABAC m_cBinCoderCABAC; ///< CABAC// processing unitTEncGOP m_cGOPEncoder; ///< GOP encoderTEncSlice m_cSliceEncoder; ///< slice encoderTEncCu m_cCuEncoder; ///< CU encoder// SPS、PPSParameterSetMap<TComSPS> m_spsMap; ///< SPS. This is the base value. This is copied to TComPicSymParameterSetMap<TComPPS> m_ppsMap; ///< PPS. This is the base value. This is copied to TComPicSym// RD cost computation码率失真计算TComRdCost m_cRdCost; ///< RD cost computation classTEncSbac*** m_pppcRDSbacCoder; ///< temporal storage for RD computationTEncSbac m_cRDGoOnSbacCoder; ///< going on SBAC model for RD stage
#if FAST_BIT_ESTTEncBinCABACCounter*** m_pppcBinCoderCABAC; ///< 用于RD计算的临时CABAC状态存储TEncBinCABACCounter m_cRDGoOnBinCoderCABAC; ///< going on bin coder CABAC for RD stage
#elseTEncBinCABAC*** m_pppcBinCoderCABAC; ///< temporal CABAC state storage for RD computationTEncBinCABAC m_cRDGoOnBinCoderCABAC; ///< going on bin coder CABAC for RD stage
#endif// quality controlTEncPreanalyzer m_cPreanalyzer; ///< image characteristics analyzer for TM5-step3-like adaptive QPTEncRateCtrl m_cRateCtrl; ///< Rate control classprotected:Void xGetNewPicBuffer ( TComPic*& rpcPic, Int ppsId ); ///< get picture buffer which will be processed. If ppsId<0, then the ppsMap will be queried for the first match.Void xInitVPS (TComVPS &vps, const TComSPS &sps); ///< initialize VPS from encoder optionsVoid xInitSPS (TComSPS &sps); ///< initialize SPS from encoder optionsVoid xInitPPS (TComPPS &pps, const TComSPS &sps); ///< initialize PPS from encoder optionsVoid xInitScalingLists (TComSPS &sps, TComPPS &pps); ///< initialize scaling listsVoid xInitHrdParameters(TComSPS &sps); ///< initialize HRD parametersVoid xInitPPSforTiles (TComPPS &pps);Void xInitRPS (TComSPS &sps, Bool isFieldCoding); ///< initialize PPS from encoder optionspublic:TEncTop();virtual ~TEncTop();Void create ();Void destroy ();Void init (Bool isFieldCoding);Void deletePicBuffer ();// 成员访问函数TComList<TComPic*>* getListPic () { return &m_cListPic; }TEncSearch* getPredSearch () { return &m_cSearch; }TComTrQuant* getTrQuant () { return &m_cTrQuant; }TComLoopFilter* getLoopFilter () { return &m_cLoopFilter; }TEncSampleAdaptiveOffset* getSAO () { return &m_cEncSAO; }TEncGOP* getGOPEncoder () { return &m_cGOPEncoder; }TEncSlice* getSliceEncoder () { return &m_cSliceEncoder; }TEncCu* getCuEncoder () { return &m_cCuEncoder; }TEncEntropy* getEntropyCoder () { return &m_cEntropyCoder; }TEncCavlc* getCavlcCoder () { return &m_cCavlcCoder; }TEncSbac* getSbacCoder () { return &m_cSbacCoder; }TEncBinCABAC* getBinCABAC () { return &m_cBinCoderCABAC; }TComRdCost* getRdCost () { return &m_cRdCost; }TEncSbac*** getRDSbacCoder () { return m_pppcRDSbacCoder; }TEncSbac* getRDGoOnSbacCoder () { return &m_cRDGoOnSbacCoder; }TEncRateCtrl* getRateCtrl () { return &m_cRateCtrl; }Void selectReferencePictureSet(TComSlice* slice, Int POCCurr, Int GOPid );Int getReferencePictureSetIdxForSOP(Int POCCurr, Int GOPid );Void setParamSetChanged(Int spsId, Int ppsId);Bool PPSNeedsWriting(Int ppsId);Bool SPSNeedsWriting(Int spsId);//编码函数///编码几个图片直到序列结束Void encode( Bool bEos,TComPicYuv* pcPicYuvOrg,TComPicYuv* pcPicYuvTrueOrg,const InputColourSpaceConversion ipCSC, const InputColourSpaceConversion snrCSC, // used for SNR calculations. Picture in original colour space.TComList<TComPicYuv*>& rcListPicYuvRecOut,std::list<AccessUnit>& accessUnitsOut, Int& iNumEncoded );/// encode several number of pictures until end-of-sequence场编码Void encode( Bool bEos, TComPicYuv* pcPicYuvOrg,TComPicYuv* pcPicYuvTrueOrg,const InputColourSpaceConversion ipCSC, const InputColourSpaceConversion snrCSC, // used for SNR calculations. Picture in original colour space.TComList<TComPicYuv*>& rcListPicYuvRecOut,std::list<AccessUnit>& accessUnitsOut, Int& iNumEncoded, Bool isTff);//输出日志TEncAnalyze::OutputLogControl getOutputLogControl() const{TEncAnalyze::OutputLogControl outputLogCtrl;outputLogCtrl.printFrameMSE=m_printFrameMSE;outputLogCtrl.printMSEBasedSNR=m_printMSEBasedSequencePSNR;outputLogCtrl.printMSSSIM=m_printMSSSIM;outputLogCtrl.printSequenceMSE=m_printSequenceMSE;outputLogCtrl.printXPSNR=m_bXPSNREnableFlag;outputLogCtrl.printHexPerPOCPSNRs=m_printHexPsnr;return outputLogCtrl;}Void printSummary(Bool isField){m_cGOPEncoder.printOutSummary (m_uiNumAllPicCoded, isField, getOutputLogControl(), m_spsMap.getFirstPS()->getBitDepths());}
Void TEncTop::xGetNewPicBuffer ( TComPic*& rpcPic, Int ppsId )
完成功能:根据ppsid获取缓冲图片;
rpcPic=0;// 此时,可以认为SPS和PPS是激活的——它们被复制到新的TComPic中。//1. 根据PSSID取PPS和SPSconst TComPPS *pPPS=(ppsId<0) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS(ppsId);assert (pPPS!=0);const TComPPS &pps=*pPPS;//根据获得的PSS取SPS参数集const TComSPS *pSPS=m_spsMap.getPS(pps.getSPSId());assert (pSPS!=0);const TComSPS &sps=*pSPS;//2. 根据POC重排TEncTop类的动态图像列表m_cListPic内部图片TComSlice::sortPicList(m_cListPic);//3. 如果缓冲列表的缓存数目已达到需要缓冲的最大数量要求,则使用一个其中缓存图片if (m_cListPic.size() >= (UInt)(m_iGOPSize + getMaxDecPicBuffering(MAX_TLAYER-1) + 2) ){TComList<TComPic*>::iterator iterPic = m_cListPic.begin();Int iSize = Int( m_cListPic.size() );for ( Int i = 0; i < iSize; i++ )//寻找有参考Slice的图片复制到rpcPic {rpcPic = *iterPic;if(rpcPic->getSlice(0)->isReferenced() == false){break;}iterPic++;}// 如果该图片的PPSID和现有的是相同的,我们将假定它自上次使用以来没有改变并返回旧的if (pps.getPPSId() == rpcPic->getPicSym()->getPPS().getPPSId()){
#if REDUCED_ENCODER_MEMORY //在需要减少编码内存量时释放它自身的重构数据类成员m_apcPicYuvv[PIC_YUV_REC]rpcPic->releaseAllReconstructionData();rpcPic->prepareForEncoderSourcePicYuv();
#endif}// 若ppsid不同则删除列表m_cListPic中对应的条目,重置rpcPic并在后面新建else{delete rpcPic;m_cListPic.erase(iterPic);rpcPic=0;}}//4. 根据现有的sps和pps创建一个图片,放入缓存列表m_cListPic,就像还没有达到3的最大缓冲状态时一样。if (rpcPic==0){if ( getUseAdaptiveQP() ){TEncPic* pcEPic = new TEncPic;
#if REDUCED_ENCODER_MEMORYpcEPic->create( sps, pps, pps.getMaxCuDQPDepth()+1);
#elsepcEPic->create( sps, pps, pps.getMaxCuDQPDepth()+1, false);
#endifrpcPic = pcEPic;}else{rpcPic = new TComPic;
#if REDUCED_ENCODER_MEMORYrpcPic->create( sps, pps, true, false );
#elserpcPic->create( sps, pps, false );
#endif}m_cListPic.pushBack( rpcPic );}//标记它未重建rpcPic->setReconMark (false);m_iPOCLast++;m_iNumPicRcvd++;//设置该图片的POC索引rpcPic->getSlice(0)->setPOC( m_iPOCLast );
#if !REDUCED_ENCODER_MEMORY//若要节省内存// 设置该图片边界扩展标志为否rpcPic->getPicYuvRec()->setBorderExtension(false);
#endif