h265、h264的RTP包封装区别

h265、h264的RTP包封装区别

一、NAL单元

1、h264 NAL单元

    /*
     *     h264 nal头部(1字节)
     *    0 1 2 3 4 5 6 7
     *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     *   |F|NRI|  Type   |  NAL payload ……
     *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
     */
    名称       bit   备注 
	禁止位      1    为0的时候合法
	优先级      2    数值越大优先级越高,表示越重要   
	NAL类型     5    一共有32种
		            (sps是7, pps是8, sei是6. I帧是5 P帧是1)	 

2、h265 NAL单元

/*
         *         h265 nal头部(2字节)
         *    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
         *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 
         *   |F|   Type    |  layerID  | TID |  NAL payload ……
         *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
名称       bit   备注 
禁止位      1    为0的时候合法
NAL类型     6    一共有64种 一半为视频数据类型 一半为非视频数据类型 
                (vps是32, sps是33, pps是34, 前缀sei是39. IDR是19或20 后置图像帧是1)
视频层ID    6    目前设为0,以后扩展
TID        3    目前通常设为1,nuh_temporal_id_plus1.  

可以看出来265的nal头部要比264多出了1字节(为了以后扩展多视点、立体视频源),封装rtp包时要注意相应数据的提取。

265的NAL类型也比264的多了一倍,主要区别是比264新增了vps(视频参数集),完整I帧的内容为vps+sps+pps+sei+I帧。

二、rtp包封装

1、小包封装(如sps、pps、sei等)

这些长度较短(小于1400字节)的NAL单元数据,只要在读取完该单元后,去掉起始码(0x 00 00 01或0x 00 00 00 01),就可以直接作为rtp负载内容加载到rtp头部后发送出去了(这里关于rtp头部内容就不说了,对于264和265 rtp头部的内容设置方法一样)。需要注意的地方是该rtp包的时间戳一定要设置,如h264的I帧前的sps、pps、sei,这三个的时间戳应该一致,而且和I帧的时间戳一致(本来编码的时候就是一起生成的)。

/*    RTP包的封装格式
 *    RTP包头部最短为12字节(不用设置CSRC,即CC=0的时候)
 *    0                   1                   2                   3
 *    7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   |V=2|P|X|  CC   |M|     PT      |       sequence number         |
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   |                           timestamp                           |
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   |           synchronization source (SSRC) identifier            |
 *   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 *   |            contributing source (CSRC) identifiers             |
 *   :                             ....                              :
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 *   |                          rtp负载内容                           |
 *   :                             ....                              :
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */

2、分包封装(如I帧等)

通常的I帧和P帧数据都是比较大的(比1400字节要大得多),这时候就需要分包处理,因为经过udp或tcp打包后,过长的数据(超过1500字节)到了ip数据报打包的时候会被分包,到了接收端会产生粘包等问题。
这里介绍一般常用的 FU-分片包

①264的分片包

 /*  264的分片包和小包封装的差别是 原先的NAL头(1字节) 变为了现在的FU indicator+FU header(共2字节)
 *  0               1               2
 *  0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * | FU indicator  |   FU header   |   FU payload   ...  |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */
 /*
 *     FU Indicator
 *    0 1 2 3 4 5 6 7
 *   +-+-+-+-+-+-+-+-+
 *   |F|NRI|  Type   |  这里的Type变为分片类型(28)
 *   +-+-+-+-+-+-+-+-+
 */  
 /*
 *      FU Header
 *    0 1 2 3 4 5 6 7
 *   +-+-+-+-+-+-+-+-+
 *   |S|E|R|  Type   |  原先NAL头部的类型保存在这里的Type
 *   +-+-+-+-+-+-+-+-+
 */

FU Indicator其实和NAL头部几乎一样,就是nal类型变成了分片包的类型28,原先的nal类型保存到了FU Header中的Type。
FU Header中:
S(start) 为1时表示分片包的第一包
E( end) 为1时表示分片包的最后一包
R 这个值一直为0(保留)
因此可以知道,不是第一包或最后一包的时候 S、E都设为0。
FU payload就是原先nal数据的一部分(分片)数据了。
这些数据都填充好后就可以放到rtp包的负载内容发送了。

②265的分片包

/*  h265的分片包,大致和264的一样,总的头部变为了3字节
 *  0                   1                   2
 *  0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |          FU indicator          |   FU header   |   FU payload   ...  
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */
/*
 *     FU Indicator
 *    0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+    
 *   |F|   Type    |  layerID  | TID | 这里的Type=49(分片包类型)
 *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 */

/*
 *      FU Header
 *    0 1 2 3 4 5 6 7
 *   +-+-+-+-+-+-+-+-+
 *   |S|E|    Type   | 原先的NAL类型同样保存在了这里
 *   +-+-+-+-+-+-+-+-+
 */

FU Indicator的填充大致和上面264的一样,修改的只是类型,而原先264中FU Header中的R被删掉了,S、E用法不变,这里的Type(6字节)也是填写该NAL单元原本的类型。

③小要点

每个RTP分片包的时间戳设置要注意,同一帧NAL单元的各个分片包时间戳应设为一致。
在264流中经常出现的是 I帧(类型5)、P帧(类型1)、B帧(较少接触),而在265流中目前接触到的是 I帧(类型19或20)、非I帧【包括前置图像帧(类型0),后置图像帧(类型1)】

三、RTSP传输时SDP内容差异

1、rtsp传输 h264 最简易的sdp内容(DESCRIBE请求回复)

v=0
o=- 91575441432 1 IN IP4 192.168.1.241
t=0 0
a=control:*
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=control:track0

2、rtsp传输 h265 最简易的sdp内容(DESCRIBE请求回复)

v=0
o=- 91575441714 1 IN IP4 192.168.1.241
t=0 0
a=control:*
m=video 0 RTP/AVP 96
a=rtpmap:96 H265/90000
a=control:track0

可以看出来sdp信息基本一致,变化的只是H264->H265(个人认为96是对应h264的,但是不修改同样可以推拉流h265,可在vlc播放)

其他的流程步骤基本和h264的一样。

下面放一张h265的rtsp推流抓包图,一开始的发送顺序是 vps、sps、pps、sei、I帧各分片、非I帧各分片,依次循环。

想了解更多RTSP相关知识可以参考该系列(入门级):
https://blog.csdn.net/weixin_42462202/article/details/98986535

  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
H.264和H.265(HEVC)是两种常用的视频编码标准,用于压缩和编码视频数据。RTP(Real-time Transport Protocol)是一种用于实时传输音视频数据的协议,常用于实时通信应用中。 封装H.264和H.265视频数据为RTP流的主要区别在于以下几个方面: 1. RTP负载类型:H.264和H.265RTP中的负载类型不同。H.264RTP负载类型为96,而H.265RTP负载类型为265。这些负载类型用于标识传输的数据类型,以便接收方能够正确解析和处理数据。 2. NAL单元:H.264和H.265编码的视频数据被划分为多个NAL单元(Network Abstraction Layer Units),每个NAL单元含一部分视频数据。封装RTP流时,需要将NAL单元进行打。对于H.264,常用的打方式是将多个NAL单元打为一个RTP,或者将一个NAL单元拆分为多个RTP进行传输。而H.265在打方面引入了更多的灵活性,允许将多个NAL单元一起打为一个RTP,或者将一个NAL单元拆分为多个RTP。 3. RTP扩展头:H.265引入了RTP扩展头(RTP header extension),用于在RTP头部中传输一些额外的信息,如帧类型、解码时间戳等。这些信息在H.265RTP封装中可以使用RTP扩展头进行传输,而在H.264RTP封装中需要使用其他方式进行传输。 总体而言,H.264和H.265RTP封装方面存在一些细微的区别,主要体现在负载类型的不同,NAL单元的打方式以及H.265引入的RTP扩展头。这些区别需要根据具体的应用场景和要求来选择适当的封装方式。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值