基本流的第一次封装(PES)

Published: 2020-09-06

Tags: 视音频

本文总阅读量

视音频领域,PES 全程 Packetized elementary stream,即原始流打包后的数据包(原始流第一次封装)。

Transport Streams and Program Streams are each logically constructed from PES packets. PES packets shall be used to convert between Transport Streams and Program Streams. In some cases the PES packets need not be modified when performing such conversions. PES packets may be much larger than the size of a Transport Stream packet.

之前解析过的 PS (Program Streams)包和 TS(Transport Streams)包都是基于 PES 包创建的,所以 PS 包与 TS 包可以相互转换,在一些场景下,PS 包和 TS 可以直接进行转换而无需修改 PES 包。

此处学习 PES 的结构,有助于弄清楚 TS 包中携带的 Payload 数据部分。

PES 包头

字段 大小 描述
Packet start code prefix 3 bytes 固定值:0x000001
Stream id 1 byte 例如: 音频流(0xC0-0xDF), 视频流 (0xE0-0xEF)
Note: 以上 4 字节称为起始代码
PES Packet length 2 bytes 指定在这个字段后的字节数,可以为零,如果这个字段为零的话,这个包可以是任意的长度,并且只有当这个 PES 包携带的是视频数据的时候,这个字段才可以为零。
Optional PES header variable length (length >= 3) 当携带数据为 Padding stream 和 Private stream 2 (navigation data) 时不存在扩展头,根据 Stream id 值确定。
Data 基本流数据

判断是否存在扩展头部

Stream ID Stream type 是否存在扩展头部?
1011 1101 0xBD Private stream 1 存在
1011 1110 0xBE Padding stream 不存在
1011 1111 0xBF Private stream 2 不存在
110x xxxx 0xC0 - 0xDF MPEG-1 audio stream number x xxxx 存在
1110 xxxx 0xE0 - 0xEF MPEG-1 video stream number xxxx 存在

先看眼之前的 TS 文件,看看 TS 包装载的是什么数据。

黄色区域为上篇解析 TS 包时的 TS 包头,蓝色框选区域即为其 Payload部分,也就是 PES 数据。

PES 头部 00 00 01 e0 表示其为视频数据。PES Packet length 值为 00 00,并没有指定 PES Payload 长度,说明其为 Payload 为任意长度。

此时,需要看一下 PES 包的扩展头部结构,才能进一步查看携带的数据。

Optional PES header

首先是三个字节长度的首部,起始为 10 开头,截图中对应的字节为 80 c0 0a 二进制表示为:10000000 11000000 00001010,固定的 10 2-bits 起始。

再挑选两个重要的字段看下:比如 PTS DTS flags,值(11 = both present, 01 is forbidden, 10 = only PTS, 00 = no PTS or DTS),本例此处值为 11,即 PTS 与 DTS 数据都存在。

另一个是 PES header length,也就是上图的第三个字节,本例的 0a,十进制的 10 字节,表示在此字节之后,PES 扩展头部还有 10 字节长度。

还是这个 TS 包,紫色和橙色(刚刚解析得到的10字节)部分即为 PES 头部(包含扩展头)。

其后的一干数据就是 PES 携带的 Payload 数据部分了,ES 基本流,本包之前根据类型判断携带的是视频数据。

00 00 00 01 起始,在查阅海康摄像头数据的时候已经了解过了,它是起始头部,其后的一个字节表明数据类型,本例值为 09 倒是之前没有见到过。

查阅后得知,09 代表 AUD(Access Unit Delimiter),可用于基本流中帧的分隔,它是可选的 NALU ,在 TS 中它是必须的。在不要求它的容器或协议下,通常可以省略它的以节省空间,不过基于它来寻找起始帧还是蛮有用的,不用解析每个 NALU。

PES 包结构跟 TS 结构都比较简单,一般来说 PES 包要比 TS 包大很多,要装在 TS 包中,需要分割成多个包装载。

接下来,是时候了解一下 H264 了,视音频中的重中之重。

参考

  1. http://dvd.sourceforge.net/dvdinfo/pes-hdr.html
  2. https://en.wikipedia.org/wiki/Packetized_elementary_stream
  3. https://doc-kurento.readthedocs.io/en/6.10.0/knowledge/h264.html