一、档次和级别
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 将一部分变换系数和量化和在一起实现,即在 Z ij =round ( Y ij /Qstep )的基础上进行,变成 Z ij =(Yij *PF/Qstep ), 这里 PF 就是变换时提取出的系数 a 2 ,ab/2,b 2 /4......
实际实现时,用移位的方法实现除法,即 Z ij =Y ij .MF/2 qbit ; 这样就有 MF/2 qbit =PF/Qstep ,则 MF=2 qbit PF/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|<β
α 和 β 的取值取决于量化步长的大小,当量化步长大的时候,量化误差也大,方块效应就明显,因此门限值就大;反之量化步长小的时候门限值就小,体现了自适应性。