虽然熵解码的过程并不是很复杂,但是因为涉及太多的文档和函数比较让人心烦,所以稍微进行一下整理
熵解码一般一开始就是需要对上下文模式进行一定得初始化
在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中对应的状态 state UInt 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)
下一步初始化是在一个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();
}
原文地址:http://blog.csdn.net/xietingcandice/article/details/42105663