最近开始做HEVC了,其中熵解码作为最底层的部分,因为和h264差不多,难度系数不是很大,主要是一些查表的操作
具体的实现原理就不细说了,主要从代码来进行解释
首先分析HM工程当中的熵解码的部分作为引导,因为最终要在DSP上进行运行,之后会重写为C代码,流程性更强
代码分析
首先介绍熵解码中比较重要的几个结构体和设计到的函数
一进入main函数,最主要的就是对应的解码类TAppDecTop
int main(int argc, char* argv[])
{
TAppDecTop cTAppDecTop;TComPrediction m_cPrediction; TComTrQuant m_cTrQuant; TDecGop m_cGopDecoder; TDecSlice m_cSliceDecoder; TDecCu m_cCuDecoder; TDecEntropy m_cEntropyDecoder; TDecCavlc m_cCavlcDecoder; TDecSbac m_cSbacDecoder; TDecBinCABAC m_cBinCABAC; SEIReader m_seiReader; TComLoopFilter m_cLoopFilter; TComSampleAdaptiveOffset m_cSAO;
TDecEntropy m_cEntropyDecoder;
看一下成员函数
Void init (TComPrediction* p) {m_pcPrediction = p;}
Void decodePUWise ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, TComDataCU* pcSubCU );
Void decodeInterDirPU ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPartIdx );
Void decodeRefFrmIdxPU ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPartIdx, RefPicList eRefList );
Void decodeMvdPU ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPartIdx, RefPicList eRefList );
Void decodeMVPIdxPU ( TComDataCU* pcSubCU, UInt uiPartAddr, UInt uiDepth, UInt uiPartIdx, RefPicList eRefList );
Void setEntropyDecoder ( TDecEntropyIf* p );
Void setBitstream ( TComInputBitstream* p ) { m_pcEntropyDecoderIf->setBitstream(p); }
Void resetEntropy ( TComSlice* p) { m_pcEntropyDecoderIf->resetEntropy(p); }
Void decodeVPS ( TComVPS* pcVPS ) { m_pcEntropyDecoderIf->parseVPS(pcVPS); }
Void decodeSPS ( TComSPS* pcSPS ) { m_pcEntropyDecoderIf->parseSPS(pcSPS); }
Void decodePPS ( TComPPS* pcPPS ) { m_pcEntropyDecoderIf->parsePPS(pcPPS); }可以看出来,就是一些解码模块对应的功能函数
但是这里有一个比较需要注意的地方就是这个函数里面对应的解码,不仅会用到熵解码的相关方法,还会有CAVLC的解码方法,那么怎么区分呢
这里一个C++相关的知识就有了,C++类的多态的实现
TDecEntropyIf* m_pcEntropyDecoderIf;
class TDecEntropyIf
{
public:
// Virtual list for SBAC/CAVLC
virtual Void resetEntropy ( TComSlice* pcSlice ) = 0;
virtual Void setBitstream ( TComInputBitstream* p ) = 0;
virtual Void parseVPS ( TComVPS* pcVPS ) = 0;
virtual Void parseSPS ( TComSPS* pcSPS ) = 0;
virtual Void parsePPS ( TComPPS* pcPPS ) = 0;
virtual Void parseSliceHeader ( TComSlice* pcSlice, ParameterSetManagerDecoder *parameterSetManager) = 0;
virtual Void parseTerminatingBit ( UInt& ruilsLast ) = 0;
virtual Void parseRemainingBytes( Bool noTrailingBytesExpected ) = 0;
virtual Void parseMVPIdx ( Int& riMVPIdx ) = 0;
public:
virtual Void parseSkipFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parseCUTransquantBypassFlag( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parseSplitFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parsePLTModeFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parsePLTModeSyntax ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiNumComp) = 0;
virtual Void parsePLTSharingModeFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parseScanRotationModeFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parseMergeFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth, UInt uiPUIdx ) = 0;
virtual Void parseMergeIndex ( TComDataCU* pcCU, UInt& ruiMergeIndex ) = 0;
virtual Void parsePartSize ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parsePartSizeIntraBC( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parsePredMode ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parseIntraDirLumaAng( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parseIntraDirChroma( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parseIntraBCFlag ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ) = 0;
virtual Void parseIntraBC ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiPartIdx, UInt uiDepth ) = 0;
virtual Void parseIntraBCBvd ( TComDataCU* pcCU, UInt uiAbsPartAddr, UInt uiPartIdx, UInt uiDepth, RefPicList eRefList ) = 0;
virtual Void parseInterDir ( TComDataCU* pcCU, UInt& ruiInterDir, UInt uiAbsPartIdx ) = 0;
virtual Void parseRefFrmIdx ( TComDataCU* pcCU, Int& riRefFrmIdx, RefPicList eRefList ) = 0;
virtual Void parseMvd ( TComDataCU* pcCU, UInt uiAbsPartAddr, UInt uiPartIdx, UInt uiDepth, RefPicList eRefList ) = 0;
virtual Void parseCrossComponentPrediction ( class TComTU &rTu, ComponentID compID ) = 0;
virtual Void parseTransformSubdivFlag( UInt& ruiSubdivFlag, UInt uiLog2TransformBlockSize ) = 0;
virtual Void parseQtCbf ( TComTU &rTu, const ComponentID compID, const Bool lowestLevel ) = 0;
virtual Void parseColourTransformFlag( UInt uiAbsPartIdx, Bool& uiFlag ) = 0;
virtual Void parseQtRootCbf ( UInt uiAbsPartIdx, UInt& uiQtRootCbf ) = 0;
virtual Void parseDeltaQP ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parseChromaQpAdjustment( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth ) = 0;
virtual Void parseIPCMInfo ( TComDataCU* pcCU, UInt uiAbsPartIdx, UInt uiDepth) = 0;
virtual Void parseCoeffNxN( class TComTU &rTu, ComponentID compID ) = 0;
virtual Void parseTransformSkipFlags ( class TComTU &rTu, ComponentID component ) = 0;
virtual Void parseExplicitRdpcmMode ( TComTU &rTu, ComponentID compID ) = 0;
virtual ~TDecEntropyIf() {}
};Void setEntropyDecoder ( TDecEntropyIf* p );
比如
class TDecSbac : public TDecEntropyIf
class TDecCavlc : public SyntaxElementParser, public TDecEntropyIf
这样上层的类就基本上差不多了
和熵解码最相关的两个类:
TDecSbac m_cSbacDecoder; TDecBinCABAC m_cBinCABAC;
Void load ( const TDecSbac* pSrc );
Void loadContexts ( const TDecSbac* pSrc );
Void xCopyFrom ( const TDecSbac* pSrc );
Void xCopyContextsFrom ( const TDecSbac* pSrc );
Void resetEntropy (TComSlice* pSlice );
Void setBitstream ( TComInputBitstream* p ) { m_pcBitstream = p; m_pcTDecBinIf->init( p ); }
Void parseVPS ( TComVPS* /*pcVPS*/ ) {}
Void parseSPS ( TComSPS* /*pcSPS*/ ) {}
Void parsePPS ( TComPPS* /*pcPPS*/ ) {}
Void parseSliceHeader ( TComSlice* /*pcSlice*/, ParameterSetManagerDecoder* /*parameterSetManager*/) {}
Void parseTerminatingBit ( UInt& ruiBit );
Void parseRemainingBytes ( Bool noTrailingBytesExpected);
Void parseMVPIdx ( Int& riMVPIdx );
Void parseSaoMaxUvlc ( UInt& val, UInt maxSymbol );
Void parseSaoMerge ( UInt& ruiVal );
Void parseSaoTypeIdx ( UInt& ruiVal );
Void parseSaoUflc ( UInt uiLength, UInt& ruiVal );
Void parseSAOBlkParam (SAOBlkParam& saoBlkParam, Bool* sliceEnabled, Bool leftMergeAvail, Bool aboveMergeAvail);
Void parseSaoSign (UInt& val);
码流的获取,底层熵解码一个bit,根据bit数据反二值化等操作,最终解出语法元素相应的值
而TDecBinCABAC类就是熵解码中最底层,从码流中解码出相应的1个bit数据的函数
也就是最底层的算术解码
Void decodeBin ( UInt& ruiBin, ContextModel& rcCtxModel );
Void decodeBinEP ( UInt& ruiBin );
Void decodeBinsEP ( UInt& ruiBin, Int numBins );
Void decodeAlignedBinsEP( UInt& ruiBins, Int numBins );
#endif
Void align ();
Void decodeBinTrm ( UInt& ruiBin );
Void xReadPCMCode ( UInt uiLength, UInt& ruiCode );
Void copyState ( const TDecBinIf* pcTDecBinIf );
TDecBinCABAC* getTDecBinCABAC() { return this; }
const TDecBinCABAC* getTDecBinCABAC() const { return this; }
private:
TComInputBitstream* m_pcTComBitstream;
UInt m_uiRange;
UInt m_uiValue;
Int m_bitsNeeded;
};在HM中和熵解码有关的类结构基本上罗列出来就是:
TAppDecTop
TDecTop
TDecEntropy
TDecSbac
TDecBinCABAC
原文地址:http://blog.csdn.net/xietingcandice/article/details/42105203