HM代码粗略介绍

本文档介绍了HEVC编码器HM的环境配置、编码流程,深入讲解了从GOP到LCU的编码细节,包括Slice划分、CU压缩与编码、帧内帧间预测、变换与熵编码等关键步骤,为理解HEVC编码原理提供了详细指导。
摘要由CSDN通过智能技术生成

北京工业大学 朱维佳

邮箱: sparkjj1985@gmail.com(欢迎探讨任何关于编码的问题)

如转发本文章,请注明出处

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来对其进行实际的熵编码工作。

 

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过程,这个函数会被调用两次:

HM6116是一款常用的静态RAM(随机存取存储器)芯片,通常用于存储数据。要进行写入操作,您需要设置地址并提供要写入的数据,然后通过控制信号使数据被存储在指定的地址。下面是一个HM6116静态RAM的写入操作的伪代码示例: ```c // 假设已经有了对HM6116的控制接口定义,包括地址线、数据线和控制信号 // 这里用伪代码表示 // 初始化RAM写入所需变量 int dataToWrite; // 要写入的数据 int address; // 目标地址 // 写入函数 void writeHM6116(int data, int addr) { // 将地址放到地址线上 setAddress(addr); // 将数据放到数据线上 setData(data); // 拉低写使能信号(WE),通知HM6116现在是一个写入周期 lowerWriteEnable(); // 延时一段时间,确保数据稳定并被存储。在实际代码中,这个延时通常非常短,甚至可以由硬件控制。 delay(); // 拉高写使能信号,完成写入操作 raiseWriteEnable(); // 完成写入操作 } // 使用示例 int main() { // 假设我们要写入数据0xAB到地址0x1234 dataToWrite = 0xAB; address = 0x1234; // 执行写入操作 writeHM6116(dataToWrite, address); return 0; } // 这里的setAddress(), setData(), lowerWriteEnable(), raiseWriteEnable(), delay()函数需要根据实际硬件平台的接口来实现。 ``` 请注意,这个伪代码仅用于展示HM6116写入操作的一般流程。在实际应用中,你需要根据你所使用的硬件平台的具体硬件接口和库函数来实现这些操作。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值