首页 > 代码库 > HEVC熵解码代码分析—代码解码流程(2)
HEVC熵解码代码分析—代码解码流程(2)
虽然熵解码的过程并不是很复杂,但是因为涉及太多的文档和函数比较让人心烦,所以稍微进行一下整理
熵解码一般一开始就是需要对上下文模式进行一定得初始化
在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)
完成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 = http://www.mamicode.com/(m_pcTComBitstream->readByte() << 8);>
HEVC熵解码代码分析—代码解码流程(2)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。