HM代码粗略介绍

来源:互联网 发布:腾讯体育nba数据库 编辑:程序博客网 时间:2024/04/29 19:04

转自http://blog.csdn.net/hq2902108007/article/details/8965090

1. 环境配置

这个文档描述的版本是HM6.0

运行的方法如下可参考之前的文章:

2. 编码端主函数的调用

主函数中会调用create函数,但是这里面是空函数,所以不做任何操作

encode是非常重要的函数,负责了实际的编码工作,在里面调用m_cTEncTop的encode

函数对每个GOP进行编码,并对每个GOP调用compressGOP。GOP的概念在HEVC中规定的并没有H.264/AVC那么严格,在H.264/AVC中,GOP是以I slice开始,而HEVC中并没有这样的规定,相当于弱化了HEVC中GOP的概念。

3. GOP划分为Slice

GOP进而会划分为slice,有raster顺序的划分和tile的划分方式,对每个slice会调用

compressSlice来的对其选出最优的参数。然后调用encodeSlice来对其进行实际的熵编码工作。

Slice:Slice是一帧中按光栅扫描顺序排列的CTU序列。一帧可以由多个Slice组成。每个Slice可以独立解码,因为Slice内像素的预测不能跨越Slice的边界。每个Slice可以按照编码类型的不同分为I/P/B Slice。该结构的主要目的是实现在传输中遭遇数据丢失后的重新同步。每个Slice可携带的最大比特数通常受限,因此根据视频场景的运动程度,Slice所包含的的CTU数量可能有很大不同。

Dependent Slice:其编码或解码的熵编码CABAC上下文状态是以上一个Slice为基础,因此,它不能完成数据丢失后的重新同步。该技术可以理解为对原先NALU数据的进一步拆分,可以适合更加灵活的打包方式。

Tile:是帧内可以进行解码的矩形区域,包含多个按矩形排列的CTU(数目不要求一定相同),定义这一结构的初衷是增强编解码的并行处理性能,同一个slice内的多个tiles可以共享相同的头信息,一个tile也可以包含多个slice,不管是slice包含tile,还是tile包含slice都必须是整数包含的关系。

4. Slice的划分(Slice到LCU)

到Slice层面后,会划分等大的LCU,对每个CU进行compress和encode的工作,调用的函数分别为compressCU和encodeCU。而在CompressSlice和EncoderSlice中都会调用encodeCU,是为了保证后续计算码率的准确性,重点在于保证了cabac的状态是准确的。下面将介绍compressCU和encodeCU,由于RDO的时候会编码CU的信息,所以着重介绍compressCU

5. compressCU

把一个slice内部的图像划分为K个LCU,同时这K个LCU是以raster的顺序来进行扫描的。LCU的尺寸默认为64x64,可以通过配置文件中的MaxCUWidth,MaxCUHeight来进行设置。而每个LCU会调用如下的compressCU函数去决定编码的参数。 而LCU是采用四叉树的表示结构,每个LCU会被递归的划分为4个子CU,并根据RD代价来确定是否进行划分,而每个LCU相当于树的第1层,所以他会调用xCompressCU。且在xCompressCU中会对每个子CU递归的调用xCompressCU,如下图所示,当然子CU的尺寸是当前CU的四分之一。




然而在每次xCompressCU时,会对当前CU进行intra模式的测试,如果是B或Pslice,还对其进行merge和inter模式的测试。下面分别介绍intra,inter和merge相关的代码

5.1 帧内

intra的调用流程如下:

estIntraPredQT主要做模式选择的工作,负责选出对于当前PU的最优模式,如DC,或方向性,或planar。estIntraPredChromaQT做了类似的工作,不过是针对于色度。xRecurIntraCodingQT和xRecurIntraChromaCodingQT函数是依据给定的候选模式进行PU的分割,进而依据TU进行重建estIntraPredQT。

5.1.1 estIntraPredQT

在这里面首先对N个候选模式进行粗粒度筛选

代价函数为,从M个模式选出N个最可能的候选模式。所涉及的函数:

l predIntraLumaAng: 算出当前PU的预测值

l calcHAD: 计算SATD代价

l xModeBitsIntra: 计算当前模式所耗费的比特数目

l xUpdateCandList: 更新模式的代价,保持前N个模式的代价最小

在选出N个模式后,这N个模式会进入xRecurIntraCodingQT函数从而进行TU的分割

5.1.2 xRecurIntraCodingQT

为了加速RQT过程,这个函数会被调用两次:

第一次的调用不进行PU分割为TU的过程,PU直接转换为TU,只为算出N个模式的RD代价,从而选出一个最优的,在这个最优的模式被选出后,会第二次调用这个函数,再对这个最优的模式进行PU的分割。区分第一次和第二次调用的变量是bCheckFirst。这个过程所涉及的函数有:

l xIntraCodingLumaBlk: 进行对当前TU进行求残差,对残差变换,量化,反量化,反变换,重建当前TU等一系列编码工作,并求得失真

l xGetIntraBitsQT: 求出当前模式的所有信息进行熵编码会产生的比特数

l calcRdCos:根据xIntraCodingLumaBlk得到的失真和xGetIntraBitsQT产生的比特数目进行RD代价的计算,从而比较各模式的优劣

l xSetIntraResultQT:保存最优模式的数据

5.1.3 estIntraPredChromaQT

estIntraPredChromaQT会决定当前PU采用哪个色度模型对色度分量进行编码,其中涉及的函数如下:

l getAllowedChromaDir:获得可用的色度

l xRecurIntraChromaCodingQT:进行当前PU的色度分量的一系列编码工作,并求得失真

l xGetIntraBitsQT:进行当前PU的色度分量的熵编码工作,并得到产生的比特数

l calcRdCost:根据失真和码率进行率失真代价的计算

l xSetIntraResultChromaQT:保存当前色度最优模式的信息

5.1.4 xRecurIntraChromaCodingQT

这个函数是求PU的色度分量的残差,首先会对PU进行分割,分割的层数与亮度完全一致。涉及的函数如下:

l xIntraCodingChromaBlk:对当前TU进行色度信息的编码工作,如求残差,变换,量化,反量化,反变换,重建等一系列工作

5.2 帧间

帧间按默认的配置文件设置有两种:inter模式和merge模式

5.2.1 inter模式和merge模式的流程

主要调用流程:

Inter流程

Merge流程

流程中涉及的函数:

l predInterSearch进行的是ME和MC的过程,当然会测试各种情况

l Motioncompensation进行的是MC的工作,由于merge模式没有ME的过程,是将已有的MV信息直接代替当前PU的MV,所以直接进行MC

l encodeResAndCalcRdInterCU是对得到预测值后求出的残差进行TU的划分及RD代价的计算

5.2.2 encodeResAndCalcRdInterCU

涉及的主要函数:

l encodeSkipFlag:编码SKIP模式的flag

l encodeMergeIndex:编码选用哪套运动参数的索引

xEstimateResidualQT:在非SKIP模式的时候要进行RQT的决定,即PU分割为什么样的TU在这个函数里面确定

l xAddSymbolBitsInter:计算当前CU的信息在进行熵编码时所产生的比特数

l xSetResidualQTData:保存当前CU的最优的残差信息

6. 一些其他常用的函数说明:

6.1 预测

6.1.1 帧内

l initPattern:判断周围块的存在性

l initAdiPattern:获取周围像素的值当做生成预测值的像素,并开辟出一片缓存 区存储经过多种滤波类型的预测值

l getPredictorPtr:根据不同模式选择经过不同类型滤波的预测集

l predIntraLumaAng: 对亮度信号进行预测,里面会调用xPredIntraPlanar,xPredIntraAng以及xDCPredFiltering

l predIntraChromaAng: 对色度信号进行预测,里面会调用xPredIntraPlanar和xPredIntraAng

l xPredIntraPlanar: planar模式的预测

l xPredIntraAng: 角度的方向性预测

l xDCPredFiltering: 对DC的预测值进行滤波

l getLumaRecPixels: 获取亮度的重建值,为进行LM模式的预测做准备

l predLMIntraChroma:对LM模式进行预测,即利用亮度的相关性,对色度进行预测

6.1.2 帧间

l getInterMergeCandidates: 获取merge的候选运动参数集

l motionCompensation:进行运动补偿

l xMotionEstimation:进行运动估计

l xEstimateMvPredAMVP:选出代价最小的MVP

l xCheckBestMVP:在知道MV的情况下比较各个MVP的优劣,并保存最优的

l xMergeEstimation:在inter模式时也可以使用merge模式的运动估计方法,这个函数用于计算这种情况时的代价

6.2 变换

l transformNxN:会调用xT和xQuant函数

l invtransformNxN:会调用xDeQuant和xIT函数

l xT: 对残差信号进行变换

l xQuant:对变换系数进行量化

l xDeQuant:反量化

l xIT:反变换

6.3 熵编码

在这节中主要介绍编码端为算RD代价而设计的熵编码函数,实际的熵编码函数在后面的章节中进行介绍

主要函数:

6.3.1 帧内熵编码

l xEncIntraHeader:编码intra的一些头部信息,主要包括:模式号,PU的分割类型,PCM标志,如果是B或P slice,还包括skip的标志位和编码模式的类型

l xEncSubdivCbfQT:会编码Cbf和TU分割的标志位

l xEncCoeffQT:编码每个TU的系数

l encodeCoeffNxN:调用codeCoeffNxN来编码每个TU的残差系数

l encodeTransformSubdivFlag:调用codeTransformSubdivFlag来编码TU分割的标志,是否继续分割

l encodeQtCbf:编码cbf标志位,检查是否有非零的系数

l encodePredMode:编码所采用的编码模式

l encodePartSize:编码PU的分割类型

l encodeIntraDirModeLuma:编码PU的亮度模式号,这里引入了3MPM的机制,具体可参考提案H0238

l encodeIntraDirModeChroma:编码PU的色度模式号

6.3.2 帧间熵编码

l encodePredMode:编码CU所采用的模式,主要决定是inter还是intra

l encodePartSize:编码PU的分割类型

l encodePredInfo:编码运动参数

(1) merge的标志位来区别是否采用merge模式,具体函数:encodeMergeFlag

然后分(2)和(3)两种情况。

(2) merge模式:只需传输运动候选集的索引,具体函数:encodeMergeIndex

(3) 正常的inter模式

A. encodeInterDirPU:编码帧间的预测方向,前向,后向,或多方向

B. encodeRefFrmIdxPU: 编码参考帧索引

C. encodeMvdPU:编码MV的残差MVD

D. encodeMVPIdxPU: 编码MVP的索引

7. EncoderCU

HEVC以LCU为基本单位,所以在进行熵编码时也是以LCU为单位进行的EncodeCU会调用从而对每个CU进行编码,如下图所示,在xEncodeCU中会调用如下几个函数:

encodeSkipFlag编码是否是skip模式

encodeMergeIndex如果是skip模式会编码选用哪套MVP的参数

encodePredMode编码CU的模式,是intra还是inter

encodePartSize编码CU中的PU的类型

encodeIPCMInfo 如果选用了PCM模式会编码PCM模式的信息

encodePredInfo编码预测的信息,如果是帧内,编码模式号,如果是帧间,则编码运动信息

encodeCoeff编码残差系数

encodeCoeff中会编码TU的分割标志位,cbf和残差系数的信息

而具体的信息可以参照3.3节

8. 一些主要变量和数据结构的说明:

8.1 TComDataCU:LCU及其子CU的数据结构,存储了一个LCU所有的相关信息,里面重要的数据结构包括:

l m_uiCUAddr:一个LCU在slice中的位置

l m_uiAbsIdxInLCU:当前CU在LCU中的位置,位置用Z扫描顺序

l m_puhWidth: CU的宽度

l m_puhHeight:CU的高度

l m_puhDepth: CU所处的深度

l m_pePartSize: PU的类型

l m_pePredMode:编码模式

l m_pcTrCoeffY,m_pcTrCoeffCb,m_pcTrCoeffCr:量化后的系数

l m_puhLumaIntraDir:亮度的模式信息

l m_puhChromaIntraDir:色度的模式信息

l m_puhInterDir:帧间的预测方向

l m_apiMVPIdx:MVP索引

l m_apiMVPNum:MVP的候选数

以上的数据结构都是以动态存储来分配空间,一般只有一维,这一维具体取值的含义就是CU里面的每个对应的4x4的小块的信息,而开辟的数目就是CU所包含的4x4的数目,而在实际编码时也是编码了这些信息。

需要着重说明2点

(1) m_uiCUAddr是一个LCU在slice中的位置,是raster的扫描顺序

(2) m_uiAbsIdxInLCU是表明CU在LCU中的位置,Z扫描顺序,最小单位为1,代表

其中的一个4x4子块,Z扫描顺序如下图所示

(3) Z扫描转换,如下图所示,展示了一个CU内部的Z扫描的顺序,在hevc中,Z扫描顺序是以4x4为基本单位的,一个具有默认尺寸的LCU,具有256个基本单元

8.2 RDO时所用到的主要临时变量

l m_ppcQTTempCoeffY,m_ppcQTTempCoeffCb,m_ppcQTTempCoeffCr:RQT时每层的量化系数,都保存在此,是为了确定最终分割后可以很容易的获取最优值

l m_pcQTTempCoeffY,m_pcQTTempCoeffCb,m_pcQTTempCoeffCr:CU层的量化系数暂存地,只有帧间编码时才会用到,是中间变量

l m_pcQTTempTComYuv: 重建视频的暂存缓冲区

l m_puhQTTempCbf: cbf的暂存

l m_puhQTTempTrIdx:变换层数的暂存

l m_ppcBestCU:存储每层最优(RD代价最小)的CU的信息

l m_ppcTempCU: 存储每层CU的信息的临时变量

l m_ppcPredYuvBest: 存储每层最优的预测值

l m_ppcResiYuvBest:存储每层最优的残差值

l m_ppcRecoYuvBest:存储每层最优的重建值

l m_ppcPredYuvTemp:存储每层预测值的临时变量

l m_ppcResiYuvTemp:存储每层残差值的临时变量

l m_ppcRecoYuvTemp:存储每层重建值的临时变量

l m_ppcOrigYuv::存储每层对应的原始值

8.3 yuv的存储的关系

8.3.1 TComYuv数据结构

由m_apiBufY,m_apiBufU以及m_apiBufV三个buffer组成,通用的yuv数据结构,存储是yuv的亮度和色度信息

8.3.2 TComPicYuv数据结构

图像层级的yuv数据结构,存储的是一帧的yuv信息,主要用于ALF和去方块滤波等处理的过程中

TComYuv的类型的变量存储的是RDO时的值,最优的信息要存在TComPicYuv中,便于输出和进行全局处理

9. 解码端的简单说明

9.1 xDecodeCU: 与xEncodeCU类似,进行LCU的读取码流并存至变量的工作,可以理解为与xEncodeCU的逆过程。涉及的函数如下:

l decodeSkipFlag:解码skip的flag,看是不是skip模式

l decodePredMode:解码编码模式

l decodePartSize: 解码PU分割的类型

l decodePredInfo:解码预测信息,帧内就是解码模式信息,帧间是解码运动信息

l decodeCoeff:解码量化系数

9.2 xDecompressCU: 具体的任务为重建这个LCU,涉及的函数如下:

9.2.1 xReconInter

负责inter部分的重建,主要函数如下:

l xDecodeInterTexture:分别对YUV分量调用invRecurTransformNxN

l invRecurTransformNxN:对特定分量进行TU的反量化和反变换

l addClip:得到残差后会加上预测值形成重建指

l copyPartToPartYuv:如果系数全是零,则直接将重构值赋值为预测值

9.2.2 xReconIntraQT

负责intra部分的重建

xIntraLumaRecQT:亮度信息的重建,会对每个TU调用xIntraRecLumaBlk

xIntraRecLumaBlk:TU的亮度信息反量化及重建工作

xIntraChromaRecQT:色度信息的重建,会对每个TU调用xIntraRecChromaBlk:TU的色度信息反量化及重建工作

原创粉丝点击