编码结构:编码树单元(CTU)、编码单元(CU)、预测单元(PU)、变换单元(TU)

核心原理:从宏块到四叉树的分层革命

在H.264/AVC中,编码的基本单位是固定大小的宏块(Macroblock,16×16像素)。这种刚性结构限制了编码效率的进一步提升。HEVC/H.265引入了全新的分层块结构,将编码的决策粒度从“像素块”提升到“语义树”层面。其核心思想是:将一帧图像划分为若干互不重叠的编码树单元(CTU),每个CTU再通过递归四叉树划分,动态生成编码单元(CU)、预测单元(PU)和变换单元(TU)。这种“一棵树、三种角色”的设计,使得编码器能够根据图像局部纹理复杂度,自适应地选择最优的划分深度和编码参数。

CTU是HEVC编码的根节点,其尺寸由序列参数集(SPS)中的 log2_min_luma_coding_block_size_minus3 和 log2_diff_max_min_luma_coding_block_size 共同决定。典型配置为64×64像素,最大可扩展至128×128,最小可降至16×16。每个CTU内部包含一个亮度编码树块(CTB)和两个色度编码树块(CTB),以及对应的语法元素。

CU是实际进行编码决策(帧内/帧间、跳过、合并等)的基本单元,其尺寸从CTU大小(如64×64)向下递归划分,最小可达8×8。PU在CU的基础上进一步划分,专门负责预测过程——决定使用哪种预测模式(帧内方向预测、帧间运动补偿等),以及运动矢量、参考帧索引等参数。TU则负责残差信号的变换与量化,其尺寸受限于CU,但可以独立于PU进行划分。三者关系可概括为:CU决定“怎么编码”,PU决定“怎么预测”,TU决定“怎么变换”。

HEVC 分层块结构:CTU → CU → PU/TU 关系图 CTU (64×64) CU₀ (32×32) PU₀: 2N×2N TU₀: 32×32 CU₁ (32×32) PU₁: 2N×N TU₁: 32×32 CU₂ (32×32) PU₂: N×2N TU₂: 32×32 CU₃ (32×32) PU₃: 2N×2N TU₃: 32×32 CU₃₀ 16×16 PU: N×N TU: 16×16 图例: CU 边界(编码决策) PU/TU 细分(预测/变换) 虚线 = 四叉树递归划分路径 CTU (编码树单元) SPS 定义尺寸,默认 64×64 CU (编码单元) 四叉树递归划分,最小 8×8 PU (预测单元) 帧内/帧间预测模式 运动矢量、参考帧 TU (变换单元) 残差变换与量化 DCT/DST,尺寸≤CU 关键语法元素与划分参数: • split_cu_flag:控制 CU 是否继续四叉树划分 • part_mode:指定 PU 划分模式(PART_2N×2N, PART_N×N 等) • rqt_root_cbf / split_transform_flag:控制 TU 划分 • inter_pred_idc:帧间预测方向(L0/L1/双向) • cu_skip_flag:跳过模式(不传残差和运动信息) PU 划分模式(帧间) 2N×2N 2N×N N×2N N×N 2N×nU 2N×nD nL×2N nR×2N 帧内

方法流程:编码器如何决策划分

在实际编码过程中,HEVC编码器通过率失真优化(RDO)遍历四叉树结构,寻找最优划分。以64×64的CTU为例,其决策流程如下:

  1. 计算当前CU的编码代价:对当前尺寸(如64×64)的CU,尝试所有可用的PU划分模式(帧内35种方向、帧间多种划分),计算率失真代价 J = D + λ·R,其中D为失真(通常用SSE或SAD),R为编码比特数,λ为拉格朗日因子。
  2. 递归尝试子划分:将当前CU四等分为4个子CU(如32×32),对每个子CU重复步骤1,得到子CU的最优代价之和。
  3. 比较并决策:若“不划分”的代价 ≤ “划分后”的代价,则停止划分,将当前CU作为最终编码单元;否则标记 split_cu_flag=1,继续向下递归。
  4. PU与TU的确定:在CU确定后,根据预测模式选择PU划分(如帧间常用2N×2N或2N×N),再根据残差特性决定TU划分。TU最大尺寸与CU相同,最小为4×4(亮度)。

这一过程可用伪代码表示:

void encode_CTU(CTU* ctu) {
    // 递归函数:尝试编码当前CU
    double cost_no_split = encode_CU(ctu, ctu->size);
    double cost_split = 0;
    
    if (ctu->size > MIN_CU_SIZE) {
        // 尝试四叉树划分
        for (int i = 0; i < 4; i++) {
            cost_split += encode_CTU(ctu->children[i]);
        }
    }
    
    // 率失真决策
    if (cost_no_split <= cost_split) {
        ctu->split_flag = 0;
        // 确定PU模式(遍历part_mode)
        // 确定TU划分(遍历split_transform_flag)
        return cost_no_split;
    } else {
        ctu->split_flag = 1;
        return cost_split;
    }
}

案例/场景:不同内容下的划分策略

为了直观理解分层结构的实际效果,考虑以下典型场景:

图像内容特征 典型划分结果 原因分析
平坦区域(如天空、墙壁) CU保持64×64,PU为2N×2N,TU为32×32或64×64 纹理简单,大块编码即可获得高压缩率,无需细分
物体边缘(如人脸轮廓) CU划分至16×16或8×8,PU采用N×2N或2N×N 边缘方向性强,非对称PU划分能更好匹配物体边界
复杂纹理(如树叶、草地) CU递归划分至8×8,TU也相应缩小至8×8或4×4 高频细节多,小尺寸TU可减少振铃效应,提高预测精度
运动剧烈区域(如快速移动的球) CU中等大小(32×32),PU采用2N×N或N×2N 需要更精细的运动补偿,但过小CU会增加运动矢量开销

以一段1080p视频为例,若画面中人物静止、背景为渐变天空,编码器可能将背景区域全部保留为64×64的CU,而人物边缘区域则划分至16×16。这种自适应策略使得HEVC相比H.264在同等画质下可节省约50%码率。

误区/复盘:面试中常见的理解偏差

误区一:认为CU、PU、TU是并列的独立块。实际上,它们是嵌套包含关系:一个CTU包含多个CU,每个CU包含一个或多个PU(通常为1个,帧间可能为2个),而TU则是在CU残差基础上进一步划分的。PU和TU不能跨越CU边界。

误区二:混淆TU与DCT变换块尺寸。TU的尺寸决定了变换矩阵的大小,但HEVC还引入了残差四叉树(RQT),允许TU在CU内部独立划分。例如,一个32×32的CU,其PU为2N×N(两个16×32的预测块),但TU可以划分为4个16×16或16个8×8的变换块,具体取决于残差分布。

面试加分点:强调HEVC中CU的最大尺寸(64×64)相比H.264宏块(16×16)扩大了16倍,这是编码效率提升的关键之一。同时,可以提及帧内预测的PU最小为4×4(对应亮度分量),而帧间PU最小为8×4或4×8(取决于 log2_min_pu_size),这些细节能体现对标准的深入理解。

另一个常见误区是认为skip模式与CU划分无关。实际上,当编码器选择skip模式时,意味着当前CU不传输残差、运动矢量差等任何信息,仅通过邻域推导运动参数。此时CU仍然存在,但PU和TU的语法元素被大幅简化——PU默认为2N×2N,TU不传输任何残差标志。理解这一点有助于解释为何skip模式在背景静止区域能极大节省码率。

最后,需要明确CTU的编码顺序。HEVC采用Z扫描(光栅扫描)顺序遍历CTU,但在每个CTU内部,CU的遍历顺序是Z形递归(先左上、再右上、再左下、最后右下)。这种顺序保证了空间相邻性,有利于上下文建模和运动矢量预测,是面试中容易被忽略的细节。