如何发送和接收RTP封包的H264,用FFmpeg解码

本文详细介绍了如何将H264分片打包成RTP包,包括三种封包模式:单一NAL单元模式、组合封包模式和分片封包模式(FU-A)。此外,还探讨了RTP包的解包过程,以及如何使用FFmpeg进行解码。文章最后展示了实现RTP发送和接收的代码示例,以及一个简单的H264网络流播放器的实现,强调了双线程处理以提高效率。
摘要由CSDN通过智能技术生成

这篇文章给大家介绍怎么打包H264分片到RTP包,并且实现一个播放程序演示接收RTP包和用FFmpeg解码。为了让大家更了解H264打包成RTP的细节,有必要罗嗦一下向大家介绍一些相关的基础知识,下面分三节介绍,其中前面两节是基础知识,第三节重点讲解怎么实现RTP包的发送和接收,以及怎么用FFmpeg解码显示。

一、H264的组成结构

H264以NALU(NALunit)为单位来支持编码数据在基于分组交换技术网络中传输的。
NALU的结构是:NAL头+RBSP,实际传输中的数据流如图所示:


264句法元素的分层结构

NALU头用来标识后面的RBSP是什么类型的数据,他是否会被其他帧参考以及网络传输是否有错误。

NALU头结构

长度:1byte
forbidden_bit(1bit) + nal_reference_bit(2bit) + nal_unit_type(5bit)
 

1.forbidden_bit:                             禁止位,初始为0,当网络发现NAL单元有比特错误时可设置该比特为1,以便接收方纠错或丢掉该单元。

2.nal_reference_bit:                   nal重要性指示,标志该NAL单元的重要性,值越大,越重要,解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU。

.nal_unit_type:NALU类型取值如下表所示。

nal_unit_type

NAL类型

C

0

未使用

 

1

非IDR图像中不采用数据划分的片段

2,3,4

2

非IDR图像中A类数据划分片段

2

3

非IDR图像中B类数据划分片段

3

4

非IDR图像中C类数据划分片段

4

5

IDR图像的片

2,3

6

补充增强信息单元(SEI)

5

7

序列参数集

0

8

图像参数集

1

9

分界符

6

10

序列结束

7

11

码流结束

8

12

填充

9

13..23

保留

 

24..31

不保留(RTP打包时会用到)

 

RBSP:RBSP数据是下表中的一种

RBSP类型 所写 描述
参数集 PS 序列的全局信息,如图像尺寸,视频格式等
增强信息 SEI 视频序列解码的增强信息
图像界定符 PD 视频图像的边界
编码片 SLICE 编码片的头信息和数据
数据分割   DP片层的数据,用于错误恢复解码
序列结束符   表明一个序列的结束,下一个图像为IDR图像
流结束符   表明该流中已没有图像
填充数据   亚元数据,用于填充字节

NAL的开始和结束

编码器将每个NAL各自独立、完整地放入一个分组,因为分组都有头部,解码器可以方便地检测出NAL的分界,并依次取出NAL进行解码。

每个NAL前有一个起始码 0x00 00 01(或者0x00 00 00 01),解码器检测每个起始码,作为一个NAL的起始标识,当检测到下一个起始码时,当前NAL结束。

同时H.264规定,当检测到0x000000时,也可以表征当前NAL的结束。那么NAL中数据出现0x000001或0x000000时怎么办?H.264引入了防止竞争机制,如果编码器检测到NAL数据存在0x000001或0x000000时,编码器会在最后个字节前插入一个新的字节0x03,这样:

0x000000->0x00000300
0x000001->0x00000301
0x000002->0x00000302
0x000003->0x00000303
解码器检测到0x000003时,把03抛弃,恢复原始数据(脱壳操作)。解码器在解码时,首先逐个字节读取NAL的数据,统计NAL的长度,然后再开始解码。

 

二、RTP封包H264的方式

NALU打包成RTP的方式有三种:

1. 单一 NAL 单元模式
     即一个RTP 包仅由一个完整的 NALU 组成. 这种情况下 RTP NAL 头类型字段和原始的 H.264的
NALU 头类型字段是一样的.

2. 组合封包模式
    即可能是由多个NAL 单元组成一个 RTP 包. 分别有4种组合方式: STAP-A, STAP-B, MTAP16, MTAP24.
那么这里的类型值分别是 24, 25, 26 以及 27.

3. 分片封包模式
    用于把一个NALU 单元封装成多个 RTP 包. 存在两种类型 FU-A 和 FU-B. 类型值分别是 28 和 29.

还记得前面nal_unit_type的定义吧,0~23是给H264用的,24~31未使用,在rtp打包时,如果一个NALU放在一个RTP包里,可以使用NALU的nal_unit_type,但是当需要把多个NALU打包成一个RTP包,或者需要把一个NALU打包成多个RTP包时,就定义新的type来标识。

      Type  Packet      Typename                      
     ---------------------------------------------------------
     0     undefined                                   -
     1-23   NAL unit    Single NAL unit packet perH.264  
     24     STAP-A     Single-timeaggregation packet    
     25     STAP-B     Single-timeaggregation packet    
     26     MTAP16    Multi-time aggregationpacket     
     27     MTAP24    Multi-time aggregationpacket     
     28     FU-A      Fragmentationunit               
     29     FU-B      Fragmentationunit                
     30-31 undefined                   
                

 

三种打包方式的具体格式

1 .单一 NAL 单元模式

对于 NALU 的长度小于 MTU 大小的包, 一般采用单一 NAL 单元模式.
对于一个原始的 H.264 NALU 单元常由 [Start Code] [NALU Header] [NALU Payload] 三部分组成, 其中 Start Code 用于标示这是一个

NALU 单元的开始, 必须是 "00 00 00 01" 或 "00 00 01", NALU 头仅一个字节, 其后都是 NALU 单元内容.
打包时去除 "00 00 01" 或 "00 00 00 01" 的开始码, 把其他数据封包的 RTP 包即可.

      0                  1                  2                  3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 01 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |F|NRI| type  |                                              |
     +-+-+-+-+-+-+-+-+                                              |
     |                                                              |
     |              Bytes 2..n of a Single NALunit                |
     |                                                              |
     |                              +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     |                              :...OPTIONAL RTP padding        |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+


如有一个 H.264 的 NALU 是这样的:

[00 00 00 01 67 42 A0 1E 23 56 0E 2F... ]

这是一个序列参数集 NAL 单元. [00 00 00 01] 是四个字节的开始码,67 是 NALU 头, 42 开始的数据是 NALU 内容.

封装成 RTP 包将如下:

[ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F]

即只要去掉 4 个字节的开始码就可以了.


2 组合封包模式

其次, 当 NALU 的长度特别小时, 可以把几个 NALU 单元封在一个 RTP 包中.


      0                  1                  2                  3
       0 1

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值