入口函数:TEncSbac::resetEntropy:
这个函数的实质就是初始化各种上下文
// 重置熵编码器 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; } // 初始化各个模型的缓存 // split标志的上下文 m_cCUSplitFlagSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SPLIT_FLAG ); // skip标志的上下文 m_cCUSkipFlagSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SKIP_FLAG ); // merge标志上下文 m_cCUMergeFlagExtSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_MERGE_FLAG_EXT); // merge索引上下文 m_cCUMergeIdxExtSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_MERGE_IDX_EXT); // partsize上下文 m_cCUPartSizeSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_PART_SIZE ); // 预测上下文 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 ); // MV残差上下文 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 ); // CBF上下文 m_cCUQtCbfSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_QT_CBF ); // 四叉树根的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 ); // 最后一个X上下文 m_cCuCtxLastX.initBuffer ( eSliceType, iQp, (UChar*)INIT_LAST ); // 最后一个Y上下文 m_cCuCtxLastY.initBuffer ( eSliceType, iQp, (UChar*)INIT_LAST ); m_cCUOneSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_ONE_FLAG ); // CU绝对索引?上下文 m_cCUAbsSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_ABS_FLAG ); // MVP索引上下文 m_cMVPIdxSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_MVP_IDX ); // TU划分标志上下文 m_cCUTransSubdivFlagSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_TRANS_SUBDIV_FLAG ); // SAO merge上下文 m_cSaoMergeSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SAO_MERGE_FLAG ); // SAO类型索引上下文 m_cSaoTypeIdxSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_SAO_TYPE_IDX ); // 变换skip标志上下文 m_cTransformSkipSCModel.initBuffer ( eSliceType, iQp, (UChar*)INIT_TRANSFORMSKIP_FLAG ); // 变换量化bypass标志上下文 m_CUTransquantBypassFlagSCModel.initBuffer( eSliceType, iQp, (UChar*)INIT_CU_TRANSQUANT_BYPASS_FLAG ); // new structure m_uiLastQp = iQp; // 二值化的一些操作 m_pcBinIf->start(); return; }
Void TEncBinCABAC::start() { m_uiLow = 0; // 下限(进行二值化的时候) m_uiRange = 510; // 范围(进行二值化的时候) m_bitsLeft = 23; m_numBufferedBytes = 0; m_bufferedByte = 0xff; }
工程中预定义了一些初始的上下文模型,预定义的各个上下模型实际就是一些二维数组:
// 上下文模型的数量 #define MAX_NUM_CTX_MOD 512 ///< maximum number of supported contexts // 上下文split标志的数量 #define NUM_SPLIT_FLAG_CTX 3 ///< number of context models for split flag // 上下文skip标志的数量 #define NUM_SKIP_FLAG_CTX 3 ///< number of context models for skip flag // 上下文merge扩展中merge标志的数量 #define NUM_MERGE_FLAG_EXT_CTX 1 ///< number of context models for merge flag of merge extended // 上下文merge扩展中merge index的数量 #define NUM_MERGE_IDX_EXT_CTX 1 ///< number of context models for merge index of merge extended // partition的类型 #define NUM_PART_SIZE_CTX 4 ///< number of context models for partition size // 预测的类型 #define NUM_PRED_MODE_CTX 1 ///< number of context models for prediction mode // 帧内预测的数量 #define NUM_ADI_CTX 1 ///< number of context models for intra prediction // 色度帧内预测的数量 #define NUM_CHROMA_PRED_CTX 2 ///< number of context models for intra prediction (chroma) // 用于帧间预测的上下文模型的数量 #define NUM_INTER_DIR_CTX 5 ///< number of context models for inter prediction direction // 用于MV的上下文模型的数量 #define NUM_MV_RES_CTX 2 ///< number of context models for motion vector difference // 用于参考索引的上下文模型的数量 #define NUM_REF_NO_CTX 2 ///< number of context models for reference index // 用于变换切分的的上下文模型的数量 #define NUM_TRANS_SUBDIV_FLAG_CTX 3 ///< number of context models for transform subdivision flags // 用于量化树的CBF的上下文模型的数量 #define NUM_QT_CBF_CTX 4 ///< number of context models for QT CBF // 用于量化树根的CBF的上下文模型的数量 #define NUM_QT_ROOT_CBF_CTX 1 ///< number of context models for QT ROOT CBF // 用于dQP的上下文模型的数量 #define NUM_DELTA_QP_CTX 3 ///< number of context models for dQP // #define NUM_SIG_CG_FLAG_CTX 2 ///< number of context models for MULTI_LEVEL_SIGNIFICANCE // 用于符号(正负号)标志的上下文模型的数量 #define NUM_SIG_FLAG_CTX 42 ///< number of context models for sig flag // 用于亮度符号标志的上下文模型的数量 #define NUM_SIG_FLAG_CTX_LUMA 27 ///< number of context models for luma sig flag // 用于色度符号标志的上下文模型的数量 #define NUM_SIG_FLAG_CTX_CHROMA 15 ///< number of context models for chroma sig flag // 用于 最后一个系数 的上下文模型的数量 #define NUM_CTX_LAST_FLAG_XY 15 ///< number of context models for last coefficient position #define NUM_ONE_FLAG_CTX 24 ///< number of context models for greater than 1 flag #define NUM_ONE_FLAG_CTX_LUMA 16 ///< number of context models for greater than 1 flag of luma #define NUM_ONE_FLAG_CTX_CHROMA 8 ///< number of context models for greater than 1 flag of chroma #define NUM_ABS_FLAG_CTX 6 ///< number of context models for greater than 2 flag #define NUM_ABS_FLAG_CTX_LUMA 4 ///< number of context models for greater than 2 flag of luma #define NUM_ABS_FLAG_CTX_CHROMA 2 ///< number of context models for greater than 2 flag of chroma // 用于MVP索引的上下文模型的数量 #define NUM_MVP_IDX_CTX 1 ///< number of context models for MVP index // 用于SAO merge的上下文模型的数量 #define NUM_SAO_MERGE_FLAG_CTX 1 ///< number of context models for SAO merge flags // 用于SAO 类型索引的上下文模型的数量 #define NUM_SAO_TYPE_IDX_CTX 1 ///< number of context models for SAO type index // 用于变换skip的上下文模型的数量 #define NUM_TRANSFORMSKIP_FLAG_CTX 1 ///< number of context models for transform skipping #define NUM_CU_TRANSQUANT_BYPASS_FLAG_CTX 1 #define CNU 154 ///< dummy initialization value for unused context models 'Context model Not Used' // ==================================================================================================================== // Tables // ==================================================================================================================== // initial probability for cu_transquant_bypass flag // cu_transquant_bypass标志的上下文模型 static const UChar INIT_CU_TRANSQUANT_BYPASS_FLAG[3][NUM_CU_TRANSQUANT_BYPASS_FLAG_CTX] = { { 154 }, { 154 }, { 154 }, }; // initial probability for split flag // split标志的上下文模型 static const UChar INIT_SPLIT_FLAG[3][NUM_SPLIT_FLAG_CTX] = { { 107, 139, 126, }, { 107, 139, 126, }, { 139, 141, 157, }, }; // skip标志的上下文模型 static const UChar INIT_SKIP_FLAG[3][NUM_SKIP_FLAG_CTX] = { { 197, 185, 201, }, { 197, 185, 201, }, { CNU, CNU, CNU, }, }; // merge模式的标志的上下文 static const UChar INIT_MERGE_FLAG_EXT[3][NUM_MERGE_FLAG_EXT_CTX] = { { 154, }, { 110, }, { CNU, }, }; // merge模式的索引的上下文 static const UChar INIT_MERGE_IDX_EXT[3][NUM_MERGE_IDX_EXT_CTX] = { { 137, }, { 122, }, { CNU, }, }; // part_size的上下文 static const UChar INIT_PART_SIZE[3][NUM_PART_SIZE_CTX] = { { 154, 139, 154, 154 }, { 154, 139, 154, 154 }, { 184, CNU, CNU, CNU }, }; // 预测模式的上下文 static const UChar INIT_PRED_MODE[3][NUM_PRED_MODE_CTX] = { { 134, }, { 149, }, { CNU, }, }; // 帧内预测的模式(亮度)的上下文 static const UChar INIT_INTRA_PRED_MODE[3][NUM_ADI_CTX] = { { 183, }, { 154, }, { 184, }, }; // 帧内预测的模式(色度)的上下文 static const UChar INIT_CHROMA_PRED_MODE[3][NUM_CHROMA_PRED_CTX] = { { 152, 139, }, { 152, 139, }, { 63, 139, }, }; // 帧间预测方向(前后两个方向) 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, }, }; // MV残差上下文 static const UChar INIT_MVD[3][NUM_MV_RES_CTX] = { { 169, 198, }, { 140, 198, }, { CNU, CNU, }, }; // 参考帧上下文 static const UChar INIT_REF_PIC[3][NUM_REF_NO_CTX] = { { 153, 153 }, { 153, 153 }, { CNU, CNU }, }; // dQP // 量化步长上下文 static const UChar INIT_DQP[3][NUM_DELTA_QP_CTX] = { { 154, 154, 154, }, { 154, 154, 154, }, { 154, 154, 154, }, }; // CBF(编码块标志)上下文 static const UChar INIT_QT_CBF[3][2*NUM_QT_CBF_CTX] = { { 153, 111, CNU, CNU, 149, 92, 167, 154 }, { 153, 111, CNU, CNU, 149, 107, 167, 154 }, { 111, 141, CNU, CNU, 94, 138, 182, 154 }, }; static const UChar INIT_QT_ROOT_CBF[3][NUM_QT_ROOT_CBF_CTX] = { { 79, }, { 79, }, { CNU, }, }; // 最后一个系数的位置 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, }, }; 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, }, }; // 整数符号的标志 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, }, }; // 1标志上下文 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, }, }; // 帧内预测索引 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, }, }; // MVP索引 static const UChar INIT_MVP_IDX[3][NUM_MVP_IDX_CTX] = { { 168 }, { 168 }, { CNU }, }; // SAO merge标志 static const UChar INIT_SAO_MERGE_FLAG[3][NUM_SAO_MERGE_FLAG_CTX] = { { 153, }, { 153, }, { 153, }, }; // SAO 类型索引 static const UChar INIT_SAO_TYPE_IDX[3][NUM_SAO_TYPE_IDX_CTX] = { { 160, }, { 185, }, { 200, }, }; // 变换分割标志 static const UChar INIT_TRANS_SUBDIV_FLAG[3][NUM_TRANS_SUBDIV_FLAG_CTX] = { { 224, 167, 122, }, { 124, 138, 94, }, { 153, 138, 138, }, }; // 变换skip标志 static const UChar INIT_TRANSFORMSKIP_FLAG[3][2*NUM_TRANSFORMSKIP_FLAG_CTX] = { { 139, 139}, { 139, 139}, { 139, 139}, }; //! \}
上下文模型在工程中是ContextModel3DBuffer类型,为了弄清楚这个结构,我们先看TEncSbac的构造函数:
TEncSbac::TEncSbac() // new structure here : m_pcBitIf ( NULL ) , m_pcSlice ( NULL ) , m_pcBinIf ( NULL ) , m_uiCoeffCost ( 0 ) , m_numContextModels ( 0 ) //context model的计数值,接下来的所有除了assert的语句都是对句法元素对应的context进行初始化 , 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) , m_cCUDeltaQpSCModel ( 1, 1, NUM_DELTA_QP_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUInterDirSCModel ( 1, 1, NUM_INTER_DIR_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCURefPicSCModel ( 1, 1, NUM_REF_NO_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUMvdSCModel ( 1, 1, NUM_MV_RES_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUQtCbfSCModel ( 1, 2, NUM_QT_CBF_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUTransSubdivFlagSCModel ( 1, 1, NUM_TRANS_SUBDIV_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUQtRootCbfSCModel ( 1, 1, NUM_QT_ROOT_CBF_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUSigCoeffGroupSCModel ( 1, 2, NUM_SIG_CG_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUSigSCModel ( 1, 1, NUM_SIG_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCuCtxLastX ( 1, 2, NUM_CTX_LAST_FLAG_XY , m_contextModels + m_numContextModels, m_numContextModels) , m_cCuCtxLastY ( 1, 2, NUM_CTX_LAST_FLAG_XY , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUOneSCModel ( 1, 1, NUM_ONE_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cCUAbsSCModel ( 1, 1, NUM_ABS_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cMVPIdxSCModel ( 1, 1, NUM_MVP_IDX_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cSaoMergeSCModel ( 1, 1, NUM_SAO_MERGE_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cSaoTypeIdxSCModel ( 1, 1, NUM_SAO_TYPE_IDX_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_cTransformSkipSCModel ( 1, 2, NUM_TRANSFORMSKIP_FLAG_CTX , m_contextModels + m_numContextModels, m_numContextModels) , m_CUTransquantBypassFlagSCModel( 1, 1, NUM_CU_TRANSQUANT_BYPASS_FLAG_CTX, m_contextModels + m_numContextModels, m_numContextModels) { assert( m_numContextModels <= MAX_NUM_CTX_MOD ); }
可以看到TEncSbac的构造函数调用的都是ContextModel3DBuffer的构造函数,ContextModel3DBuffer的构造函数定义如下:
ContextModel3DBuffer::ContextModel3DBuffer( 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; // m_contextModel由basePtr赋值,即指向指定的context的内存区 count += m_sizeXYZ; // count记录的是到目前为止所有context的尺寸 }
结合ContextModel3DBuffer和TEncSbac的构造函数可以看到,实际的上下文数据都存放在ContextModel中(或者ContextModel类型的指针指向的内存中),ContextModel3DBuffer只是一个便于访问的接口类。
上下文模型内容初始化的函数ContextModel3DBuffer::initBuffer定义如下:
Void ContextModel3DBuffer::initBuffer( SliceType sliceType, Int qp, UChar* ctxModel ) { ctxModel += sliceType * m_sizeXYZ; // 根据当前slice的类型(I,P,B)选择对应的context,为什么这么做,下面会解释 // 根据sliceType计算initType并将context指针移动到正确的位置上,这个initType用于索引context model,且由slice_type来决定 for ( Int n = 0; n < m_sizeXYZ; n++ ) { m_contextModel[ n ].init( qp, ctxModel[ n ] ); // 完成context的各个状态变量的初始化工作 m_contextModel[ n ].setBinsCoded( 0 ); } }
Void ContextModel::init( Int qp, Int initValue ) { // 选取中间值 qp = Clip3(0, 51, qp); // 具体的意思可能需要看一些文档,我现在还没弄清 Int slope = (initValue>>4)*5 - 45; // m Int offset = ((initValue&15)<<3)-16; // n Int initState = min( max( 1, ( ( ( slope * qp ) >> 4 ) + offset ) ), 126 ); // preCtxState UInt mpState = (initState >= 64 ); // MPS m_ucState = ( (mpState? (initState - 64):(63 - initState)) <<1) + mpState; }
时间: 2024-10-12 20:20:42