VVC 参考软件 VTM 全面深度解析:架构设计、核心算法与工程实践

摘要:本文对 VVC(H.266)国际标准参考软件 VTM(VVC Test Model)v23.4 进行全面深度解析。从项目整体架构、模块组成,到帧内/帧间预测、变换量化、环路滤波、熵编码等核心技术模块,逐一剖析其算法原理与 C++ 实现。同时结合配置文件分析,揭示 VTM 在随机存取、全帧内、低延迟三大编码场景下的参数设定策略。适合视频编码研究者、工程师深入参考。


一、项目背景

1.1 VVC 标准简介

VVC(Versatile Video Coding,通用视频编码) ,正式标准编号为 Rec. ITU-T H.266 | ISO/IEC 23090-3 ,于 2020 年 7 月由 ITU-T VCEG 和 ISO/IEC MPEG 联合发布。相较于上一代 HEVC(H.265),VVC 在相同感知质量下可节省约 50% 的码率,代价是编码复杂度提升约 10 倍。

VVC 的主要应用场景包括:

  • 8K/4K 超高清视频流媒体
  • 360° 全景视频
  • HDR 高动态范围视频
  • VR/AR 媒体内容
  • 视频会议与直播

1.2 VTM 项目定位

VTM(VVC Test Model) 是由 JVET(Joint Video Experts Team)联合开发的 VVC 官方参考软件,当前版本为 v23.4。其主要用途:

用途 说明
一致性检验 验证编解码实现是否符合标准规范
互操作性测试 不同厂商实现之间的互操作验证
性能基准 为新工具/算法提供对比基线
教学研究 理解 VVC 标准技术细节的权威参考

项目托管于 Fraunhofer HHI 的 GitLab:https://vcgit.hhi.fraunhofer.de/jvet/VVCSoftware_VTM.git


二、项目整体架构

2.1 目录结构一览

复制代码
VVCSoftware_VTM-master/
├── source/
│   ├── App/                    # 应用程序层
│   │   ├── EncoderApp/         # 编码器应用(EncoderApp main 入口)
│   │   ├── DecoderApp/         # 解码器应用(DecoderApp main 入口)
│   │   ├── DecoderAnalyserApp/ # 解码分析工具
│   │   ├── BitstreamExtractorApp/   # 码流提取工具
│   │   ├── SEIFilmGrainApp/    # 胶片颗粒 SEI 工具
│   │   ├── SEIRemovalApp/      # SEI 删除工具
│   │   ├── StreamMergeApp/     # 码流合并工具
│   │   ├── SubpicMergeApp/     # 子图合并工具
│   │   ├── Parcat/             # 参数集合并工具
│   │   └── utils/              # 通用工具
│   └── Lib/                    # 核心库层
│       ├── CommonLib/          # 公共库(编解码共用)
│       ├── EncoderLib/         # 编码器专用库
│       ├── DecoderLib/         # 解码器专用库
│       ├── CommonAnalyserLib/  # 公共分析库
│       ├── DecoderAnalyserLib/ # 解码分析库
│       ├── Utilities/          # I/O 工具(YUV 读写等)
│       └── libmd5/             # MD5 校验库
├── cfg/                        # 编码配置文件
│   ├── encoder_intra_vtm.cfg               # 全帧内编码(AI)
│   ├── encoder_randomaccess_vtm.cfg        # 随机存取(RA)
│   ├── encoder_lowdelay_vtm.cfg            # 低延迟 B(LDB)
│   ├── encoder_lowdelay_P_vtm.cfg          # 低延迟 P(LDP)
│   ├── 444/                    # YUV 4:4:4 格式配置
│   ├── hbd/                    # 高比特深度配置
│   ├── multi-layer/            # 多层编码配置
│   ├── rpr/                    # 参考图像重采样配置
│   └── ...
├── doc/                        # 软件使用手册
├── cmake/                      # CMake 构建脚本
├── CMakeLists.txt              # 根 CMake 构建文件
├── Makefile                    # Make 构建文件
└── README.md

2.2 分层架构设计

复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                         应用层 (App Layer)                           │
│  EncoderApp  │  DecoderApp  │  AnalyserApp  │  其他工具 Apps        │
├─────────────────────────────────────────────────────────────────────┤
│                         编码器库 (EncoderLib)                        │
│  EncLib  │  EncGOP  │  EncSlice  │  EncCu  │  InterSearch           │
│  IntraSearch  │  RateCtrl  │  CABACWriter  │  EncALF  │  EncSAO    │
├─────────────────────────────────────────────────────────────────────┤
│                         解码器库 (DecoderLib)                        │
│  DecLib  │  DecSlice  │  DecCu  │  CABACReader  │  SEIread         │
├─────────────────────────────────────────────────────────────────────┤
│                         公共库 (CommonLib)                           │
│  IntraPrediction  │  InterPrediction  │  TrQuant                   │
│  AdaptiveLoopFilter  │  SampleAdaptiveOffset  │  DeblockingFilter  │
│  CodingStructure  │  UnitPartitioner  │  ContextModelling          │
│  MatrixIntraPrediction(MIP)  │  DepQuant  │  Buffer  │  Slice      │
├──────────────────────────────────────┬──────────────────────────────┤
│        x86 SIMD 加速 (SSE/AVX)       │   MIPS / ARM NEON 支持      │
└──────────────────────────────────────┴──────────────────────────────┘

三、CommonLib 公共库深度剖析

3.1 基础常量与类型定义

CommonDef.h 是整个项目的基础,定义了大量关键常量:

cpp 复制代码
// 编码单元尺寸
static constexpr int MAX_CU_DEPTH  = 7;       // 最大 CU 深度 (log2(128)=7)
static constexpr int MAX_CU_SIZE   = 128;     // CTU 最大尺寸 128×128
static constexpr int MIN_CU_SIZE   = 4;       // 最小 CU 尺寸 4×4

// 帧内预测模式数量
static constexpr int NUM_DIR                  = 16;
static constexpr int NUM_INTRA_ANGULAR_MODES  = 4 * NUM_DIR + 1;  // 65 个角度模式
static constexpr int NUM_LUMA_MODE            = 67;   // 亮度模式总数(含 Planar/DC)
static constexpr int NUM_INTRA_MODE           = 70;   // 含色度 LMC 模式

// 帧间预测参数
static constexpr int MRG_MAX_NUM_CANDS        = 6;   // Merge 最大候选数
static constexpr int AFFINE_MRG_MAX_NUM_CANDS = 5;   // 仿射 Merge 最大候选数
static constexpr int AMVP_MAX_NUM_CANDS       = 2;   // AMVP 最大候选数

// ALF(自适应环路滤波)
static constexpr int MAX_NUM_ALF_CLASSES      = 25;  // 最大分类数
static constexpr int MAX_NUM_ALF_LUMA_COEFF   = 13;  // 亮度滤波器系数数
static constexpr int ALF_FIXED_FILTER_NUM     = 64;  // 固定滤波器数量

// 运动向量精度
static constexpr int MV_FRACTIONAL_BITS_INTERNAL = 4;  // 内部 1/16 精度
static constexpr int MV_FRACTIONAL_BITS_SIGNAL   = 2;  // 信号 1/4 精度

TypeDef.h 定义了全局宏开关,控制所有编码工具的使能状态:

cpp 复制代码
// 典型工具开关(数值为 1 表示在当前版本中已整合)
#define JVET_AH0078_DPF          1   // 失真传播因子(DPF)
#define REUSE_CU_RESULTS         1   // CU 结果复用加速
#define ENABLE_SIMD_OPT          1   // SIMD 优化
// 针对 x86 平台支持 SSE4.1/4.2, AVX, AVX2, AVX512

3.2 编码结构 CodingStructure

CodingStructure(CodingStructure.h)是 VTM 的核心数据承载体,描述一个图像区域完整的编码信息:

cpp 复制代码
class CodingStructure {
public:
    UnitArea area;              // 当前区域(位置 + 尺寸)
    const Slice *slice;         // 所属 Slice
    const SPS *sps;             // 序列参数集
    const PPS *pps;             // 图像参数集

    std::vector<CodingUnit*>    cus;  // CU 列表
    std::vector<PredictionUnit*> pus; // PU 列表
    std::vector<TransformUnit*>  tus; // TU 列表

    PelStorage  getPredBuf();   // 预测像素缓冲区
    PelStorage  getResiBuf();   // 残差缓冲区
    PelStorage  getRecoBuf();   // 重建像素缓冲区

    // RD Cost 相关
    double      cost;
    double      costDbOffset;
    uint64_t    fracBits;
    Distortion  dist;
};

CodingStructure 实现了竞争式编码决策 :对于每个 CU,分配 tempCS(临时结构)和 bestCS(最优结构),通过 RD cost 比较选出最优模式。

3.3 分区分割器 UnitPartitioner

VVC 采用 QTBT(四叉树 + 二叉树)加三叉树(TT) 的灵活分割结构,由 QTBTPartitioner 类实现:

复制代码
分割类型枚举 (PartSplit):
- CU_QUAD_SPLIT         四叉树分割(QT)
- CU_HORZ_SPLIT         水平二叉树分割(BT-H)
- CU_VERT_SPLIT         垂直二叉树分割(BT-V)
- CU_TRIH_SPLIT         水平三叉树分割(TT-H)
- CU_TRIV_SPLIT         垂直三叉树分割(TT-V)
- TU_MAX_TR_SPLIT       TU 最大变换尺寸分割
- TU_NO_ISP / TU_1D_HORZ_SPLIT / TU_1D_VERT_SPLIT  ISP 子块分割

关键参数(来自配置文件):

复制代码
CTUSize               = 128   # CTU 为 128×128
MinQTLumaISlice       = 8     # I 帧最小 QT 叶节点尺寸
MinQTNonISlice        = 8     # P/B 帧最小 QT 叶节点
MaxMTTHierarchyDepth  = 3     # MTT 最大深度

四、帧内预测模块

4.1 传统角度帧内预测

VVC 将角度预测模式从 HEVC 的 33 个扩展到 65 个方向(含 Planar=0, DC=1),横跨水平、对角线、垂直四个扇区:

cpp 复制代码
// CommonDef.h 中的帧内模式索引
static constexpr int PLANAR_IDX = 0;          // Planar 模式
static constexpr int DC_IDX     = 1;          // DC 模式
static constexpr int HOR_IDX    = 18;         // 水平方向
static constexpr int DIA_IDX    = 34;         // 对角线方向
static constexpr int VER_IDX    = 50;         // 垂直方向
static constexpr int VDIA_IDX   = 66;         // 反对角线方向
static constexpr int BDPCM_IDX  = (5*NUM_DIR + ANGULAR_BASE); // BDPCM 模式

IntraPrediction 类中的核心函数:

cpp 复制代码
// 平坦模式预测
void xPredIntraPlanar(const CPelBuf &pSrc, PelBuf &pDst);

// DC 模式预测
void xPredIntraDc(const CPelBuf &pSrc, PelBuf &pDst, 
                  const ChannelType channelType);

// 角度预测(含整数/分数精度插值)
void xPredIntraAng(const CPelBuf &pSrc, PelBuf &pDst, 
                   const ChannelType channelType, const ClpRng& clpRng);

// BDPCM(块差分脉冲编码调制)
void xPredIntraBDPCM(const CPelBuf &pSrc, PelBuf &pDst, 
                     BdpcmMode dirMode, const ClpRng &clpRng);

4.2 VVC 新增帧内工具

① MRL(Multi-Reference Line,多参考行)
cpp 复制代码
static constexpr int MRL_NUM_REF_LINES = 3;   // 3 条参考行选择
static constexpr int MULTI_REF_LINE_IDX[4] = { 0, 1, 2, 0 };

VVC 允许选择距当前块 第 0、1、2 行作为帧内参考,弥补复杂纹理区域单参考行预测不足的问题。

② ISP(Intra Sub-Partitions,帧内子块分割)

ISP 将一个 CU 在水平或垂直方向分割为多个矩形 TU,每个 TU 依次使用已重建子块作为参考:

cpp 复制代码
// TUIntraSubPartitioner 专门处理 ISP 分割
class TUIntraSubPartitioner : public Partitioner {
    void splitCurrArea(const PartSplit split, const CodingStructure &cs);
    void getTUIntraSubPartitions(Partitioning &sub, const UnitArea &tuArea, 
                                 const CodingStructure &cs, const PartSplit splitType);
};
③ MIP(Matrix-based Intra Prediction,矩阵帧内预测)

MatrixIntraPrediction(MatrixIntraPrediction.h)是 VVC 最具创新性的帧内工具之一:

cpp 复制代码
class MatrixIntraPrediction {
public:
    // 准备输入:下采样边界像素
    void prepareInputForPred(const CPelBuf &pSrc, const Area &block, 
                             const int bitDepth, const ComponentID compId);
    
    // 矩阵乘法预测
    void predBlock(Pel *const result, const int modeIdx, const bool transpose, 
                   const int bitDepth, const ComponentID compId);
    
    static int getNumModesMip(const Size &block);

private:
    // 根据块尺寸分组(S0: 4×4, S1: 8×8 or 4×8, S2: 16×16+)
    enum class MipSizeId { S0 = 0, S1, S2, NUM };
    
    static constexpr int MIP_MAX_INPUT_SIZE = 8;             // 最大输入向量长度
    static constexpr int MIP_MAX_REDUCED_OUTPUT_SAMPLES = 64; // 最大输出采样数
};

MIP 核心思想 :将边界像素下采样为向量 → 与预存矩阵相乘 → 上采样得到预测块。矩阵系数存于 MipData.h,支持最多 32 种 MIP 模式

④ CCLM(Cross-Component Linear Model,跨分量线性模型)

色度预测采用 CCLM,从重建亮度信号线性预测:

cpp 复制代码
// 从亮度重建像素估计线性模型参数 a, b
void xGetLMParameters(const PredictionUnit &pu, const ComponentID compID, 
                      const CompArea &chromaArea, int &a, int &b, int &iShift);

// 实际色度预测:Chroma = a × Luma + b
void predIntraChromaLM(const ComponentID compID, PelBuf &piPred, 
                       const PredictionUnit &pu, const CompArea &chromaArea, 
                       int intraDir);

##🏃 五、帧间预测模块

5.1 运动向量精度与搜索

VVC 的 MV 精度达到 1/16 像素(内部),比 HEVC 提高了一倍:

cpp 复制代码
static constexpr int MV_FRACTIONAL_BITS_INTERNAL = 4;  // 1/16 精度
static constexpr int NTAPS_LUMA          = 8;           // 亮度 8 抽头插值
static constexpr int NTAPS_LUMA_AFFINE   = 6;           // 仿射 6 抽头插值
static constexpr int NTAPS_CHROMA        = 4;           // 色度 4 抽头插值

AMVR(自适应运动向量分辨率) :VVC 允许在同一帧内对不同 CU 选择不同的 MV 精度(1/4、1/2、整数或 4 整数像素),由 IMV 工具控制。

5.2 Merge 模式体系

复制代码
VVC Merge 候选列表(最多 6 个)
├── 空间 Merge 候选(5 个空间邻居)
├── 时域 Merge 候选(TMVP/ATMVP)
├── HMVP(History-based MVP)候选  ← VVC 新增
│   static constexpr int MAX_NUM_HMVP_CANDS = 5
├── 配对平均 MVP 候选(Pairwise Average)
└── 零 MV 补位候选

MergeCtx 类管理 Merge 候选列表:

cpp 复制代码
class MergeCtx {
    bool     mvSolid[MRG_MAX_NUM_CANDS][2];   // MV 是否稳定
    bool     mvValid[MRG_MAX_NUM_CANDS][2];   // MV 是否有效
    bool     useAltHpelIf[MRG_MAX_NUM_CANDS]; // 是否使用半像素插值

    // MMVD(Merge with MVD)模式
    bool     mmvdSolid[MmvdIdx::BASE_MV_NUM][2];
    
    void setMergeInfo(PredictionUnit &pu, int candIdx) const;
    void setMmvdMergeCandiInfo(PredictionUnit &pu, MmvdIdx candIdx);
};

5.3 VVC 高级帧间工具

① 仿射运动预测(Affine Motion)

VVC 支持 4 参数(平移+旋转+缩放)6 参数(+剪切) 仿射模型:

cpp 复制代码
enum class AffineModel : uint8_t { _4_PARAMS, _6_PARAMS, NUM };
static constexpr int AFFINE_MAX_NUM_CP = 3;     // 最多 3 个控制点
static constexpr int AFFINE_SUBBLOCK_SIZE = 4;  // 仿射子块最小尺寸 4×4
static constexpr int AFFINE_MRG_MAX_NUM_CANDS = 5; // 仿射 Merge 候选数

xPredAffineBlk() 将 CU 划分为 4×4 子块,对每个子块分别计算 MV 并独立进行运动补偿。

② DMVR(Decoder-side Motion Vector Refinement)
cpp 复制代码
// DMVR 子块尺寸
static constexpr int DMVR_SUBCU_WIDTH  = 16;
static constexpr int DMVR_SUBCU_HEIGHT = 16;
static constexpr int DMVR_RANGE        = 2;    // 搜索半径 ±2 像素
static constexpr int DMVR_SPAN         = 5;    // = 2*RANGE + 1

DMVR 在解码端对双预测 MV 进行精细化搜索,无需额外码字,仅需微小的计算开销。

③ BDOF(Bi-Directional Optical Flow,双向光流精细化)
cpp 复制代码
static constexpr int MAX_BDOF_APPLICATION_REGION = 16;  // 最大应用区域

void applyBiOptFlow(const PredictionUnit &pu, 
                    const CPelUnitBuf &yuvSrc0, 
                    const CPelUnitBuf &yuvSrc1,
                    PelUnitBuf &yuvDst, 
                    const BitDepths &clipBitDepths);

BDOF 利用光流约束方程在 4×4 子块级对双预测信号进行像素级精细化,显著提升双向预测精度。

④ PROF(Prediction Refinement with Optical Flow,基于光流的仿射预测精细化)
cpp 复制代码
static constexpr int PROF_BORDER_EXT_W = 1;
static constexpr int PROF_BORDER_EXT_H = 1;

PROF 对仿射运动补偿后的预测块进行光流精细化,消除仿射子块边界的不连续性。

⑤ GEO(Geometric Partitioning,几何分割)
cpp 复制代码
static constexpr int GEO_NUM_PARTITION_MODE = 64;     // 64 种几何分割模式
static constexpr int GEO_NUM_ANGLES         = 32;     // 32 个分割角度
static constexpr int GEO_MAX_NUM_UNI_CANDS  = 6;      // 最大单向候选数
static constexpr int GEO_MAX_NUM_CANDS      = 30;     // 最大双向候选组合数

GEO 允许 CU 被任意角度的直线分割为两个非矩形区域,两区域使用独立的运动向量,适合覆盖物体边界的 CU。

⑥ BCW(Bi-Prediction with CU-level Weights,CU 级加权双预测)
cpp 复制代码
static constexpr int BCW_NUM     = 5;   // 5 种权重组合 (−2/8, 3/8, 4/8, 5/8, 10/8)
static constexpr int BCW_DEFAULT = 2;   // 默认 = 等权 4/8:4/8
static constexpr int BCW_SIZE_CONSTRAINT = 256;   // 仅对 ≥256 像素 CU 启用
⑦ IBC(Intra Block Copy,帧内块拷贝)
cpp 复制代码
static constexpr int IBC_MAX_CU_SIZE = 64;         // 最大 IBC 块 64×64
static constexpr int IBC_NUM_CANDIDATES = 64;       // 候选存储数
static constexpr int IBC_REF_IDX = MAX_NUM_ACTIVE_REF;  // IBC 参考帧索引

IBC 在当前图像内搜索匹配块,对于屏幕内容(界面、文字、游戏)编码效率极高。


六、变换与量化模块

6.1 变换工具体系

VVC 支持多种变换类型,统一由 TrQuant 类管理:

cpp 复制代码
class TrQuant {
    // 正向变换 (编码端)
    void transformNxN(TransformUnit &tu, const ComponentID &compID, 
                      const QpParam &cQP, TCoeff &absSum, const Ctx &ctx, 
                      RDPCostList &trModes, ...);

    // 逆变换 (解码端)
    void invTransformNxN(TransformUnit &tu, const ComponentID &compID, 
                         PelBuf &pResi, const QpParam &cQPs);

    // 变换类型选择
    void getTrTypes(const TransformUnit tu, const ComponentID compID, 
                    TransType &trTypeHor, TransType &trTypeVer);

    // LFNST 正/逆变换
    void fwdLfnstNxN(TCoeff* src, TCoeff* dst, uint32_t mode, 
                     uint32_t index, uint32_t size, int zeroOutSize);
    void invLfnstNxN(TCoeff* src, TCoeff* dst, uint32_t mode, 
                     uint32_t index, uint32_t size, int zeroOutSize, 
                     const int maxLog2TrDynamicRange);
};

VVC 支持的变换类型

变换 说明 应用场景
DCT-2 标准 2D DCT 通用,默认选择
DST-7 正弦类型 VII 帧内残差(接近边界的 TU)
DCT-8 余弦类型 VIII 帧内残差
TS(Transform Skip) 跳过变换 屏幕内容/高频纹理
BDPCM 块 DPCM 屏幕内容帧内

MTS(Multiple Transform Selection):允许对同一 CU 评估多种变换组合(水平+垂直独立选择):

cpp 复制代码
static constexpr uint32_t NUM_TRAFO_MODES_MTS = 6;     // 最多 6 种变换组合
static constexpr uint32_t MTS_INTRA_MAX_CU_SIZE = 32;  // 帧内 MTS 最大 CU
static constexpr uint32_t MTS_INTER_MAX_CU_SIZE = 32;  // 帧间 MTS 最大 CU

LFNST(Low-Frequency Non-Separable Transform)

cpp 复制代码
static constexpr int MAX_LFNST_COEF_NUM   = 16;  // 最多 16 个非分离变换系数
static constexpr int NUM_LFNST_NUM_PER_SET = 3;  // 每组 3 个 LFNST 矩阵

LFNST 在主变换(DCT-2/DST-7)后对左上角 4×4 系数块应用一个额外的非分离变换,进一步去除能量集中区域的相关性,尤其适合帧内编码。

SBT(Sub-block Transform,子块变换)

cpp 复制代码
static constexpr int SBT_MAX_SIZE    = 64;   // SBT 最大 CU 尺寸
static constexpr int SBT_NUM_SL     = 10;    // 历史保存的 PU 决策数
static constexpr int SBT_NUM_RDO    = 2;     // 每 PU 最多尝试的 SBT 模式数

SBT 将 CU 残差限制在半块(水平或垂直的上/左半部分),变换仅应用于有残差能量的子块,减少需要传输的系数。

6.2 量化模块

cpp 复制代码
// 量化参数范围
static constexpr int MAX_QP      = 63;   // VVC 将 QP 范围扩展至 0-63
static constexpr int QUANT_SHIFT = 14;   // Q(4) = 2^14
static constexpr int IQUANT_SHIFT = 6;

// 色度 QP 映射
static constexpr int MAX_NUM_CQP_MAPPING_TABLES = 3;  // Cb/Cr/联合
static constexpr int MAX_QP_OFFSET_LIST_SIZE    = 6;

// 依赖量化 (DepQuant)
// DepQuant.h: 基于 Trellis 的上下文依赖量化,显著提升 RD 效率

RDOQ(Rate-Distortion Optimized Quantization):在量化过程中考虑码率代价,选择最优量化步骤(通过 Lagrange 乘子 λ 折衷 R 和 D)。

依赖量化(DepQuant):VVC 引入了状态机依赖的量化方案,通过前后系数的状态转移进一步优化 RD 性能,是相比 HEVC 的重要改进之一。


七、环路滤波模块

7.1 去方块滤波(DBF)

VVC 的 DBF 相较 HEVC 有所增强,支持对 Cb 和 Cr 分量独立配置:

cpp 复制代码
// 配置文件参数示例
DeblockingFilterBetaOffset_div2   : -2   // β 偏移
DeblockingFilterTcOffset_div2     : 0    // Tc 偏移
DeblockingFilterCbBetaOffset_div2 : -2   // Cb β 偏移
DeblockingFilterCrBetaOffset_div2 : -2   // Cr β 偏移

7.2 SAO(样本自适应偏移)

cpp 复制代码
class SampleAdaptiveOffset {
    // SAO 类型:Band Offset(BO)和 Edge Offset(EO)
    // EO 方向:水平/垂直/135°/45°
};

SAO 通过在重建样本中添加查找表偏移量来减少量化失真,是 HEVC 引入并在 VVC 中保留的工具。

7.3 ALF(自适应环路滤波)------ VVC 核心改进

ALF 是 VVC 相较 HEVC 最重要的新增环路滤波工具之一:

cpp 复制代码
class AdaptiveLoopFilter {
    // 分类:将 CTU 内的 4×4 块分为 25 类
    void deriveClassification(AlfClassifier **classifier, 
                              const CPelBuf &srcLuma, 
                              const Area &blkDst, const Area &blk);

    // 滤波器应用(5×5 和 7×7 两种形状)
    void (*m_filter5x5Blk)(...);  // 5×5 钻石形
    void (*m_filter7x7Blk)(...);  // 7×7 钻石形

    // CC-ALF(跨分量 ALF)
    static void filterBlkCcAlf(const PelBuf &dstBuf, 
                                const CPelUnitBuf &recSrc,
                                const Area &blkDst, const Area &blkSrc, 
                                ComponentID compID, ...);
};

ALF 关键参数:

cpp 复制代码
static constexpr int MAX_NUM_ALF_CLASSES         = 25;   // Laplacian 梯度分 25 类
static constexpr int MAX_NUM_ALF_LUMA_COEFF      = 13;   // 亮度 7×7 13 系数(钻石)
static constexpr int MAX_NUM_ALF_CHROMA_COEFF    = 7;    // 色度 5×5 7 系数
static constexpr int ALF_FIXED_FILTER_NUM        = 64;   // 固定 64 个预置滤波器集合
static constexpr int MAX_NUM_CC_ALF_FILTERS      = 4;    // CC-ALF 最多 4 个滤波器
static constexpr int MAX_NUM_CC_ALF_CHROMA_COEFF = 8;    // CC-ALF 系数数

CC-ALF(Cross-Component ALF):色度 ALF 中引入亮度信号辅助滤波,进一步提升色度质量:

cpp 复制代码
void applyCcAlfFilter(CodingStructure &cs, ComponentID compID, 
                      const PelBuf &dstBuf, 
                      const PelUnitBuf &recYuvExt, ...);

7.4 LMCS(Luma Mapping with Chroma Scaling,亮度映射+色度缩放)

cpp 复制代码
// EncReshape.cpp 中实现
// LMCS = 自适应分段线性亮度映射 + 色度残差缩放
// 主要用于 HDR 内容,调整 QP 分配使亮度均匀量化

LMCSEnable      : 1     # 使能 LMCS
LMCSSignalType  : 0     # 0=SDR, 1=HDR-PQ, 2=HDR-HLG
LMCSOffset      : 6     # 色度残差缩放偏移

八、熵编码模块(CABAC)

8.1 算术编码器架构

VVC 延续 HEVC 的 CABAC(Context-based Adaptive Binary Arithmetic Coding)框架,在 BinEncoder/BinDecoder 中实现:

复制代码
编码端 CABAC 调用链:
EncCu → CABACWriter → BinEncoder
         ├── VLCWriter(VLC 固定码)
         └── 上下文自适应模型(Contexts.h)

解码端 CABAC 调用链:
DecCu → CABACReader → BinDecoder
         ├── VLCReader
         └── 上下文模型

8.2 上下文模型管理

cpp 复制代码
// ContextModelling.h
class CUCtx {
    // CU 级上下文管理
    void setNumCtxBins(int n);            // 设置上下文 bin 限制
    void decimateNumCtxBins(int n);       // 消耗上下文 bin 计数
};

// 分割决策上下文
void CtxSplit(const CodingStructure &cs, Partitioner &partitioner,
              unsigned &ctxSpl, unsigned &ctxQt, unsigned &ctxHv,
              unsigned &ctxHorBt, unsigned &ctxVerBt, bool *canSplit);

// Rice 参数自适应更新
void updateRiceStat(unsigned &riceStat, TCoeff rem, int remainderFlag);

VVC 引入了 TU 级 bin 约束机制,限制每个 TU 中可使用的上下文 bin 数量,有效控制解码复杂度:

cpp 复制代码
static constexpr int MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_LUMA   = 28;
static constexpr int MAX_TU_LEVEL_CTX_CODED_BIN_CONSTRAINT_CHROMA = 28;

九、编码器核心决策:EncCu

9.1 CU 压缩主流程

EncCu::compressCtu() 是编码器的核心入口,对每个 CTU 进行 RDO 搜索:

cpp 复制代码
void EncCu::compressCtu(CodingStructure &cs, const UnitArea &area, 
                         const unsigned ctuRsAddr,
                         const EnumArray<int, ChannelType> &prevQP, 
                         const EnumArray<int, ChannelType> &currQP) {
    // 入口 → 递归分割 → 模式选择
    xCompressCU(tempCS, bestCS, partitioner);
}

void EncCu::xCompressCU(CodingStructure *&tempCS, CodingStructure *&bestCS,
                         Partitioner &pm, double maxCostAllowed) {
    // 1. 初始化当前级别上下文 (EncModeCtrl::initCULevel)
    // 2. 遍历所有候选模式 (通过 EncModeCtrl 迭代)
    //    - xCheckRDCostIntra()          帧内编码 RD 代价
    //    - xCheckRDCostMerge2Nx2N()     Merge 模式 RD 代价
    //    - xCheckRDCostInter()          帧间编码 RD 代价
    //    - xCheckModeSplit()            分割模式 RD 代价
    // 3. 选出最优模式 → 更新 bestCS
}

关键核心函数(EncCu.cpp 共 4825 行)

cpp 复制代码
// 分割决策
void xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
                     Partitioner &pm, const EncTestMode &encTestMode, 
                     const ModeType modeTypeParent, ...);

// 帧内编码
bool xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS, 
                        Partitioner &pm, const EncTestMode &encTestMode, 
                        bool adaptiveColorTrans);

// 抑制增益计算(去块优化)
void xCalDebCost(CodingStructure &cs, Partitioner &partitioner, bool calDist);

// 几何分割
// Geo Merge 候选组合评估(多达 30 种方向组合)

9.2 编码模式控制器 EncModeCtrl

EncModeCtrl(抽象基类)管理编码决策流程,提供早终止、快速算法等优化:

cpp 复制代码
class EncModeCtrl {
    virtual void initCTUEncoding(const Slice &slice) = 0;
    virtual void initCULevel(Partitioner &partitioner, const CodingStructure &cs) = 0;
    virtual void finishCULevel(Partitioner &partitioner) = 0;

    // 早终止优化
    void setEarlySkipDetected();
    
    // 快速决策相关
    void setBestCostWithoutSplitFlags(double cost);
    void setMtsFirstPassNoIspCost(double cost);
    void setStopNonDCT2Transforms(bool val);
    
    // ISP/MTS/LFNST 快速控制
    void setISPMode(const ISPType val);
    void setISPLfnstIdx(uint8_t val);
    void setBestPredModeDCT2(uint16_t intraMode, bool mipFlag);
};

9.3 GOP 层编码 EncGOP

EncGOP(EncGOP.h/EncGOP.cpp)管理 GOP 级编码流程:

cpp 复制代码
// EncGOP 集成的组件
├── EncSampleAdaptiveOffset  // SAO 编码
├── EncAdaptiveLoopFilter    // ALF 编码
├── EncReshape               // LMCS 编码
├── EncSlice                 // Slice 编码
├── VLCWriter                // VLC 码流写入
├── CABACWriter              // CABAC 编码
├── SEIwrite / SEIEncoder    // SEI 消息编写
├── SEIFilmGrainAnalyzer     // 胶片颗粒 SEI 分析
└── RateCtrl                 // 码率控制

十、码率控制系统

10.1 层次化码率控制

VVC 的码率控制在三个层次进行:

cpp 复制代码
class RateCtrl {
    EncRCSeq *m_encRCSeq;   // 序列级码控
    EncRCGOP *m_encRCGOP;   // GOP 级码控
    EncRCPic *m_encRCPic;   // 图像级码控
    
    void init(int totalFrames, int targetBitrate, 
              const Fraction &frameRate, int GOPSize, 
              int intraPeriod, int picWidth, int picHeight, ...);
};

class EncRCPic {
    void create(EncRCSeq *encRCSeq, EncRCGOP *encRCGOP, int frameLevel, ...);
    void updateAfterCTU(int LCUIdx, int bits, int QP, double lambda, ...);
    void updateAfterPicture(int actualHeaderBits, int actualTotalBits, 
                            double averageQP, double averageLambda, bool isIRAP);
};

10.2 λ-QP 模型

VVC 码率控制采用 R-λ 模型,基于 Hyperbolic 函数

复制代码
R = α × λ^β    (其中 α, β 为 CTU 级自适应估计参数)
λ = (α/R)^(1/β)

通过在 CTU 级持续更新 (α, β) 参数,实现精细的 QP 自适应调整。


十一、SIMD 加速架构

VTM 支持多级 x86 SIMD 优化:

复制代码
source/Lib/CommonLib/x86/
├── sse41/    # SSE4.1 优化(最低兼容要求)
├── sse42/    # SSE4.2 优化
├── avx/      # AVX 优化(256-bit)
└── avx2/     # AVX2 优化(推荐生产环境)

优化覆盖的模块:
- AdaptiveLoopFilterX86.h    # ALF SIMD
- BufferX86.h                # 像素缓冲操作 SIMD
- InterpolationFilterX86.h   # 运动补偿插值 SIMD
- TrQuantX86.h               # 变换量化 SIMD
- RdCostX86.h                # SAD/SATD/SSE 代价函数 SIMD
- AffineGradientSearchX86.h  # 仿射梯度计算 SIMD
- IbcHashMapX86.h            # IBC 哈希检索 SIMD

SIMD 运行时检测:

cpp 复制代码
typedef enum { SCALAR=0, SSE41, SSE42, AVX, AVX2, AVX512 } X86_VEXT;
X86_VEXT read_x86_extension_flags(const std::string &extStrId);

内存对齐配置(AVX2 需要 32 字节对齐):

cpp 复制代码
constexpr size_t MEMORY_ALIGN_DEF_SIZE = 32;  // AVX2 对齐
#define xMalloc(type, len) _aligned_malloc(sizeof(type) * (len), MEMORY_ALIGN_DEF_SIZE)

十二、编码配置文件解析

12.1 随机存取(RA)配置

文件:cfg/encoder_randomaccess_vtm.cfg

ini 复制代码
# 编码结构
CTUSize          = 128      # 128×128 CTU(VVC 标准最大)
IntraPeriod      = 32       # 每 32 帧一个 I 帧
GOPSize          = 32       # 32 帧 GOP,多级 B 帧层次
DecodingRefreshType = 1     # CRA(Clean Random Access)

# MTT 分割
MaxMTTHierarchyDepth = 3    # 最大 3 级 MTT(在 QT 叶节点后)
DualITree = 1               # I 帧亮度/色度独立分割树

# 全套工具使能
MTS=1  LFNST=1  ISP=1  MIP=1  MRL=1
Affine=1  DMVR=1  BIO=1  BDOF=1  BCW=1
MMVD=1  CIIP=1  Geo=1  SbTMVP=1  SMVD=1
ALF=1  LMCS=1  JointCbCr=1  PROF=1  DepQuant=1

# 时域预滤波
TemporalFilter=1
TemporalFilterStrengthFrame8  = 0.95
TemporalFilterStrengthFrame16 = 1.5

12.2 三种编码配置对比

参数 全帧内 (AI) 随机存取 (RA) 低延迟 B (LDB)
IntraPeriod -1(仅首帧)或1 32 -1
GOPSize 1 32 16
B 帧 多层 B 只有 B(低延迟)
参考帧数 1 5(双向) 4(单向)
时域滤波 有(强) 有(弱)
主要用途 图像/高质量帧 点播/直播 会议/低延

十三、解码器架构

13.1 解码流程

复制代码
码流输入 → NALread → VLCReader → CABACReader
                                    ↓
                              DecLib(DecLib.cpp: 4289行)
                                    ↓
                              DecSlice → DecCu
                                    ↓
                    IntraPrediction / InterPrediction
                    TrQuant(逆变换逆量化)
                    AdaptiveLoopFilter
                    SampleAdaptiveOffset
                    DeblockingFilter
                                    ↓
                              重建图像输出

13.2 解码器工具类

DecoderLib 目录(共 19 个文件):

文件 功能
DecLib.cpp 解码器主类,管理参数集、POC、参考图像列表
DecCu.cpp CU 级解码(重建预测、残差、重建)
CABACReader.cpp CABAC 算术解码器
BinDecoder.cpp 二值化解码器(VLC/CABAC bin)
NALread.cpp NAL 单元解析(起始码检测、RBSP 脱壳)
SEIread.cpp SEI 消息解析
VLCReader.cpp 可变长码读取

十四、性能特性与工程实践

14.1 编码复杂度分布

复制代码
帧内预测(I帧): ~25-30% 总编码时间
帧间搜索(P/B帧):
  ├── InterSearch.cpp (11458行): 全搜索/TZ搜索/仿射搜索 ~35-40%
  └── IntraSearch.cpp (6376行): 帧内候选评估 ~10-15%
变换量化 (EncCu.cpp 4825行): ~15-20%
ALF/SAO/DBF: ~5-10%
熵编码: ~3-5%

14.2 快速算法(Fast Tools)

ini 复制代码
# 配置文件中的快速算法开关
PBIntraFast      : 1   # 快速帧内决策(哈达玛 SATD 初筛)
FastMrg          : 1   # 快速 Merge(早终止)
AMaxBT           : 1   # 自适应最大 BT 深度
FastLocalDualTreeMode : 1  # 快速双树决策
BcwFast          : 1   # BCW 快速搜索
LCTUFast         : 1   # 大 CTU 快速决策
MTTSkipping      : 1   # MTT 跳过优化
MmvdDisNum       : 6   # MMVD 搜索点数限制

14.3 构建方法

bash 复制代码
# 创建构建目录
mkdir build && cd build

# Windows Visual Studio 2019
cmake .. -G "Visual Studio 16 2019" -A x64

# Linux Release 版本(推荐)
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)

# macOS Xcode
cmake .. -G "Xcode"

14.4 基本使用

bash 复制代码
# 编码(随机存取,QP=32)
EncoderApp -c encoder_randomaccess_vtm.cfg \
           -c per-sequence/BasketballDrive.cfg \
           -i input.yuv -o output.bin --QP 32

# 解码
DecoderApp -b output.bin -o decoded.yuv

# 解码分析(统计工具使用信息)
DecoderAnalyserApp -b output.bin

# 码流提取(多层编码)
BitstreamExtractorApp -b input.bin -o extracted.bin

十五、VVC vs HEVC 技术对比

特性 HEVC (H.265) VVC (H.266)
CTU 最大尺寸 64×64 128×128
分割结构 QT QT + BT + TT
帧内预测角度 33 67
新增帧内工具 MIP、ISP、MRL、CCLM
仿射运动 4/6 参数仿射
高级 Merge TMVP HMVP、MMVD、CIIP、GEO、BCW
运动精度 1/4 (HEVC) 1/16 像素
帧间优化 BDOF、DMVR、PROF
变换 DCT-2 DCT-2/DST-7/DCT-8/MTS/LFNST/SBT
量化 固定 依赖量化 + RDOQ
环路滤波 DBF+SAO DBF+SAO+ALF(含CC-ALF)+LMCS
最大 QP 51 63
压缩效率 基准 约提升 50%(BD-Rate -50%)

十六、总结与展望

VTM(VVC 参考软件)是迄今为止技术复杂度最高的视频编解码参考软件之一,本文从以下维度进行了全面剖析:

  1. 宏观架构:三层设计(App / EncoderLib / CommonLib),模块职责清晰
  2. 帧内创新:67 个角度模式 + MRL + ISP + MIP + CCLM,全面覆盖各类纹理
  3. 帧间突破:仿射运动、BDOF/DMVR/PROF 光流优化、GEO 几何分割、BCW 加权双预测
  4. 变换革命:MTS + LFNST + SBT + 依赖量化,极大提升变换域压缩效率
  5. 滤波升级:ALF(含 CC-ALF)+ LMCS,显著提升重建质量
  6. 工程优化:AVX2/SSE4.1 SIMD 全模块覆盖,运行时指令集检测

随着 VVC 在 OTT 流媒体(Disney+、Netflix)和广播(DVB、ATSC 3.0)中的逐步部署,VTM 的价值将持续提升。对于研究者来说,VTM 既是研究新算法的实验平台,也是理解 VVC 标准底层实现的不二之选。


参考资料

  1. ITU-T H.266 / ISO/IEC 23090-3: Versatile Video Coding 国际标准
  2. VTM 官方 Git 仓库: https://vcgit.hhi.fraunhofer.de/jvet/VVCSoftware_VTM
  3. JVET 会议文稿: https://www.jvet-experts.org/
  4. VTM 软件手册: VVCSoftware_VTM-master/doc/ 目录
  5. BD-Rate 工具: https://www.itu.int/rec/T-REC-H.265

标签: VVC, H.266, VTM, 视频编码, 帧内预测, 帧间预测, ALF, CABAC, MIP, 仿射运动, 依赖量化, LFNST, 视频压缩, ITU, ISO

项目版本: VTM v23.4 (2024, ITU/ISO/IEC)

创作日期: 2026年5月

相关推荐
ZC跨境爬虫2 小时前
跟着 MDN 学 HTML day_13:多媒体嵌入 —— 视频与音频
前端·css·笔记·ui·html·音视频
jinglong.zha20 小时前
AI萌宠短剧实战:从0孵化动物IP,用AI制作爆款短视频
人工智能·ai·音视频·网赚教程·萌宠
大学生小郑1 天前
CMOS 传感器堆叠结构
图像处理·学习·音视频·视频
luoqice1 天前
利用librtmp实现h264和AAC音频的推流
音视频·aac
byte轻骑兵1 天前
蓝牙CAP规范解析:构建多设备协同的通用音频新生态
人工智能·音视频·le audio·低功耗音频·蓝牙通话
大象AI共学1 天前
我让AI写了个网页,它自动变成了视频
人工智能·音视频
Prannt1 天前
星朗智能语音——视频音色替换
ai·音视频·语音识别
时空自由民.2 天前
音视频图片压缩
音视频
日取其半万世不竭2 天前
PeerTube 部署指南:自建视频托管平台
云原生·eureka·音视频