HEVC熵解码代码分析—代码解码流程(2)

来源:互联网 发布:太阳线直销软件 编辑:程序博客网 时间:2024/05/23 16:54

虽然熵解码的过程并不是很复杂,但是因为涉及太多的文档和函数比较让人心烦,所以稍微进行一下整理

熵解码一般一开始就是需要对上下文模式进行一定得初始化

在HEVC中

因为是类结构,所以在声明对象的时候,基本就完成了一般的初始化工作,下面详细介绍一下:

在类TDecSbac当中包含所有的上下文模式,但是在HM中有两个对应的结构

 ContextModel         m_contextModels[MAX_NUM_CTX_MOD]; //<一共512个 元素  Int                  m_numContextModels;  ContextModel3DBuffer m_cCUSplitFlagSCModel;  ContextModel3DBuffer m_cCUSkipFlagSCModel;  ContextModel3DBuffer m_cCUMergeFlagExtSCModel;  ContextModel3DBuffer m_cCUMergeIdxExtSCModel;  ContextModel3DBuffer m_cCUPartSizeSCModel;  ContextModel3DBuffer m_cCUPredModeSCModel;  ContextModel3DBuffer m_cCUIntraPredSCModel;
ContextModel         m_contextModels[MAX_NUM_CTX_MOD];  HEVC一共有512个上下文模式

然后m_numContextModels 这个类成员变量用于记录每一个语法元素有多少的上下文模式

ContextModel3DBuffer类型对应的是每一个语法元素的上下文模式

m_numContextModels中比较重要的两个变量

UChar         m_ucState;        //<当前slice中对应的状态 stateUInt          m_binsCoded;      //<当前对应的bin的数量,具体还不是很清楚,后续继续解释

ContextModel3DBuffer

ContextModel* m_contextModel; ///< array of context models  const UInt    m_sizeX;        ///< X size of 3D buffer  const UInt    m_sizeXY;       ///< X times Y size of 3D buffer  const UInt    m_sizeXYZ;      ///< total size of 3D buffer

一共有512个上下文模式,在每一个3D模式中,ContextModel指向512中的模式,三个Size变量是对应在一个语法元素中模式有多少,

再通过具体偏移量得到对应的ContextModel


初始化:

在创建对象的时候就进行初始化

<span style="color:#ff0000;">ContextModel3DBuffer::ContextModel3DBuffer</span>( UInt uiSizeZ, UInt uiSizeY, UInt uiSizeX, ContextModel *basePtr, Int &count ): m_sizeX  ( uiSizeX ), m_sizeXY ( uiSizeX * uiSizeY ), m_sizeXYZ( uiSizeX * uiSizeY * uiSizeZ ){  // allocate 3D buffer  m_contextModel = basePtr;  count += m_sizeXYZ;}
<span style="color:#ff0000;">TDecSbac::TDecSbac()</span>// new structure here: m_pcBitstream                              ( 0 ), m_pcTDecBinIf                              ( NULL ), m_numContextModels                         ( 0 ), m_cCUSplitFlagSCModel                      ( 1,             1,                      NUM_SPLIT_FLAG_CTX                   , m_contextModels + m_numContextModels, m_numContextModels), m_cCUSkipFlagSCModel                       ( 1,             1,                      NUM_SKIP_FLAG_CTX                    , m_contextModels + m_numContextModels, m_numContextModels), m_cCUMergeFlagExtSCModel                   ( 1,             1,                      NUM_MERGE_FLAG_EXT_CTX               , m_contextModels + m_numContextModels, m_numContextModels), m_cCUMergeIdxExtSCModel                    ( 1,             1,                      NUM_MERGE_IDX_EXT_CTX                , m_contextModels + m_numContextModels, m_numContextModels), m_cCUPartSizeSCModel                       ( 1,             1,                      NUM_PART_SIZE_CTX                    , m_contextModels + m_numContextModels, m_numContextModels), m_cCUPredModeSCModel                       ( 1,             1,                      NUM_PRED_MODE_CTX                    , m_contextModels + m_numContextModels, m_numContextModels), m_cCUIntraPredSCModel                      ( 1,             1,                      NUM_ADI_CTX                          , m_contextModels + m_numContextModels, m_numContextModels), m_cCUChromaPredSCModel                     ( 1,             1,                      NUM_CHROMA_PRED_CTX                  , m_contextModels + m_numContextModels, m_numContextModels)

完成ContextModel3DBuffer模式中对应的ContextModel和每一个语法元素中包含的上下文模式的大小


下一步初始化是在一个Slice开始的时候进行初始化,这里的初始化,主要是初始化解码环境

主要是包括算数编码中的range,MPS等信息

函数入口:

Void TDecSlice::decompressSlice(TComInputBitstream** ppcSubstreams, TComPic* pcPic, TDecSbac* pcSbacDecoder)中的  m_pcEntropyDecoder->setEntropyDecoder ( pcSbacDecoder  );  //<多态信息中设置编码方式为CABAC  m_pcEntropyDecoder->setBitstream      ( ppcSubstreams[0] ); //<设置对应的码流信息  m_pcEntropyDecoder->resetEntropy      (pcSlice); //<初始化解码环境


在函数
<pre name="code" class="cpp">Void TDecSbac::resetEntropy(TComSlice* pSlice){  SliceType sliceType  = pSlice->getSliceType();  Int       qp         = pSlice->getSliceQp();  if (pSlice->getPPS()->getCabacInitPresentFlag() && pSlice->getCabacInitFlag())  //XT?  {    switch (sliceType)    {    case P_SLICE:           // change initialization table to B_SLICE initialization      sliceType = B_SLICE;      break;    case B_SLICE:           // change initialization table to P_SLICE initialization      sliceType = P_SLICE;      break;    default     :           // should not occur      assert(0);      break;    }  }  m_cCUSplitFlagSCModel.initBuffer                ( sliceType, qp, (UChar*)INIT_SPLIT_FLAG );  m_cCUSkipFlagSCModel.initBuffer                 ( sliceType, qp, (UChar*)INIT_SKIP_FLAG );  m_cCUMergeFlagExtSCModel.initBuffer             ( sliceType, qp, (UChar*)INIT_MERGE_FLAG_EXT );  m_cCUMergeIdxExtSCModel.initBuffer              ( sliceType, qp, (UChar*)INIT_MERGE_IDX_EXT );  m_cCUPartSizeSCModel.initBuffer                 ( sliceType, qp, (UChar*)INIT_PART_SIZE );  m_cCUPredModeSCModel.initBuffer                 ( sliceType, qp, (UChar*)INIT_PRED_MODE );  m_cCUIntraPredSCModel.initBuffer                ( sliceType, qp, (UChar*)INIT_INTRA_PRED_MODE );  m_cCUChromaPredSCModel.initBuffer               ( sliceType, qp, (UChar*)INIT_CHROMA_PRED_MODE );  m_cCUInterDirSCModel.initBuffer                 ( sliceType, qp, (UChar*)INIT_INTER_DIR );  m_cCUMvdSCModel.initBuffer                      ( sliceType, qp, (UChar*)INIT_MVD );  m_cCURefPicSCModel.initBuffer                   ( sliceType, qp, (UChar*)INIT_REF_PIC );  m_cCUDeltaQpSCModel.initBuffer                  ( sliceType, qp, (UChar*)INIT_DQP );  m_cCUQtCbfSCModel.initBuffer                    ( sliceType, qp, (UChar*)INIT_QT_CBF );  m_cCUQtRootCbfSCModel.initBuffer                ( sliceType, qp, (UChar*)INIT_QT_ROOT_CBF );  m_cCUSigCoeffGroupSCModel.initBuffer            ( sliceType, qp, (UChar*)INIT_SIG_CG_FLAG );  m_cCUSigSCModel.initBuffer                      ( sliceType, qp, (UChar*)INIT_SIG_FLAG );  m_cCuCtxLastX.initBuffer                        ( sliceType, qp, (UChar*)INIT_LAST );  m_cCuCtxLastY.initBuffer                        ( sliceType, qp, (UChar*)INIT_LAST );  m_cCUOneSCModel.initBuffer                      ( sliceType, qp, (UChar*)INIT_ONE_FLAG );  m_cCUAbsSCModel.initBuffer                      ( sliceType, qp, (UChar*)INIT_ABS_FLAG );  m_cMVPIdxSCModel.initBuffer                     ( sliceType, qp, (UChar*)INIT_MVP_IDX );  m_cSaoMergeSCModel.initBuffer                   ( sliceType, qp, (UChar*)INIT_SAO_MERGE_FLAG );  m_cSaoTypeIdxSCModel.initBuffer                 ( sliceType, qp, (UChar*)INIT_SAO_TYPE_IDX );  m_cCUTransSubdivFlagSCModel.initBuffer          ( sliceType, qp, (UChar*)INIT_TRANS_SUBDIV_FLAG );  m_cTransformSkipSCModel.initBuffer              ( sliceType, qp, (UChar*)INIT_TRANSFORMSKIP_FLAG );  m_CUTransquantBypassFlagSCModel.initBuffer      ( sliceType, qp, (UChar*)INIT_CU_TRANSQUANT_BYPASS_FLAG );  m_explicitRdpcmFlagSCModel.initBuffer           ( sliceType, qp, (UChar*)INIT_EXPLICIT_RDPCM_FLAG);  m_explicitRdpcmDirSCModel.initBuffer            ( sliceType, qp, (UChar*)INIT_EXPLICIT_RDPCM_DIR);  m_cIntraBCPredFlagSCModel.initBuffer            ( sliceType, qp, (UChar*)INIT_INTRABC_PRED_FLAG );  m_cCrossComponentPredictionSCModel.initBuffer   ( sliceType, qp, (UChar*)INIT_CROSS_COMPONENT_PREDICTION );  m_ChromaQpAdjFlagSCModel.initBuffer             ( sliceType, qp, (UChar*)INIT_CHROMA_QP_ADJ_FLAG );  m_ChromaQpAdjIdcSCModel.initBuffer              ( sliceType, qp, (UChar*)INIT_CHROMA_QP_ADJ_IDC );  m_cCUColourTransformFlagSCModel.initBuffer      ( sliceType, qp, (UChar*)INIT_COLOUR_TRANS);  m_cIntraBCBVDSCModel.initBuffer                 ( sliceType, qp, (UChar*)INIT_INTRABC_BVD );  m_PLTModeFlagSCModel.initBuffer                 ( sliceType, qp, (UChar*)INIT_PLTMODE_FLAG );  m_SPointSCModel.initBuffer                      ( sliceType, qp, (UChar*)INIT_SPOINT );  m_cCopyTopRunSCModel.initBuffer                 ( sliceType, qp, (UChar*)INIT_TOP_RUN);  m_cRunSCModel.initBuffer                        ( sliceType, qp, (UChar*)INIT_RUN);  m_PLTSharingModeFlagSCModel.initBuffer          ( sliceType, qp, (UChar*)INIT_PLT_REUSE_FLAG );  m_PLTScanRotationModeFlagSCModel.initBuffer     ( sliceType, qp, (UChar*)INIT_SCAN_ROTATION_FLAG );  for (UInt statisticIndex = 0; statisticIndex < RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS ; statisticIndex++)  {    m_golombRiceAdaptationStatistics[statisticIndex] = 0;  }  m_pcTDecBinIf->start();}

其中初始化buffur

Void ContextModel3DBuffer::initBuffer( SliceType sliceType, Int qp, UChar* ctxModel ){  ctxModel += sliceType * m_sizeXYZ;  for ( Int n = 0; n < m_sizeXYZ; n++ )  {    m_contextModel[ n ].init( qp, ctxModel[ n ] );    m_contextModel[ n ].setBinsCoded( 0 );  }}
传入的ctxModel是预先知道的表格,通过init进行初始化各个 contextModel 的state 和bin变量

在start()函数当中初始化算数解码中解码环境

TDecBinCABAC::start(){  assert( m_pcTComBitstream->getNumBitsUntilByteAligned() == 0 );#if RExt__DECODER_DEBUG_BIT_STATISTICS  TComCodingStatistics::UpdateCABACStat(STATS__CABAC_INITIALISATION, 512, 510, 0);#endif  m_uiRange    = 510;  m_bitsNeeded = -8;  m_uiValue    = (m_pcTComBitstream->readByte() << 8);  m_uiValue   |= m_pcTComBitstream->readByte();}







0 0
原创粉丝点击