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

本文详细解读了SVC视频编码的JSVM代码,从main()开始,涉及编码器创建、初始化、参数配置、码流及重建文件的读写,以及编码过程的实现。通过对H264AVCEncoderTest类的方法分析,揭示了SVC编码的内部工作机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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的空间

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值