HM学习
TAppEncoder的函数调用关系图
函数背景色
函数在图中以方框的形式表现出来。不同的背景色标志了该函数不同的作用:
白色背景的函数:不加区分的普通内部函数。
黄色背景函数:滤波函数(Filter)。用于环路滤波,半像素插值,SSIM/PSNR的计算。
绿色背景的函数:CU编码函数(Encode)。通过对残差的DCT变换、量化等方式对CU进行编码。
紫色背景的函数:熵编码函数(Entropy Coding)。对CU编码后的数据进行CABAC熵编码。
浅蓝色背景函数:码率控制函数(Rate Control)。对码率进行控制的函数。
箭头线
箭头线标志了函数的调用关系:
黑色箭头线:不加区别的调用关系。
黄色箭头线:滤波函数(Filter)之间的调用关系。
绿色箭头线:CU编码函数(Encode)之间的调用关系。
紫色箭头线:熵编码函数(Entropy Coding)之间的调用关系。
函数所在的文件:每个函数标识了它所在的文件路径。
下文记录结构图中关键部分
普通内部函数
普通内部函数指的是TAppEncoder中还没有进行分类的函数。例如:
编码器的main()函数中调用的TAppEncTop类的配置读取函数parseCfg()、编码函数encode()等。
编码器最主要的函数:TEncTop中的encode()、TEncGOP中的compressGOP()、TEncSlice的compressSlice()等。
CU编码函数
CU编码函数通过运动估计、DCT变换、量化等步骤对图像数据进行编码。编码的工作都是在TEncCu类中的compressCtu()中完成的。compressCtu()调用了xCompressCU()完成了CU的编码工作。xCompressCU()本身是一个递归调用的函数,其中的xCheckRDCostInter()完成了分析帧间CU编码代价的工作;其中的xCheckRDCostIntra()则完成了分析帧内CU编码代价的工作。
熵编码函数
熵编码函数使用CABAC的方式对CU编码后的数据进行熵编码。熵编码的工作都是在TEncCu类中的encodeCtu()中完成的。
环路滤波函数
环路滤波函数对重建帧数据进行滤波,去除方块效应和振铃效应。TComLoopFilter类的loopFilterPic()完成了去块效应滤波器的工作; TComSampleAdaptiveOffset类的SAOProcess()完成了去除振铃效应的SAO滤波器的工作。
码率控制函数
码率控制模块函数分布在lencod源代码不同的地方,包括rc_init_seq()、rc_init_GOP()、rc_init_frame()、rc_handle_mb()等。
HM解决方案
总共包含了7个工程:
1. TAppCommon 2. TAppDecoder 3. TAppEncoder
4. TLibCommon 5. TLibDecoder 6. TLibEncoder7. TLibVideoIO
应用函数与库函数的主要区别是:前者是面向用户的,主要是通过调用若干库函数实现更为丰富和复杂的功能,而后者是面向程序设计者的,或者说对用户是不可见的,它由程序设计者来实现,主要是对一些基本的功能进行底层设计与实现,对于用户来说,只关心这些库函数的接口以及如何调用,不需也不应该关心它的实现。'Common'表明该工程包含的一些函数是编码器和解码器共用的,'Decoder'表明该工程包含的函数是解码器使用的,而'Encoder'表明该工程包含的函数是编码器使用的。'VideoIO'工程主要是实现对YUV文件的读写操作。
(1)类的命名:
一般来说,一个头文件只包含一个类的定义,文件名即为类名,且该类是属于哪个工程的,它的名字就以该工程的前几个字母开头,如类TAppEncTop,它就是以工程TAppEncoder的前7个字母开头,因此,从该类的名字,就能够看出该类是属于哪个工程的。
(2)变量的命名:
对于类的数据成员来说,一般以'm_'开头,即'member';对于全局变量来说,一般以'g_'开头,即'global'。
对于一般的变量(包含上述两种变量)来说,有如下命名规则:'p',该变量是指针类型,即'pointer',n个'p'则表明该指针为n级指针;'c',该变量是某个类的对象,即'class';'i',该变量是整型,即'int';'u',该变量是无符号型,即'unsigned';'h',该变量是字符型,这里不用'c'来代表'char’应该是为了避免跟前面的'class'冲突了;'b',该变量是布尔类型,即'bool’;'d',该变量是双精度浮点数,即'double';'f',该变量是单精度浮点数,即'float';'a',该变量是类组,即'array';'e',该变量是枚举类型,即'enum';'r',该变量是引用类型,等等。值得一提的是,不是每个变量的命名都满足这些规则,具体情况还是要具体分析的。但是,按照这些规则,80%以上的变量都能一眼看出它的特性来。
(3)函数的命名:
一般来说,对于一个类的成员函数来说,如果该函数的访问权限是'protected',则在其函数名前加上'x';
在工程TLibEncoder的头文件TEncCu.h中,定义了一个类TEncCu,有个数据成员m_ppcBestCU,根据前面的命名规则,它首先是个数据成员,是个二级指针,且是指向一个类的,实际上,它是这么声明的,TComDataCU**,TComDataCU它就是一个类,且该变量被声明为二级指针,据此,符合上述命名规则。
还有一个数据成员这么声明UChar
m_uhTotalDepth; 无符号字符型,同样也是符合命名规则的。
在该类中,有这么一个成员函数xCompressCU,以'x'开头命名,在类中被声明为'protected',符合命名规则。
compress 选出最优的参数 encode进行编码
Encmain-TappEnctop.encode-TEncTop.encodecompressGOP ---
(1)TEncGOP::compressGOP/ compressSlice(789)-
TEncSlice.compressSlice--1) TEncCu::compressCU(1040)- TEncCu::xCompressCU
--2)TEncCu::encodeCU(1087)-TEncCu::xEncodeCU
-----TEncCu::xCheckRDCostIntra(帧内预测692、698、1356)---TEncSearch::estIntraPredQT
----- TEncCu::xCheckRDCostInter(帧间)------------------------TEncSearch:: predInterSearch
------ TEncCu:: xCheckRDCostMerge2Nx2N (merge)
(2) TEncGOP:: encodeSlice--1)TEncSlice.encodeSlice(熵编码)/
--2)TEncSlice.CompressSlice
HM的代码流程
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,是为了保证后续计算码率的准确性,CompressSlice中对encodeCU的调用是为了保证在模式选择中后续CU的CABAC状态的正确,EncodeSlice中调用encodeCU就是为了编码得到码流。下面将介绍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的调用流程如下:
xCheckRDCostIntra(TEncCu)
1)estIntraPredQT主要做模式选择的工作,负责选出对于当前PU的最优模式,如DC,或方向性,或planar。estIntraPredChromaQT做了类似的工作,不过是针对于色度。
2)xRecurIntraCodingQT和xRecurIntraChromaCodingQT函数是依据给定的候选模式进行PU的分割,进而依据TU进行重建estIntraPredQT。
5.1.1estIntraPredQT(TEncSearch)
在这里面首先对N个候选模式进行粗粒度筛选
代价函数为,从M个模式选出N个最可能的候选模式。所涉及的函数:
l predIntraLumaAng(TComPrediction): 算出当前PU的预测值
l calcHAD(TComRdCost): 计算SATD代价
l xModeBitsIntra(TEncSearch): 计算当前模式所耗费的比特数目
l xUpdateCandList(TEncSearch): 更新模式的代价,保持前N个模式的代价最小
在选出N个模式后,这N个模式会进入xRecurIntraCodingQT函数从而进行TU的分割
5.1.2xRecurIntraCodingQT(TEncSearch)
为了加速RQT过程,这个函数会被调用两次:
第一次的调用不进行PU分割为TU的过程,PU直接转换为TU,只为算出N个模式的RD代价,从而选出一个最优的,在这个最优的模式被选出后,会第二次调用这个函数,再对这个最优的模式进行PU的分割。区分第一次和第二次调用的变量是bCheckFirst。这个过程所涉及的函数有:
lxIntraCodingLumaBlk(TEncSearch): 进行对当前TU进行求残差,对残差变换,量化,反量化,反变换,重建当前TU等一系列编码工作,并求得失真
l xGetIntraBitsQT(TEncSearch): 求出当前模式的所有信息进行熵编码会产生的比特数
lcalcRdCost(TComRdCost):
根据xIntraCodingLumaBlk得到的失真和xGetIntraBitsQT产生的比特数目进行RD代价的计算,从而比较各模式的优劣
lxSetIntraResultQT(TEncSearch):保存最优模式的数据
5.1.3estIntraPredChromaQT(TEncSearch)
estIntraPredChromaQT会决定当前PU采用哪个色度模型对色度分量进行编码,其中涉及的函数如下:
l getAllowedChromaDir(TComDataCU):获得可用的色度
l xRecurIntraChromaCodingQT(TEncSearch):进行当前PU的色度分量的一系列编码工作,并求得失真
l xGetIntraBitsQT:进行当前PU的色度分量的熵编码工作,并得到产生的比特数
l calcRdCost:根据失真和码率进行率失真代价的计算
l xSetIntraResultChromaQT:保存当前色度最优模式的信息
5.1.4xRecurIntraChromaCodingQT(TEncSearch)
这个函数是求PU的色度分量的残差,首先会对PU进行分割,分割的层数与亮度完全一致。涉及的函数如下:
l xIntraCodingChromaBlk:对当前TU进行色度信息的编码工作,如求残差,变换,量化,反量化,反变换,重建等一系列工作
5.2 帧间
帧间按默认的配置文件设置有两种:inter模式和merge模式
5.2.1inter模式和merge模式的流程
xCheckRDCostInter(TEncCu)和xCheckRDCostmerge2Nx2N(TEncCu)主要调用流程:
Inter流程
Merge流程
流程中涉及的函数:
l predInterSearch(TEncSearch)进行的是ME和MC的过程,当然会测试各种情况
l Motioncompensation(TComPrediction)进行的是MC的工作,由于merge模式没有ME的过程,是将已有的MV信息直接代替当前PU的MV,所以直接进行MC
l encodeResAndCalcRdInterCU(TEncSearch)是对得到预测值后求出的残差进行TU的划分及RD代价的计算
5.2.2encodeResAndCalcRdInterCU
涉及的主要函数:
l encodeSkipFlag(TEncEntropy):编码SKIP模式的flag
l encodeMergeIndex(TEncEntropy):编码选用哪套运动参数的索引
xEstimateResidualQT(TEncSearch):在非SKIP模式的时候要进行RQT的决定,即PU分割什么样的TU在这个函数里面确定
l xAddSymbolBitsInter(TEncSearch):计算当前CU的信息在进行熵编码时所产生的比特数
l xSetResidualQTData(TEncSearch):保存当前CU的最优的残差信息
6. 一些其他常用的函数说明:
6.1 预测
6.1.1帧内
l initPattern(TComPattern):判断周围块的存在性
l initAdiPattern(TComPattern):获取周围像素的值当做生成预测值的像素,并开辟出一片缓存区存储经过多种滤波类型的预测值
l getPredictorPtr(TComPattern):根据不同模式选择经过不同类型滤波的预测集
l predIntraLumaAng(TComPrediction): 对亮度信号进行预测,里面会调用xPredIntraPlanar,xPredIntraAng以及xDCPredFiltering
l predIntraChromaAng(TComPrediction):对色度信号进行预测,里面会调用xPredIntraPlanar和xPredIntraAng
l xPredIntraPlanar:planar模式的预测
l xPredIntraAng: 角度的方向性预测
l xDCPredFiltering: 对DC的预测值进行滤波
l getLumaRecPixels: 获取亮度的重建值,为进行LM模式的预测做准备
l predLMIntraChroma:对LM???模式进行预测,即利用亮度的相关性,对色度进行预测
6.1.2帧间
l getInterMergeCandidates(TComDataCU):获取merge的候选运动参数集
l motionCompensation(TComPrediction):进行运动补偿
l xMotionEstimation(TEncSearch):进行运动估计
l xEstimateMvPredAMVP(TEncSearch):选出代价最小的MVP
l xCheckBestMVP(TEncSearch):在知道MV的情况下比较各个MVP的优劣,并保存最优的
l xMergeEstimation(TEncSearch):在inter模式时也可以使用merge模式的运动估计方法,这个函数用于计算这种情况时的代价
6.2 变换
l transformNxN(TComTrQuant):会调用xT和xQuant函数
l invtransformNxN(TComTrQuant):会调用xDeQuant和xIT函数
l xT(TComTrQuant): 对残差信号进行变换
l xQuant(TComTrQuant):对变换系数进行量化
l xDeQuant(TComTrQuant):反量化
l xIT(TComTrQuant):反变换
6.3 熵编码
在这节中主要介绍编码端计算RD代价而设计的熵编码函数,实际的熵编码函数在后面的章节中进行介绍
主要函数:
6.3.1帧内熵编码
l xEncIntraHeader(TEncSearch):编码intra的一些头部信息,主要包括:模式号,PU的分割类型,PCM标志,如果是B或P slice,还包括skip的标志位和编码模式的类型
l xEncSubdivCbfQT (TEncSearch):会编码Cbf和TU分割的标志位
l xEncCoeffQT (TEncSearch):编码每个TU的系数
l encodeCoeffNxN(TEncEntropy):调用codeCoeffNxN来编码每个TU的残差系数
l encodeTransformSubdivFlag(TEncEntropy):调用codeTransformSubdivFlag来编码TU分割的标志,是否继续分割
l encodeQtCbf(TEncEntropy):编码cbf标志位,检查是否有非零的系数
l encodePredMode(TEncEntropy):编码所采用的编码模式
l encodePartSize(TEncEntropy):编码PU的分割类型
l encodeIntraDirModeLuma(TEncEntropy):编码PU的亮度模式号,这里引入了3MPM的机制,具体可参考提案H0238
l encodeIntraDirModeChroma(TEncEntropy):编码PU的色度模式号
6.3.2帧间熵编码
l encodePredMode(TEncEntropy):编码CU所采用的模式,主要决定是inter还是intra
l encodePredInfo(TEncEntropy):编码运动参数
(1) merge的标志位来区别是否采用merge模式,具体函数:encodeMergeFlag
(TEncEntropy)
然后分(2)和(3)两种情况。
(2) merge模式:只需传输运动候选集的索引,具体函数:encodeMergeIndex(TEncEntropy)
(3) 正常的inter模式
A. encodeInterDirPU(TEncEntropy)
:编码帧间的预测方向,前向,后向,或多方向
B. encodeRefFrmIdxPU(TEncEntropy): 编码参考帧索引
C. encodeMvdPU(TEncEntropy):编码MV的残差MVD
D. encodeMVPIdxPU(TEncEntropy): 编码MVP的索引
7.EncoderCU(TEncCu)
HEVC以LCU为基本单位,所以在进行熵编码时也是以LCU为单位进行的EncodeCU会调用从而对每个CU进行编码,如下图所示,在xEncodeCU(TEncCu)中会调用如下几个函数:
encodeSkipFlag(TEncEntropy)编码是否是skip模式
encodeMergeIndex(TEncEntropy)如果是skip模式会编码选用哪套MVP的参数
encodePredMode(TEncEntropy)编码CU的模式,是intra还是inter
encodePartSize(TEncEntropy)编码CU中的PU的类型
encodeIPCMInfo(TEncEntropy) 如果选用了PCM模式会编码PCM模式的信息
encodePredInfo(TEncEntropy)编码预测的信息,如果是帧内,编码模式号,如果是帧间,则编码运动信息
encodeCoeff(TEncEntropy)编码残差系数
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子块,
(3) Z扫描转换,如下图所示,展示了一个CU内部的Z扫描的顺序,在hevc中,Z扫描顺序是以4x4为基本单位的,一个具有默认尺寸的LCU,具有256个基本单元
8.2RDO时所用到的主要临时变量
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.3yuv的存储的关系
8.3.1TComYuv数据结构
由m_apiBufY,m_apiBufU以及m_apiBufV三个buffer组成,通用的yuv数据结构,存储是yuv的亮度和色度信息
8.3.2TComPicYuv数据结构
图像层级的yuv数据结构,存储的是一帧的yuv信息,主要用于ALF和去方块滤波等处理的过程中
TComYuv的类型的变量存储的是RDO时的值,最优的信息要存在TComPicYuv中,便于输出和进行全局处理
9. 解码端的简单说明
9.1xDecodeCU
与xEncodeCU类似,进行LCU的读取码流并存至变量的工作,可以理解为与xEncodeCU的逆过程。涉及的函数如下:
l decodeSkipFlag:解码skip的flag,看是不是skip模式
l decodePredMode:解码编码模式
l decodePartSize: 解码PU分割的类型
l decodePredInfo:解码预测信息,帧内就是解码模式信息,帧间是解码运动信息
l decodeCoeff:解码量化系数
9.2xDecompressCU
具体的任务为重建这个LCU,涉及的函数如下:
9.2.1xReconInter
负责inter部分的重建,主要函数如下:
l xDecodeInterTexture:分别对YUV分量调用invRecurTransformNxN
l invRecurTransformNxN:对特定分量进行TU的反量化和反变换
l addClip:得到残差后会加上预测值形成重建值
l copyPartToPartYuv:如果系数全是零,则直接将重构值赋值为预测值
9.2.2xReconIntraQT
负责intra部分的重建
xIntraLumaRecQT:亮度信息的重建,会对每个TU调用xIntraRecLumaBlk
xIntraRecLumaBlk:TU的亮度信息反量化及重建工作
xIntraChromaRecQT:色度信息的重建,会对每个TU调用xIntraRecChromaBlk:TU的色度信息反量化及重建工作
HMintra部分
intra中几个函数:
estIntraPredQT主要做模式选择的工作,选出对于当前PU的最优模式,如DC,planar,角度方向。
estIntraPredChromaQT做了类似的工作,不过是针对于色度。
xRecurIntraCodingQT和xRecurIntraChromaCodingQT函数是依据给定的候选模式采用递归进行PU的分割,进而依据TU进行重建estIntraPredQT。
estIntraPredQT在这里面首先对N个候选模式进行粗粒度筛选:采用SATD+λ*ModeBits,从M个模式选出N个最可能的候选模式,在粗选时没有采用TU分割。所涉及的函数:
predIntraLumaAng: 根据mode算出当前PU的预测值
calcHAD: 计算SATD代价
xModeBitsIntra: 计算当前模式所耗费的比特数目
xUpdateCandList: 更新mode代价,保持前N个模式的代价最小
在选出N个模式后,这N个模式会进入xRecurIntraCodingQT函数从而进行TU的分割
xRecurIntraCodingQT
为了加速RQT过程,这个函数会被调用两次:
第一次的调用不进行PU分割为TU的过程, PU直接转换为TU,只为算出N个模式的RD代价,从而选出一个最优的,在这个最优的模式被选出后,会第二次调用这个函数,再对这个最优的模式进行PU的分割。这个过程所涉及的函数:
xIntraCodingLumaBlk: 进行对当前TU进行求残差,对残差变换,量化,反量化,反变换,重建当前TU等一系列编码工作,并求得失真
xGetIntraBitsQT: 求出当前模式的所有信息进行熵编码会产生的比特数
calcRdCos:根据xIntraCodingLumaBlk得到的失真和xGetIntraBitsQT产生的比特数目进行RD代价的计算,比较各模式的优劣
xSetIntraResultQT:保存最优模式的数据
CABAC
Context-based Adaptive Binary Arithmetic Coding 基于自适应二元算术编码
算术编码是一种常用的变字长编码,对出现概率大的符号赋予短码,对概率小的符号赋予长码;它和 Huffman 编码最大的区别在于它不是使用整数码;
算术编码是把各符号出现的概率表示在单位概率[0,1]区间之中,区间的宽度代表概率值的大小。符号出现的概率越大对应于区间愈宽,可用较短码字表示;符号出现概率越小对应于区间愈窄,需要较长码字表示;
CABAC分为三个部份,Binarizer,ContextModeler和ArithmeticCodingEngine。
CABAC的设计概念,对于发生机率>0.5的事件有效地编码,改进了传统霍夫曼编码法需要大量的乘法运算的问题,而在效能与压缩效率上取得相当大的改善空间。
CABAC的生命周期是slice,CABAC与UVLC最大的不同点在于其编码方式具有适应性(adaptive),对于编码过程中各个符号(symbol)出现的机率会一直动态地去统计并更新。
CABAC编码之所以能取得很高的压缩比,是因为:a)根据每一个语法元素的上下文来选取预测模型;b)使用本地的统计数据来估计概率;c)使用算术编码而不是变长编码
编码一个符号需要经过下面几步
1.CABAC使用的算术编码是基于二进制的算术编码,因此非二进制形式的编码首先要转化为二进制的形式表示
2.“上下文模型”是指对二值化后的符号中的bit位进行编码时使用的概率模型,一种regular coding mode 另一种为 bypass coding mode.。概率模型与最近编码的符号相关,会有多个概率模型可供选择。对于每个bit,编码器选择一个合适的概率模型,并通过相邻元素的信息来优化这个概率模型
3.算术编码。算术编码器根据第2步选择的概率模型对每个bit进行编码。
需要注意的是每个bit的子范围只有两个数:0和1
4.更新预测模型。根据实际编码的值来更新所选择的预测模型。例如,如果所编码的二进制bit为1,则预测模型中的1计数要增加。
CABAC 不支持 Baseline 以及 Extendedprofiles.
Overviewof the High Efficiency Video Coding(HEVC) Standard
G. 帧内预测
Intrapicture Prediction
Fig. 6. Modes and directional orientations for intrapicture prediction.
Intrapicture prediction operates according to the TB size,
and previously decoded boundary samples from spatially
neighboring TBs are used to form the prediction signal.
Directional prediction with 33 different directional orientations
is defined for (square) TB sizes from 4×4 up to 32×32. The
possible prediction directions are shown in Fig. 6. Alternatively,
planar prediction (assuming an amplitude surface with a
horizontal and vertical slope derived from the boundaries) and
DC prediction (a flat surface with a value matching the mean
value of the boundary samples) can also be used. For chroma,
the horizontal, vertical, planar, and DC prediction modes can
be explicitly signaled, or the chroma prediction mode can be
indicated to be the same as the luma prediction mode (and, as a
special case to avoid redundant signaling, when one of the first
four choices is indicated and is the same as the luma prediction
mode, the Intra_Angular[34] mode is applied instead).
帧内预测是以TB尺寸进行操作的;
并且在空域上相邻的前面已解码的边界像素将被用作预测参考信号;
对从4x4到32x32的TB定义了33个不同的预测方向;
所有可能的预测方向如图6中所示;
而且Planar预测和DC预测同样可以使用;
对于色度分量,水平,垂直,planar,DC预测模式可以显示使用;
也可以直接沿用相应的亮度分量的预测模式;
Each CB can be coded by one of several coding types,
depending on the slice type. Similar to H.264/MPEG-4 AVC,
intrapicture predictive coding is supported in all slice types.
HEVC supports various intrapicture predictive coding methods
referred to as Intra_Angular, Intra_Planar, and Intra_DC. The
following subsections present a brief further explanation of
these and several techniques to be applied in common.
依据片类型,每个CB可以使用一个或多个编码类型编码;
和H.264/MPEG-4 AVC一样,帧内预测编码支持所有的片类型;
HEVC支持多种帧内预测编码方法,包括方向,planar, DC;
下面将对通常使用的技术做进一步的解析;
1) 预测块(PB)的划分
PB Partitioning:
An intrapicture-predicted CB of size
M×M may have one of two types of PB partitions referred
to as PART_2N×2N and PART_N×N,the first of which
indicates that the CB is not split and the second indicates that
the CB is split into four equal-sized PBs. (Conceptually, in this
notation, N = M/2.) However, it is possible to represent the
same regions that would be specified by four PBs by using
four smaller CBs when the size of the current CB is larger
than the minimum CU size. Thus, the HEVC design only
allows the partitioning type PART_N×N to be used whenthe
current CB size is equal to the minimum CU size. This means
that the PB size is always equal to the CB size when the
CB is coded using an intrapicture prediction mode and the
CB size is not equal to the minimum CU size. Although the
intrapicture prediction mode is established at the PB level, the
actual prediction process operates separately for each TB.
一个尺寸为MxM的帧内预测CB,是PART_2Nx2N和PART_NxN两中PB划分类型中的一种;
第一种类型,PART_2Nx2N,表示这个CB不能再被划分;
第二种类型,PART_NxN, 表示这个CB可以再被划分成四个相同尺寸(N = M/2)的PB;
然而,当当前CB尺寸大于最小的CU尺寸时,四个PB会使用四个更小的CB来表示相同区域;
因此,当当前CB的尺寸等于最小的CU尺寸时,HEVC只允许PART_NxN划分类型;
这意味着,当CB使用帧内预测编码且CB尺寸不等于最小CU尺寸时,PB尺寸问题等于CB尺寸;
尽管帧内预测是建立在PB级,但实际上帧内预测会独立地在TB级实现;
2) 帧内角度预测
Intra_Angular Prediction:
Spatial-domain intrapicture
prediction has previously been successfully used in
H.264/MPEG-4 AVC. The intrapicture prediction of HEVC
similarly operates in the spatial domain, but is extended
significantly—mainly due to the increased size of theTB
and an increased number of selectable prediction directions.
空域帧内预测在H.264/MPEG-4 AVC中得到了成功的应用;
在HEVC中,随着TB尺寸的增加,提供更多可选的预测方向;
Compared to the eight prediction directions of H.264/MPEG-
4 AVC, HEVC supports a total of 33 prediction directions,
denoted as Intra_Angular[k], where k is a mode number from
2 to 34. The angles are intentionally designed to provide
denser coverage for near-horizontal and near-vertical angles
and coarser coverage for near-diagonal angles to reflect the
observed statistical prevalence of the angles and the effectiveness
of the signal prediction processing.
相对于H.264/MPEG-4 AVC中的8个帧内预测方向,
HEVC支持33个预测方向,总称为Intra_Angular[k],其中k为2到34;
这些角度是对相邻的水平和垂直边界在统计学上的信号预测处理;
When using an Intra_Angular mode, each TB is predicted
directionally from spatially neighboring samples that are reconstructed
(but not yet filtered by the in-loop filters) before
being used for this prediction. For a TB of size N×N, atotal
of 4N+1 spatially neighboring samples may be used for the
prediction, as shown in Fig. 6. When available from preceding
decoding operations, samples from lower left TBs can be used
for prediction in HEVC in addition to samples from TBs at
the left, above, and above right of the current TB.
The prediction process of the Intra_Angular modes can
involve extrapolating samples from the projected reference
sample location according to a given directionality. To remove
the need for sample-by-sample switching between reference
row and column buffers, for Intra_Angular[k] with k in the
range of 2–17, the samples located in the above row are
projected as additional samples located in the left column;
and with k in the range of 18–34, the samples locatedat the
left column are projected as samples located in the above row.
当使用Intra_Angular模式时,每个TB都是使用空域上相邻的已重建的像素来预测;
如图6中所示,对于一个尺寸为NxN的TB, 它一共有4N+1个相邻像素用来预测;
在HEVC中,当先前TB解码操作有效时,左下角相邻TB,左相邻TB,上和右上相邻TB的
相邻边界像素均可用作预测;
Intra_Angular模式的预测处理可以从给定的方向的像素位置中推断得到;
为了去掉在参考行和列buffer中的逐像素的切换,对于Intra_Angular[k]中,
k为2-17时,位于上行的像素被投影成位于左列的额外像素;
k为18-34时,位于左列的像素被投影成位于上行的像素;(投影成一维像素,便于计算)
To improve the intrapicture prediction accuracy, the projected
reference sample location is computed with 1/32 sample
accuracy. Bilinear interpolation is used to obtain the value
of the projected reference sample using two closest reference
samples located at integer positions.
为了提高帧内预测的精度,被投影的参考像素精度位置使用1/32像素精度;
为了获得被投影的参考像素,需要对位于整数位置间的两个最近的参考像素使用线性插值;
The prediction process of the Intra_Angular modes is consistent
across all block sizes and prediction directions, whereas
H.264/MPEG-4 AVC uses different methods for its supported
block sizes of 4×4, 8×8, and 16×16. This design consistency
is especially desirable since HEVC supports a greater variety
of TB sizes and a significantly increased number of prediction
directions compared to H.264/MPEG-4 AVC.
Intra_Angular模式的预测处理可以用于所有块尺寸和预测方向;
这一点是不同于H.264/MPEG-4 AVC对不同的块尺寸(4x4,8x8,16x16)使用不同的帧内预测模式集;
HEVC的这个设计很适合大的TB尺寸预测;
3) 帧内planar和帧内DC预测
Intra_Planar and Intra_DC Prediction:
In addition to Intra_Angular prediction that targets regions with strong
directional edges, HEVC supports two alternative prediction
methods, Intra_Planar and Intra_DC, for which similar modes
were specified in H.264/MPEG-4 AVC. While Intra_DC prediction
uses an average value of reference samples for the
prediction, average values of two linear predictions using four
corner reference samples are used in Intra_Planar prediction
to prevent discontinuities along the block boundaries. The
Intra_Planar prediction mode is supported at all block sizes in
HEVC, while H.264/MPEG-4 AVC supports plane prediction
only when the luma PB size is 16×16, and its planeprediction
operates somewhat differently from the planar prediction in HEVC.
除了Intra_Angular预测外,HEVC还和H.264/MPEG-4 AVC一样,支持Intra_Planar, Intra_DC预测模式;
. Intra_DC 使用参考像素的均值进行预测;
. Intra_Planar 使用四个角的参考像素得到的两个线性预测的均值;
在HEVC中,Intra_Planar预测模式可用于所有块尺寸,
不像在H.264/MPEG-4 AVC中,plane预测模式只能用在16x16的亮度块,且它们的方法也不一样;
4) 参考像素平滑
Reference Sample Smoothing:
In HEVC, the reference
samples used for the intrapicture prediction are sometimes
filtered by a three-tap [1 2 1]/4 smoothing filter in a manner
similar to what was used for 8×8 intrapictureprediction in
H.264/MPEG-4 AVC. HEVC applies smoothing operations
more adaptively, according to the directionality, the amount of
detected discontinuity, and the block size. As in H.264/MPEG-
4 AVC, the smoothing filter is not applied for 4×4blocks. For
8×8 blocks, only the diagonal directions, Intra_Angular[k]
with k = 2, 18, or 34, use the reference sample smoothing.
在HEVC中,用于帧内预测的参考像素可以使用三阶([1 2 1]/4)平滑滤波器来平滑,
这个和H.264/MPEG-4 AVC中的8x8帧内预测模式一样;
HEVC可以根据预测方向,不连续的数量,和块大小对平滑操作灵活使用;
而在H.264/MPEG-4 AVC中,平滑操作不能用于4x4块,对于8x8块,也只能用于对角线预测方向;
HEVC则可以对Intra_Angular[k], k=2, 18, 34,使用参考像素平滑;
For 16×16 blocks, the reference samples are filteredfor
most directions except the near-horizontal and near-vertical
directions, k in the range of 9–11 and 25–27. For 32×32
blocks, all directions except the exactly horizontal (k = 10)
and exactly vertical (k = 26) directions use the smoothing
filter, and when the amount of detected discontinuity exceeds a
threshold, bilinear interpolation from three neighboring region
samples is applied to form a smooth prediction.
对于16x16块,除了近水平和近垂直方向外,可以对k为9-11和25-27预测方向使用参考像素平滑滤波;
对于32x32块,除了水平(k=10)和垂直(k=26)方向外,可以对所有剩下的预测方向使用参考像素平滑滤波;
当不连续侦测的数量超过阈值时,可以对三个相邻区域像素使用线性插值来做平滑预测;
The Intra_Planar mode also uses the smoothing filter when
the block size is greater than or equal to 8×8, and the
smoothing is not used (or useful) for the Intra_DC case.
当块尺寸等于或大于8x8时,可以Intra_Planar模式使用平滑滤波;
不能对Intra_DC模式使用平滑滤波操作,因为本来对这个模式也没有作用;
5) 边界值平滑
Boundary Value Smoothing:
To remove discontinuities along block boundaries, in three modes, Intra_DC(mode 1)
and Intra_Angular[k] with k = 10 or 26 (exactly horizontal
or exactly vertical), the boundary samples inside the TB
are replaced by filtered values when the TB size is smaller
than 32 × 32. For Intra_DC mode, both the first row and
column of samples in the TB are replaced by the output of
a two-tap [3 1]/4 filter fed by their original value and the
adjacent reference sample. In horizontal (Intra_Angular[10])
prediction, the boundary samples of the first column of the
TB are modified such that half of the difference between
their neighbored reference sample and the top-left reference
sample is added. This makes the prediction signal more
smooth when large variations in the vertical direction are
present. In vertical (Intra_Angular[26]) prediction, the same
is applied to the first row of samples.
为了去掉块边界的不连续性,对于这三种模式,
Intra_DC(mode 1),
Intra_Angular[k], k = 10, 26,
当TB的尺寸小于32x32时,TB内的边界像素将被滤波后的值替代;
对于Intra_DC模式,TB内的第一行和第一列的像素,
使用以原像素和相邻像素作为二阶([3 1]/4)滤波器输入的输出值代替;
对于Intra_Angular[10], 水平方向,TB的第一列边界像素,
使用相邻参考像素的差值,再加上左上角参考像素除二来代替;
对于Intra_Angular[26], 垂直方向,TB的第一行边界像素,
和水平的处理类似;
(可能理解不是很准确:-)
6) 参考像素替换
Reference Sample Substitution:
The neighboring reference samples are not available at the slice or tile
boundaries. In addition, when a loss-resilience feature known
as constrained intra prediction is enabled, the neighboring
reference samples inside any interpicture-predicted PB
are also considered not available in order to avoid letting
potentially corrupted prior decoded picture data propagate
errors into the prediction signal. While only Intra_DC
prediction mode is allowed for such cases in H.264/MPEG-4
AVC, HEVC allows the use of other intrapicture prediction
modes after substituting the nonavailable reference sample
values with the neighboring available reference sample values.
在片和瓦片的边界,相邻参考像素是无效的;
另外,当受限帧内预测的丢失恢复功能开启后,为了避免由前面的解码图像造成差错扩散,
所有帧间预测PB的相邻参考像素也是无效的;
在H.264/MPEG-4 AVC中只有Intra_DC预测模式能使用这个功能;
HEVC则允许使用相邻有效的参考像素值替换无效的参考像素值后用于其它帧内预测模式;
7) 模式编码
Mode Coding:
HEVC supports a total of 33 Intra_Angular prediction modes and Intra_Planar and
Intra_DC prediction modes for luma prediction for all block
sizes. Due to the increased number of directions, HEVC
considers three most probable modes (MPMs) when coding the
luma intrapicture prediction mode predictively, rather than the
one most probable mode considered in H.264/MPEG-4 AVC.
Among the three most probable modes, the first two are initialized
by the luma intrapicture prediction modes of the above
and left PBs if those PBs are available and are coded using an
intrapicture prediction mode. Any unavailable prediction mode
is considered to be Intra_DC. The PB above the luma CTB is
always considered to be unavailable in order to avoid the need
to store a line buffer of neighboring luma prediction modes.
HEVC对所有块尺寸的亮度预测支持33种Intra_Angular,Intra_Planar, Intra_DC预测模式;
由于方向的增加,HEVC提供对亮度帧内预测模式的三种最可能模式(MPM)的预测;
不同于H.264/MPEG-4 AVC只提供最可能模式的预测;
在这三个最可能模式中,如果相邻的上方和左方的PB都有效且是帧内预测编码模式,
则前两个使用上方和左方的PB的亮度帧内预测模式来初始化;
所有无效的预测模式都被认为是Intra_DC;
为了避免需要存储相邻亮度预测模式的一行buffer,亮度CTB之上的PB都认为是无效的;
When the first two most probable modes are not equal,
the third most probable mode is set equal to Intra_Planar,
Intra_DC, or Intra_Angular[26] (vertical), according to which
of these modes, in this order, is not a duplicate of one of
the first two modes. When the first two most probable modes
are the same, if this first mode has the value Intra_Planar
or Intra_DC, the second and third most probable modes are
assigned as Intra_Planar, Intra_DC, or Intra_Angular[26],
according to which of these modes, in this order, are not
duplicates. When the first two most probable modes are the
same and the first mode has an Intra_Angular value, the
second and third most probable modes are chosen as the two
angular prediction modes that are closest to the angle (i.e., the
value of k) of the first.
当前两个最可能模式不相等时,
则依据Intra_Planar,Intra_DC,或Intra_Angular[26](垂直)这三种模式,
将第三个最可能预测模式设为在顺序上不和前两种模式重复的模式;
当前两个最可能模式是相等时,
且第一个模式的值为Intra_Planar或Intra_DC,
则依据Intra_Planar,Intra_DC,或Intra_Angular[26](垂直)这三种模式,
将第二个和第三个模式依据顺序上的不重复设为这三个模式中的两个;
当前两个最可能模式是相等时,
且第一个模式的值为Intra_Angular,
则将第二个和第三个最可能模式设为和第一个模式在方向最近的预测方向值;
In the case that the current luma prediction mode is one
of three MPMs, only the MPM index is transmitted to the
decoder. Otherwise, the index of the current luma prediction
mode excluding the three MPMs is transmitted to the decoder
by using a 5-b fixed length code.
如果当前的亮度预测模式是三个最可能模式(MPM)中的一种,
则只有MPM的索引号被传输给解码器;
否则,
除了三个最可能模式外,当前亮度预测模式的索引也要使用5比特的定长码字传输给解码器;
For chroma intrapicture prediction, HEVC allows
the encoder to select one of five modes: Intra_Planar,
Intra_Angular[26] (vertical), Intra_Angular[10] (horizontal),
Intra_DC, and Intra_Derived. The Intra_Derived mode
specifies that the chroma prediction uses the same angular
direction as the luma prediction. With this scheme, all angular
modes specified for luma in HEVC can, in principle, also be
used in the chroma prediction, and a good tradeoff is achieved
between prediction accuracy and the signaling overhead. The
selected chroma prediction mode is coded directly (without
using an MPM prediction mechanism).
对于色度帧内预测模式,HEVC允许其选择下面五种模式:
Intra_Planar,
Intra_Angular[26](垂直),
Intra_Angular[10](水平),
Intra_DC,
Intra_Derived,
中的一种,
其中,Intra_Derived是将色度预测模式设定为对应亮度块的帧内方向预测模式;
对于这样一种设计, 在原则上,HEVC支持的所有亮度方向预测模式在色度上也同样支持;
这样的设计很好地取得了预测精度和信号传输开销间的平衡;
被选择的色度预测模式是直接编码的(不使用对预测模式进行预测的机制);
CU中光栅扫描(RasterScan)和Z字形扫描(Z-Scan)
在HEVC中CU(Codingunit)是基本的编码单元,通常一个亮度CB通常和两个色度CB及它们相关的句法共同组成一个编码单元(这个可想而知!)CU支持64*64,32*32,16*16,8*8四种尺寸分割方式,通常深度较大的CU模式适用于处理文理较复杂的区域,深度较小的CU模式适合处理平滑区域,换句话说就是,编码后平坦区域用大尺寸表示,复杂区域用小尺寸表示。如图所示:
这是编码后的效果,那么在编码前后需要对CU进行扫描就涉及到两种扫描方式,一种是光栅扫描(RasterScan)另一种的Z字形扫描(Z-Scan)。
光栅扫描(RasterScan)是指从左往右,由上往下,先扫描完一行,再移至下一行起始位置继续扫描,H.264使用的主要就是光栅扫描顺序。
Z字形扫描(Z-Scan)中Z是形象的表示方式,图像如下,
在HEVC中CU采用的是递归划分的方式,Z字形扫描顺序保证了对于不同分割都能按照相同的遍历顺序进行寻址,有利于程序中的递归实现。
这两种表示方式可以用下图进行表示:
回到HM代码中,
HM中的CU划分过程是按Z-order处理的,所以预测中的很多信息是按z-order存储的,比如划分深度、预测方向、帧内模式等等,而我们的寻址方式都是习惯性按照光栅的顺序,所以在HM中存在Z-order到Raster之间的映射,也存在Raster到Zorder之间的映射,注意:HM中的信息都是按照4*4块的大小保存的,例如,一个CTU会保存256个深度信息,对应256个4*4存储块,显然会有很多值是重复的。
HM代码中g_auiZscanToRaster,g_auiRasterToZscan数组实现地址映射问题:
g_auiZscanToRaster[ z-scan index ] = rasterscan index // Z->Raster
g_auiRasterToZscan[ raster index ] = z-scanindex // Raster->Z