系列音视频开发



前言

在安防行业中,onvif协议与gb协议是两种标准,gb是国内安防行业的标准,onvif是国外的安防行业的标准,其中gb28181中视频流是ps流、由设备、下级平台推送到上级平台,具有上公有云的特点,而onvif视频流采用的是rtsp,通常用于内网访问,当需要rtsp流可以上公有云的话,可以使用r-rtsp,r-rtsp交互流程正好与rtsp流程相反,由服务端主动发起请求。


一、RTSP是什么?

RTSP是类似HTTP的应用层协议,一个典型的流媒体框架网络体系可参考下图,其中rtsp主要用于控制命令,rtcp主要用于视频质量的反馈,rtp用于视频、音频流从传输。
在这里插入图片描述
重要概念:
1、RTSP(Real Time Streaming Protocol),RFC2326,实时流传输协议,是TCP/IP协议体系中的一个应用层协议,由哥伦比亚大学、网景和RealNetworks公司提交的IETF RFC标准。该协议定义了一对多应用程序如何有效地通过IP网络传送多媒体数据。RTSP在体系结构上位于RTP和RTCP之上,它使用TCP或UDP完成数据传输。
2、Real-time Transport Protocol或简写RTP,它是由IETF的多媒体传输工作小组1996年在RFC 1889中公布的。RTP协议详细说明了在互联网上传递音频和视频的标准数据包格式。它是创建在UDP协议上的。
3、Real-time Transport Control Protocol或RTP Control Protocol或简写RTCP)是实时传输协议(RTP)的一个姐妹协议。RTCP由RFC 3550定义(取代作废的RFC 1889)。RTP 使用一个 偶数 UDP port ;而RTCP 则使用 RTP 的下一个 port,也就是一个奇数 port。RTCP与RTP联合工作,RTP实施实际数据的传输,RTCP则负责将控制包送至会话中的每个接收者。其主要功能是就RTP正在提供的服务质量做出反馈。

RTSP的消息格式:
RTSP的消息有两大类,一是请求消息(request),一是回应消息(response),两种消息的格式不同。

请求消息格式:
方法 URI RTSP版本 CR LF
消息头 CR LF CR LF
消息体 CR LF
其中方法包括OPTIONS、SETUP、PLAY、TEARDOWN等,URI是接收方(服务端)的地址,例如:rtsp://192.168.22.136:5000/v0,每行后面的CR LF表示回车换行,需要接收端有相应的解析,最后一个消息头需要有两个CR LF。

回应消息格式:
RTSP版本 状态码 解释 CR LF
消息头 CR LF CR LF
消息体 CR LF
其中RTSP版本一般都是RTSP/1.0,状态码是一个数值,200表示成功,解释是与状态码对应的文本解释。
状态码由三位数组成,表示方法执行的结果,定义如下:
1XX:保留,将来使用;
2XX:成功,操作被接收、理解、接受(received,understand,accepted);
3XX:重定向,要完成操作必须进行进一步操作;
4XX:客户端出错,请求有语法错误或无法实现;
5XX:服务器出错,服务器无法实现合法的请求。

RTSP流程
在这里插入图片描述

//获取服务器提供的可用方法
客户端->>服务器:OPTION
服务器->>客户端: 200 OK (Method)
在这里插入图片描述
在这里插入图片描述

//得到会话描述信息
客户端->>服务器:DESCRIBE
服务器->>客户端: 200 OK (SDP)

流程Digest需要返回401,再次认证,返回成功,得到sdp信息
在这里插入图片描述
在这里插入图片描述
服务端返回401状态,第一次返回response:WWW-Authenticate: Digest realm=“IP Camera(G8494)”, nonce=“84379c4a040fe7363230964e51194943”, stale=“FALSE”
在这里插入图片描述
客户端通过第一次返回信息,组装认证信息,计算出response值,服务端同样的方法计算response,如果response是相同的即认证通过,可以进行setup环节
Authorization: Digest username=“admin”, realm=“IP Camera(G8494)”, nonce=“84379c4a040fe7363230964e51194943”, uri=“rtsp://10.20.40.202:554/h264/ch33/main/av_stream”, response=“ff1b51065ef890dce943f8441f463009”
下面是具体计算过程(参考后面的digest计算过程):
通过http://www.jsons.cn/md5/s/ 进行计算md5 32 小写value
hs1 = md532(admin+ “:” + IP Camera(G8494)+ “:” + pwd)
hs2 = md532(DESCRIBE+ “:” + rtsp://10.20.40.202:554/h264/ch33/main/av_stream)
response = md532(hs1+ “:” + 84379c4a040fe7363230964e51194943+ “:” + hs2)----->ff1b51065ef890dce943f8441f463009

hs1=MD5(admin:IP Camera(G8494):pwd)---------------> d071898e5aab2922b75aeb0512b68a47
hs2=MD5(DESCRIBE:rtsp://10.20.40.202:554/h264/ch33/main/av_stream)-----------> 03912128d187828d77ce683a4027f9d6
MD5(d071898e5aab2922b75aeb0512b68a47:84379c4a040fe7363230964e51194943:03912128d187828d77ce683a4027f9d6) -------->ff1b51065ef890dce943f8441f463009

在这里插入图片描述
1.version(必选)
格式: v=< version>
描述:
表示sdp的版本号,不包含次版本号
如:v=0

2.origin(必选)
格式:o=< username> < sessionid> < version> < network type> < address type> < address>
描述:
o=选项对会话的发起者进行了描述;
< username>:是用户的登录名, 如果主机不支持,则用"-“代替, 不能包含空格;
< session id>:是一个数字串,在整个会话中,必须是唯一的,建议使用个NTP 时间戳;
< version>: 该会话公告的版本,供公告代理服务器检测同一会话的如果干个公告哪个是最新公告,基本要求是会话数据修改后该版本值递增,建议使用NTP时间戳
< networktype>: 网络类型,一般为"IN”,表示internet
< addresstype>: 地址类型,一般为IP4
< adress>:地址
如:o=- 1645565010348646 1645565010348646 IN IP4 10.20.40.*

3.Session Name(必选)
格式:s=< session>
描述:
会话名称,在整个会话中有且只有1个"s=session"
如:s=Media Presentation

4.Connection Data(可选)
格式: c=< networktype> < address type> < connection address>
描述:
表示媒体连接信息;一个会话级描述中必须有"c="或者在每个媒体级描述中有一个"c="选项,也可能在会话级描述和媒体级描述中都有"c="选项;
network type表示网络类型,一般为IN,表示internet;
address type,地址类型,一般为IP4;
connection address,地址,可能为域名或ip地址两种形式
如:c=IN IP4 0.0.0.0

5.Bandwidth(可选)
格式: b=< modifier> < bandwidth-value>
描述:该选项描述了建议的带宽,单位 kbs/s,可选,modifier包括两种类型,CT和AS,CT表示总带宽,AS表示单个媒体带宽的最大值;bandwidth-value表示具体的带宽
如:b=AS:5050

6.Times(必选)
格式:t=< start time> < stop time>
描述:
t字段描述了会话的开始时间和结束时间,< start time> < stop time>为NTP时间,单位是秒;如果 为0表示过了< start time>之后,会话一直持续;当< start time> 和< stop time>都为0的时候,表示持久会话;建议两个值不设为0,如果设为0,不知道开始时间和结束时间,增大了调度的难度
如:t=0 0

7.email(可选)
格式:e=< email address>
描述:
用来描述邮件地址
如:e=NONE

8.phone number(可选)
格式:p=< phone number>
描述:
比较简单,用来描述电话号码
如:p=NONE

9.URI(可选)
格式:u=< uri>
描述:类似于url的一个值,这里不过多介绍了
如:u=NONE

10.Attribute (可选)
格式 :a=< attr>
描述:
表示一个会话级别或媒体级别下的0个或多个属性
如:
a=recvonly
a=x-dimensions:1920,1080
a=control:rtsp://10.20.40.202:554/h264/ch33/main/av_stream/trackID=1
a=rtpmap:96 H264/90000
a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z00AKY2NQDwBE/LNwEBAUAAAcIAAFfkAQA==,aO48gA==
a=Media_header:MEDIAINFO=494D4B48010300000400000100000000000000000000000000000000000000000000000000000000;
a=appversion:1.0

trackID=1表示视频流用的是通道1
x-dimensions:1920 1080表示分辨率为1920*1080
rtpmap:96 H264/90000:表示负载类型264,编码名称H264,采样率90000

payload type表示动态负载类型,如98表示h264
fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=****
profile-level-id:profile_idc(8 bits)、profile_iop(8 bits)、level_idc(8 bits),含义如下:
base-profile:0x42=66 Baseline profile,00兼容性,0x29=41 表示level,参考途中 41 = 4.1*10
66 Baseline profile,77 Main profile, 88 Extended profile
在这里插入图片描述
当packetization-mode 的值为 0 时或不存在时, 必须使用单一 NALU 单元模式
当packetization-mode 的值为 1 时必须使用非交错(non-interleaved)封包模式
当packetization-mode 的值为 2 时必须使用交错(interleaved)封包模式

sprop-parameter-sets:sps+pps,主要包括:解码器所需要的信息参数,profile,level,图像的宽和高,deblock滤波器等
Media_header:海康解码器需要的解码头内容的16进制值

11.media information(必选)
格式:m=< media> < port> < transport type> < fmt list>
描述:
表示媒体类型
有"audio",“video”,“application”,“data”(不向用户显示的数据),“control”(描述额外的控制通道);
表示媒体流发往传输层的端口,对于RTP,偶数端口用来传输数据,奇数端口用来;
表示传输协议,与"c="一行相关联,一般用RTP/AVP表示,即 Realtime Transport Protocol using the Audio/Video profile over udp,即我们常说的RTP over udp;
表示媒体格式,分为静态绑定和动态绑定
静态绑定:媒体编码方式与RTP负载类型有确定的一一对应关系,如: m=audio 0 RTP/AVP 8
动态绑定:媒体编码方式没有完全确定,需要使用rtpmap进行进一步的说明:
如:m=video 0 RTP/AVP 96,表示UDP传输,如果TCP传输,RTP/AVP/TCP

//客户端请求建立会话,并确立传输模式
客户端->>服务器:SETUP
服务器->>客户端: 200 OK
在这里插入图片描述
在这里插入图片描述
uri中带有trackID=0,表示对该通道进行设置。
Transport参数设置了传输模式,包的结构。
interleaved值有两个0或1,0表示rtp包,1表示rtcp包,接受端根据interleaved的值来区别是哪种数据包。
建立session1258026621,客户端rtp、rtcp端口60018、60019,unicast单播,RTP/AVP 传输类型
服务端rtp、rtcp端口8220、8221,信源ssrc 22496f7e,模式mode为play(rtsp连接是播放模式)

//客户端发起播放请求
客户端->>服务器:PLAY
服务器->>客户端: (RTP包 RTCP包)
在这里插入图片描述
在这里插入图片描述
会话 1258026621
实时流范围从0.000开始,结束时间不设定:Range: npt=0.000-
seq=64710;rtptime=987935664都是rtp包中的信息,表示rtp包sequence起始序列值与rtptime与起始时间

//客户端发起关闭会话请求
客户端->>服务器:TEARDOWN
服务器->>客户端: 200 OK
在这里插入图片描述
在这里插入图片描述
关闭会话 1258026621

补充:
RTSP客户端应该使用username + password并计算response如下:
(1)当password为MD5编码,则
response = md5(password:nonce:md5(public_method:url));
(2)当password为ANSI字符串,则
response= md5(md5(username:realm:password):nonce:md5(public_method:url));
客户端在每次发起不同的请求方法时都需要计算response字段,同样在服务器端校验时也默认采取同样的计算方法。

Digest 认证方式:
第一次返回401,第二次客户端发起请求,服务端认证。
hs1 := md5hash(username + “:” + realm + “:” + password)
hs2 := md5hash(method + “:” + requestUri)
response := md5hash(hs1 + “:” + nonce + “:” + hs2)
username:用户名
password: 密码
realm: 通常一个 server 对应一个 realm
method:请求方法(OPTIONS/DESCRIBE/SETUP/PLAY)
requestUri: 请求的 uri
nonce: 随机字符串,通常一个 session 对应一个 nonce

二、RTP是什么?

在这里插入图片描述

填充位(1bit)若p=1则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分。填充可能用于某些具有固定长度的加密算法或者用在底层数据单元中传输多个RTP包
扩展(X):1个比特,置“1”表示RTP报头后紧随一个扩展报头
参与源数(CSRC计数(CC) )4位,CSRC计数包括紧接在固定头后CSRC标识符个数。
标记(M):1个比特,其具体解释由应用文档来定义。例如,对于视频流,它表示一帧的结束,而对于音频,则表示一次谈话的开始
有效载荷类型,7个比特,它指示在用户数据字段中承载数据的载荷类别,记录后面资料使用哪种编码,接收端找出相应的 decoder 解码出来
序列号16比特 每发送一个RTP数据包,序列号加一,接收机可以据此检测包损和重建包序列.序列号的初始值是随机的(不可预测),以使即便在源本身不加密时(有时包要通过翻译器,它会这样做),对加密算法泛知的普通文本攻击也会更加困难
时间戳,32位,时标反映RTP数据包中第一个八进制数的采样时刻,采样时刻必须从单调、线性增加的时钟导出,以允许同步与抖动计算。时标可以让receiver端知道在正确的时间将资料播放出来。只有系列号而没有时标,并不能完整按照顺序的将data播放出来,因为如果data中间有一段是没有资料的,只有系列号的话会造成错误.
SSRC ,32位,SSRC段标识同步源。此标识不是随机选择的,目的在于使同一RTP包连接中没有两个同步源有相同的SSRC标识。尽管多个源选择同一个标识的概率很低,所有RTP实现都必须探测并解决冲突。
CSRC列表,0到15项,每项32位。CSRC列表表示包内的对载荷起作用的源。标识数量由CC段给出。如超出15个作用源,也仅标识15个。

真实抓包数据如下:
在这里插入图片描述
在这里插入图片描述
Version:2
Padding: False 不填充
PT:负载类型(Payload Type)96,表示H264,比如音频、视频、文档等;
Sequence number:序列号初始值为1332,16比特,发送方在每发送完一个RTP包后就将该值增加1,接收方可以由该值检测包的丢失及恢复包序列。序列号的初始值是随机的;
Timestamp:时间戳 988202064,32比特,表示RTP数据包中第一个字节的采样时间;
Synchronization source (SSRC) identifier:同步源标示符,32比特,表示RTP数据包的来源,在同一个RTP会话中不可能存在两个相同的SSRC,SSRC的值是随机选取的;0x7d544194

Payload分析:674d00298d8d403c0113f2cdc0404050000070800015f90040
Payload数据为:67 4D ********
Type: 67&0x1F即0110 0111 & 0x0001 1111 = 0000 0111 即4+2+1=1 表示SPS
SER:000

Payload分析:68ee3c80
Payload数据为:68 EE ********
Type: 68&0x1F即011 01000 & 0x0001 1111 = 0000 1000 即8 表示PPS
SER: 000

Payload分析:7c858880000003018044000017fffa*******
Payload数据为:7C 85 ********
首字节 为FU Indicatior
7C&0x1F即011 11100 & 0x0001 1111 = 0001 1100 即16+8+4=28采用FU-A分片方式
第二字节为FU Header
Type: 85&0x1F即100 00101 & 0x0001 1111 = 0000 0101 即5,表示I帧
SER: 100 表示一帧的开始

Payload分析:5c41 017fffa003018044000*******
Payload数据为:5C 41 ********
首字节 为FU Indicatior
5C&0x1F即010 11100 & 0x0001 1111 = 0001 1100 即16+8+4=28采用FU-A分片方式
第二字节为FU Header
Type: 41 &0x1F即010 00001 & 0x0001 1111 = 0000 0001 即1,表示P帧
SER: 010 表示一帧的结束

Payload分析:5c819a00020004117ffa9aed859100b97823cd31829b24*****
Payload数据为:5C 81 ********
首字节 为FU Indicatior
5C&0x1F即010 11100 & 0x0001 1111 = 0001 1100 即16+8+4=28采用FU-A分片方式
第二字节为FU Header
Type: 81&0x1F即100 00001 & 0x0001 0001 = 0000 0001 即1,表示 P帧
SER: 100 表示一帧的开始
在这里插入图片描述
当网络不好的时候,采用udp传输rtp包时,会出现包乱序、丢包、包重复等问题,为了解决此问题,可以根据Seq的值来调整收到的包顺序、删除重复包、补包(并不是最佳的方法,可以使用fec、nack等)来解决网络到导致的问题。
通过Time可以判定数据是不是同一个rtp包,比如I帧分包了100个,即需要发送100次。接收端需要把Time相同的包合并起来去解码。其中Mark=true,表示最后一帧数据,下一帧Time为2129558556区别于2129554956。

知识点补充:
H264在网络中传输的基本单元为NALU,NALU结构:NALU header(1byte) + NALU payload。NALU header 部分可以判断类型等信息。
8 = header & 0x1F PPS
7 = header & 0x1F SPS
6 = header & 0x1F SEI
5 = header & 0x1F I帧
1 = header & 0x1F P帧

RTP中H264分包规则:
单NALU: P帧或者B帧比较小的包,直接将NALU打包成RTP包进行传输即RTP header(12bytes) + NALU header (1byte) + NALU payload
多NALU: 特别小的包几个NALU放在一个RTP包中
FUs(Fragment Units): I帧长度超过MTU的,就必须要拆包组成RTP包了,有FU-A,FU-B,其中FU-A为RTP header (12bytes)+ FU Indicator (1byte) + FU header(1 byte) + NALU payload

h264或者h265裸流中, NALU 单元常由 Start Code NALU Header NALU Payload三部分组成,NALU由起始码startcode进行分隔,起始码分割有两种:0x000001(3Byte)或者0x00000001 (4Byte)组成。RTP包时去除 “00 00 01” 或 “00 00 00 01” 的开始码, 将数据打包成RTP 包.

单一 NALU 单元模式
在这里插入图片描述
NAL单元头部是由forbidden_bit(1bit),nal_reference_bit(2bits)(优先级),nal_unit_type(5bits)(类型)三个部分组成的,
在这里插入图片描述
1、F(forbiden):禁止位,占用NAL头的第一个位,当禁止位值为1时表示语法错误;一般为0
2、NRI:参考级别,占用NAL头的第二到第三个位;值越大,该NAL越重要。
3、Type:Nal单元数据类型,也就是标识该NAL单元的数据类型是哪种,占用NAL头的第四到第8个位,具体NAL type内容如下图所示
nal_unit_type. 这个 NALU 单元的类型. 简述如下:
0 没有定义
1-23 NAL单元 单个 NAL 单元包.
24 STAP-A 单一时间的组合包
24 STAP-B 单一时间的组合包
26 MTAP16 多个时间的组合包
27 MTAP24 多个时间的组合包
28 FU-A 分片的单元
29 FU-B 分片的单元
30-31 没有定义

组合封包模式
当 NALU 的长度特别小时, 可以把几个 NALU 单元封在一个 RTP 包中.
在这里插入图片描述

分片封包模式
当 NALU 的长度超过 MTU 时, 就必须对 NALU 单元进行分片封包. 也称为 Fragmentation Units (FUs).
在这里插入图片描述
其中FU Indicator与FU header格式如下:
在这里插入图片描述

F: 1 个比特.
forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.
NRI: 2 个比特. 取 00 ~ 11, 指示这个 NALU 的重要性, 如 00 的 NALU 解码器可以丢弃它而不影响图像的回放. I帧应设置成11.
Type:Nal单元数据类型,也就是标识该NAL单元的数据类型是哪种,占用NAL头的第四到第8个位,具体NAL type内容如下图所示
nal_unit_type. 这个 NALU 单元的类型. 简述如下:
0 没有定义
1-23 NAL单元 单个 NAL 单元包.
24 STAP-A 单一时间的组合包
24 STAP-B 单一时间的组合包
26 MTAP16 多个时间的组合包
27 MTAP24 多个时间的组合包
28 FU-A 分片的单元
29 FU-B 分片的单元
30-31 没有定义

S:开始标志
E:结束标志 (与 Mark相同)
R:必须为0
Type:NALU Type

三、RTCP是什么?

RTCP封装的仅仅是一些控制信息,因而分组很短,所以可以将多个RTCP分组封装在一个UDP包中。RTCP有如下五种分组类型。根据所携带的控制信息不同RTCP信息包可分为RR(接收者报告包)、SR(源报告包)、SEDS(源描述包)、BYE(离开申明)和APP(特殊应用包)五类5类:
在这里插入图片描述
SR:
在这里插入图片描述
版本(V):同RTP包头域。
填充(P):同RTP包头域。
接收报告计数器(RC):5比特,该SR包中的接收报告块的数目,可以为零。
包类型(PT):8比特,SR包是200。
长度域(Length):16比特,其中存放的是该SR包以32比特为单位的总长度减一。
同步源(SSRC of sender):SR包发送者的同步源标识符。与对应RTP包中的SSRC一样。
SR包发送时的绝对时间值 NTP Timestamp(Network time protocol)。NTP的作用是同步不同的RTP媒体流。
与NTP时间戳对应(RTP Timestamp),与RTP数据包中的RTP时间戳具有相同的单位和随机初始值。
发送数据包总数(Sender’s packet count):从开始发送包到产生这个SR包这段时间里,发送者发送的RTP数据包的总数. SSRC改变时,这个域清零。
发送数据包总字节数(Sender`s octet count):从开始发送包到产生这个SR包这段时间里,发送者发送的净荷数据的总字节数(不包括头部和填充)。发送者改变其SSRC时,这个域要清零。
同步源n的SSRC标识符:该报告块中包含的是从该源接收到的包的统计信息。
丢失率(Fraction Lost):表明从上一个SR或RR包发出以来从同步源n(SSRC_n)来的RTP数据包的丢失率。
累计的包丢失数目(Cumulativenumber of packetslost):从开始接收到SSRC_n的包到发送SR,从SSRC_n传过来的RTP数据包的丢失总数。
收到的扩展最大序列号(Extendedhighestsequencenumber received):从SSRC_n收到的RTP数据包中最大的序列号,
接收抖动(Interarrival jitter):RTP数据包接受时间的统计方差估计
上次SR时间戳(Last SR,LSR):取最近从SSRC_n收到的SR包中的NTP时间戳的中间32比特。如果目前还没收到SR包,则该域清零。
上次SR以来的延时(Delay since last SR,DLSR):上次从SSRC_n收到SR包到发送本报告的延时。

RR:
接收者报告包,用于接收非活动站的统计信息;
SR源报告包和RR接收者报告包用于提供接收质量反馈,除包类型代码外,SR与RR间唯一的差别是源报告包含有一个20字节发送者信息段。
RR针对每个信源都提供信息包丢失数、已收信息包最大序列号、到达时间抖动、接收最后一个SR的时间、接收最后一个SR的延迟等信息。
在这里插入图片描述

真实rtcp包的RR报文:
在这里插入图片描述
SDES:
源描述包,用于报告和站点相关的信息,包括CNAME;
在这里插入图片描述

BYE:
断开RTCP包,是站点离开系统的报告,表示结束;
在这里插入图片描述

APP:
APP包用于开发新应用和新特征的实验,不要求注册包类型值

抓包数据如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、RTSP 源码学习

如果对RTSP流程转发感兴趣的话,可以通过以下源码学习其交互过程
1、 live555 c++实现
2、easydarwin go实现

五、H265 RTSP流

H264与H265的RTSP流程几乎一样,其中主要差异点为sdp信息以及rtp包解析h265有所区别,其实也就是h264与h265的区别,h265有vps,以及nalu header有所不同,rtp 分包组合包类型、header不同。

sdp:
在这里插入图片描述
其中rtpmap: 96 H265/90000
fmtp:包含了vps,sps,pps信息
rtp包:
在这里插入图片描述
其中payloaderheader 占用两个字节,type为首字节[1-6] 6Bit ----> 0 111111 0 = 0x7E

Payload分析:40010c01ffff01600000030000030000030000030078ac09
Payload数据为:40 01 0C ********
Type: 40&0x7E>1即0x20 即32 表示VPS

Payload分析:42010101600000030000030000030000030078a003c0801107cb8dae49394cdc040404100000e1000015f90a10
Payload数据为:42 01 01********
Type: 42&0x7E>1即0x21 即33 表示SPS

Payload分析:4401c0f2f03324
Payload数据为:44 01 C0********
Type: 44&0x7E>1即0x22 即34 表示VPS

Payload分析:620193ad26065*****
Payload数据为:62 01 93********
Type: 62&0x7E>即0x31 即49 表示分片模式
FuType:93&0x3F = 0x13即 19 即 IDR
SE:1 0

Payload分析:62014187604b671*****
Payload数据为:62 01 41********
Type: 62 &0x7E>1即0x31 即49 表示分片模式
FuType:41&0x3F = 0x01 即 1 表示P帧
SE: 0 1

Payload分析:620181d000117421*****
Payload数据为:62 01 81********
Type: 62 &0x7E>1即0x31 即49 表示分片模式
FuType:81&0x3F = 0x01 即1 表示P帧
SE: 1 0

补充H265编码知识:
在这里插入图片描述
F:禁止位,1bit(最高位:15位),必须是0,为1标识无效帧
Type: 帧类型,6bits(9~14位),0-31是vcl nal单元;32-63,是非vcl nal单元,VCL是指携带编码数据的数据流,而non-VCL则是控制数据流。
在这里插入图片描述
LayerID:6 bits,表示NAL所在的Access unit所属的层,该字段是为了HEVC的继续扩展设置,一般为0
TID:3bits,一般为1,此字段指定nal单元加1的时间标识符。时间id的值等于tid-1,tid的值为0是非法的,以确保nal单元报头中至少只有一个比特等于1,以便能够在nal单元头和nal单元有效负载数据中独立考虑启动代码仿真。

通常情况下F为0,layerid为0,TID为1。
H265帧类型与H264不一样,其位置在第一个字节的1~6位(buf[0]&0x7E>>1),常见的NALU类型:
40 >> 01,type=32,VPS(视频参数集)
42 >> 01,type=33,SPS(序列参数集)
44 >> 01,type=34,PPS(图像参数及)
4E >> 01, type=39,SEI(补充增强信息)
26 >> 01,type=19,可能有RADL图像的IDR图像的SS编码数据 IDR
02 >>01, type=01,被参考的后置图像,且非TSA、非STSA的SS编码数据

H265码流RTP封装方式:分为单一NALU封装模式/组合帧封装模式/分片封装模式
单一帧封装模式
在这里插入图片描述
其中PayloadHeader一般与NALU Header定义完全一致,DONL:Decoding Order Number。当使用多slice编码模式时使用,用于判断一帧的每个slice是否收齐,一般使用单slice,无此字段,所以通常境况下,单一帧模式封装方式与H264一致,H265帧去掉起始位直接作为负载,这里不做过多接收。

组合帧封装方式
在这里插入图片描述
当帧较小,且多个帧合并后小于MTU的情况,可以多帧组合封装到一个RTP包中,比如(VPS/SPS/PPS)合并封装,注意多帧合并后大小必须小于MTU,不然会被IP分片。
不带DONL的组合包封装模式与H264类似,这里不做多说,一般情况下很少用到组合帧封装方式,小于MTU的帧一般是单一帧封装,减少解封装复杂性。

分片封装模式
在这里插入图片描述
这里PayloadHeader中F=0,LayerID=0,TID=1,Type必须为49表示FU分片
FU header定义与FU-A定义基本一致,由于NALU Type在H265中为6bits表示,所以这里去掉了R,只保留S/E/TYPE格式如下:
在这里插入图片描述
S:1bit,1-表示是首个分片报文,0-非首个分片报文
E:1bit,1-表示最后一个分片报文,0-非最后一个分片报文
FuType:6 bits,对应的NALU type

总结

本文主要讲解了RTSP的主要流程以及RTP,RTCP的包分析,本文主要介绍的H264的包结构,希望能够让你对rtsp有个深刻的认识。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐