首页 > 代码库 > HEVC熵解码代码分析—重写熵解码(3)

HEVC熵解码代码分析—重写熵解码(3)

在HM代码中熵解码的部分写得比较复杂,通过分析后,用C代码重写了熵解码的部分,思路会更加清晰一些

数据结构:

typedef struct ContextModel
{
	HEVC_UINT8 State;
	HEVC_UINT32 BinsCoded;
}ContextModel;

typedef struct ContextModel3D
{
	ContextModel* pContextModel; ///< array of context models
	HEVC_UINT32 SizeX;  ///< X size of 3D buffer
	HEVC_UINT32 SizeXY;  ///< X times Y size of 3D buffer
	HEVC_UINT32 SizeXYZ;  ///< total size of 3D buffer
}ContextModel3D;

typedef struct CABACModel {
	ContextModel3D CUSplitFlagSCModel;
	ContextModel3D CUSkipFlagSCModel;
	ContextModel3D CUMergeFlagExtSCModel;
	ContextModel3D CUMergeIdxExtSCModel;
	ContextModel3D CUPartSizeSCModel;
	ContextModel3D CUPredModeSCModel;
	ContextModel3D CUIntraPredSCModel;
	ContextModel3D CUChromaPredSCModel;
	ContextModel3D CUDeltaQpSCModel;
	ContextModel3D CUInterDirSCModel;
	ContextModel3D CURefPicSCModel;
	ContextModel3D CUMvdSCModel;
	ContextModel3D CUQtCbfSCModel;
	ContextModel3D CUTransSubdivFlagSCModel;
	ContextModel3D CUQtRootCbfSCModel;
	ContextModel3D CUSigCoeffGroupSCModel;
	ContextModel3D CUSigSCModel;
	ContextModel3D CuCtxLastXModel;
	ContextModel3D CuCtxLastYModel;
	ContextModel3D CUOneSCModel;
	ContextModel3D CUAbsSCModel;
	ContextModel3D MVPIdxSCModel;
	ContextModel3D SaoMergeSCModel;
	ContextModel3D SaoTypeIdxSCModel;
	ContextModel3D TransformSkipSCModel;
	ContextModel3D CUTransquantBypassFlagSCModel;
	ContextModel3D explicitRdpcmFlagSCModel;
	ContextModel3D explicitRdpcmDirSCModel;
	ContextModel3D IntraBCPredFlagSCModel;
	ContextModel3D CrossComponentPredictionSCModel;
	ContextModel3D ChromaQpAdjFlagSCModel;
	ContextModel3D ChromaQpAdjIdcSCModel;
	ContextModel3D CUColourTransformFlagSCModel;
	ContextModel3D IntraBCBVDSCModel;
	ContextModel3D PLTModeFlagSCModel;
	ContextModel3D SPointSCModel;
	ContextModel3D CopyTopRunSCModel;
	ContextModel3D RunSCModel;
	ContextModel3D PLTSharingModeFlagSCModel;
	ContextModel3D PLTScanRotationModeFlagSCModel;  

}CABACModel;

解码环境:

//<------------------CABAC解码解码环境变量----------------//
typedef struct DecCABACEnviro
{
	HEVC_UINT32 Range;
	HEVC_UINT32 Value;
	HEVC_INT32 BitsNeeded;
}DecCABACEnviro;

上下文模式的数据结构在Slice结构中进行声明:

	<pre name="code" class="cpp">typedef struct sliceInfo{
ContextModel contextModesls[MAX_NUM_CTX_MOD];CABACModel pCABACModel;DecCABACEnviro decCABACEnviro;HEVC_UINT32 GolombRiceAdaptationStatistics[RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS];}SLICEINFO;


在一个slice开始解码的时候进行初始化:

InitCABACModel(pSlice->contextModesls,&pSlice->pCABACModel);


ResetEntropy(pSlice,pImg);

void InitContextModel(ContextModel *pContextModel)
{
	pContextModel->BinsCoded = 0;
	pContextModel->State = 0;
}
void InitContextModel3D(ContextModel3D *pContextModel3D,HEVC_UINT32 SizeZ, HEVC_UINT32 SizeY, HEVC_UINT32 SizeX, ContextModel *basePtr,HEVC_UINT32 *ModelIndex)
{	
	pContextModel3D->pContextModel = basePtr;
	InitContextModel(pContextModel3D->pContextModel);
	pContextModel3D->SizeX = SizeX;
	pContextModel3D->SizeXY = SizeX*SizeY;
	pContextModel3D->SizeXYZ = SizeX*SizeY*SizeZ;
	*ModelIndex += pContextModel3D->SizeXYZ;
}
<strong>void InitCABACModel(ContextModel *basePtr,CABACModel * pCABACModel)</strong>
{
	HEVC_UINT32 ModelIndex = 0;
	InitContextModel3D(&pCABACModel->CUSplitFlagSCModel,1,1,NUM_SPLIT_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUSkipFlagSCModel,1,1,NUM_SKIP_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);    
	InitContextModel3D(&pCABACModel->CUMergeFlagExtSCModel,1,1,NUM_MERGE_FLAG_EXT_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUMergeIdxExtSCModel,1,1,NUM_MERGE_IDX_EXT_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUPartSizeSCModel,1,1,NUM_PART_SIZE_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUPredModeSCModel,1,1,NUM_PRED_MODE_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUIntraPredSCModel,1,1,NUM_ADI_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUChromaPredSCModel,1,1,NUM_CHROMA_PRED_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUDeltaQpSCModel,1,1,NUM_DELTA_QP_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUInterDirSCModel,1,1,NUM_INTER_DIR_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CURefPicSCModel,1,1,NUM_REF_NO_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUMvdSCModel,1,1,NUM_MV_RES_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUQtCbfSCModel,1,NUM_QT_CBF_CTX_SETS,NUM_QT_CBF_CTX_PER_SET,basePtr+ModelIndex,&ModelIndex);	
	InitContextModel3D(&pCABACModel->CUTransSubdivFlagSCModel,1,1,NUM_TRANS_SUBDIV_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUQtRootCbfSCModel,1,1,NUM_QT_ROOT_CBF_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUSigCoeffGroupSCModel,1,2,NUM_SIG_CG_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUSigSCModel,1,1,NUM_SIG_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CuCtxLastXModel,1,NUM_CTX_LAST_FLAG_SETS,NUM_CTX_LAST_FLAG_XY,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CuCtxLastYModel,1,NUM_CTX_LAST_FLAG_SETS,NUM_CTX_LAST_FLAG_XY,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUOneSCModel,1,1,NUM_ONE_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUAbsSCModel,1,1,NUM_ABS_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->MVPIdxSCModel,1,1,NUM_MVP_IDX_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->SaoMergeSCModel,1,1,NUM_SAO_MERGE_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->SaoTypeIdxSCModel,1,1,NUM_SAO_TYPE_IDX_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->TransformSkipSCModel,1,2,NUM_TRANSFORMSKIP_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUTransquantBypassFlagSCModel,1,1,NUM_CU_TRANSQUANT_BYPASS_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->explicitRdpcmFlagSCModel,1,2,NUM_EXPLICIT_RDPCM_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->explicitRdpcmDirSCModel,1,2,NUM_EXPLICIT_RDPCM_DIR_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->IntraBCPredFlagSCModel,1,1,NUM_INTRABC_PRED_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CrossComponentPredictionSCModel,1,1,NUM_CROSS_COMPONENT_PREDICTION_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->ChromaQpAdjFlagSCModel,1,1,NUM_CHROMA_QP_ADJ_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->ChromaQpAdjIdcSCModel,1,1,NUM_CHROMA_QP_ADJ_IDC_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CUColourTransformFlagSCModel,1,1,NUM_COLOUR_TRANS_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->IntraBCBVDSCModel,1,1,NUM_INTRABC_BVD_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->PLTModeFlagSCModel,1,1,NUM_PLTMODE_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->SPointSCModel,1,1,NUM_SPOINT_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->CopyTopRunSCModel,1,1,NUM_TOP_RUN_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->RunSCModel,1,1,NUM_LEFT_RUN_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->PLTSharingModeFlagSCModel,1,1,NUM_PLT_REUSE_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
	InitContextModel3D(&pCABACModel->PLTScanRotationModeFlagSCModel,1,1,NUM_SCAN_ROTATION_FLAG_CTX,basePtr+ModelIndex,&ModelIndex);
}
<strong>void ResetEntropy(SLICEINFO *pSlice,IMGINFO *pImg)</strong>
{
	SliceType sliceType = pSlice->sliceType;
	HEVC_UINT8 sliceQP = pSlice->iSliceQp;
	HEVC_UINT32 i = 0;
	if (pImg->pps.cabacInitPresentFlag && pSlice->cabacInitFlag)
	{
		switch (sliceType)
		{
		case B_SLICE: // change initialization table to P_SLICE initialization
			sliceType = P_SLICE;
			break;
		case P_SLICE:// change initialization table to B_SLICE initialization
			sliceType = B_SLICE; 
			break;
		default:
			printf("decode error, should not occur");
			break;
		}
	}
	InitCABACModelBuffur(&pSlice->pCABACModel.CUSplitFlagSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_SPLIT_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUSkipFlagSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_SKIP_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUMergeFlagExtSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_MERGE_FLAG_EXT );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUMergeIdxExtSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_MERGE_IDX_EXT );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUPartSizeSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_PART_SIZE );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUPredModeSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_PRED_MODE );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUIntraPredSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_INTRA_PRED_MODE );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUChromaPredSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_CHROMA_PRED_MODE );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUDeltaQpSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_DQP );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUInterDirSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_INTER_DIR );
	InitCABACModelBuffur(&pSlice->pCABACModel.CURefPicSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_REF_PIC );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUMvdSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_MVD );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUQtCbfSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_QT_CBF );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUTransSubdivFlagSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_TRANS_SUBDIV_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUQtRootCbfSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_QT_ROOT_CBF );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUSigCoeffGroupSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_SIG_CG_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUSigSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_SIG_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.CuCtxLastXModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_LAST );
	InitCABACModelBuffur(&pSlice->pCABACModel.CuCtxLastYModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_LAST );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUOneSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_ONE_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUAbsSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_ABS_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.MVPIdxSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_MVP_IDX );
	InitCABACModelBuffur(&pSlice->pCABACModel.SaoMergeSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_SAO_MERGE_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.SaoTypeIdxSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_SAO_TYPE_IDX );
	InitCABACModelBuffur(&pSlice->pCABACModel.TransformSkipSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_TRANSFORMSKIP_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUTransquantBypassFlagSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_CU_TRANSQUANT_BYPASS_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.explicitRdpcmFlagSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_EXPLICIT_RDPCM_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.explicitRdpcmDirSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_EXPLICIT_RDPCM_DIR );
	InitCABACModelBuffur(&pSlice->pCABACModel.IntraBCPredFlagSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_INTRABC_PRED_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.CrossComponentPredictionSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_CROSS_COMPONENT_PREDICTION );
	InitCABACModelBuffur(&pSlice->pCABACModel.ChromaQpAdjFlagSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_CHROMA_QP_ADJ_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.ChromaQpAdjIdcSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_CHROMA_QP_ADJ_IDC );
	InitCABACModelBuffur(&pSlice->pCABACModel.CUColourTransformFlagSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_COLOUR_TRANS );
	InitCABACModelBuffur(&pSlice->pCABACModel.IntraBCBVDSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_INTRABC_BVD );
	InitCABACModelBuffur(&pSlice->pCABACModel.PLTModeFlagSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_PLTMODE_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.SPointSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_SPOINT );
	InitCABACModelBuffur(&pSlice->pCABACModel.CopyTopRunSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_TOP_RUN );
	InitCABACModelBuffur(&pSlice->pCABACModel.RunSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_RUN );
	InitCABACModelBuffur(&pSlice->pCABACModel.PLTSharingModeFlagSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_PLT_REUSE_FLAG );
	InitCABACModelBuffur(&pSlice->pCABACModel.PLTScanRotationModeFlagSCModel,sliceType,sliceQP,(HEVC_UINT8*)INIT_SCAN_ROTATION_FLAG );
	for (i = 0; i < RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS; i++)
	{
		pSlice->GolombRiceAdaptationStatistics[i] = 0;
	}
	StartSliceCABAC(&pSlice->decCABACEnviro,pImg);
}
void InitCABACModelBuffur(ContextModel3D *pContextModel3D,SliceType sliceType, HEVC_UINT8 sliceQP, HEVC_UINT8* ctxModel)
{                          //<ContextModel3DBuffer::initBuffer
	HEVC_INT32 i = 0;
	HEVC_INT32 value = http://www.mamicode.com/0;>
void StartSliceCABAC(DecCABACEnviro *decCABACEnviro,IMGINFO *pImg)
{
	const HEVC_INT8*	pUnitBuf 	= pImg->pUnitBuf;
	HEVC_UINT32	bitOffset = pImg->bitOffset;
	decCABACEnviro->Range = 510;
	decCABACEnviro->BitsNeeded = -8;
	decCABACEnviro->Value = http://www.mamicode.com/(READ_BITS(pUnitBuf,&bitOffset,8,"XT_StartSliceCABAC") << 8);>

然后初始化就完成了,是不是清楚一些了

然后就是真正解码的过程了

在解码中主要从码流中读取算数编码的过程,重写的时候尽量简化,在码流中用两个变量就够了

HEVC_INT8 *pUnitBuf; //码流缓存

HEVC_UINT32 bitOffset; //读取的bit的偏移量

这里写出来一个decodeBin的函数

void DecodeBin(IMGINFO *pImg,HEVC_UINT8 *Bin, ContextModel *pCtxModel,DecCABACEnviro *pDecCABACEnviro)
{
	HEVC_UINT32 Range = pDecCABACEnviro->Range; //< Remebeer to exchange the value at last
	HEVC_UINT32 Value = http://www.mamicode.com/pDecCABACEnviro->Value;>




HEVC熵解码代码分析—重写熵解码(3)