RTSP 协议中 RTP包的封装 以及如何避免封包的时候malloc申请新的内存

最近在参考别人的例子 实现自己的RTSP服务器端

在写到RTP封包的时候 大多数 使用了一个叫做rtp_header的结构体的那种方式 如下

 这种方式需要考虑到大小端的问题 ,

然后封包的时候一般填充标黄的字段即可 但是我在使用ffplay 或者vlc测试的时候发现 end_flag这个值 设不设置都没啥影响都能正常播放,按照RTP协议来表示的意思是

1.如果是视频表示是否是视频结束帧

2.如果是音频表示音频开始帧

理一下RTP封包的规则 通用规则就是RTP header +RTP data

从别的博主那copy过来的一张图片比较直观

在这里插入图片描述

具体的协议每个字段 可以去博主的这个文章去看下  

RTP协议基本分析(RTSP、WebRTC使用)_“好记性不如烂“博客的博客-CSDN博客_rtsp webrtc

一般的RTP header就是12个字节  一般用在摄像头里面的RTSP服务也不需要考虑 CSRC

所以暂时不考虑

然后封包的时候 我们知道 H264/H265的视频流都是00 00 00 01 或者00 00 01开头的 一般称为start code

不同的摄像头 厂家实时流出来的时候 有的时候 是每一个startcode 一个packet出来 

有的会将SPS PPS IDR帧合在一个packet出来 

这种情况还蛮多的 FFMpeg 拉取RTSP流的时候发现也是这样子如下图高亮的部分

 在封装之前 需要将其拆分成单独的SPS PPS I帧包 

送到RTP封装的时候还需要去掉starcode 如上图的00 00 00 01 四个字节

然后封包有三种方式 单独的包 拆分包 聚合包  聚合包比较复杂 我们就使用

单独的包 和拆分包

一般比较小的比如sps pps 有的还有sei 单独封包 

大的packet需要拆包 拆包的话为了知道 起始包 中间包 结束包 引入了在RTP header和RTP data中间引入了两个字节的FU信息 第一个字节叫FU indicator 第二个叫FU header 如下在这里插入图片描述

F NRI 和NALU的相同  后面5位的Type表示FU的类型 使用较多的FU-A 这个值是28

在这里插入图片描述

S表示分片的第一包 E表示分片的结束包 Type就是Nalu中的type 比如SPS PPS I帧

然后还有一点需要注意的是就是在需要分片的包进来的码流第一个字节表示Nalu类型 这里和FU的重复了 所以 需要分片的时候讲nalu type提取出来填充到FU 这里之后要跳过码流的这个字节

后面不是分片的第一包 则不需要 充分理解了 规则之后再看下面的代码就比较容易了

 显示填充rtpheader  这里是测试的所以就硬编码了 

如果码流帧小于1400 直接打包成一个rtp包发走

下面来看大于1400的情况

 这里主要是获取要打包成多少个包 

nalu_t 就是startcode之后的第一个字节

代码中的rtp_payload[0] 就是FU indicator rtp_payload[1]就是FU header

FU indicator都是一样的 固定值  nalu_ & 0x60 这个是取出NRI 然后 加上FU的type 28 

FU header 通过nalu_t &0x1F取出视频帧的类型 

然后下面 如果是第一个包 要设置S位 为 1  图中的 0x80  如果写成 1<<7 可能更容易理解

如果是结束包则或上0x40 即1<<6 

还要注意途中的pos这个变量初始值为1  就是需要跳过第一个字节

然后还要考虑如果不能整除的话 最后一个包的情况

 

然后两种方式发送 数据

 TCP需要加上4个字节的 Interleaved frame  

因为TCP的话 rtsp报文 rtp报文 rtcp报文 共用 一个socket  要通过这个来区分 0x24 就是一个美元符号

写完就会对rtp协议有充分的理解了 当然这里还只是针对H264的视频封装格式 

上面的方式中初始化的时候 需要给给rtppakcet申请一个很大的内存空间 如果视频帧超过这个空间还得重新申请更大的  如下图

 如果是tcp发送方式的话为了填充 interleaved frame 4个字节就又得申请1000多个字节的内存空间

而且很频繁 并不是很好 还得考虑大小端字节序的方式

然后有在其他地方看到过一个另一种方式  

不定义结构体 直接按字节填充数据  这样就不需要考虑大小端的问题

另外就是其实h264码流送过来封包的时候 已经是别人申请好的一块内存空间了 

然后 将视频码流送入队列的时候 预先把 这部分的数据申请出来  之后通过指针移动 就可以避免后面的特别是tcp这段重复malloc 如下 这里 多申请64个字节的空间 留作后面用

后面填充rtp头部信息的数据时候 通过指针前移 这样就不用重复malloc内存了 如下图

 还是很妙的想法

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

QMCY_jason

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值