Key Points

  • 研究表明,H.266 VVC 可以在 MPEG2-TS 流中传输,DVB 标准将其流类型定义为 0x2c。
  • 编写 Wireshark LUA 插件需要解析 TS 包、重组 PES 包,并提取 H.266 NAL 单元进行分析。
  • 实现可能复杂,需处理 NAL 单元的跨包重组,建议参考 Wireshark 现有 H.264 解码器。

背景

H.266 VVC(多功能视频编码)是继 H.265 HEVC 后的最新视频压缩标准,旨在提供更高的压缩效率,特别适用于 4K 和 8K 视频流。MPEG2-TS(MPEG-2 传输流)是一种用于数字电视广播的容器格式,常用于地面或卫星传输。Wireshark 是一个网络协议分析工具,支持通过 LUA 脚本扩展功能,以分析特定协议或数据流。

实现步骤

要编写支持在 MPEG2-TS 中分析 H.266 VVC 的 Wireshark LUA 插件,需要以下步骤:

  1. 注册解码器:在 Wireshark 的 "ts.stream_type" 解码器表中,为流类型 0x2c 注册 H.266 解码器,这是 DVB 标准为 H.266 定义的流类型。
  2. 解析 TS 包:从 TS 包中提取基本流数据,处理可能的适应字段,确保获取到 PES(分组基本流)数据。
  3. 重组 PES 包:由于 PES 包可能跨多个 TS 包,需维护缓冲区按 PID(包标识符)累积数据,重组完整的 PES 包。
  4. 提取 H.266 位流:从 PES 包中提取 H.266 位流,识别以 0x00 0x00 0x01 开头的 NAL(网络抽象层)单元。
  5. 解析 NAL 单元:解析每个 NAL 单元的头部(2 字节),提取 nu_type(NAL 单元类型)、nu_layer_id(层 ID)等信息,并在 Wireshark 中显示。

注意事项

  • H.266 在 MPEG2-TS 中的支持较新,流类型 0x2c 的定义基于 DVB 标准,可能在某些系统中未广泛实现,需验证实际流是否符合。
  • NAL 单元可能跨多个 PES 包,需通过缓冲区处理部分 NAL 单元的累积和重组,类似 Wireshark 中 H.264 解码器的实现。
  • 建议参考 Wireshark 开发者文档,了解 LUA 脚本的 API 和现有解码器的实现方式。

详细报告

引言

H.266 VVC(多功能视频编码)是 2020 年 7 月 6 日由联合视频专家组(JVET) finalized 的视频压缩标准,旨在提供比 H.265 HEVC 更高的压缩效率,平均可节省 50% 的比特率,同时支持 4K、8K 等高分辨率视频流 Versatile Video Coding - Wikipedia。MPEG2-TS(MPEG-2 传输流)是一种标准数字容器格式,广泛用于数字电视广播,如 DVB、ATSC 和 IPTV 系统 MPEG transport stream - Wikipedia。Wireshark 是一个开源的网络协议分析工具,支持通过 LUA 脚本扩展功能,以分析特定协议或数据流。本报告详细探讨如何编写 Wireshark LUA 插件,支持在 MPEG2-TS 中分析 H.266 VVC。

H.266 VVC 在 MPEG2-TS 中的传输

研究表明,H.266 VVC 可以封装在 MPEG2-TS 流中,主要通过 DVB(数字视频广播)标准支持。DVB 项目已将 VVC(H.266)纳入其核心规范,用于广播和宽带应用,特别是在支持 4K 和 8K 视频的场景中 Next-gen video codec VVC (H.266) added to DVB tuner specification - FlatpanelsHD。具体而言,DVB 标准在文档 "DVB Commercial Module A155: Implementation guidelines for the use of VVC in DVB systems" 中定义,H.266 的流类型(stream_type)为 0x2c,这与 MPEG2-TS 中 PMT(程序映射表)中用于标识基本流的字段相对应。

MPEG2-TS 的结构包括固定长度的 188 字节包,每个包包含 4 字节的头部和 184 字节的有效载荷。头部包括同步字节(0x47)、PID(包标识符,13 位)等信息,而有效载荷可能包含适应字段(adaptation field)或基本流数据。对于视频流,基本流通常以 PES(分组基本流)包形式传输,PES 包可能跨多个 TS 包,需要重组才能获取完整的 H.266 位流 MPEG-2: Understanding the Transport Stream Structure | by Amitdogra | Medium

H.266 位流的结构

H.266 位流由 NAL(网络抽象层)单元组成,类似于 H.264 和 H.265。在字节流格式中,NAL 单元以起始码 0x00 0x00 0x01 开头,后面跟随 NAL 单元头部(2 字节)和有效载荷。NAL 单元头部定义如下:

  • 第一个字节:
  • 位 0-4:nu_type(NAL 单元类型,5 位)
  • 位 5:nu_reserved_bit(1 位,必须为 0)
  • 位 6-7:nu_reserved_two_bits(2 位,必须为 0)
  • 第二个字节:
  • 位 0-5:nu_layer_id(层 ID,6 位)
  • 位 6-7:nu_temporal_id(时间 ID,2 位)

这与 H.264 和 H.265 的 NAL 单元头部类似,但 H.266 引入了更多支持多层和时间层级的功能 Everything You Need to Know about H.266/VVC - VideoProc

Wireshark LUA 插件的实现

编写 Wireshark LUA 插件以分析 MPEG2-TS 中的 H.266 VVC 涉及以下步骤:

1. 注册解码器

在 Wireshark 中,TS 解码器使用 "ts.stream_type" 解码器表,根据 PMT 中的 stream_type 调用相应的子解码器。对于 H.266,stream_type 为 0x2c,因此需要在 LUA 脚本中注册:

local h266_proto = Proto("h266", "H.266 VVC Protocol")
-- 注册到 ts.stream_type 表,值为 0x2c
dissector_table = DissectorTable.get("ts.stream_type")
dissector_table:add(0x2c, h266_proto)

这确保当 TS 解码器遇到 stream_type 为 0x2c 的 PID 时,会调用我们的 H.266 解码器。

2. 维护缓冲区以处理跨包数据

由于 PES 包可能跨多个 TS 包,H.266 的 NAL 单元也可能不完整地分布在多个 TS 包中。需要为每个 PID 维护一个缓冲区,累积数据以重组完整的 NAL 单元。使用 LUA 全局表实现:

h266_buffers = h266_buffers or {} -- 初始化缓冲区表

在解码器函数中,根据 pinfo.ts_pid 获取对应 PID 的缓冲区:

local pid = pinfo.ts_pid
local buffer = h266_buffers[pid] or ByteArray.new()
buffer:append(buf) -- 追加当前 TS 包的有效载荷
h266_buffers[pid] = buffer
3. 提取和解析 NAL 单元

从缓冲区中搜索起始码 0x00 0x00 0x01,提取完整的 NAL 单元。假设缓冲区内容为字节数组,搜索起始码的位置:

  • 找到所有起始码位置,例如使用 string.find 或手动遍历。
  • 对于每个起始码,NAL 单元数据从起始码后的第 3 字节开始,到下一个起始码前的字节结束。
  • 解析 NAL 单元头部(2 字节),提取 nu_type、nu_layer_id 等字段。

例如,假设找到起始码位置 pos1 和 pos2:

  • 第一个 NAL 单元数据为 buffer[pos1+3, pos2-1]。
  • 解析头部,显示在 Wireshark 树中:
local subtree = tree:add(h266_proto, buf, "H.266 NAL Unit")
local nu_type = bit.rshift(bit.band(buffer:raw(0,1), 0x1F), 0) -- 提取 nu_type
subtree:add(f_nu_type, buffer(0,1), nu_type)

需要定义字段:

f_nu_type = ProtoField.uint8("h266.nu_type", "NAL Unit Type", base.DEC)
h266_proto.fields = {f_nu_type, ...}
4. 处理部分 NAL 单元

处理缓冲区中不完整的 NAL 单元:

  • 如果缓冲区开头没有起始码,可能是前一个 NAL 单元的延续,保留在缓冲区。
  • 处理完所有完整 NAL 单元后,缓冲区中剩余数据(最后一个起始码后的数据)是新 NAL 单元的开头,保留为下次处理。

例如,假设处理后剩余数据为 10 字节,更新 h266_buffers[pid]

h266_buffers[pid] = buffer:range(last_pos, buffer:len()-last_pos)
挑战与注意事项
  • 流类型确认:H.266 的 stream_type 为 0x2c 基于 DVB 标准,但可能在某些非 DVB 系统未实现,需验证实际流是否符合。
  • 跨包重组:NAL 单元可能跨多个 PES 包,需确保缓冲区机制能正确累积和解析,类似 Wireshark 中 H.264 解码器的实现。
  • 性能考虑:对于高比特率流,频繁的缓冲区操作可能影响性能,建议优化搜索起始码的算法。
参考实现

建议参考 Wireshark 现有 H.264 解码器实现,特别是在 TS 流中的处理方式 Wireshark 开发者文档。此外,可使用工具如 FFmpeg 生成包含 H.266 的 TS 文件进行测试 FFmpeg - Unknown key_frame and pict_type of encoded H.266 video stream - Stack Overflow

结论

通过在 Wireshark LUA 脚本中注册 stream_type 为 0x2c 的 H.266 解码器,并实现缓冲区机制以处理 NAL 单元的跨包重组,可以成功分析 MPEG2-TS 中的 H.266 VVC 流。尽管实现复杂,参考现有解码器和 DVB 标准可有效推进开发。

表 1:H.266 NAL 单元头部字段

字段名称

位数

描述

nu_type

5

NAL 单元类型

nu_reserved_bit

1

保留位,必须为 0

nu_reserved_two_bits

2

保留位,必须为 0

nu_layer_id

6

层 ID

nu_temporal_id

2

时间 ID

表 2:常见视频流类型

流类型 (Hex)

描述

标准

0x01

MPEG-1 视频

ISO/IEC 11172-2

0x02

MPEG-2 视频

ISO/IEC 13818-2

0x1b

H.264/AVC 视频

ISO/IEC 14496-10

0x24

H.265/HEVC 视频

ISO/IEC 23008-2

0x2c

H.266/VVC 视频

DVB A155 (推测)

Key Citations