从本篇开始,接下来的若干篇会逐步分析HM 9.1中有关熵编码的过程。在此以及以后的几篇,我都默认大家对熵编码(针对CABAC,因为HEVC只有这一种编码方式,而H.264有CAVLC和CABAC两种)的基本概念和流程有了一定的基础,同时,由于HEVC中的CABAC基本流程与H.264中的基本一致,因此,这里暂时不会介绍熵编码框架和流程,有兴趣的可以参考H.264中的相关资料。我会按照编码的执行顺序逐步地分析代码,到最后会再给出总结。
本文首先介绍编码器的初始化过程,即draft 9.3.4.1的部分。
在Void TEncSlice::compressSlice( TComPic*& rpcPic )有这么一段:
// set entropy coder if( m_pcCfg->getUseSBACRD() ) //!< 默认条件下m_bUseSBACRD为true //!< draft 9.3.4.1 { m_pcSbacCoder->init( m_pcBinCABAC ); m_pcEntropyCoder->setEntropyCoder ( m_pcSbacCoder, pcSlice ); m_pcEntropyCoder->resetEntropy (); //!< 主要进行上下文模型的初始化,codILow和codIRange的初始化等 m_pppcRDSbacCoder[0][CI_CURR_BEST]->load(m_pcSbacCoder); pppcRDSbacCoder = (TEncBinCABAC *) m_pppcRDSbacCoder[0][CI_CURR_BEST]->getEncBinIf(); pppcRDSbacCoder->setBinCountingEnableFlag( false ); pppcRDSbacCoder->setBinsCoded( 0 ); }
重点看m_pcEntropyCoder->resetEntropy ();
该函数中调用的initBuffer功能即是对相应的context变量进行初始化,这个可参考draft 9.3.1.1的相关内容。
Void TEncSbac::resetEntropy () { Int iQp = m_pcSlice->getSliceQp(); SliceType eSliceType = m_pcSlice->getSliceType(); Int encCABACTableIdx = m_pcSlice->getPPS()->getEncCABACTableIdx(); if (!m_pcSlice->isIntra() && (encCABACTableIdx==B_SLICE || encCABACTableIdx==P_SLICE) && m_pcSlice->getPPS()->getCabacInitPresentFlag()) { eSliceType = (SliceType) encCABACTableIdx; } //! draft 9.3.1.1 Initialization process for context variables m_cCUSplitFlagSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SPLIT_FLAG ); m_cCUSkipFlagSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SKIP_FLAG ); m_cCUMergeFlagExtSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_MERGE_FLAG_EXT); m_cCUMergeIdxExtSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_MERGE_IDX_EXT); m_cCUPartSizeSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_PART_SIZE ); m_cCUAMPSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_CU_AMP_POS ); m_cCUPredModeSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_PRED_MODE ); m_cCUIntraPredSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_INTRA_PRED_MODE ); m_cCUChromaPredSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_CHROMA_PRED_MODE ); m_cCUInterDirSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_INTER_DIR ); m_cCUMvdSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_MVD ); m_cCURefPicSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_REF_PIC ); m_cCUDeltaQpSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_DQP ); m_cCUQtCbfSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_QT_CBF ); m_cCUQtRootCbfSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_QT_ROOT_CBF ); m_cCUSigCoeffGroupSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SIG_CG_FLAG ); m_cCUSigSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SIG_FLAG ); m_cCuCtxLastX.initBuffer ( eSliceType, iQp, (UChar*)INIT_LAST ); m_cCuCtxLastY.initBuffer ( eSliceType, iQp, (UChar*)INIT_LAST ); m_cCUOneSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_ONE_FLAG ); m_cCUAbsSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_ABS_FLAG ); m_cMVPIdxSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_MVP_IDX ); m_cCUTransSubdivFlagSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_TRANS_SUBDIV_FLAG ); m_cSaoMergeSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SAO_MERGE_FLAG ); m_cSaoTypeIdxSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SAO_TYPE_IDX ); m_cTransformSkipSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_TRANSFORMSKIP_FLAG ); m_CUTransquantBypassFlagSCModel.initBuffer( eSliceType, iQp, (UChar*)INIT_CU_TRANSQUANT_BYPASS_FLAG ); // new structure m_uiLastQp = iQp; m_pcBinIf->start(); return; }
这些initBuffer初始化的context的变量值可以参考draft中Table 9-5 至Table 9-31,代码中的数组及对应的表格如下所列:
// initial probability for cu_transquant_bypass flag static const UChar INIT_CU_TRANSQUANT_BYPASS_FLAG[3][NUM_CU_TRANSQUANT_BYPASS_FLAG_CTX] = { { 154 }, { 154 }, { 154 }, }; //!< Table 9-8 // initial probability for split flag static const UChar INIT_SPLIT_FLAG[3][NUM_SPLIT_FLAG_CTX] = { { 107, 139, 126, }, { 107, 139, 126, }, { 139, 141, 157, }, }; //!< Table 9-7 static const UChar INIT_SKIP_FLAG[3][NUM_SKIP_FLAG_CTX] = { { 197, 185, 201, }, { 197, 185, 201, }, { CNU, CNU, CNU, }, }; //!< Table 9-9 static const UChar INIT_MERGE_FLAG_EXT[3][NUM_MERGE_FLAG_EXT_CTX] = { { 154, }, { 110, }, { CNU, }, }; //!< Table 9-15 static const UChar INIT_MERGE_IDX_EXT[3][NUM_MERGE_IDX_EXT_CTX] = { { 137, }, { 122, }, { CNU, }, }; //!< Table 9-16 static const UChar INIT_PART_SIZE[3][NUM_PART_SIZE_CTX] = { { 154, 139, CNU, CNU, }, { 154, 139, CNU, CNU, }, { 184, CNU, CNU, CNU, }, }; //!< Table 9-12 static const UChar INIT_CU_AMP_POS[3][NUM_CU_AMP_CTX] = { { 154, }, { 154, }, { CNU, }, }; static const UChar INIT_PRED_MODE[3][NUM_PRED_MODE_CTX] = { { 134, }, { 149, }, { CNU, }, }; //!< Table 9-11 static const UChar INIT_INTRA_PRED_MODE[3][NUM_ADI_CTX] = { { 183, }, { 154, }, { 184, }, }; //!< Table 9-13 static const UChar INIT_CHROMA_PRED_MODE[3][NUM_CHROMA_PRED_CTX] = { { 152, 139, }, { 152, 139, }, { 63, 139, }, }; //!< Table 9-14 static const UChar INIT_INTER_DIR[3][NUM_INTER_DIR_CTX] = { { 95, 79, 63, 31, 31, }, { 95, 79, 63, 31, 31, }, { CNU, CNU, CNU, CNU, CNU, }, }; //!< Table 9-17 static const UChar INIT_MVD[3][NUM_MV_RES_CTX] = { { 169, 198, }, { 140, 198, }, { CNU, CNU, }, }; //!< Table 9-19 static const UChar INIT_REF_PIC[3][NUM_REF_NO_CTX] = { { 153, 153 }, { 153, 153 }, { CNU, CNU }, }; static const UChar INIT_DQP[3][NUM_DELTA_QP_CTX] = { { 154, 154, 154, }, { 154, 154, 154, }, { 154, 154, 154, }, }; //!< Table 9-10 static const UChar INIT_QT_CBF[3][2*NUM_QT_CBF_CTX] = { { 153, 111, CNU, CNU, CNU, 149, 92, 167, CNU, CNU, }, { 153, 111, CNU, CNU, CNU, 149, 107, 167, CNU, CNU, }, { 111, 141, CNU, CNU, CNU, 94, 138, 182, CNU, CNU, }, }; //!< Table 9-23、Table 9-24 static const UChar INIT_QT_ROOT_CBF[3][NUM_QT_ROOT_CBF_CTX] = { { 79, }, { 79, }, { CNU, }, }; //!< Table 9-21 static const UChar INIT_LAST[3][2*NUM_CTX_LAST_FLAG_XY] = { { 125, 110, 124, 110, 95, 94, 125, 111, 111, 79, 125, 126, 111, 111, 79, 108, 123, 93, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, }, { 125, 110, 94, 110, 95, 79, 125, 111, 110, 78, 110, 111, 111, 95, 94, 108, 123, 108, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, }, { 110, 110, 124, 125, 140, 153, 125, 127, 140, 109, 111, 143, 127, 111, 79, 108, 123, 63, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, CNU, }, }; //!< Table 9-26、Table 9-27 static const UChar INIT_SIG_CG_FLAG[3][2 * NUM_SIG_CG_FLAG_CTX] = { { 121, 140, 61, 154, }, { 121, 140, 61, 154, }, { 91, 171, 134, 141, }, }; //!< Table 9-28 static const UChar INIT_SIG_FLAG[3][NUM_SIG_FLAG_CTX] = { { 170, 154, 139, 153, 139, 123, 123, 63, 124, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 170, 153, 138, 138, 122, 121, 122, 121, 167, 151, 183, 140, 151, 183, 140, }, { 155, 154, 139, 153, 139, 123, 123, 63, 153, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 166, 183, 140, 136, 153, 154, 170, 153, 123, 123, 107, 121, 107, 121, 167, 151, 183, 140, 151, 183, 140, }, { 111, 111, 125, 110, 110, 94, 124, 108, 124, 107, 125, 141, 179, 153, 125, 107, 125, 141, 179, 153, 125, 107, 125, 141, 179, 153, 125, 140, 139, 182, 182, 152, 136, 152, 136, 153, 136, 139, 111, 136, 139, 111, }, }; //!< Table 9-29 static const UChar INIT_ONE_FLAG[3][NUM_ONE_FLAG_CTX] = { { 154, 196, 167, 167, 154, 152, 167, 182, 182, 134, 149, 136, 153, 121, 136, 122, 169, 208, 166, 167, 154, 152, 167, 182, }, { 154, 196, 196, 167, 154, 152, 167, 182, 182, 134, 149, 136, 153, 121, 136, 137, 169, 194, 166, 167, 154, 167, 137, 182, }, { 140, 92, 137, 138, 140, 152, 138, 139, 153, 74, 149, 92, 139, 107, 122, 152, 140, 179, 166, 182, 140, 227, 122, 197, }, }; //!< Table 9-30 static const UChar INIT_ABS_FLAG[3][NUM_ABS_FLAG_CTX] = { { 107, 167, 91, 107, 107, 167, }, { 107, 167, 91, 122, 107, 167, }, { 138, 153, 136, 167, 152, 152, }, }; //!< Table 9-31 static const UChar INIT_MVP_IDX[3][NUM_MVP_IDX_CTX] = { { 168, CNU, }, { 168, CNU, }, { CNU, CNU, }, }; //!< Table 9-20 static const UChar INIT_SAO_MERGE_FLAG[3][NUM_SAO_MERGE_FLAG_CTX] = { { 153, }, { 153, }, { 153, }, }; //!< Table 9-5 static const UChar INIT_SAO_TYPE_IDX[3][NUM_SAO_TYPE_IDX_CTX] = { { 200, }, { 185, }, { 160, }, }; //!< Table 9-6 static const UChar INIT_TRANS_SUBDIV_FLAG[3][NUM_TRANS_SUBDIV_FLAG_CTX] = { { 153, 138, 138, }, { 124, 138, 94, }, { 224, 167, 122, }, }; //!< Table 9-22 static const UChar INIT_TRANSFORMSKIP_FLAG[3][2*NUM_TRANSFORMSKIP_FLAG_CTX] = { { 139, 139}, { 139, 139}, { 139, 139}, }; //!< Table 9-25
需要注意的是,HM和draft不是每一个地方都是一一对应的,可能有若干变量的值或者命名有所差异,具体情况还是等具体进行编码时再来讨论吧。
TEncSbac::resetEntropy()在最后还调用了m_pcBinIf->start();它完成如下工作:
Void TEncBinCABAC::start() { m_uiLow = 0; //!< codILow m_uiRange = 510; //!< codIRange m_bitsLeft = 23; m_numBufferedBytes = 0; m_bufferedByte = 0xff; }