HEVC编码器HM源码阅读
NB_vol_1
这个作者很懒,什么都没留下…
展开
-
HEVC多次进行熵编码的原因
HEVC多次进行熵编码的原因 在HM中有个让人很疑惑的地方,就是熵编码会被多次调用 1、compressSlice中有两次 (1)第一次是compressCU中,使用熵编码来进行RDO优化,用来选择最优的编码参数 (2)第二次是紧接着compressCU后面调用了encodeCU 2、encodeSlice中有一次原创 2017-05-08 17:05:25 · 3013 阅读 · 3 评论 -
HM编码器代码阅读(2)——框架以及主要流程
编码器的运行方式:encoder -c encoder_lowdelay_main.cfg -c akiyo.cfg其中encoder就是编码器可执行文件的名字,encoder_lowdelay_main.cfg是编码器的配置信息,akiyo.cfg是待编码的视频数据的信息。下面是运行截图:编码器主函数在文件encmain.cpp中,调用如下原创 2016-04-12 17:12:38 · 5529 阅读 · 2 评论 -
HM编码器代码阅读(46)——SAO总结
SAO总结理论HEVC/H.265理论知识(7)——环路滤波代码解读HM编码器代码阅读(27)——样点自适应补偿SAO(一)SAO介绍以及入口函数HM编码器代码阅读(43)——样点自适应补偿SAO(二)收集像素块的统计信息HM编码器代码阅读(44)——样点自适应补偿SAO(三)选取最优的SAO模式并确定补偿值HM编原创 2017-02-22 21:25:39 · 2148 阅读 · 1 评论 -
HM编码器代码阅读(45)——样点自适应补偿SAO(四)对重建像素进行补偿
对重建像素进行补偿 前面我们已经选取了最优的模式和补偿值,接下来需要根据最优的模式和补偿值对重新像素进行补偿(即对重建像素进行修正)。入口函数 和选取最优模式一样,入口函数还是decideBlkParams 步骤如下: 1、对图像的每一个CTU进行处理 2、CTU尝试每一种SAO模式,选出最优的SAO模式 3、原创 2017-02-22 21:18:16 · 1647 阅读 · 0 评论 -
HM编码器代码阅读(44)——样点自适应补偿SAO(三)选取最优的SAO模式并确定补偿值
选取最优的SAO模式并确定补偿值对像素值进行统计之后,需要确定应该SAO的哪一种模式,具体的方法是利用率失真优化的方式来确定最优的模式。同时还要得到该模式下的补偿值,后面就可以利用这个补偿值对像素块进行补偿(所谓补偿就是对像素值进行修正)。选取最优模式的入口函数入口函数是decideBlkParams,流程如下:1、对图像的每一个CTU进行处理2原创 2017-02-22 20:01:58 · 2272 阅读 · 0 评论 -
HM编码器代码阅读(28)——比特流
比特流NALU在讲比特流之前先了解下VCL和NAL,HEVC编码分成两个层次,高层处理编码具体细节的被称为VCL(视频编码层)、底层处理比特流的被称为NAL(网络适配层)。预测编码、变换、量化、环路滤波以及熵编码都属于VCL。而处理比特流封装细节的部分则属于NAL。编码之后的数据要在网络上传输,必须按照一定的格式进行封装成报文,这样的数据报文被称为nal unit简称NALU。一个原创 2017-02-13 21:53:17 · 2179 阅读 · 1 评论 -
HM编码器代码阅读(43)——样点自适应补偿SAO(二)收集像素块的统计信息
收集像素块的统计信息在进行SAO之前,要对像素块的像素值进行归类,然后判断它们属于EO的那个种类,或者BO的哪个边带入口函数getStatisticsgetStatistics是收集像素统计信息的入口函数流程如下:1、遍历图像的每一个CTU2、对于每一个CTU,调用deriveLoopFilterBoundaryAvailib原创 2017-02-22 17:44:57 · 2304 阅读 · 0 评论 -
HM编码器代码阅读(27)——样点自适应补偿SAO(一)SAO介绍以及入口函数
样点自适应补偿(SAO)由于使用了变换量化导致高频交流系数失真,解码后会在图像的边缘产生波纹现象,这种被称为振铃效应。样点自适应补偿就是从像素与入手降低振铃效应:对重构曲线(通过对像素值进行划分分类可以得到)中出现的波峰像素添加负值补偿,波谷添加正值进行补偿。SAO以CTU为基本单位,通过选择一个合适的分类器将冲击的像素划分类别,然后对不同类别像素使用不同的补偿值。SAO包括两原创 2017-02-12 20:49:35 · 3649 阅读 · 0 评论 -
HM编码器代码阅读(26)——去方块滤波
去方块滤波主函数:TComLoopFilter::loopFilterPic 1、水平边界滤波 遍历图像中的每一个CU,对每一个CU中的PU或者TU的水平边界进行滤波(CU可以划分成TU或者PU),即调用xDeblockCU 2、垂直边界滤波 操作同上Void TComLoopFilter::loopFilterPic( TComPi原创 2017-02-12 17:40:11 · 2783 阅读 · 0 评论 -
HM编码器代码阅读(24)——变换系数的编码
入口函数TEncSlice::encodeSlice。在处理完VPS,SPS,PPS和片头信息之后就开始对片的数据(不仅是数据还有一些其他的参数和控制信息)进行编码了。encodeSlice函数就是熵编码的重头戏了。处理过程如下:(1)先初始化熵编码器,然后设置CABAC熵编码器为当前的熵编码器。(2)然后就是加载各种熵编码器,各种初始化,各种加载上下文信息。(3)遍历片中的每原创 2016-04-24 21:49:11 · 3735 阅读 · 1 评论 -
HM编码器代码阅读(20)——与变换量化有关的其他知识
其他和变换量化相关的函数(以后补充)原创 2016-04-19 16:54:35 · 2698 阅读 · 1 评论 -
HM编码器代码阅读(23)——参数集的熵编码
在HEVC中,各种参数集以及控制信息等使用CAVLC编码,而帧或者片中的数据(连同CU的语法元素等)使用的是CABAC进行熵编码(不知道还有没有其他的编码方法)。下面介绍一下各种参数集的熵编码。在TEncGOP::compressGOP函数(图像组编码函数)中可以看到,在调用compressSlice对片编码之后,调用了m_pcEntropyCoder->setEntropyCoder原创 2016-04-24 21:04:33 · 2846 阅读 · 0 评论 -
HM编码器代码阅读(3)——一些比较容易混淆的类和结构
TcomPic 是图片类,它包含TComPicSym(图像符号类)和TComPicYuv(yuv数据类:包括原始数据,预测数据、惨差数据)TvideoIOYuv 是用来读取yuv文件的类,读取出来之后把数据放到TComPicYuv中TComPicSym中则存放了指向片(TComSlice)的二级指针,和指向CU(TComDataCU)的二维指针,其实片和CU的实际数据仍然存放在TComPi原创 2016-04-12 17:42:51 · 4353 阅读 · 7 评论 -
HM编码器代码阅读(4)——一些概念
AMVP 即先进运动矢量预测WPP 波前编码SEI 图像增强提高信息NAL单元的前两个字节是头部(第一个字节总是0,接着是NAL类型,然后是layer标志,最后是temporal标志)DPB 是解码图像缓存VCL NAL包含编码数据no-VCL NAL包含控制信息IRAP图像必须属于时域层0,且使用帧内预测leading Picture在解码顺序上紧跟着IRAP图像原创 2016-04-12 17:43:24 · 3447 阅读 · 0 评论 -
HEVC中的CABAC
HEVC中的CABAC CABAC(上下文自适应的二进制算术编码)基于算术编码,在HEVC中,除了参数集、SEI和slice头部之外,其余的所有数据都使用CABAC来进行熵编码。 CABAC有三个步骤: 1、初始化,构建上下文概率模型 2、根据上下文概率模型获取语法元素的概率,对语法元素进行熵编码 3、根据编码结果更新上下文概率模原创 2017-05-07 22:31:16 · 6632 阅读 · 1 评论 -
HEVC中的CAVLC
HEVC中的CAVLCCAVLC 基于上下文的自适应变长编码首先,HEVC的熵编码使用了两种算术编码:CABAC和CAVLC。CAVLC主要用于编码SEI、参数集、片头等,剩下的所有数据和语法元素均使用CABAC来编码。HEVC标准文档中使用到的一些描述符(描述符也表示操作方法):1、ae(v) 使用cabac2、b(8) 读进连续的8 bit3原创 2017-05-05 17:45:58 · 2122 阅读 · 0 评论 -
CU的划分、地址以及索引
CU的划分、地址以及索引 在看HM源码的时候,最蛋疼的一件事就是被CU的划分以及它们的地址搞懵。为了搞清楚,仔细研究了一下源码,有什么错误请指出。为了弄清楚这个问题,必须要对扫描顺序、深度等概念有所理解。扫描顺序 HEVC中对像素块的扫描方式有两种:Raster和Zscan Raster扫描方式:从上到下,从左到右进行扫描,原创 2017-05-04 21:54:44 · 5292 阅读 · 0 评论 -
TComPicYuv、TComPic、TComPicSym、TComDataCU以及TComYuv的关系
TComPicYuv、TComPic、TComPicSym、TComDataCU以及TComYuv的关系首先用一张图来描述它们之间的关系1、HM首先使用TComPicYuv保存从文件中读取出来的YUV数据2、利用TComPicYuv构造TComPic,并把YUV数据复制给他(TComPic包含了TComPicYuv成员)3、TComPic表示一帧图像,包含了原创 2017-05-04 18:06:11 · 5365 阅读 · 5 评论 -
HM编码器代码阅读(13)——帧间预测之AMVP模式(一)总体流程
入口函数xCheckRDCostInter。主要流程如下:(1)得到当前的深度。(2)调用predInterSearch,进行ME(运动估计)和MC(运动补偿)。(3)调用encodeResAndCalcRdInterCU,根据预测值,求出残差,然后进行TU的划分,然后进行变换、量化等操作以及RD代价的计算。(4)调用xCheckBestMode选择最好的模式。#if原创 2016-04-14 16:43:28 · 5715 阅读 · 1 评论 -
HM编码器代码阅读(14)——帧间预测之AMVP模式(二)predInterSearch函数
predInterSearch主要的工作是ME(运动估计)和MC(运动补偿)。函数中有一个bTestNormalMC变量,它表示是否进行正常的MC过程,正常的MC过程就是进行ME再进行MC。正常的MC流程是,遍历所有的参考帧,进行ME(运动估计:xEstimateMvPredAMVP),然后记录AVP或者MV的信息,进行MC(运动补偿,目的是选出最优的参数),然后更新最优的参数,遍历完所有原创 2016-04-15 15:59:57 · 10981 阅读 · 2 评论 -
HM编码器代码阅读(12)——CU编码
入口函数:TEncCu::compressCU(或者xCompressCU)。xCompressCU是一个递归函数,对于每一个CU,该函数都会被调用,主要是计算当前CU编码之后代价,然后再计算当前CU的每一个子CU编码后的代价,和当前CU的编码代价相比较,用来决定是否对当前CU进行分割。详细流程:(1)复制原始yuv数据(2)计算当前CU四个角的坐标(3)调用xComputeQP计原创 2016-04-14 16:28:03 · 12258 阅读 · 3 评论 -
HM编码器代码阅读(29)——码率控制
码率控制介绍码率控制码率控制也叫速率控制,主要是控制编码后的比特率。存在码率控制模块的原因是,有时候解码器处理的速度不够快、网络带宽不行这些情况的存在要求我们必须减少数据的发送量(即比特率要变小),减少数据的发送量意味着我们要对数据进行更近一步的压缩,在编码器中就表现为量化参数QP的变化。当满足一定码率要求的情况下,我们还需要让编码的失真尽量小。码率控制的核原创 2017-02-14 11:38:51 · 6197 阅读 · 0 评论 -
HM编码器代码阅读(6)——GOP、IDR帧、I帧周期的关系(待修改)
关于GOP中IDR帧的说明:1、在H.264中一个图像组的起始帧一定是IDR帧,因此在H.264中在处理一个GOP之前会把参考图像集清空,因此一个GOP中的帧一定不会参考另一个GOP的帧——这就是封闭式GOP。2、在HEVC中,一个GOP的第一帧默认不是IDR帧,而是普通的I帧,在处理一个GOP之前,编码器不会把参考集清空,因此在HEVC中一个GOP是会参考另一个GOP的数据,造成了GOP原创 2016-04-13 14:30:32 · 6146 阅读 · 1 评论 -
HM编码器代码阅读(22)——cabac的流程
TEncSbac::resetEntropy函数详解(熵编码的初始化过程):这个函数的实质就是初始化各种上下文// 重置熵编码器Void TEncSbac::resetEntropy (){ Int iQp = m_pcSlice->getSliceQp(); SliceType eSliceType = m_pcSlice->ge原创 2016-04-24 17:57:57 · 9585 阅读 · 0 评论 -
HM编码器代码阅读(21)——熵编码的概念以及在HEVC中应用
熵编码把一系列用于表示视频序列的元素符号转变为一个用来传输或存储的压缩码流。信息的多少用信息量来度量,显然,信息量与不确定性的消除程度有关,消除的不确定性越大,信息量就越大。不确定性的大小与事件发生的概率相关,因此不确定性可以度量,更进一步信息量也可以度量。假设某一个信源(就是产生信息的地方)的概率空间是:X(表示信源产生的符号的集合),P(原创 2016-04-22 17:39:20 · 9080 阅读 · 0 评论 -
HM编码器代码阅读(19)——量化
下面要讲解变换和量化具体的执行函数。TComTrQuant::transformNxN函数详解:这是变换和量化的具体执行函数(1)首先判断是否确实需要变换量化(2)如果使用了skip模式,那么调用xTransformSkip进行处理;否则调用xT进行变换处理(3)调用xQuant函数进行量化// 变换和量化!!!!!Void TComTrQuant::transformN原创 2016-04-19 16:52:59 · 4579 阅读 · 1 评论 -
HM编码器代码阅读(33)——帧间预测的总结
原理理论介绍:HEVC/H.265理论知识(4)——帧间预测AMVP模式HM编码器代码阅读(13)——帧间预测之AMVP模式(一)总体流程HM编码器代码阅读(14)——帧间预测之AMVP模式(二)predInterSearch函数HM编码器代码阅读(15)——帧间预测之AMVP模式(三)xGetBlkBits函数HM编码器代码阅读(16)——帧间预测之AMV原创 2017-02-16 21:59:27 · 5147 阅读 · 1 评论 -
HM编码器代码阅读(17)——帧间预测之merge模式(一)Merge模式的介绍以及相关函数
入口函数:TEncCu::xCheckRDCostMerge2Nx2N主要流程:(1)获取可用merge候选MV数量以及merge候选MV(2)判断是否为无损模式,如果是无损模式,那么下面的for循环只需迭代一次,如果不是武勋模式,那么下面的for循环要迭代两次(3)一个for循环,遍历所有的merge模式候选者 1)设置相关参数 2)调用motionCom原创 2016-04-15 17:57:07 · 7741 阅读 · 0 评论 -
HM编码器代码阅读(32)——帧间预测之AMVP/Merge模式(七)encodeResAndCalcRdInterCU函数:残差计算、变换量化
encodeResAndCalcRdInterCU经过运动估计、运动补偿,我们得到了MV以及参考块,那么接下来是计算残差、计算MVD,然后对系数进行变换、量化。encodeResAndCalcRdInterCU函数就是帧间预测之后,专门用来计算残差、进行变换量化的函数。但是,除了变换量化之外,encodeResAndCalcRdInterCU函数中还有熵编码方面的处理,我们原创 2017-02-16 18:11:49 · 4071 阅读 · 1 评论 -
HM编码器代码阅读(31)——帧间预测之AMVP/Merge模式(六)运动补偿
运动补偿原理说实话一直很难理解运动补偿中“补偿”二字的意思,在参考了 http://blog.csdn.net/hevc_cjl/article/details/8457642 和百度百科以及分析的源代码之后,我大致猜测了一下它的功能:百科上说“运动补偿是通过先前的局部图像来预测、补偿当前的局部图像,它是减少帧序列冗余信息的有效方法”,通过前面的运动估计我们得到了MV(运动向量原创 2017-02-16 12:10:07 · 5041 阅读 · 0 评论 -
HM编码器代码阅读(30)——帧间预测之AMVP模式(五)运动估计
运动估计通过http://blog.csdn.net/nb_vol_1/article/details/55212970介绍的方法得到MVP之后,可以根据该MVP确定运动估计的搜索起点,然后进行运动估计xMotionEstimation就是进行运动估计的入口函数1、先进行一些初始化,设置搜索范围2、如果是B类型的slice,或者没有使用快速搜索模式,那么调用xPattern原创 2017-02-15 21:12:59 · 3504 阅读 · 2 评论 -
HM编码器代码阅读(16)——帧间预测之AMVP模式(四)预测MV的获取
入口函数:motionCompensation 运动补偿是一种描述相邻帧(相邻在这里表示在编码关系上相邻,在播放顺序上两帧未必相邻) 差别的方法, 具体来说是描述前面一帧(相邻在这里表示在编码关系上的前面,在播放顺序上未必在当前帧前面)的每个小块怎样移动到当前帧中的某个位置去最早的运动补偿的设计只是简单的从当前帧中减去参考帧,从而得到通常含有较少能量(或者成为信息)的"残差",从而可以原创 2016-04-15 16:44:02 · 5904 阅读 · 2 评论 -
HM编码器代码阅读(15)——帧间预测之AMVP模式(三)xGetBlkBits函数
入口函数:xMotionEstimation基本思想:就是用TZSearch算法先进行整像素搜索,确定一个局部的最佳值,然后以这个最佳点为中心再进行精度更高的分像素搜索。主要流程:(1)首先计算搜索范围(2)获取相邻块像素的访问方式(通过调用getPattern)(3)计算当前CU(或者说PU)大小(4)如果是B帧(使用双向预测),还要设置权重?(5)访问方式的初始化原创 2016-04-15 16:12:00 · 3031 阅读 · 0 评论 -
HM编码器代码阅读(11)——CU的初始化
入口函数TComDataCU::initCU主要流程:(1)计算当前LCU在图像中的像素地址(2)计算LCU可以被分成多少个4x4的CU(3)把片的起始CU的地址存储起来(4)设置每一个4x4子CU的参数信息(5)设置当前LCU的左边、上方、右上角、左上角的相邻的LCU(6)设置参考帧的数组// 编码单元初始化Void TComDataCU::initCU( TC原创 2016-04-14 15:32:43 · 3483 阅读 · 4 评论 -
HM编码器代码阅读(10)——片的编码
入口函数TEncSlice::compressSlice这个函数主要是设置一些参数和初始化一些东西,然后对片中的每一个LCU调用initCU(初始化CU)和compressCU(对CU编码)和encodeCU(对CU进行熵编码,目的是选择最优参数)。TEncSlice::compressSlice函数的详解:(1)计算当前slice的开始CU和结束CU(2)初始化Sbac编码器原创 2016-04-14 15:14:19 · 3909 阅读 · 2 评论 -
HM编码器代码阅读(9)——片编码器的初始化
入口函数:TEncSlice::initEncSlice。在处理图像组的时候,遍历图像组的每一帧,对每一帧调用TEncSlice::initEncSlice。主要是设置和计算一些参数,为片的编码做准备。主要功能包括:(1)取出当前帧的第一片(HM15中每一帧只被划分成一片)(2)设置片的SPS(序列参数集)和PPS(图像参数集)(3)设置片所属的帧;片初始化原创 2016-04-14 15:00:55 · 3288 阅读 · 0 评论 -
HM编码器代码阅读(5)——参考帧的选择
参考帧是怎么来的以及如何设置这个问题困扰了我很久,现在理出了一点头绪。参考帧的选择主要涉及几个函数:selectReferencePictureSetcreateExplicitReferencePictureSetFromReferenceapplyReferencePictureSetarrangeLongtermPicturesInRPSset原创 2016-04-12 17:53:27 · 5760 阅读 · 6 评论 -
HM编码器代码阅读(34)——帧内预测(一)
帧内预测原理 帧内预测,利用当前图像内已经编码的像素生成预测值,生成预测值之后,和原始的值相减,得到残差,后续的变换量化等操作就是基于残差进行处理的。具体细节参考 HEVC/H.265理论知识(3)——帧内预测流程帧内预测的大致流程是这样的(1)遍历所有的预测模式,得到每种模式下的残差信号,再对残差信号进行Hadamard变换计原创 2017-02-17 10:59:26 · 3953 阅读 · 0 评论 -
HM编码器代码阅读(37)——帧内预测(四)帧内预测之候选模式列表的建立
候选模式列表的建立 帧内预测也可以分成两种方式,一种是常规方式,另一种是快速方式在常规方式 所有的35种帧内预测模式都被添加到候选模式列表中,在后续的惭怍中,对每一个模式都进行预测、变换、量化等操作,速度很慢。 相关代码在estIntraPredQT函数中 UInt uiRdModeList[FAST_UDI_MAX_RDMODE_NUM];原创 2017-02-17 15:58:20 · 3261 阅读 · 1 评论 -
HM编码器代码阅读(18)——变换
入口函数:encodeResAndCalcRdInterCU。这个函数的作用是根据预测值,求出残差,然后进行TU的划分,然后进行变换、量化等操作以及RD代价的计算。流程:(1)如果是帧内预测,那么直接返回(2)判断是否使用skip模式,如果使用了: 1)对所有的子分割设置skip标志 2)清理残差 3)把预测的CU直接设置为重建的CU原创 2016-04-19 16:29:40 · 7405 阅读 · 1 评论