H.264 7个主要模块的分析
来源:互联网 发布:煤矿储量图里数据 编辑:程序博客网 时间:2024/04/28 12:57
一、档次和级别
1、基本档次:
支持I和P片。I片包括16×16或4×4亮度区域和8×8色度区域的帧内宏块编码,被同一片中的已经编码的样本进行预测。P片包括帧内编码、帧间编码或skipped MBs。
在p片中的帧间编码的宏块用先前已经编码的图象预测,其中用到1∕4亮度象素精度的运动矢量进行运动补偿。
经过预测,每个宏块的残差数据用基于DCT的4×4整数变换进行变换和量化。量化变换系数被重排序,接着进行熵编码。在基本档次,变换系数用CAVLC进行熵编码,而其它的语法元素则用固定长度或变长的指数哥伦布码编码。量化后的系数经过反量化,反变换,重建(与编码时形成的预测相加),去块滤波器进行滤波,然后存储,用作后面帧内和帧间编码宏块的参考图象。
基本档次主要用于视频电话,视频会议,无线通信等。
2、主要档次:
支持隔行视频(把一幅图象分成两场来分别扫描),采用B片的帧间编码和采用加权的帧内编码;支持基于上下文的自适应的算术编码CABAC。
主要档次主要用于数字广播电视和数字视频存储。
3、扩展档次:
支持码流之间有效的切换(SP和SI片)、改进误码性能,但不支持隔行视频和CABAC,主要应用于流媒体(指用一个视频传送服务器把节目当成数据包发出,传送到网络上。用户通过解压设备对这些数据进行解压后,节目就会像发送前那样显示出来)。
二、H.264的编解码
2.1 帧内预测
帧内预测是消除时间冗余,依据先前编码和重建之后形成的预测块P,当前块减去这个预测块,得到的差值进行编码。这种预测是基于块的,对于亮度分量(1uma),块的大小可以在16×16和4×4之间选择,16×16块有4种预测模式,4×4块有9种预测模式;对于色度分量(chroma),预测是对整个8×8块进行的,有4种预测模式。除了DC预测外,其他每种预测模式对应不同方向上的预测。
对每个区域选择最佳的4×4或16×16预测模式,就是使要编码的信息量最小的模式。
2.1.1 4×4亮度预测模式
模式2:DC预测,此种模式有如下 4 种情形:
(1)若A ,B ,C,D , I,J ,K ,L 均在图像界内, 则从a 到p 均由如下公式计算, (A + B + C + D + I + J +K + L + 4) > > 3;
(2) 若A ,B ,C,D 在图像外, I,J ,K ,L 在图像之内, 则a 到p 所有像素均如下计算, (I+ J + K + L + 2) > > 2;
(3) 与(2) 相反, 若A ,B ,C,D 在图像内而 I,J ,K ,L , 在外, 则为(A + B + C+ D + 2) > > 2;
(4)A ,B ,C,D , I,J ,K ,L 均在图像外,a 到p 均取值 128.
会遍历这9种预测模式,找到一种误差(SAE)最小的方案。
2.1.2 16×16亮度预测模式
8×8色度块的4种预测模式类似于帧内16×16亮度预测模式,两种色度成分常用同一种预测模式。
2.2 帧间预测
编码器每个宏块以帧内(Intra)或帧间(Inter)模式进行编码。在帧间模式下,参考帧F(n-1)经过运动估计和运动补偿得到预测值P,预测值与当前帧F(n)相减后得到残差值,再对该残差值进行变换编码和量化,以得到量化变换系数,最后经熵编码输出到网络提取层NAL。
在解码端,首先对码流进行解码得到当前宏块的参考帧,然后通过当前宏块周围宏块计算运动矢量预测值。然后通过对码流进行解码得到当前宏块的运动矢量残差。将运动矢量残差与运动矢量预测值相加得到实际的运动矢量。然后通过对码流进行解码得到当前宏块的像素残差(如果当前宏块有像素残差的话)。然后通过参考帧与上面计算得到的MV计算出当前宏块的像素预测值。再将像素预测值与像素残差相加就得到当前宏块的重构。
2.2.1 树状结构运动补偿
每个宏块(16×16像素)可以按4种方式进行分割:1个16×16,或2个16×8,或2个8×16,或4个8×8。其运动补偿也相应的有4个。而8×8模式的每个子宏块还可以进一步以4种方式进行分割:1个8×8,2个4×8,或2个8×4及4个4×4。这种分割下的运动补偿则称为树状运动补偿。
2.2.2 运动矢量
预测图象和参考图象的差异(MV)对亮度成分采用1/4像素精度,色度1/8像素精度。亚像素位置的亮度和色度像素并不存在于参考图象中,需要利用邻近已编码点进行内插而得。
1/4像素的运动补偿过程:首先,运动估计在整数像素的网格(圆圈)上找到一个最佳匹配位置,然后,编码器在该位置(正方形)附近的半像素位置上继续搜索,寻找更好的匹配位置;如果找到新的匹配位置(三角形),编码器在其附近进一步进行1/4像素的搜索。最后,由当前块减去匹配块得到残差块。(见下图)
2.3 变换编码
空间域的图象变换到频域或变换域,会产生相关性很小的一些变换系数,并可对其进行压缩编码。
H.264的整数变化是基于DCT的,但是又有一些不同:
(1)它是一个整数变换(所有的操作可以使用整数算法,而不丢失解码精度);
(2)它可以实现编码端和解码端反变换之间的零匹配(使用整数算法);
(3)变换的核心部分可以仅仅使用加法和位移操作实现。
(4)变换中的一部分乘法运算可以和量化器结合到一起,减少了乘法的数量。
H.264根据要编码的残差数据类型使用三种变换:帧内16×16模式预测的宏块中,亮度DC系数的4×4矩阵使用哈达玛变换;任何宏块的色度DC系数的2×2矩阵使用哈达玛变换和所有其他残差数据的4×4块使用基于DCT的整数变换。
基于DCT的整数变换过程:
加速尺度操作 需要对每一个系数进行一次乘法操作,这一步被归化到量化过程。
2.4量化
为去除图象信号中的相关性及减少图象编码的动态范围,通常采用变换编码和量化技术。 量化可以用来降低图象数据的精度,去除不重要的数据值,而不明显影响图象质量。H.264将一部分变换系数和量化和在一起实现,即在Zij=round(Yij/Qstep)的基础上进行,变成Zij=(Yij*PF/Qstep),这里PF就是变换时提取出的系数a2,ab/2,b2/4......
实际实现时,用移位的方法实现除法,即Zij=Yij.MF/2qbit;这样就有MF/2qbit=PF/Qstep,则MF=2qbitPF/Qstep,qbit=15+(QP/6),所以有QP相差6,MF增加一倍。QP=4时,Qstep=1,求出对应ij的MF,就是量化矩阵了。具体量化过程:
|Zij|=(|Wij|.MF+f)>>qbits
Sign(Zij)=sign(Wij)
2.5 熵编码
熵编码是为了去除统计冗余,在H.264的基本档次中用的是基于上下文自适应的可变长编码(CAVLC)。CAVLC用于亮度和色度残差数据的编码,残差经过变换量化后的数据表现出如下特性:4×4块数据经过预测、变换、量化后,非零系数主要集中在低频部分,而高频系数大部分是零;量化后的数据经过据齿形(zig-zag)扫描,DC系数附近的非零系数值较大,而高频位置上的非零系数值大部分是+1和-1;相邻的4×4块的非零系数的数目是相关的。CAVLC充分利用残差经过整数变换、量化后数据的这些特性进行压缩,可进一步减少数据中的冗余信息。
例:编码过程:
假设有一个4*4数据块
{
0, 0, -1, 0,
5, 2, 0, 0,
3, 0, 0, 0,
1, 0, 0, 0
}
数据重排列:0,0,5,3,2,-1,0,0,0,1……
1) 初始值设定:
非零系数的数目(TotalCoeffs) = 5;
拖尾系数的数目(TrailingOnes)= 2;
最后一个非零系数前零的数目(Total_zeros) = 5;
变量NC=3;
(说明:NC值的确定:色度的直流系数NC=-1;其他系数类型NC值是根据当前块左边4*4块的非零系数数目(NA)当前块上面4*4块的非零系数数目(NB)求得的,见毕厚杰书P120表6.10)
suffixLength = 0;
i = TotalCoeffs = 5;
2) 编码coeff_token:
查标准可得:
If (TotalCoeffs == 5 && TrailingOnes == 2&& 2 <= NC <4)
coeff_token = 0000 101;
Code = 0000 101;
3) 编码所有TrailingOnes的符号:
逆序编码,三个拖尾系数的符号依次是+(0),-(1);
即:
TrailingOne sign[i--] = 0;
TrailingOne sign[i--] = 1;
Code = 0000 1010 1;
4) 编码除了拖尾系数以外非零系数幅值Levels:
过程如下:
(1)将有符号的Level[i]转换成无符号的levelCode;
如果Level[i]是正的,levelCode = (Level[i]<<1) – 2;
如果Level[i]是负的,levelCode = - (Level[i]<<1) – 1;
(2)计算level_prefix:level_prefix = levelCode / (1<<suffixLength);
查表可得所对应的bit string;
(3)计算level_suffix:level_suffix = levelCode % (1<<suffixLength);
(4)根据suffixLength的值来确定后缀的长度;
(5)suffixLength updata:
If ( suffixLength == 0 )
suffixLength++;
else if ( levelCode > (3<<suffixLength-1) && suffixLength <6)
suffixLength++;
回到例子中,依然按照逆序,Level[i--] =2;
levelCode = 2;level_prefix = 2;
查表,可得level_prefix = 2时对应的bit string = 001;
因为suffixLength初始化为0,故该Level没有后缀;
Code = 0000 1010 1001;
编码下一个Level:Level[1] = 3;
levelCode = 4;level_prefix = 2; level_suffix = 0;
查表可得 level_prefix = 2时对应的bit string=001;后缀为0;
编码下一个Level: Level[0] = 5;
levelCode = 8;level_prefix = 2; level_suffix = 0;
查表得 对应的bit string=001;后缀为0;
Code = 0000 1010 1001 0010 0010
编码Level结束。
5)编码最后一个非零系数前零的数目(TotalZeros):
查表,当TotalCoeffs = 5,total_zero = 5时,bit string = 101;
Code = 0000 1000 1110 0101 11;
6) 对每个非零系数前零的个数(RunBefore)进行编码:
i = TotalCoeffs = 5;ZerosLeft = Total_zeros = 5;查表:
依然按照逆序编码
ZerosLeft =5, run_before = 3 run_before[4]=010;
ZerosLeft =2, run_before = 0 run_before[3]=1;
ZerosLeft =2, run_before = 0 run_before[2]=1;
ZerosLeft =2, run_before = 0 run_before[1]= 1;
ZerosLeft =2, run_before = 2 run_before[0]最后一个系数不需要编码
Code = 0000 1010 1001 0010 0010 1010 1011 1;
编码完毕。
2.6 基于Lagrangian优化算法得率失真优化
H.264 采用基于率失真优化的模式判决方法,编码器对每个宏块所有可能的模式分别计算率失真代价,然后对它们进行比较,选择率失真代价最小的模式为最佳模式。率失真代价函数J定义如下:
J = Distortion + * Rate ――――(1)
率失真代价由两部分组成,比特流的失真度和码率。失真度确定重建图象的质量同时比特率衡量特定模式编码宏块需要的比特数。运动估计和补偿之后,经过变换和量化,剩下残差图像和MV等编码信息.这个残差就相当于distortion,而编码MV等信息的比特数就相当于RATE.
最好的模式是使失真度最小,同时尽可能小的码率。
用于帧内模式和P片的帧间模式
用于B片, QP 是宏块的量化参数
另一个Lagrange参数 与 有关。 是用于计算P片或B片的运动矢量。运动矢量的计算也是类似于上式(1)J = Distortion + * Rate,
当失真度是用SSD ( sum of the squared differences平方误差和between an original block and its reconstruction): =
当失真度是用SAD (Sum of Absolute Differences绝对误差和between the original and prediction values )计算时: =
2.7 去方块滤波
编解码反变换量化后图象会出现方块效应,原因有二:一是基于块的帧内和帧间预测残差的整数变换和量化过程相对粗糙,因而恢复出来的数据有误差,会造成图象块在视觉上的不连续。二是运动补偿块的匹配不可能是绝对准确的,所以就会在复制块的边界上产生数据的不连续。
对于滤波器来说,分清图象的真实边界和量化变化系数后产生的边缘很重要。一般来说,真实边界两侧的像素值梯度差要比虚假边界两侧的像素值梯度差大。为了区分这两种情况,定义两个相邻4×4块中一条线上的样点为p3,p2,p1,p0,q0,q1,q2,q3,实际的图象边界在p0和q0之间,如图。
当边界强度Bs值为0时,滤波器对边界不起作用。对于Bs值为非0的边界,定义了两个门限值α和β。α表示块间的边界门限,β表示块内的边界门限。只有满足以下三个条件,样点才需要进行滤波处理:
|p0-q0|<α
|p1-p0|<β
|q1-q0|<β
α和β的取值取决于量化步长的大小,当量化步长大的时候,量化误差也大,方块效应就明显,因此门限值就大;反之量化步长小的时候门限值就小,体现了自适应性。
- H.264 7个主要模块的分析
- OA主要模块的分析(一)
- H.264与H.265的主要差异
- logging模块的4个主要对象[Python]
- Heritrix的主要模块
- HI3518C 的主要模块
- 深入分析H.264/AVC标准的去块效应滤波系统模块
- linux内核的主要模块
- keras的主要模块介绍
- keras的主要模块介绍
- string.h/string/CString的主要区别
- H.265与H.264的区别技术分析
- h.264主要分为几个档次
- MM 模块主要 T-CODE 和主要使用的表
- MM 模块主要 T-CODE 和主要使用的表
- H.264码流结构的分析
- H.264码流结构的分析
- h.264的RTP/SDP分析
- zoj 1789 || poj 1611 The Suspects(并查集)
- 《BREW进阶与精通——3G移动增值业务的运营、定制与开发》连载之97——BREW的应用管理器
- Geoserver不能在Google App Engine中部署的几个原因及在Amazon中的部署方式
- ubuntu 10.04 重新安装VMwareTools-8.4.4-301548过程记录
- Using a Stateful Session Bean
- H.264 7个主要模块的分析
- Basic properties of smart pointers
- 《BREW进阶与精通——3G移动增值业务的运营、定制与开发》连载之98——BREW中RUIM的相关问题
- 21.Observer(行为型模式)
- 有关码率控制的FAQ
- SAP中寻找增强的实现方法(全)-转贴
- .NET开源项目
- js网页特效代码 弹出窗口网页特效代码集锦
- 《BREW进阶与精通——3G移动增值业务的运营、定制与开发》连载之99——BREW中的应用删除和召回