rtp载荷H264解包过程分析,ffmpeg解码qt展示

本文详细解读了NALU头的结构,包括禁止位、重要性标识和类型,深入剖析了不同类型NALU单元(如单个帧、聚合包、分片单元)的含义及在RTP中的应用。重点介绍了如何处理SPS/PPS、FU-A/FU-B,以及如何利用ffmpeg解码H264数据。

网络抽象层单元 (NALU)

   NALU头

        NALU 头由1个byte组成, 它的语法如下:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+

  • F : 1 个比特. forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.
  • NRI:  2 个比特. nal_ref_idc. 取 00 ~ 11, 似乎指示这个 NALU 的重要性, 如 00 的 NALU 解码器可以丢弃它而不影响图像,不过一般情况下不太关心这个属性.
  • Type:  5 个比特.nal_unit_type表示这个 NALU 单元的类型.

        NALU头中表示的type类型

Type取值 包类型名称
0 未定义
1-23 为NALU包,且该NALU内包含一个完整的H264帧
1 不分区,非IDR图像的片
2 片分区A
3 片分区B
4 片分区C
5 IDR图像中的片
6 补充增强信息单元(SEI)
7 SPS
8 PPS
9 序列结束
10 序列结束
11 码流借宿
12 填充
13-23 保留
24 STAP-A Single-time aggregation packet
25 STAP-B Single-time aggregation packet
26 MTAP16 Multi-time aggregation packet
27 MTAP24 Multi-time aggregation packet
28 FU-A Fragmentation unit
29 FU-B Fragmentation unit
30-31 undefined

        上述type中,单个mtu中包含一个独立完整的h264帧和多个mtu组成一个单独完整的h264帧的情形比较容易见到。以下图为例,就是我们从三光吊舱拿到的payload:


        因为我使用了wireshark的extract_h264插件,所以这里显示的是H.264字段,如果没有使用该插件,则显示的是RTP的payload字段。同图中可以看到FU identifier是一个字节0x3C,对应的是0011 1100,对照上述的NALU 头的解释,F位为0,NRI为01,表示重要性;type为28,表示这个包为FU-A分片单元,也说明这个是某个h264帧的一个分片,该帧需要多个分片构成分片方式为FU-A。

也就是说,一个使用RTP封装的h264的包的payload和h264的帧存在3种对应关系:

  • Single NAL unit packet(单NALU包): 也就是实际的NAL类型,可以理解为一个包就是一帧H264数据,这个在实际中是比较多的。
  • Aggregation packet (聚合包):一包数据中含有多个H264帧,封装在Aggregation packet中的 NAL单元大小为65535字节。
    • STAP-A 包内的帧含有相同的NALU-Time,没有DON;
    • STAP-B 包内的帧含有相同的NALU-Time,有DON
    • MTAP16 包内的帧含有不同的NALU-Time,timestamp offset = 16
    • MTAP24 包内的帧含有不同的NALU-Time,timestamp offset = 24
  • Fragmentation unit(分片包): 一帧数据被分为多个RTP包,这也是很常见的,特别是对于关键帧。现存两个版本FU-A,FU-B。实际应用就是要加上个H264 STREAM 的头h264_stream_head = 0x00,0x00,0x00,0x01 4字节,送去解码即可。

分包规则

        这里讲解上述三种情况下,h264的数据和payload的关系;

单个NAL单元包(type值为1-23)

        对于 NALU 的长度小于MTU 大小的包, 一般采用单个NAL 单元模式。

        一个原始的 H.264 NALU (也就是还原后的应该有的样子)单元常由 [Start Code] [NALU Header] [NALU Payload]三部分组成, 其中 Start Code 用于标示这是一个 NALU 单元的开始, 必须是 "00 00 00 01" 或 "00 00 01", NALU 头(上述的0x3C)仅一个字节, 其后都是 NALU 单元内容。

        对于这样的包,在rtp打包时只是去除了 "00 00 01" 或 "00 00 00 01" 的开始码(Start Code), 把其他数据(包括NALU header和NALU payload)封包的 RTP 包即可。

        一个封装单个NAL单元包到RTP的NAL单元流的RTP序号必须符合NAL单元的解码顺序。单个NAL单元包的结构显示如图。(NAL单元的第一字节和RTP荷载头第一个字节重合)
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|NRI| type | |
+-+-+-+-+-+-+-+-+ |
| |
| Bytes 2..n of a Single NAL unit |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

     &n

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值