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

    技术2022-05-20  44

    main()         // 主函数

      //H264AVCEncoderTest*  pcH264AVCEncoderTest分配空间,后面函数用它调用

      H264AVCEncoderTest::create()

     

      //初始化pcH264AVCEncoderTest的成员,主要是编码器的参数配置

      pcH264AVCEncoderTest->init()

        //EncoderCodingParameter* m_pcEncoderCodingParameter分配空间

    //它是H264AVCEncoderTest *pcH264AVCEncoderTest的成员

    EncoderCodingParameter::create( m_pcEncoderCodingParameter )    //编码参数

     

    //解析输入命令行,并把相应参数写入EncoderCodingParameter的基类CodingParameter的成员中

    m_pcEncoderCodingParameter->init()

          //读取配置文件

      xReadFromFile( cFilename, rcBitstreamFile )

    fopen( rcFilename.c_str(), "r");              encoder.cfg

    //先创建每个参数

    m_pEncoderLines[uiParLnCount++] = new EncoderConfigLineXXX

    //从配置文件里读一行,重复直到文件末尾

    xReadLine( f, acTags )

    //查找读到的参数对应的m_pEncoderLines,更新值

    fclose( f );

     

    //从上面的配置文件读到的参数中得到有几层,和每层配置文件路径

    //对每一层

      setDependencyId(ui);     //设置Did

      //读取每一层的配置文件  读到如下类中

    //EncoderCodingParameter::LayerParameters m_acLayerParameters[n]

      xReadLayerFromFile( acLayerConfigName[ui], getLayerParameters(ui) )

    //打开配置文件         layerX.cfg

     

    //分配空间并初始化参数m_pLayerLines[]  ,也是CodingParameter成员

    //读取配置文件每行,并更新对应m_pLayerLines的值

     

    //初始化ScalingList

    xReadScalMat()

     

    //设置输入输出文件路径

    rcLayer.setInputFilename     ( (Char*)cInputFilename.c_str() );

    rcLayer.setOutputFilename    ( (Char*)cOutputFilename.c_str() );

     

    //初始化每个LayerParameters::ResizeParameters m_cResizeParameters

     

    //读取SliceGroup的配置文件

    xReadSliceGroupCfg( rcLayer)

    //读取ROI配置文件

    xReadROICfg( rcLayer)

    //关闭配置文件

      //设置CGS/MGSDependency_IdQuality_id

      //BaseLayer更新当前LayerResizeParameter----------ESS

         

          //对每一层 rcLayer = m_pcEncoderCodingParameter->getLayerParameters( uiLayer );

            //创建并打开重建输出文件

            WriteYuvToFile::create( m_apcWriteYuv[uiLayer] )

            m_apcWriteYuv[uiLayer]->init( rcLayer.getOutputFilename() )

     

            //创建并打开读入的视频文件

            ReadYuvFile   ::create( m_apcReadYuv [uiLayer] )

            m_apcReadYuv[uiLayer]->init()

     

            //创建并打开码流文件

            WriteBitstreamToFile::create   ( m_pcWriteBitstreamToFile )

            m_pcWriteBitstreamToFile->init ( m_cEncoderIoParameter.cBitstreamFilename )

            

    注意:

    以上三个文件都是H264AVCEncoderTest类的成员

      WriteBitstreamToFile*         m_pcWriteBitstreamToFile;

      WriteYuvToFile*               m_apcWriteYuv           [MAX_LAYERS];

      ReadYuvFile*                  m_apcReadYuv            [MAX_LAYERS];

     

    也用到了辅助IO的成员

    EncoderIoParameter            m_cEncoderIoParameter; 

     

          //给编码器分配空间:它是H264AVCEncoderTest *pcH264AVCEncoderTest的成员

          h264::CreaterH264AVCEncoder::create( m_pcH264AVCEncoder )

       ParameterSetMng             ::create( m_pcParameterSetMng )

       BitWriteBuffer              ::create( m_pcBitWriteBuffer )

       BitCounter                  ::create( m_pcBitCounter )

       NalUnitEncoder              ::create( m_pcNalUnitEncoder)

       SliceEncoder                ::create( m_pcSliceEncoder )

       UvlcWriter                  ::create( m_pcUvlcWriter )

       UvlcWriter                  ::create( m_pcUvlcTester, false )

       CabacWriter                 ::create( m_pcCabacWriter )

       MbCoder                     ::create( m_pcMbCoder )

       MbEncoder                   ::create( m_pcMbEncoder )

       LoopFilter                  ::create( m_pcLoopFilter )

       IntraPredictionSearch       ::create( m_pcIntraPrediction )

       MotionEstimationQuarterPel  ::create( m_pcMotionEstimation )

       H264AVCEncoder              ::create( m_pcH264AVCEncoder )

       ControlMngH264AVCEncoder    ::create( m_pcControlMng )

       ReconstructionBypass        ::create( m_pcReconstructionBypass )

       QuarterPelFilter            ::create( m_pcQuarterPelFilter )

       Transform                   ::create( m_pcTransform )

       SampleWeighting             ::create( m_pcSampleWeighting )

       XDistortion                 ::create( m_pcXDistortion )

       PicEncoder                  ::create( m_pcPicEncoder )

    //每一层的编码器

      for( UInt uiLayer = 0; uiLayer < MAX_LAYERS; uiLayer++ )

      {

         LayerEncoder  ::create( m_apcLayerEncoder        [uiLayer] )

         PocCalculator ::create( m_apcPocCalculator       [uiLayer] )

         YuvBufferCtrl ::create( m_apcYuvFullPelBufferCtrl[uiLayer] )

         YuvBufferCtrl ::create( m_apcYuvHalfPelBufferCtrl[uiLayer] )

      }

          //设置NAL UNIT起始码m_aucStartCodeBuffer[],绑定到H264AVCEncoderTest::BinData  m_cBinDataStartCode;

      //进行编码

    pcH264AVCEncoderTest->go ()

        //初始化编码器参数  h264::CreaterH264AVCEncoder*  m_pcH264AVCEncoder;  H264AVCEncoderTest成员

    m_pcH264AVCEncoder->init( m_pcEncoderCodingParameter )

    /*

    几个参数关系

    1.       H264AVCEncoderTest的成员CreaterH264AVCEncoder*  m_pcH264AVCEncoder调用init

    2.  初始化H264AVCEncoderTest的成员EncoderCodingParameter * m_pcEncoderCodingParameter

    3.  CreaterH264AVCEncoder的成员CodingParameter*  m_pcCodingParameter

    被赋值传入的参数m_pcEncoderCodingParameter

    */

     

    RateDistortion::create( m_pcRateDistortion )   //给率失真计算类分配空间   RateDistortion

    m_pcBitWriteBuffer ->init()    //初始化写Packet/比特流的类           BitWriteBuffer

    m_pcBitCounter ->init()       //初始化计算比特数类                BitCounter

    m_pcXDistortion ->init()      //初始化计算失真所需的参数 (块行数/列数/Dist计算函数指针)XDistortion

    m_pcSampleWeighting ->init()   //初始化加权函数                  SampleWeighting

     

    //初始化写NalUnit的类 NalUnitEncoder

    m_pcNalUnitEncoder->init( m_pcBitWriteBuffer, m_pcUvlcWriter, m_pcUvlcTester )

    m_pcUvlcWriter ->init( m_pcBitWriteBuffer )    //关联比特流缓存和写Uvlc的类  UvlcWriter

    m_pcUvlcTester ->init( m_pcBitCounter )       //关联比特计数和写Uvlc的类    UvlcWriter

    m_pcCabacWriter ->init( m_pcBitWriteBuffer )   //初始化Cabac的缓存       CabacWriter   CabacEncoder

    m_pcParameterSetMng ->init()             //空函数

    m_pcSliceEncoder->init()  //关联MbEncoderMbCoderControlMngH264AVCEncoderCodingParameter

    PocCalculatorTransform Slice编码器        SliceEncoder

    m_pcReconstructionBypass ->init()          //空函数  

    m_pcLoopFilter->init( m_pcControlMng, m_pcReconstructionBypass, true )   //关联  ControlMngH264AVCEncoder

                                                             ReconstructionBypass给去块滤波器 LoopFilter

    m_pcQuarterPelFilter->init()   //分配1/4像素插值滤波器         QuarterPelFilter

    m_pcMbEncoder->init()       //关联TransformIntraPredictionSearchMotionEstimationCodingParameter

                               RateDistortionXDistortion给宏块编码器    MbEncoder

    m_pcMotionEstimation ->init()                  MotionEstimation

       MotionCompensation::init()   //初始化MC相关—1/4插值滤波、变换、加权

       //设置计算失真、MV搜索参数

       MotionEstimationCost::xInit()   //设置RD相关

       //设置跟搜索范围搜索深度有关参数

    // spiral search参数

     

    m_pcControlMng->init()     //分配上面所有的编码过程类到ControlMngH264AVCEncoder类中,集中管理

                             //包括每层的LayerEncoderPocCalculatorYuvBufferCtrl

     

    m_pcPicEncoder->init()      //初始化AVC编码器

    m_pcH264AVCEncoder ->init()   //初始化SVC编码器 分配LayerEncoderParameterSetMngPocCalculator

    // NalUnitEncoderControlMngIfCodingParameter

                                //初始化LayerEncoder*  m_apcLayerEncoder[MAX_LAYERS]

    AccessUnitDataList  m_cAccessUnitDataList;    H264AVCEncoder

     

    //对每层

      m_apcLayerEncoder[uiLayer]->init()        //初始化每层编码所需的参数

    //把配置文件读入的参数LayerParameter复制过来

    xInitCodingOrder()    // 初始化编码顺序和分层的对应关系

    //初始化如ESSLARDO等参数

     

    //计算每层采用LARDO的情况

     

    //Rate Control相关初始化,与GOP有关

       

    //SPSPPS

    参数:

    UChar   aucParameterSetBuffer[1000] 作为缓存

    BinData  cBinData  绑定上面的缓存

    ExtBinDataAccessor cExtBinDataAccessor   操纵上面的cBinData

    m_pcH264AVCEncoder->writeParameterSets( &cExtBinDataAccessor, pcAVCSPS, bMoreSets )  CreaterH264AVCEncoder

      m_pcH264AVCEncoder->writeParameterSets( pcExtBinDataAccessor, rpcAVCSPS, rbMoreSets ) H264AVCEncoder

         //如果是第一次调用

        xInitParameterSets()

           //对每一层

             //设置基本参数

             SequenceParameterSet::create( pcSPS )     // 分配SPS空间

             PictureParameterSet ::create( pcPPS )       // 分配PPS空间

             //设置SPSPPSIDNalUnitType

         

    ParameterSetMng*  m_pcParameterSetMng有成员

      StatBuf<SequenceParameterSet*,2*NUM_SPS_IDS> m_cSPSBuf;   当前对应SPS_IDSPS

      StatBuf<PictureParameterSet*,256> m_cPPSBuf;                当前对应PPS_IDPPS

      std::list<SequenceParameterSet*>  m_cSPSList;   历史上的SPS存在此(和当前SPS_ID重合的)

      std::list<PictureParameterSet*>   m_cPPSList;    历史上的PPS存在此和当前PPS_ID重合的)

    调用store()函数将(ID)

    PPS =>m_cPPSBuf   而从m_cPPSBuf取出的PPS => m_cPPSList

    SPS =>m_cSPSBuf   而从m_cSPSBuf取出的SPS => m_cSPSList

             m_pcParameterSetMng->store( pcPPS )

    m_pcParameterSetMng->store( pcSPS )

     

    设置m_auiActiveSPSId[uiDQId] = SPS_ID

    每个QualityLayer都有一个m_auiActiveSPSId[uiDQId]

    m_pcParameterSetMng->setActiveSPS( pcSPS->getSeqParameterSetId(), uiDQId + ui );

     

    //设置SPS的内

    //设置subset SPS内容

    //设置PPS内容

     

    // 初始化每层与帧分辨率有关的参数

    m_pcControlMng->initParameterSets( *pcSPS, *pcPPS )     ControlMngH264AVCEncoder

               m_apcYuvFullPelBufferCtrl[uiLayer]->initSPS( uiAllocY, uiAllocX, YUV_Y_MARGIN, YUV_X_MARGIN)

               m_apcYuvHalfPelBufferCtrl[uiLayer]->initSPS( uiAllocY, uiAllocX, YUV_Y_MARGIN, YUV_X_MARGIN, 1 )

               m_apcLayerEncoder      [uiLayer]->initParameterSets( rcSPS, rcPPS )

     

                  //ParameterSetMng类中的SPSPPS缓存m_cSPSBufm_cPPSBuf读取并保存到

    //std::list<SequenceParameterSet*>  m_cUnWrittenSPS   std::list<PictureParameterSet*>   m_cUnWrittenPPS;

             m_pcParameterSetMng->setParamterSetList( m_cUnWrittenSPS, m_cUnWrittenPPS )

       

    // SEI相关信息

     

    //m_cUnWrittenSPSm_cUnWrittenPPS非空,则

           m_pcNalUnitEncoder->initNalUnit( pcExtBinDataAccessor )     //初始化写Nalunit的类

             m_pcBitWriteBuffer->initPacket( (UInt*)(m_pucTempBuffer), m_uiPacketLength-1 )   //初始化写比特流的类

           //读取SPS/PPS

           m_pcNalUnitEncoder->write( rcSPS )

             rcSPS.write( m_pcHeaderSymbolWriteIf )   //m_pcHeaderSymbolWriteIfNalUnit

           m_pcNalUnitEncoder->closeNalUnit( uiBits )

             xWriteTrailingBits()          //1000补齐

             m_pcBitWriteBuffer->flushBuffer()   //把拖尾等最后的数据写入并计算bit

             convertRBSPToPayload(…)      //加上0x03

     

    m_pcWriteBitstreamToFile->writePacket ( &m_cBinDataStartCode )    //先写starcode  0x00000001  区分NALUNIT

    m_pcWriteBitstreamToFile->writePacket ( &cExtBinDataAccessor )     //再写实际NAL内容

     

    //计算每层图像宽高、Crop信息和lumachromaOffset

     

    //对每个Frame ==============================START===============================

      //对每一层 XXXXXXXXXXXXXXX START

       本函数的重要参数:在H264AVCEndoderTest::go()函数里

    PicBuffer*              apcOriginalPicBuffer    [MAX_LAYERS];      //原始图像list

    PicBuffer*              apcReconstructPicBuffer [MAX_LAYERS];      //重建图像list

    PicBufferList           acPicBufferOutputList   [MAX_LAYERS];       //输出图像list  

    PicBufferList           acPicBufferUnusedList   [MAX_LAYERS];

    ExtBinDataAccessorList  cOutExtBinDataAccessorList;          //输出NalUnitlist

        //PicBufferList  m_acUnusedPicBufferList [MAX_LAYERS] 中弹出一个PicBuffer

        //并存入PicBufferList  m_acActivePicBufferList [MAX_LAYERS];

            xGetNewPicBuffer( apcReconstructPicBuffer [uiLayer], uiLayer, auiPicSize[uiLayer] )   //重建帧

            xGetNewPicBuffer( apcOriginalPicBuffer    [uiLayer], uiLayer, auiPicSize[uiLayer] )   //原始帧

            m_apcReadYuv[uiLayer]->readFrame(…)     // 读取一帧到apcOriginalPicBuffer [uiLayer]

          XXXXXXXXXXXXXXX END

         

          //处理一帧,所有Layer都处理,数据写入cOutExtBinDataAccessorList    CreaterH264AVCEncoder调用

          m_pcH264AVCEncoder->process(cOutExtBinDataAccessorList,apcOriginalPicBuffer,

    apcReconstructPicBuffer, acPicBufferOutputList, acPicBufferUnusedList )

            àm_pcH264AVCEncoder->process( rcExtBinDataAccessorList,               H264AVCEncoder调用

                                         apcOriginalPicBuffer,

                                         apcReconstructPicBuffer,

                                         apcPicBufferOutputList,

                                         apcPicBufferUnusedList )

     

          xWrite  ( cOutExtBinDataAccessorList, uiBytesUsed )    //把编码一帧后的NALUNIT写到比特流中

            //重复,直到cOutExtBinDataAccessorList为空

            m_pcWriteBitstreamToFile->writePacket( &m_cBinDataStartCode )   //写起始码

            m_pcWriteBitstreamToFile->writePacket( rcList.front() )            //NalUnit

           

          //对每层

            xWrite  ( acPicBufferOutputList[uiLayer], uiLayer )    //把输出图像(重建文件)写到文件中

              //list中弹出一个图像

    m_apcWriteYuv[uiLayer]->writeFrame()

                m_cFile.write( pucSrc, uiWidth )              //重复调用此函数写重建图像

     

            xRelease( acPicBufferUnusedList[uiLayer], uiLayer )

              xRemovePicBuffer( rcPicBufferList, uiLayer )       //删除未使用的图像

                //m_acActivePicBufferList中找到acPicBufferUnusedList中每一帧

                //m_acActivePicBufferList中删除,添加到m_acUnusedPicBufferList

    ==============================END===============================

     

    m_pcH264AVCEncoder->finish(…)

          m_pcH264AVCEncoder->finish(…)

            //把不足GOP数量剩下的帧进行编码

            xProcessGOP( apcPicBufferOutputList, apcPicBufferUnusedList )

     

            //AccessUnitDataList m_cAccessUnitDataList的成员std::list<AccessUnitData>m_cAccessUnitDataList

    //取出编码后的NalUnitcOutExtBinDataAccessorList

            m_cAccessUnitDataList.emptyNALULists( rcExtBinDataAccessorList )       

    m_apcLayerEncoder[uiLayer]->finish()     //输出每层的编码信息,如比特数和PSNR

     

            xWrite  ( cOutExtBinDataAccessorList, uiWrittenBytes )     //cOutExtBinDataAccessorList中的Nal写到比特流

    //对每一层

    xWrite  ( acPicBufferOutputList[uiLayer], uiLayer )    //把输出图像(重建文件)写到文件中

              xRelease( acPicBufferUnusedList[uiLayer], uiLayer )    //删除未使用的图像

     

            //SEI信息

            m_pcH264AVCEncoder->writeParameterSets( &cExtBinDataAccessor, pcAVCSPS, bMoreSets )

            m_pcWriteBitstreamToFile->writePacket       ( &m_cBinDataStartCode )

                       m_pcWriteBitstreamToFile->writePacket       ( &cExtBinDataAccessor )

     

            m_pcWriteBitstreamToFile->uninit()          //关闭比特流文件

            m_pcWriteBitstreamToFile->destroy()         //释放空间

     

            ScalableDealing()          //把临时的比特流文件转成Scalable比特流

     

      //结束函数

      pcH264AVCEncoderTest->destroy()

    //释放m_cBinDataStartCodem_pcH264AVCEncoder、读写文件、m_pcEncoderCodingParameter和一些List的空间

     

     


    最新回复(0)