從本篇開始,接下來的若干篇會逐步分析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;
}