HEVC中类,对象和指向对象的指针

来源:互联网 发布:人工智能能否超越人脑 编辑:程序博客网 时间:2024/06/06 05:43

HEVC代码中定义了几十种类,这些类的对象一般只实例化一次,在编码过程中都是通过指针来访问实例化的对象。
唯一以类名实例化的对象:cTAppEncTop

main (){ TAppEncTop   cTAppEncTop;}

这个对象被建立时,它的所有数据成员也被建立,并实例化(占据存储空间)

class TAppEncTop{    TEncTop  m_cTEncTop}

而m_cTEncTop这个数据成员,本身作为一个对象,它自己的数据成员也被建立并实例化

class TEncTop : public TEncCfg{private:  // picture  Int                     m_iPOCLast;                     ///< time index (POC)  Int                     m_iNumPicRcvd;                  ///< number of received pictures  UInt                    m_uiNumAllPicCoded;             ///< number of coded pictures  TComList<TComPic*>      m_cListPic;                     ///< dynamic list of pictures  // encoder search  TEncSearch              m_cSearch;                      ///< encoder search class  //TEncEntropy*            m_pcEntropyCoder;                     ///< entropy encoder  TEncCavlc*              m_pcCavlcCoder;                       ///< CAVLC encoder    // coding tool  TComTrQuant             m_cTrQuant;                     ///< transform & quantization class  TComLoopFilter          m_cLoopFilter;                  ///< deblocking filter class  TEncSampleAdaptiveOffset m_cEncSAO;                     ///< sample adaptive offset class  TEncEntropy             m_cEntropyCoder;                ///< entropy encoder  TEncCavlc               m_cCavlcCoder;                  ///< CAVLC encoder  TEncSbac                m_cSbacCoder;                   ///< SBAC encoder  TEncBinCABAC            m_cBinCoderCABAC;               ///< bin coder CABAC  TEncSbac*               m_pcSbacCoders;                 ///< SBAC encoders (to encode substreams )  TEncBinCABAC*           m_pcBinCoderCABACs;             ///< bin coders CABAC (one per substream)  // processing unit  TEncGOP                 m_cGOPEncoder;                  ///< GOP encoder  TEncSlice               m_cSliceEncoder;                ///< slice encoder  TEncCu                  m_cCuEncoder;                   ///< CU encoder  // SPS  TComSPS                 m_cSPS;                         ///< SPS  TComPPS                 m_cPPS;                         ///< PPS  // RD cost computation  TComBitCounter          m_cBitCounter;                  ///< bit counter for RD optimization  TComRdCost              m_cRdCost;                      ///< RD cost computation class  TEncSbac***             m_pppcRDSbacCoder;              ///< temporal storage for RD computation  TEncSbac                m_cRDGoOnSbacCoder;             ///< going on SBAC model for RD stage  TEncBinCABACCounter***  m_pppcBinCoderCABAC;            ///< temporal CABAC state storage for RD computation  TEncBinCABACCounter     m_cRDGoOnBinCoderCABAC;         ///< going on bin coder CABAC for RD stage  Int                     m_iNumSubstreams;                ///< # of top-level elements allocated.  TComBitCounter*         m_pcBitCounters;                 ///< bit counters for RD optimization per substream  TComRdCost*             m_pcRdCosts;                     ///< RD cost computation class per substream  TEncSbac****            m_ppppcRDSbacCoders;             ///< temporal storage for RD computation per substream  TEncSbac*               m_pcRDGoOnSbacCoders;            ///< going on SBAC model for RD stage per substream  TEncBinCABAC****        m_ppppcBinCodersCABAC;           ///< temporal CABAC state storage for RD computation per substream  TEncBinCABAC*           m_pcRDGoOnBinCodersCABAC;        ///< going on bin coder CABAC for RD stage per substream  // quality control  TEncPreanalyzer         m_cPreanalyzer;                 ///< image characteristics analyzer for TM5-step3-like adaptive QP  TComScalingList         m_scalingList;                 ///< quantization matrix information  TEncRateCtrl            m_cRateCtrl;                    ///< Rate control class

到此为止,在整个编码过程中使用的GOP编码器,slice编码器,CU编码器,以及各种RDO编码器,熵编码器等等,这些类的对象都建立完毕,且只建立了唯一的对象,在后续编码过程中,均是通过指针访问这些对象实现不同的编码功能。
这里面有一个m_cListPic对象,它是一个list队列,队列中的每个元素都是指向TComPic类型的对象的指针

class TComPic{    TComPicYuv*         m_apcPicYuv[2];    TComPicYuv*         m_pcPicYuvPred;    TComPicYuv*         m_pcPicYuvResi;}

TComPic类和TComPicYuv类有非常紧密的联系。它包含了3个重要对象:

  • m_apcPicYuv[2]。这是一个数组,数组中每个元素都是指向TComPicYuv类型对象的指针
  • m_pcPicYuvPred。这是一个指针,该成员变量的值是一个地址
  • m_pcPicYuvResi。这也是一个指针,指向一个TComPicYuv类型的对象,该成员变量的值也是一个地址
    注意:区分指针型成员变量和对象类成员变量
    再来看TComPicYuv这个类的定义:
class TComPicYuv{private:  // ------------------------------------------------------------------------------------------------  //  YUV buffer  // ------------------------------------------------------------------------------------------------  Pel*  m_apiPicBufY;           ///< Buffer (including margin)  Pel*  m_apiPicBufU;  Pel*  m_apiPicBufV;  Pel*  m_piPicOrgY;            ///< m_apiPicBufY + m_iMarginLuma*getStride() + m_iMarginLuma  Pel*  m_piPicOrgU;  Pel*  m_piPicOrgV;  // ------------------------------------------------------------------------------------------------  //  Parameter for general YUV buffer usage  // ------------------------------------------------------------------------------------------------  Int   m_iPicWidth;            ///< Width of picture  Int   m_iPicHeight;           ///< Height of picture  Int   m_iCuWidth;             ///< Width of Coding Unit (CU)  Int   m_iCuHeight;            ///< Height of Coding Unit (CU)  Int*  m_cuOffsetY;  Int*  m_cuOffsetC;  Int*  m_buOffsetY;  Int*  m_buOffsetC;  Int   m_iLumaMarginX;  Int   m_iLumaMarginY;  Int   m_iChromaMarginX;  Int   m_iChromaMarginY;  Bool  m_bIsBorderExtended;

这个类保存了YUV像素的值,在TAppEncTop::encode()中,建立该类型的一个对象,并且在每读入一帧后,对该对象保存的YUV值进行修改

TAppEncTop::encode(){  TComPicYuv*       pcPicYuvOrg = new TComPicYuv;   //新建一个指针,并开辟空间  TComPicYuv*       pcPicYuvRec = NULL;  ...  pcPicYuvOrg->create(m_iSourceWidth, m_iSourceHeight, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxCUDepth);  //完善视频尺寸,LCU尺寸信息  while (!bos)  {  //get buffers  xGetBuffer(pcPicYuvRec);  //read input YUV file  m_cTVideoIOYuvInputFile.read(pcPicYuvOrg, m_aiPad);//从视频输入流读取Yuv数据保存在pcPicYuvOrg中  m_cTEncTop.encode(bEos, flush ? 0 : pcPicYuvOrg, m_cListPicYuvRec, outputAccessUnits, iNumEncoded)  }}

可以看到,pcPicYuvOrg这个指针的空间开辟是在while()之前,而在while(!bos)循环中,每读入一帧,都将YUV数据写进pcPicYuvOrg所指的对象中,这样岂不是前一帧的YUV数据会被覆盖?难道只能保存一帧的YUV数据吗?事实不是这样的!在执行m_cTEncTop.encode()函数时,将当前读入的YUV数据赋值给TEncTop的一个成员 m_cListPic.

Void TEncTop::encode(Bool flush, TComPicYuv* pcPicYuvOrg, TComList<TComPicYuv*>& rcListPicYuvRecOut, std::list<AccessUnit>& accessUnitsOut, Int& iNumEncoded){    ...    TComPic* pcPicCurr = NULL;    xGetNewPicBuffer( pcPicCurr );  //pcPicCurr申请地址,并放在m_cListPic队列中。TComPic->create()函数中,为成员变量m_apcPicYuv[0],m_apcPicYuv[1]申请空间,并初始化相关信息    pcPicYuvOrg->copyToPic( pcPicCurr->getPicYuvOrg() );    ...    compressGOP(m_cListPic);}

可以看到,先执行xGetNewPicBuffer(),为pcPicCurr指定位于m_cListPic中的地址,然后执行copyToPic()函数,将临时保存YUV数据赋值给pcPicCurr。(pcPicCurr->getPicYuvOrg()返回的是m_apcPicYuv[0])

Void  TComPicYuv::copyToPic (TComPicYuv*  pcPicYuvDst){  assert( m_iPicWidth  == pcPicYuvDst->getWidth()  );  assert( m_iPicHeight == pcPicYuvDst->getHeight() );  ::memcpy ( pcPicYuvDst->getBufY(), m_apiPicBufY, sizeof (Pel) * ( m_iPicWidth       + (m_iLumaMarginX   << 1)) * ( m_iPicHeight       + (m_iLumaMarginY   << 1)) );  ::memcpy ( pcPicYuvDst->getBufU(), m_apiPicBufU, sizeof (Pel) * ((m_iPicWidth >> 1) + (m_iChromaMarginX << 1)) * ((m_iPicHeight >> 1) + (m_iChromaMarginY << 1)) );  ::memcpy ( pcPicYuvDst->getBufV(), m_apiPicBufV, sizeof (Pel) * ((m_iPicWidth >> 1) + (m_iChromaMarginX << 1)) * ((m_iPicHeight >> 1) + (m_iChromaMarginY << 1)) );  return;}

通过copyToPic()操作,将当前读入帧的YUV信息保存在m_ListPic队列的元素中,元素pcPicCurr()指向一段地址空间,并且其数据成员m_apcPicYuv[0]也指向一段空间。

原创粉丝点击