变换量化
如上图所示,在基于块的混合编码框架中,每一个经过帧内/帧间预测的残差块都需要进行二维的变换。对每一行和每一列分别应用一维变换以此来实现二维可分离变换。将变换系数 c o e f f Q coeff_Q coeffQ 进行量化(除以量化步长 Qstep 并进行舍入操作)得到量化的变换系数 level 并进行熵编码生成码流。在解码端,熵解码之后的 level 进行反量化(乘以 Qstep)得到 c o e f f Q coeff_Q coeffQ。注意:这里的量化、反量化过程会产生失真,这是编码过程中唯一产生失真的地方。最后,对 c o e f f Q coeff_Q coeffQ 进行反变换,得到重建的残差块(这里由于量化失真,已经与预测的残差块不同了),将其加上预测值即可得到重建块。
通常,正变换矩阵和反变换矩阵是彼此的转置,当正变换和反变换之间没有量化和反量化步骤时,输入的残差块几乎可以无损失的被重构出来。在 HEVC 等视频编码标准中,反量化过程和反变换是由标准指定的,而正变换和量化过程则可以自由选择。
HEVC 中的变换
HEVC 标准中规定了 4 × 4 4 \times 4 4×4、 8 × 8 8 \times 8 8×8、 16 × 16 16 \times 16 16×16 和 32 × 32 32 \times 32 32×32 四种尺寸的核心变换矩阵,用于基于块的运动补偿的视频压缩过程中的两维变换。多样的变换尺寸改善了编码的性能,但同时增加了编码的复杂度。因此,需要对核心变换进行精心的设计。
对于所有的变换尺寸,HEVC 规定了有限精度的核心变换来近似(浮点) IDCT。由于只是一种近似,HEVC 的核心变换并不等于(浮点) IDCT,然而未使用(浮点) IDCT 并不意味着 HEVC 的核心变换不完美。变换的主要目的是去除残差之间的相关性。最优的去相关变换是 Karhunen-Loeve transform (KLT),而不一定是 DCT。特别是对于 4 × 4 4 \times 4 4×4 块的帧内预测残差块来说,HEVC 指定了 DST 来进行变换。需要特别注意的是,HEVC 标准只规定了反变换,而没有规定正变换,因此编码器可以通过选择实际正变换的形式来获得更高的编码效率,而不是使用反变换的转置。
HEVC 的核心变换矩阵必须具有以下性质:
- 近似于 IDCT
- 基向量是正交的
- 所有基向量的范数几乎相等
- 具有与 IDCT 的基向量相同的对称性性质
- 较小的变换矩阵可以嵌入到较大的变换矩阵中
- 8 比特表示变换矩阵的元素
- 16 比特的转置 buffer
- 乘法器可以用 16 位或更少来表示,没有级联乘法或中间舍入
- 加法器少于32位
DCT
N 点的一维 DCT 可以表示为:
v
i
=
∑
j
=
0
N
−
1
u
j
c
i
j
(1)
v_i = \sum_{j=0}^{N-1}u_jc_{ij} \tag{1}
vi=j=0∑N−1ujcij(1)
其中,
u
j
u_j
uj 表示输入信号,
c
i
j
c_ij
cij 表示 DCT 变换矩阵的系数:
c
i
j
=
P
N
cos
[
π
N
(
j
+
1
2
i
)
]
(2)
c_ij = \frac{P}{\sqrt{N}} \cos[\frac{\pi}{N} (j + \frac{1}{2}i)] \tag{2}
cij=NPcos[Nπ(j+21i)](2)
当
i
=
0
i = 0
i=0 时,
P
=
1
P = 1
P=1;当
i
>
0
i > 0
i>0 时,
P
=
2
P = \sqrt{2}
P=2。定义 DCT 基向量
c
i
=
[
c
i
0
,
.
.
.
,
c
i
(
N
−
1
)
]
T
\textbf{c}_i = [c_{i0},...,c_{i(N-1)}]^T
ci=[ci0,...,ci(N−1)]T。
DCT 有以下几个特性,被认为对压缩效率和高效的实现都很有用:
- 基向量是正交的, c i T c j = 0 \textbf{c}_i^T\textbf{c}_j=0 ciTcj=0。这个特性通过获得不相关的变换系数来提高压缩效率。
- DCT 的基向量能提供良好的能量聚焦,这也是压缩效率所需要的。
- DCT 的基向量具有相等的范数, c i T c i = 1 \textbf{c}_i^T\textbf{c}_i = 1 ciTci=1。这个特性可以简化量化/反量化过程。存疑:相同的基向量范数能够消除对量化/反量化矩阵的量化误差必须具有相同的频域权重的要求。
- 小尺寸 DCT 矩阵的基向量等于的大尺寸 DCT 矩阵的偶数基向量的前半部分。这个有助于降低实现成本,因为相同的矩阵可以复用于各种不同的变换尺寸。
- DCT 矩阵可以通过少量的独特元素来指定,这在硬件实现中特别有利。
- DCT 矩阵的偶数基向量是对称的,而奇数基向量是反对称的,可以减少算术运算的次数。
- DCT 矩阵的系数具有一定的三角关系,允许通过利用(反)对称特性来减少算术运算的数量。
有限精度DCT 近似
HEVC 的核心变换矩阵是 DCT 矩阵的有限精度近似。在视频编码标准中使用有限精度的好处是 DCT 矩阵的近似值是在标准中定义好的,不会随着实现方式的变化而变化。因为不同的 IDCT 实现方式可能会采用不同的浮点数进行表示,导致编码端与解码端之间存在不匹配与偏移问题,而采用固定的有限精度近似值就可以有效的避免这些问题。但是,另一方面,使用近似的矩阵元素存在的缺陷是可能会使上述一些 DCT 性质得不到满足。
一种简单直观的整数近似方法是将每一个 DCT 矩阵元素与一个较大的数相乘,然后四舍五入。但是这种方式并不一定能获得最好的压缩性能。对于给定比特深度的矩阵元素,使用不同的策略对 DCT 矩阵元素进行近似将会使得DCT 的变换特性得到不同程度的满足。
HEVC 核心变换的设计准则
用作 HEVC 核心变换的 DCT 近似需要遵循以下原则:首先,上述性质中的 4-6 一定要得到满足,这样就能保留 DCT 在硬件实现的简便性。其次,对于性质 1-3和7,其满足的程度与表示每个矩阵元素所需要的比特数之间需要进行权衡。
为了衡量近似后的矩阵满足性质 1-3 的程度,假设 N 点 DCT 整数近似后的矩阵元素等于 d i j d_{ij} dij,基向量等于 d i = [ d i 0 , . . . , d i ( N − 1 ) ] \textbf{d}_i = [d_{i0},...,d_{i(N-1)}] di=[di0,...,di(N−1)],定义如下指标:
- 正交性测量: o i j = d j T d j / d 0 T d 0 o_{ij} = \textbf{d}_j^T\textbf{d}_j / \textbf{d}_0^T\textbf{d}_0 oij=djTdj/d0Td0
- 与 DCT 接近度测量: m i j = ∣ α c i j − d i j ∣ / d 00 m_{ij} = \left| \alpha c_{ij} - d_{ij} \right| / d_{00} mij=∣αcij−dij∣/d00
- 范数测量: n i = ∣ 1 − d i T d i / d 0 T d 0 ∣ n_i = \left| 1 - \textbf{d}_i^T\textbf{d}_i / \textbf{d}_0^T\textbf{d}_0 \right| ni=∣∣∣1−diTdi/d0Td0∣∣∣
其中, c i j c_{ij} cij 是公式 ( 2 ) (2) (2) 中的 DCT 矩阵元素,缩放因子 α \alpha α 定义为 d 00 N 1 / 2 d_{00}N^{1/2} d00N1/2。
作为仔细实验的结果,确定每个矩阵元素用 8 比特来表示(包括符号位),并且第一个基向量的所有元素均为 64。需要注意的是,与正交 DCT 相比较,实验所确定的上述结果意味着 HEVC 变换矩阵的缩放因子为 2 6 + M / 2 2^{6+M/2} 26+M/2。第一个基向量以外的其它矩阵元素通过手动调整来更好的平衡性质 1-3(在性质 4-6 的约束条件下)。手动调整步骤如下:
- 推导出缩放后的矩阵元素真实值 α c i j \alpha c_{ij} αcij。
- 对与 α c i j \alpha c_{ij} αcij 的偏差在 [ − 1.5 , 1.5 ] [-1.5,1.5] [−1.5,1.5] 范围内的每一个整数,都计算它们对应的 o i j o_{ij} oij, m i j m_{ij} mij, n i n_i ni。
- 由于变换矩阵中只有 31 个独特的数字,所以可以系统性的检查各种排列组合(虽然不是穷举遍历)。根据所有排列组合对应的 o i j o_{ij} oij, m i j m_{ij} mij, n i n_i ni 进行权衡,选出最终整数矩阵元素。上表中的第二列给出了最差情况下的值。当范数充分的接近 1 时(即 n i n_i ni 充分接近于 0),则可以认为 HEVC 中没有使用非平坦反量化矩阵(即所有变换系数的缩放因子都相同)。
为了进行对比,将 DCT 矩阵元素的真实值乘以 2 6 + M / 2 2^{6+M/2} 26+M/2,然后四舍五入到最近的整数。此时 o i j o_{ij} oij, m i j m_{ij} mij, n i n_i ni 的结果如上表的第三列所示。从表中可以看出,虽然 HEVC 核心变换的矩阵元素与缩放后的 DCT 矩阵元素有较大偏差,但是 HEVC 核心变换矩阵具有更好的正交性和范数性质。
最后,只用 8 个比特来表示矩阵元素使得性质 7(即矩阵元素之间的三角关系)很难被保留下来。
HEVC 核心变换的基向量
上图给出了 32 点正变换的
32
×
32
32 \times 32
32×32 矩阵的左半部分,右半部分可以通过基向量的对称、反对称性质得到。HEVC 的反变换矩阵定义为正变换矩阵的转置。
32
×
32
32 \times 32
32×32 矩阵有 31 个独特的数字如下所示:
d
i
,
0
32
,
i
=
1
,
.
.
.
,
31
=
{
90
,
90
,
90
,
89
,
88
,
87
,
85
,
83
,
82
,
80
,
78
,
75
,
73
,
70
,
67
,
64
,
61
,
57
,
54
,
50
,
46
,
43
,
38
,
36
,
31
,
25
,
22
,
18
,
13
,
9
,
4
}
d_{i,0}^{32},i=1,...,31=\{90,90,90,89,88,87,85,83,82,80,78,75,73,70,67,64,61,57,54,50,46,43,38,36,31,25,22,18,13,9,4\}
di,032,i=1,...,31={90,90,90,89,88,87,85,83,82,80,78,75,73,70,67,64,61,57,54,50,46,43,38,36,31,25,22,18,13,9,4}
这些独特的数字是正变换矩阵第一列中的第 1-31 个元素。需要注意的是,虽然数字 90 出现了 3 次,但这完全是偶然的,取整导致的。
此外,更小变换尺寸的矩阵元素
d
i
j
N
d_{ij}^N
dijN 都可以从
32
×
32
32 \times 32
32×32 变换矩阵的元素
d
i
j
32
d_{ij}^{32}
dij32 中推导获得,如下所示:
d
i
j
N
=
d
32
/
N
32
,
i
,
j
=
0
,
.
.
.
,
N
−
1
d_{ij}^N = d_{32/N}^{32},i,j = 0,...,N-1
dijN=d32/N32,i,j=0,...,N−1
这个性质使得不同尺寸的变换矩阵可以用相同的架构来实现,从而共享硬件资源。
中间缩放
与正交 DCT 变换相比,HEVC 的矩阵元素放大了 2 6 + M / 2 2^{6+M/2} 26+M/2 倍,为了使经过正变换和反变换之后的残差块的范数与变换前的残差块的范数保持一致,需要用到一些额外的缩放因子,如上图中的 S T 1 , S T 2 , S I T 1 , S I T 2 S_{T1},S_{T2},S_{IT1},S_{IT2} ST1,ST2,SIT1,SIT2。HEVC 标准中只规定了反变换的缩放因子 ( S I T 1 , S I T 2 ) (S_{IT1},S_{IT2}) (SIT1,SIT2),而其参考软件还规定了正变换的缩放因子 ( S T 1 , S T 2 ) (S_{T1},S_{T2}) (ST1,ST2)。缩放因子的选择需要遵循以下约束:
- 所有的缩放因子都应该是 2 的幂次方,以便于缩放操作可以用右移来实现。
- 假设输入残差块的所有元素都是最大值,则每个变换状态之后的变换系数的比特深度都是 16 比特(包括符号位)。这样做可以达到精度和实现复杂度的合理平衡。
- 由于 HEVC 变换矩阵放大了 2 6 + M / 2 2^{6+M/2} 26+M/2 倍,所以二维正变换与二维反变换级联将导致每一个一维行正变换、一维列正变换、一维行反变换、一维列反变换都放大 2 6 + M / 2 2^{6+M/2} 26+M/2 倍。为了使经过二维正变换和二维反变换之后的残差块的范数与变换前的残差块的范数保持一致,所有缩放因子的乘积必须等于 ( 1 / 2 6 + M / 2 ) 4 = 2 − 24 2 − 2 M (1/2^{6+M/2})^4=2^{-24}2^{-2M} (1/26+M/2)4=2−242−2M
以上图的 4 × 4 4 \times 4 4×4 正变换为例来解释选择正变换缩放因子的过程。当原始视频信号的比特深度为 B B B 比特时,残差的数值范围在 [ − 2 B + 1 , 2 B − 1 ] [-2^B+1,2^B-1] [−2B+1,2B−1] 之间,需要用 B + 1 B+1 B+1个比特来表示。接下来将分析最差情况下每个数据处理节点所需要的比特深度。假设残差块的所有值都是最大值 − 2 B -2^B −2B。这里需要注意的是,用 − 2 B -2^B −2B 代替 − 2 B + 1 -2^B + 1 −2B+1 或者 2 B − 1 2^B-1 2B−1 是因为它是 2 的整数次方。对于这种最差情况下的输入残差块,第一个基向量(长度为 N,每个元素都等于 64)与输入向量(每个元素的值都为 − 2 B -2^B −2B)进行内积后输出的最大值是 − 2 B × N × 64 -2^B \times N \times 64 −2B×N×64。因此,当 N = 2 M N = 2^M N=2M 时,为了使输出能用不多于 16 个比特进行表示(最大值为 − 2 15 -2^{15} −215),需要缩放 1 / ( 2 B × 2 M × 2 6 × 2 − 15 ) 1/(2^B\times 2^M \times 2^6 \times 2^{-15}) 1/(2B×2M×26×2−15) 倍。所以,第一个变换阶段的缩放因子为 S T 1 = 2 − ( B + M − 9 ) S_{T1} = 2^{-(B+M-9)} ST1=2−(B+M−9)。
正变换的第二阶段是将正变换第一阶段的结果乘以 D 4 T \textbf{D}_4^T D4T。正变换第一阶段的输出作为正变换第二阶段的输入,其是一个矩阵,第一行的所有元素均为 − 2 15 -2^{15} −215,其他的元素都为 0。如上图所示。该矩阵乘以 D 4 T \textbf{D}_4^T D4T 后,得到新矩阵。其中只有表示 DC 直流分量的元素等于 − 2 15 × N × 2 6 -2^{15}\times N\times 2^6 −215×N×26,其余元素的值都是 0。为了使输出能用不多于 16 个比特进行表示,则正变换第二阶段的输出值还需要进行 S T 2 = 2 − ( M + 6 ) S_{T2} = 2^{-(M+6)} ST2=2−(M+6) 倍的缩放。
反变换的第一阶段是将正变换的结果乘 D 4 T \textbf{D}_4^T D4T。在这个例子中,反变换第一阶段的输入是正变换的输出矩阵,而且这个矩阵只有表示直流分量的那个元素等于 − 2 15 -2^{15} −215,乘以 D 4 T \textbf{D}_4^T D4T之后,得到的矩阵只有第一列所有元素的值等于 − 2 15 × 2 6 -2^{15}\times 2^6 −215×26,其余元素的值都等于 0。为了使反变换第一阶段输出的结果能用不多于 16 个比特进行表示,则输出值还需要进行 S I T 1 = 2 − 6 S_{IT1} = 2^{-6} SIT1=2−6 倍的缩放。
反变换的第二阶段是将第一阶段的结果乘 D 4 \textbf{D}_4 D4。反变换第二段的输入是反变换第一阶段的输出,该输出矩阵只有第一列的所有元素等于 − 2 15 -2^{15} −215,其它元素都为 0,将其乘 D 4 \textbf{D}_4 D4 之后所得到的输出矩阵的所有元素都等于 − 2 15 × 2 6 -2^{15}\times 2^6 −215×26,为了使反变换第二段的输出值范围与原始正变换第一阶段输入值范围 [ − 2 B + 1 , 2 B − 1 ] [-2^B+1,2^B-1] [−2B+1,2B−1] 一致,则反变换第二阶段的输出值还需要进行 S I T 1 = 2 − ( 21 − B ) S_{IT1} = 2^{-(21-B)} SIT1=2−(21−B) 倍的缩放。
综上所述,在变换的不同阶段,所采用的缩放因子如下所示:
- 正变换第一阶段之后: S T 1 = 2 − ( B + M − 9 ) S_{T1} = 2^{-(B+M-9)} ST1=2−(B+M−9)
- 正变换第二阶段之后: S T 2 = 2 − ( M + 6 ) S_{T2} = 2^{-(M+6)} ST2=2−(M+6)
- 反变换第一阶段之后: S I T 1 = 2 − 6 S_{IT1} = 2^{-6} SIT1=2−6
- 反变换第二阶段之后: S I T 1 = 2 − ( 21 − B ) S_{IT1} = 2^{-(21-B)} SIT1=2−(21−B)
其中, B B B 是输入、输出信号的比特深度, M = l o g 2 N M=log_2N M=log2N。
如果没有量化和反量化,这样的缩放因子可以确保变换各个阶段的输出值都能用 16 比特进行表示。但是,量化/反量化所引入的量化误差,可能使得反变换各个阶段的输入值的动态范围超过了 16 比特所能表示的数值范围。例如,当 B = 8 B=8 B=8,正变换的输入矩阵的所有元素值均等于 255 255 255,在这种情况下,正变换的输出将是一个直流系数值,等于 255 < < 7 = 32640 255 << 7 = 32640 255<<7=32640。对于较大的 QP 值,并且量化器对量化值向上取整,那么反变换每个阶段的输入都很容易超过 16 比特所表示的数值动态范围 [ − 32768 , 32767 ] [-32768,32767] [−32768,32767]。将反量化的输出值截断为 16 比特是可以接受的,但是,将反变换第一阶段的输出值截断为 16 比特是不可接受的。为了容许一定的合理幅度的量化误差,并且将反变换两个阶段之间的所有结果限制在 16 比特范围内,则反变换的缩放因子最终修正为:
- 反变换第一阶段之后: S I T 1 = 2 − 7 S_{IT1} = 2^{-7} SIT1=2−7
- 反变换第二阶段之后: S I T 1 = 2 − ( 20 − B ) S_{IT1} = 2^{-(20-B)} SIT1=2−(20−B)
上表总结了正变换和反变换所采用的不同缩放因子,其中 2 ( 6 + M / 2 ) 2^{(6+M/2)} 2(6+M/2) 表示乘以变换矩阵的放大。
最后,系数采用 8 比特来表示,同时中间数据的比特深度限制为 16 比特,这样做有两个好处:
- 所有的乘法都可以用 16 比特或更少比特的乘法器进行表示;
- 对于所有的变换阶段,右移运算之前的累加器都可以用少于 32 比特来实现。
HEVC 额外的 4 × 4 4\times 4 4×4 变换
额外变换适用于
4
×
4
4\times 4
4×4 的帧内预测的亮度残差块,其正变换矩阵如下:
A
4
=
[
29
55
74
84
74
74
0
−
74
84
−
29
−
74
55
55
−
84
74
−
29
]
A_4 = \begin{bmatrix} 29 & 55 & 74 & 84 \\ 74 & 74 & 0 & -74 \\ 84 & -29 & -74 & 55 \\ 55 & -84 & 74 & -29 \\\end{bmatrix}
A4=⎣⎢⎢⎡297484555574−29−84740−747484−7455−29⎦⎥⎥⎤
A
4
A_4
A4 矩阵元素是第七类 DST 的定点表示,计算公式如下:
a
i
j
=
r
o
u
n
d
(
128
∗
2
2
N
+
1
sin
(
2
i
+
1
)
(
j
+
1
)
π
2
N
+
1
)
a_{ij} = round(128*\frac{2}{\sqrt{2N+1}} \sin{\frac{(2i+1)(j+1)\pi}{2N+1}})
aij=round(128∗2N+12sin2N+1(2i+1)(j+1)π)
中间结果的缩放因子以及量化/反量化的方法均与 HEVC 核心变换一样。
在进行帧内预测编码时,替代变换可以使比特率减少 1 % 1\% 1%。在进行帧内预测时,当前块的预测值是根据其左边和上方的相邻样本值获得的。因此,接近左侧边界和上侧边界的像素的预测效果会更好,其残差幅值会比较小;而远离左上方边界的像素,帧内预测后得到的残差幅值会比较大。在对帧内预测残差的这种空间特性进行建模时,DST 基函数比 DCT 基函数具有更好的效果,这也可以从 DST 的第一行(基函数)看出来,第一行元素的值从左到右是递增,而 DCT 的第一行是平坦的(即第一行元素均相等)。
在 HEVC 的发展过程中,用于 8 × 8 8\times 8 8×8 甚至更大尺寸的 DST 也有被研究过,然而由于大尺寸的 DST 所能获得的额外编码增益不明显,同时由于 DST 是非对称的,复杂度更高,实现变换时必须进行完整的矩阵乘法,所以 HEVC 只采用了 4 × 4 4\times 4 4×4 的 DST。
HEVC 中的量化和反量化
量化是先除以量化步长 Q s t e p Q_{step} Qstep,再对结果进行四舍五入,而反量化是乘以量化步长。 Q s t e p Q_{step} Qstep 标准正交变换的等效步长(即没有缩放因子)。与 H.264 类似, HEVC 中也采用量化参数 QP 来确定量化步长,对于比特深度为 8 的视频序列,QP 有 52 个值,从 0 到 51,QP 每增加1,则量化步长大概增加 12 % 12\% 12%(即 2 1 / 6 2^{1/6} 21/6),QP 每增加 6,则量化步长增加一倍。
一个标准正交变换的等效量化步长
Q
s
t
e
p
Q_{step}
Qstep 与 QP 之间的关系如下:
Q
s
t
e
p
(
Q
P
)
=
(
2
1
/
6
)
Q
P
−
4
(1)
Q_{step}(QP) = (2^{1/6})^{QP-4} \tag{1}
Qstep(QP)=(21/6)QP−4(1)
下图展示了
Q
s
t
e
p
Q_{step}
Qstep 与 QP 之间的非线性关系:
公式
(
1
)
(1)
(1) 可以写成下面的形式:
Q
s
t
e
p
(
Q
P
)
=
G
Q
P
%
6
<
<
Q
P
6
G
=
[
G
0
,
G
1
,
G
2
,
G
3
,
G
4
,
G
5
]
T
=
[
2
−
4
/
6
,
2
−
3
/
6
,
2
−
2
/
6
,
2
−
1
/
6
,
2
0
,
2
1
/
6
]
T
(2)
Q_{step}(QP) = G_{QP\%6} << \frac{QP}{6} \\ \textbf{G} = [G_0,G_1,G_2,G_3,G_4,G_5]^T = [2^{-4/6},2^{-3/6},2^{-2/6},2^{-1/6},2^{0},2^{1/6}]^T \tag{2}
Qstep(QP)=GQP%6<<6QPG=[G0,G1,G2,G3,G4,G5]T=[2−4/6,2−3/6,2−2/6,2−1/6,20,21/6]T(2)
HEVC 中对公式
(
2
)
(2)
(2) 进行定点近似:
g
Q
P
%
6
=
r
o
u
n
d
(
2
6
×
G
Q
P
%
6
)
g_{QP\%6} = round(2^6 \times G_{QP\%6})
gQP%6=round(26×GQP%6),得到:
g
=
[
g
0
,
g
1
,
g
2
,
g
3
,
g
4
,
g
5
]
T
=
[
40
,
45
,
51
,
57
,
64
,
72
]
T
\textbf{g} = [g_0,g_1,g_2,g_3,g_4,g_5]^T = [40,45,51,57,64,72]^T
g=[g0,g1,g2,g3,g4,g5]T=[40,45,51,57,64,72]T
对于量化器的输出
l
e
v
e
l
[
x
]
[
y
]
level[x][y]
level[x][y],HEVC 标准中规定反量化器的输出如下:
c
o
e
f
f
Q
[
x
]
[
y
]
=
(
l
e
v
e
l
[
x
]
[
y
]
×
(
g
Q
P
%
6
<
<
Q
P
6
)
+
o
f
f
s
e
t
I
Q
)
>
>
s
h
i
f
t
1
coeff_Q[x][y] = (level[x][y] \times (g_{QP\%6} << \frac{QP}{6}) + offset_{IQ}) >> shift1
coeffQ[x][y]=(level[x][y]×(gQP%6<<6QP)+offsetIQ)>>shift1
其中,
s
h
i
f
t
1
=
M
−
5
+
B
shift1 = M-5+B
shift1=M−5+B,
o
f
f
s
e
t
I
Q
=
1
<
<
(
M
−
6
+
B
)
offset_{IQ} = 1 << (M-6+B)
offsetIQ=1<<(M−6+B)。其是通过如下方式获得的:当
Q
P
=
4
QP=4
QP=4 (即
Q
s
t
e
p
=
1
Q_{step} = 1
Qstep=1)时,为了保持反变换和反量化之后的残差块的范数不变,那么反变换和反量化的缩放因子的乘积应该等于 1,即
2
−
s
h
i
f
t
1
×
g
4
×
16
×
2
−
(
15
−
M
−
B
)
=
1
2^{-shift1} \times g_4 \times 16 \times 2^{-(15-M-B)} = 1
2−shift1×g4×16×2−(15−M−B)=1
16 表示没有频域相关缩放。对于正变换的输出
c
o
e
f
f
[
x
]
[
y
]
coeff[x][y]
coeff[x][y],一种直观的量化方案是按照下面的公式来实现:
l
e
v
e
l
[
x
]
[
y
]
=
s
i
g
n
(
c
o
e
f
f
[
x
]
[
y
]
)
∗
(
(
(
a
b
s
(
c
o
e
f
f
[
x
]
[
y
]
)
×
f
Q
P
%
6
+
o
f
f
s
e
t
Q
)
>
>
Q
P
6
)
>
>
s
h
i
f
t
2
)
level[x][y] = sign(coeff[x][y])*(((abs(coeff[x][y]) \times f_{QP\%6} + offset_Q) >> \frac{QP}{6}) >> shift2)
level[x][y]=sign(coeff[x][y])∗(((abs(coeff[x][y])×fQP%6+offsetQ)>>6QP)>>shift2)
其中,
s
h
i
f
t
2
=
29
−
M
−
B
shift2 = 29-M-B
shift2=29−M−B,
f
=
[
f
0
,
f
1
,
f
2
,
f
3
,
f
4
,
f
5
]
T
=
[
26214
,
23302
,
20560
,
18396
,
16384
,
14564
]
T
\textbf{f}=[f_0,f_1,f_2,f_3,f_4,f_5]^T = [26214,23302,20560,18396,16384,14564]^T
f=[f0,f1,f2,f3,f4,f5]T=[26214,23302,20560,18396,16384,14564]T。值得注意的是
f
Q
P
%
6
=
2
14
/
(
g
Q
P
%
6
/
2
6
)
f_{QP\%6} = 2^{14}/(g_{QP\%6}/2^6)
fQP%6=214/(gQP%6/26)。求
s
h
i
f
t
2
shift2
shift2 的过程中也对正变换和量化的缩放因子的乘积进行与类似的约束,即
2
−
s
h
i
f
t
2
×
f
4
×
2
(
15
−
M
−
B
)
=
1
2^{-shift2} \times f_4 \times 2^{(15-M-B)} = 1
2−shift2×f4×2(15−M−B)=1。
量化矩阵
在 HEVC 中,编码器可以标记是否使用量化矩阵来实现频域相关的缩放。频域相关的缩放对于基于人类视觉系统(HVS) 的量化有很大作用,在基于 HVS 的量化过程中,变换块中的低频系数采用比高频系数更加精细/小的量化步长。对于某些视频序列,基于 HVS 的量化能够提供比频域独立量化更好的视觉性能。HEVC 使用以下 20 种与变换块的尺寸和类型相关的量化矩阵:
使用语法元素 scaling_list_enabled_flag 开启频域相关的缩放功能时,参考软件HM 中 4 × 4 4\times 4 4×4 和 8 × 8 8\times 8 8×8 量化矩阵的默认值如下图所示。
16 × 16 16\times 16 16×16 和 32 × 32 32\times 32 32×32 量化矩阵可以通过 8 × 8 8\times 8 8×8 量化矩阵进行上采样复制而获得,复制过程如下所示:
可以通过设置序列参数集(SPS)或者图像参数集(PPS),实现在码流中传输非默认的量化矩阵。采用对角扫描方式对量化矩阵的元素进行扫描,然后经过 DPCM 编码再进行传输。
QP 的推导
为了实现码率控制和感知量化,可能需要改变一帧图像的量化步长(即 QP 值)。HEVC 允许通过在量化组(Quantization Group,QG)层传输 delta QP 来改变一幅图像的 QP 值。QG 的尺寸是 CU 尺寸的倍数,并由 CTU 的尺寸以及语法元素 diff_cu_qp_delta_depth 决定,其范围从 8 × 8 8\times 8 8×8 到 64 × 64 64\times 64 64×64 。
只有具有非零变换系数的 CU 才会传输 delta QP。如果 CTU 被分割后的 CU 尺寸比 QG 尺寸大,delta QP 就会在比 QG 尺寸还大的 CU 上标记出来。如果 CTU 被分割后的 CU 尺寸比 QG 尺寸小,delta QP 只在 QG 的第一个非零变换系数的 CU 上标记出来。如果 QG 里面所有的 CU 全为零,则不标记 delta QP 。
如上图所示,QP 预测器通过结合左侧、上方以及前一个 QG(按解码顺序)的 QP 值来计算delta QP。QP 预测器结合使用了两种预测技术:空域 QP 预测(从左侧和上方的 QGs )和前一个 QP 预测。当 QG 处于 CTU 内部时,根据左侧和上方的 QG 进行空域预测,当 QG 处于 CTU 的边界时,根据前一个 QG 的 QP 值进行预测。当 QG 属于不同的 CTU,或者当前 QG 处于 slice/tile/picture 的边缘,则空域相邻的 QP 值 Q P L E F T QP_{LEFT} QPLEFT 和 Q P A B O V E QP_{ABOVE} QPABOVE 被认为是不存在的。而如果空域相邻的 QP 值不存在,就用解码顺序上的前一个 QP 值 Q P P R E V QP_{PREV} QPPREV 进行代替。 Q P P R E V QP_{PREV} QPPREV 在 slice/tile 或者 wavefront 开始的时候就初始化成 slice 的 QP 值。
上面描述的 QP 推导过程用于计算亮度的 QP 值,色度的 QP 值则是根据亮度的 QP 值推导出来的。
HEVC 特殊编码模式
HEVC 有三种特殊的编码模式,它们对变换和量化进行了修改,三种模式分别是:I_PCM 模式、lossless 模式和 transform skip 模式。这些模式要么省略掉变换,要么变换和量化都省略掉。下通用视频解码器的数据流程上展示这三种模式。
- 在 I_PCM 模式中,变换和量化都被省略掉。除此之外,熵编码和预测也被省略掉,直接通过规定的 PCM 比特深度对样本值进行编码。I_PCM 模式用于编码过程中存在数据扩展的场合,例如当视频编解码器中存在随机噪声时。通过直接对样本值进行编码,可以避免这类极端的视频序列的数据扩展。通过在 CU 层使用 pcm_flag 语法元素判断是否属于 I_PCM 模式。
- 在 lossless 模式中,变换和量化都被省略掉(上图中没有显示出来的环路滤波也被省略掉)。从数学上分析,无失真重构是可以做到的,因为直接对帧内或者帧间预测后的残差进行编码。为了使有损编码和无损编码能混合进行,在 CU 层使用 cu_transquant_bypass_flag 语法元素判断是否是 lossless 模式。这种方法对于编码混合内容的视频序列特别有用,例如叠加了文本和图形的自然视频。文本和图形区域可以采用无损编码方式来获得最大程度的可读性,而自然内容可以采用有损编码方式。
- 在 transform skip 模式中,只有变换被省略掉。这种模式可以改善诸如远程桌面、幻灯片等屏幕内容视频序列的压缩性能。这类视频序列主要包含文本和图形内容。transform skip 模式只能使用 4 × 4 4\times 4 4×4 的变换块。在 TU 层通过 transform_skip_flag 语法元素进行判断。
复杂度分析
编码性能
上表比较了 HEVC 中不同变换尺寸的编码性能。BD-rate 作为评价性能的指标。anchor 是仅使用 4 × 4 4\times 4 4×4 和 8 × 8 8\times 8 8×8 的尺寸。使用结果表明,HEVC 通过采纳较大的变换尺寸( 16 × 16 16\times 16 16×16 和 32 × 32 32\times 32 32×32)使得比特率平均减少 5.6 − 6.8 % 5.6-6.8\% 5.6−6.8%,对于更高分辨率的视频,比如 4K 和 1080p,节省的比特率更多。测试模型是 HM-9.0.1。
上表比较了 HEVC 中 4 × 4 4\times 4 4×4 和 8 × 8 8\times 8 8×8 变换的增益。anchor 是 H.264 中采用的 4 × 4 4\times 4 4×4 和 8 × 8 8\times 8 8×8 变换。