ffmpeg基础四:RTP协议

Posted qq_40170041

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ffmpeg基础四:RTP协议相关的知识,希望对你有一定的参考价值。

参考:零声学院

协议学习方法
1、协议是什么:双方约定好如何传输消息,比如视频传输协议,要告诉你这个包是h264包,还是aac音频包,这个信息一般放在协议头,对方收到网络包,可以直接在协议头部获取出这些信息,所以协议的组成一般都是:协议头 + 数据
2、学习这个协议的作用:这个协议用来干什么的
3、将协议抽象成可靠传输机制,他要保证能把数据发送给对方
如何保证传输,并且还让对方能够快速使用数据:加一些字段来告诉对方一些属性,比如TCP协议头里的字段,序列号,确认号,标志位,这些都是保证数据传输的
4、如何通信呢?使用数据包!那这些数据包如何生成呢?首先协议要有头,然后通过一定的组织格式将数据和头封装在一起。然后传输。
5、对方拿到这个包以后呢?所以在协议头里面加入一些字段,告诉对方一些属性。

RTSP 、SDP和RTP

RTP只是一个承载媒体数据的协议,怎么传输,比如说双方的IP,传输数据的端口,通信方式是TCP还是UDP,都是由rtsp,SDP这些去协商完成,这个协商就是建立链接的过程,当协商好了以后就建立好了会话,这个会话部分才是RTP传输数据的过程,前面的协商就是在协商建立这个会话,rtsp和rtp这两个协议部分是可以分开的。
一、RTP与RTCP协议
RTP位于传输层(通常是UDP)之上,应用程序之下,实时语音、视频数据经过模数转换和压缩编码处理后,先送给RTP封装成为RTP数据单元,RTP数据单元被封装为UDP数据报,然后再向下递交给IP封装为IP数据包。
当应用程序提供RTSP协议建立一个RTP会话时,应用程序将确定一对目的传输地址(一个网络地址和两个端口号),这两个端口号1024到65535之间,RTP在选择一个未使用的偶数UDP端口号,而在同一次会话中的RTCP则使用下一个奇数UDP端口号。RTP分组只包含RTP数据,而控制是由RTCP提供。  
具体会话流程为:
1)RTP协议从上层应用接收流媒体信息码流(如H.264),封装成RTP数据包;RTCP从上层接收控制信息,封装成RTCP控制包。
2)RTP将RTP数据包发往UDP端口对中偶数端口;RTCP将RTCP控制包发往UDP端口对中的奇数端口。
二、RTP传输端口号的协商
对于端口号之间的协商是在rtsp的SETUP方法中或者SDP中
(1)SETUP方法中
首先C–>S(客户端到服务器)

SETUP rtsp://192.168.0.31:8554/chn0 RTSP/1.0\\r\\n
CSeq: 4\\r\\n
Transport: RTP/AVP;unicast;client_port=54492-54493\\r\\n
\\r\\n

客户端发送建立请求,请求建立连接会话,准备接收音视频数据,其中rtsp://192.168.0.31:8554/chn0 中的8554端口是rtsp的端口,属于推流方的,对于这个url的解析:格式一般为rtsp://ip:port/session,ip表主机ip,也就是推流方,port表端口号,如果不写那么就是默认端口,rtsp的默认端口为554,session表明请求哪一个会话
解析一下Transport: RTP/AVP;unicast;client_port=54492-54493\\r\\n
RTP/AVP:表示RTP通过UDP发送,如果是RTP/AVP/TCP则表示RTP通过TCP发送
unicast:表示单播,如果是multicast则表示多播
client_port=54492-54493:由于这里希望采用的是RTP OVER UDP,所以客户端发送了两个用于传输数据的端口,客户端将这两个端口绑定到两个udp套接字上并监听用于接收媒体流数据,54492表示是RTP端口,54493表示RTCP端口(RTP端口为某个偶数,RTCP端口为RTP端口+1)

S–>C(服务器到客户端)
RTSP/1.0 200 OK\\r\\n
CSeq: 4\\r\\n
Transport: RTP/AVP;unicast;client_port=54492-54493;server_port=56400-56401\\r\\n
Session: 66334873\\r\\n
\\r\\n

服务端接收到请求之后,得知客户端要求采用RTP OVER UDP发送数据,单播,客户端用于传输RTP数据的端口为54492,RTCP的端口为54493,服务器也有两个udp套接字,绑定好两个端口,一个用于传输RTP,一个用于传输RTCP,这里的端口号为56400-56401,之后客户端会使用54492-54493这两端口和服务器通过udp传输数据,服务器会使用56400-56401这两端口和这个客户端传输数据,也就是客户端和服务器通过SETUP方法协商好以后,发送方需要初始化UDP并且绑定端口,用于向接收方发送。接收方绑定并监听UDP端口用于接收。
(2)在SDP中也会包含UDP端口

m=video 9832 RTP/AVP 96 
a=rtpmap:96 H264/90000
a=framerate:25
c=IN IP4 127.0.0.1

这个一个媒体级的sdp描述
m=video 9832 RTP/AVP 96
格式为 m=<媒体类型> <端口号> <传输协议> <媒体格式 >
媒体类型:video,表示这是一个视频流
端口号:9832,表示UDP发送的目的端口为9832,将数据流发送到对方的9832端口
传输协议:RTP/AVP,表示RTP OVER UDP,通过UDP发送RTP包
媒体格式:表示负载类型(payload type),一般使用96表示H.264
a=rtpmap:96 H264/90000
格式为a=rtpmap:<媒体格式><编码格式>/<时钟频率>
a=framerate:25
表示帧率
c=IN IP4 127.0.0.1
IN:表示internet
IP4:表示IPV4
127.0.0.1:表示UDP发送的目的地址为127.0.0.1
特别注意:这段sdp文件描述的udp发送的目的IP为127.0.0.1,目的端口为9832
总结:
RTP通常和RTCP一起工作,在RTP会话期间,各参与者周期的发送RTCP消息。RTCP消息也被封装为UDP数据报进行传输。

RTP协议解析

RTP数据协议负责对流媒体数据进行封包并实现媒体流的实时传输,每一个RTP数据报都由头部(Header)和负载(Payload)两个部分组成,其中头部的含义是固定的,而负载则可以是音频或者视频数据。
RTP协议是由RTP Header和RTP Payload两部分组成的

RTP头部


V:RTP协议的版本号,占2位,当前协议版本号为2
P:填充标志,占1位,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分。
X:扩展标志,占1位,如果X=1,则在RTP报头后跟有一个扩展信息。
CC:CSRC计数器,占4位,指示CSRC 标识符的个数。
M: 标记,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始。如果M被置位,表示一些重要的项目如帧边界在包中被标记。例如,如果包中有几个比特的当前帧,连同前一帧,那么RTP的这一位就被置位。
PT(payload type): 有效荷载类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM图像等,在流媒体中大部分是用来区分音频流和视频流的,这样便于客户端进行解析。
序列号:占16位,用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。这个字段当下层的承载协议用UDP的时候,网络状况不好的时候可以用来检查丢包。当出现网络抖动的情况可以用来对数据进行重新排序。序列号的初始值是随机的,同时音频包和视频包的sequence 是分别记数的。
时戳(Timestamp):占32位,必须使用90 kHz 时钟频率(程序中的90000)。时戳反映了该RTP报文的第一个八位组的采样时刻。接收者使用时戳来计算延迟和延迟抖动,并进行同步控制。可以根据RTP包的时间戳来获得数据包的时序。
这个域长度为32个比特,时间戳反映了RTP数据包的头一个字节的采样时刻。 采样时刻必须是由一个单调线性增加的时钟产生,这样做是为了接收方的同步和抖动计算。初始值必须为随机数,这是为了避免对原码的攻击。例如,如果RTP源使用了一个编码器, 缓冲20ms的音频数据,那么RTP时间戳必须每个包增加160,无论包是被传递了还是被丢失了。
同步信源(SSRC)标识符:占32位,用于标识同步信源。同步信源是指产生媒体流的信源,它通过RTP报头中的一个32位数字SSRC标识符来标识,而不依赖于网络地址,接收者将根据SSRC标识符来区分不同的信源,进行RTP报文的分组。该标识符是随机选择的,参加同一视频会议的两个同步信源不能有相同的SSRC。
特约信源(CSRC)标识符:每个CSRC标识符占32位,可以有0~15个CSRC。每个CSRC标识了包含在该RTP报文有效载荷中的所有特约信源。
这⾥的同步信源是指产⽣媒体流的信源,例如⻨克⻛、摄像机、RTP混合器等;它通过RTP报头中的⼀个 32位数字SSRC标识符来标识,⽽不依赖于⽹络地址,接收者将根据SSRC标识符来区分不同的信源,进行RTP报⽂的分组。
特约信源是指当混合器接收到⼀个或多个同步信源的RTP报⽂后,经过混合处理产生一个新的组合RTP报文,并把混合器作为组合RTP报⽂的 SSRC,⽽将原来所有的SSRC都作为CSRC传送给接收者,使接收者 知道组成组合报⽂的各个SSRC。
若⼀个RTP包流的源,对由RTP混频器生成的组合流起了作用,则它就是⼀个作用源。对特定包的生成起作用的源,其SSRC标识符组成的列表,被混频器插⼊到包的RTP报头中。这个列表叫做CSRC表。
⽤图表示⼤概是这样:

例如,有三个信号源各发出⼀路rtp流,RTP1携带的SSRC是SSRC1,RTP2携带的SSRC是SSRC2,RTP3携带SSRC3,这三路RTP流到达混合器时,混合器会将这三路流混合成⼀路流发出去,它会把这三路流的SSRC记录下来,形成⼀个列表,叫CSRC表,在发送的混合RTP流中,SSRC域填充的字段是混合 器本身的SSRC4,⽽CSRC字段则会根据该包的负载的源来填⼊。
例如当前的RTP包的负载是来⾃SSRC1的,那么在当前RTP包的CSRC字段填⼊SSRC1。
这样接收者就可以根据CSRC来区分不同的信源;
⼀般的,混合的RTP流中,每隔⼀段时间,就会有⼀个RTP报⽂包含了完整的CSRC表。例如在发送混合流 时的第⼀个RTP包,它的CSRC域把CSRC表都填⼊,此时该包的负载可能是⽆意义或者并不是媒体流;此 后的RTP报⽂中则根据负载的来源来填⼊CSRC域。

时间戳

从帧率及采样率,即可知道视频/音频播放速度。声卡和显卡均是以一帧数据来作为播放单位,如果单纯依赖帧率及采样率来进行播放,在理想条件下,应该是同步的,不会出现偏差。
以一个44.1KHz的AAC音频流和24FPS的视频流为例:
一个AAC音频frame每个声道包含1024个采样点,则一个frame的播放时长(duration)为:(1024/44100)×1000ms = 23.22ms;一个视频frame播放时长(duration)为:1000ms/24 = 41.67ms。理想情况下,音视频完全同步,音视频播放过程如下图所示:

但实际情况下,如果用上面那种简单的方式,慢慢的就会出现音视频不同步的情况,要不是视频播放快了,要么是音频播放快了。可能的原因如下:一帧的播放时间,难以精准控制。音视频解码及渲染的耗时不同,可能造成每一帧输出有一点细微差距,长久累计,不同步便越来越明显。(例如受限于性能,42ms才能输出一帧),音频输出是线性的,而视频输出可能是非线性,从而导致有偏差。
媒体流本身音视频有差距。(特别是TS实时流,音视频能播放的第一个帧起点不同)

所以,解决音视频同步问题,引入了时间戳:
1、首先选择一个参考时钟(要求参考时钟上的时间是线性递增的);
2、编码时依据参考时钟上的给每个音视频数据块都打上时间戳;
3、播放时,根据音视频时间戳及参考时钟,来调整播放。
所以,视频和音频的同步实际上是一个动态的过程,同步是暂时的,不同步则是常态。以参考时钟为标准,放快了就减慢播放速度;播放慢了就加快播放的速度。
时间戳增加一并不是我们通常意义上的过了一个微秒,而是增加了一帧显示间隔那么长的时间。比如视频采样率是帧率为25帧每秒,视频时间戳的单位为1/90k秒.比如: 25帧,每帧40ms.40ms有多少时间戳的基本单位呢? 40除以1/90k等于3600,也就是上一个帧的时间戳基础上增加3600
将一秒钟划分成90K个刻度,每一帧的显示占3600个刻度
扩展内容:
Single Nalu:如果一个视频帧包含1个NALU,可以单独打包成一个RTP包,那么RTP时间戳就对应这个帧的采集时间;
FU-A:如果一个视频帧的NALU过大(超过MTU)需要拆分成多个包,可以使用FU-A方式来拆分并打到不同的RTP包里,那么这几个包的RTP时间戳是一样的;
STAP-A:如果某帧较大不能单独打包,但是该帧内部单独的NALU比较小,可以使用STAP-A方式合并多个NALU打包发送,但是这些NALU的时间戳必须一致,打包后的RTP时间戳也必须一致

RTP包的时间戳计算
RTP包的时间戳增量怎么计算?
假设时钟频率为90000,视频帧率为25 ,90k是用于视频同步的时间尺度(TimeScale),就是每秒90k个时钟tick。为什么采用90k呢?目前视频的帧速率主要有25fps、29.97fps、30fps等,而90k刚好是它们的倍数,所以就采用了90k。
频率为90000表示一秒用90000点来表示
帧率为25,那么一帧就是1/25秒
所以一帧有90000*(1/25)=3600个点来表示
因此每一帧数据的时间增量为3600
对于音频,如果采样率是8K,假设每个音频帧中是1000个采样点,那么一秒钟是多少个音频帧:1/8k(每个采样点占的时间),那么一帧数据1k1/8K = 1/8秒,假设rtp音频的时间尺度是8K,那么一帧就要有8k1/8=1000个点来表示,因此每一帧音频数据的增量是1000
但是音频和视频的时间刻度不同,所以这里要进行转化
Rtp打包时相应的音频时间戳计算公式:
音频时间戳 = 两个RTP包时间差(毫秒)* 32000(采样率) / 1000
rtp流,在播放时,需要选定一个参考时钟,读取帧上的时间戳,同时根据的参考时钟来动态调节播放。时间戳就是PTS,那么参考时钟的选择一般来说有以下三种:
1.将视频同步到音频上:就是以音频的播放速度为基准来同步视频。
2.将音频同步到视频上:就是以视频的播放速度为基准来同步音频。
3.将视频和音频同步外部的时钟上:选择一个外部时钟为基准,视频和音频的播放速度都以该时钟为标准。
这三种是最基本的策略,考虑到人对声音的敏感度要强于视频,频繁调节音频会带来较差的观感体验,且音频的播放时钟为线性增长,所以一般会以音频时钟为参考时钟,视频同步到音频上,也就是转换时间基
Ffmpeg上就有将音视频的pts和dts转化为同一时间基的函数 av_rescale_q_rnd,采用的第三种办法
在基于sip的rtp的流媒体应用中,一个rtp只会携带一个audio frame,sdp中的ptime的值为20ms的倍数(20ms时长采样数据大小是rtp中音频数据的一个audio frame的基本长度),也被认为是一个audio frame。
E1和G.711:为什么是8K,8位深
PDH设备,SDH 155622设备
再后来就是PTN包,兼容E1
1 typedef struct _rtp_header_t
2
3 uint32_t v:2; /* protocol version /
4 uint32_t p:1; /
padding flag /
5 uint32_t x:1; /
header extension flag /
6 uint32_t cc:4; /
CSRC count /
7 uint32_t m:1; /
marker bit /
8 uint32_t pt:7; /
payload type /
9 uint32_t seq:16; /
sequence number /
10 uint32_t timestamp; /
timestamp /
11 uint32_t ssrc; /
synchronization source */
12 rtp_header_t;
3、RTP Payload
RTP Payload负载有很多形式,可以传输编码的数据如视频H264、H265、音频G711A(U)、AAC等数据,也可以传输封装好的数据,如GB28181中常用的PS流等,本文接下来介绍一下RTP Payload Format for H.264 Video(ES流)的具体实现形式。
H264的NALU作为RTP Payload负载:
H.264标准协议定义了两种不同的类型:⼀种是VCL即Video Coding Layer , ⼀ 种 是 NAL 即 Network Abstraction Layer。其中前者就是编码器吐出来的原始编码数据,没有考虑传输和存储问题。后⾯这种就是为了展现H.264的⽹络亲和性,对VCL输出的slice⽚数据进⾏了封装为 NALUs(NAL Units),然后再封装为RTP包进⾏传输
H.264的功能分为两层,视频编码层(VCL)和网络提取层(NAL),VCL数据即被压缩编码后的视频数据序列。在VCL数据要封装到NAL单元中之后,才可以用来传输或存储
NALU的基本格式是:NALU Header + NALU Data(VCL数据),其中NALU的头由⼀个字节组成如下所示:
|0|1|2|3|4|5|6|7|
|F|NRI| Type |



这也就是
264常见的帧头数据为:
00 00 00 01 67 (SPS) 0110 0111 type为后5位0 0111 = 7 对应上表的sps
00 00 00 01 68 (PPS) 0110 1000 type为后5位0 1000 = 8 对应上表的pps
00 00 00 01 65 ( IDR 帧) 0110 0101 type为后5位0 0101 = 5 对应上表的IDR
00 00 00 01 61 (P帧) 0110 0001 type为后5位0 0001 = 1 对应上表的非IDR,P帧
rtp payload数据包的形式主要包含以下三种:

(1)单个NALU包模式

12字节的RTP头后面的就是音视频数据。一个封装单个NAL单元包到RTP的NAL单元流的RTP序号必须符合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 包即可.

如有一个 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)组合封包

其中Type表示媒体类型。当为1~23时,与NALU中的Type是一致的定义。除此以外还可取以下值:
序号 类型 解释
24 STAP-A 单一时间的组合包
25 STAP-B 单一时间的组合包
26 MTAP16 多个时间的组合包
27 MTAP24 多个时间的组合包
28 FU-A 分片的单元
29 FU-B 分片的单元
组合封包模式:
当NALU的长度特别小时,可以把几个NALU封在一个RTP包中。
时戳位移域必须设置成等于以下公式的值:如果NALU-time大于等于包的RTP时戳,则时戳位移等于(NALU-time - 包的RTP时戳)。
如果NALU-time小于包的RTP时戳,则时戳位移等于 NALU-time + (2^32 - 包的RTP时戳)。

(3)FU-A的分片格式

数据比较大的H264视频包,NALU 的长度超过 MTU(网络最大传输单元大约为1500字节),就必须对 NALU 单元进行分片封包发送,12字节的RTP头后面跟随的就是FU-A分片,也称为 Fragmentation Units (FUs)。
这个时候NALU的Header就要变为两个字节
第一个字节(FU indication )中的前三个bit位和前面的表1中代表的是一样的,此时因为是分包模式,后⾯的TYPE就是NALU的FU-A类型28,这个和前面的表2中是对应的,这样在RTP固定头后⾯第⼀字节的后⾯5bit提取出来就确认了该 RTP包承载的不是⼀个完整的NALU,是其⼀部分。
FU indication的格式

当第一个字节的Header取出来的后5位是28代表了分片模式后,可以知道⼀个NALU被切分成了多个RTP包传输
但是这个被分片的NALU从哪⼉开始哪⼉结束呢?可能有⼈说 RTP包固定头不是有mark标记么,注意区分那个是以帧图像的结束标记,这⾥要确定是NALU结束 的标记,其次NALU的类型呢?那么就需要RTP固定12字节后⾯的Fu Header来进⾏区分。
那么这个时候就需要第二个字节(FU header)
FU header

字段解释:
S: 1 bit 当设置成1,开始位指示分⽚NAL单元的开始。当跟随的FU荷载不是分⽚NAL单元荷载的开始,开始位设为0。
E: 1 bit 当设置成1, 结束位指示分⽚NAL单元的结束,即, 荷载的最后字节也是分⽚NAL单元的最后 ⼀个字节,当跟随的FU荷载不是分⽚NAL单元的最后分⽚,结束位设置为0。
也就是说⼀个NALU切⽚时,第⼀个切⽚的SE是10,然后中间的切⽚是00,最后⼀个切⽚时11。
R: 1 bit
保留位必须设置为0,接收者必须忽略该位。
Type: 5 bits
此处的Type就是NALU头中的Type,取1-23的那个值,表示 NAL单元荷载类型定义,对应了表2中的类型,因为不管是不是分片,都需要知道这一帧的类型,所以这里的type就承载了帧类型
综上所述:
对于⽐较⼤的NLAU进⾏FU-A切⽚时,其中NALU的Header字段在RTP打包时划分为两个字节
1、NALU header的前3bit为RTP固定头后⾯第⼀个字节FU-indication的前3bit,后⾯5bit后⾯跟了FU-A打包这种类型28;
2、NALU header的后⾯5bit变成了RTP固定头第⼆字节的后⾯5bit,其中前3bit标识了分⽚的开始和结束。

第⼀个IDR帧的NALU第⼀个切⽚:

FU indication (第一个字节)
⼗六机制:0x7C
二进制:0111 1100 后5位11100为十进制28,对应表2中的FU-A
FU header (第二个字节)
⼗六进制:0x85
⼆进制:1000 0101 前两位10分别对应S,E,代表这个是分⽚NAL单元的开始,说明该 RTP包承载的NALU的第⼀个切⽚。后五位00101为10进制的5,对 应表2中的IDR帧
这样提取FU indication(第一个字节)的前3bit位和Fu header(第二个字节)的后5bit位则为0110 0101即0x65这刚好符合IDR帧的NALU Header定义,后⾯的b8 00 00 03等⼆进制就是NALU的DATA字段。
第⼀个IDR帧的NALU第⼆个切⽚:

FU indication (第一个字节)
⼗六机制:0x7C
⼆进制:0111 1100 后5位11100为十进制28,对应表2中的FU-A
FU header (第二个字节)
⼗六进制:0x05
⼆进制:0000 0101 这⾥的前两位SE是00,则说明该RTP包承载的NALU的中间切⽚。后 五位00101为10进制的5,对应表2中的IDR帧
按照同样⽅法提取,则NALU Header的二进制为0110 0101即0x65,同样说明是IDR帧类型,类似 这种的中间切⽚有很多,从31-56RTP包都是中间切⽚,直到最后⼀个NALU的切⽚。
第⼀个IDR帧的NALU最后⼀个切⽚:

FU indication (第一个字节)
⼗六机制:0x7C
⼆进制:0111 1100 后5位11100为十进制28,对应表2中的FU-A
FU header (第二个字节)
⼗六进制:0x45
⼆进制:0100 0101
这⾥的SE是01,则说明该RTP包承载的NALU的最后⼀个切⽚。
当然通过抓包你还可以得到IDR帧时⽐较⼤的,⽽后⾯的P帧就相对⽐较⼩,因为⼀个NALU切⽚4次就 完了,同样能看到时间戳的变化值等信息。
我们可以看到发送端⼀般采⽤Single NAL Unit和FU-A打包⽅式就基本可以将H264数据发送到接 收端了,对于AAC⾳频来说,直接将ADTS头部去掉以1024字节组成⼀帧直接塞到RTP即可。

附录:
像TCP这样的可靠传输协议,通过超时和重传机制来保证传输数据流中的每一个bit的正确性,但这样会使得无论从协议的实现还是传输的过程都变得非常的复杂。而且,当传输过程中有数据丢失的时候,由于对数据丢失的检测(超时检测)和重传,会数据流的传输被迫暂停和延时。
RTP协议是一种基于UDP的传输协议,RTP本身并不能为按顺序传送数据包提供可靠的传送机制,也不提供流量控制或拥塞控制,它依靠RTCP提供这些服务。这样,对于那些丢失的数据包,不存在由于超时检测而带来的延时,同时,对于那些丢弃的包,也可以由上层根据其重要性来选择性的重传。比如,对于I帧、P帧、B帧数据,由于其重要性依次降低,故在网络状况不好的情况下,可以考虑在B帧丢失甚至P帧丢失的情况下不进行重传,这样,在客户端方面,虽然可能会有短暂的不清晰画面,但却保证了实时性的体验和要求。
先拉流,再抓包显示不出rtp,

以上是关于ffmpeg基础四:RTP协议的主要内容,如果未能解决你的问题,请参考以下文章

ffmpeg rtp传输使用

使用FFmpeg将RTP的数据包保存为mp4文件

协议圣经 RTP组播音视频技巧

尝试通过RTP cpp使用ffmpeg库发送视频流时数据包丢失

超越RFC3550 - RTP/RTCP协议族分析

音视频RTP协议