RTSP实时流协议解析

2017-04-09

版权声明:本文为作者原创文章,可以随意转载,但必须在明确位置表明出处!!!

RTSP介绍

RTSP(Real-Time Stream Protocol)是一种基于文本的应用层协议,在语法及一些消息参数等方面,RTSP协议与HTTP协议类似。RTSP被用于建立的控制媒体流的传输,它为多媒体服务扮演“网络远程控制”的角色。尽管有时可以把RTSP控制信息和媒体数据流交织在一起传送,但一般情况RTSP本身并不用于转送媒体流数据。媒体数据的传送可通过RTP/RTCP等协议来完成。

RTSP协议与HTTP协议区别

  • RTSP引入了许多新的方法(OPTIONDE、SCRIBE、SETUP、PLAY),并且都具有不同的协议标识
  • 在几乎所有的情况下,RTSP服务器都需要默认维护状态,而不是像HTTP那样的无状态
  • RTSP客户端和服务端都可以发起requests请求
  • 在RTSP协议中,载荷数据一般是通过带外方式来传送的(除了交织的情况),及通过RTP协议在不同的通道中来传送载荷数据。而HTTP协议的载荷数据都是通过带内方式传送的,比如请求的网页数据是在回应的消息体中携带的。
  • 使用ISO10646(UTF-8) 而不是ISO 8859-1,以配合当前HTML的国际化。
  • RTSP使用URI请求时包含绝对URI。而由于历史原因造成的向后兼容性问题,HTTP/1.1只在请求中包含绝对路径,把主机名放入单独的标题域中。

RTSP协议支持操作

  1. 从媒体服务器检索媒体
    客户端可以通过HTTP或其他方法请求演示描述,如果演示正在进行组播,则演示描述包含要用于连续媒体的组播地址和端口,如果演示文稿仅是一单播的方式发送给客户端,则为了安全原因客户端应该提供一个目的地址。
  2. 邀请媒体服务器加入会议
    媒体服务器能够被“邀请”加入一个已存在的会议中,可以回放媒体文件,可以录像全部媒体文件或部分媒体文件。这种模式通常被用在教育应用上,会议中的多方人员可以轮流的去获取控制权限。
  3. 将媒体添加到现有演示文稿中

术语

  1. 总体控制(Aggregate control)
    服务器使用单个时间轴控制多个流,对于音频/视频来说,这就意味着客户端可以仅发送一条播放或暂停控制信息来控制音频和视频的播放
  2. 会议(Conference)
    多方面的多媒体演示,其中“多”意味着大于或等于1
  3. 客户端(Client)
    客户端从流媒体服务端请求连续的流媒体数据
  4. 连接(Connection)
    这连个程序之间建立传输层的虚拟链路,用于它们之间的通信
  5. 容器文件(Container file)
    可以容纳多个媒体流的文件。RTSP服务器可以为这些容器文件提供集合控制。
  6. 连续媒体(Continuous media)
    源和传输渠道之间存在时序关系的数据,也就是说传输渠道必须要体现和源头数据存在的时间关系,连续媒体最常见的例子就是音频和动态视频。
  7. 实体(Entity)
    作为请求或者回应的有效负荷传输的信息。由以实体标题域(entity-header field)形式存在的元信息和以实体主体(entity body)形式存在的内容组成
  8. 媒体初始化(Media initialization)
    数据类型/编解码器初始化,它包括像时钟分配器,颜色表等任何独立传输的信息,客户端要求媒体流回放发生在媒体初始化阶段。
  9. 媒体参数(Media parameter)
    可以在流播放之前或期间更改的媒体类型的特定参数
  10. 媒体服务(Media server)
    服务器为一个或多个媒体流提供回放或记录服务,不通的流媒体可能来自不通的流媒体服务器,媒体服务器可以驻留在与调用演示文稿的web服务器相同或不同的主机上。
  11. 重定向媒体服务器(Media Server Indirection)
    将媒体客户端重定向到不同的媒体服务器
  12. 流(Stream)
    单个媒体的实例,不比一个音频流或者一个视频流,当使用RTP协议时,在一个RTP会话中流由所有的RTP和RTCP包组成。
  13. 消息(Message)
    RTSP协议的基本通信单元,由结构化字节序列通过链接或无连接的协议传输。
  14. 参与者(Participant)
    会议成员,一个参与者也许是一台机器,也可能是一个媒体记录或回放服务器。
  15. 呈现(Presentation)
    一个或多个流作为完整媒体馈送呈现给客户端。
  16. 呈现描述(Presentation description)
    演示文稿描述包含有关演示文稿中的一个或多个媒体流的信息,例如编码集合,网络地址和关于内容的信息。其他IETF协议(如SDP)使用术语“会话”用于现场演示。 呈现描述可以采用几种不同的格式,包括但不限于会话描述格式SDP
  17. 应答(Response)
    媒体服务回应客户端的请求
  18. 请求(Resquest)
    客户端发起的请求
  19. RTSP会话(RTSP session)
    完整的RTSP“交易”,例如观看电影。会话通常由客户端设置连续媒体流(SETUP)的传输机制,使用PLAY或RECORD启动流使用TEARDOWN关闭流。
  20. 传输初始化(Transport initialization)
    客户端和服务器之间的传输信息(例如,端口号,传输协议)的协商。

RTSP流媒体服务器工作流程

在学习一种新的协议我个人比较喜欢通过抓包工具把协议包抓出出来对应着协议说明来看,这样可以让你更直观的了解到协议本身,让理论变得充实起来,希望各位读者也能养成这样的学习惯。下图是我通过wireshark抓包工具抓取来的RTSP流程,从协议中我们就可以直接看出RTSP流媒体服务器的工作流程。

从上图我们可以看到RTSP的工作流程是DESCRIBE–>SETUP–>PLAY,这个流程就我们在线看视频的流程了,当然完整的流程应该是DESCRIBE–>SETUP–>PLAY–>PAUSE/TEARDOWN。

RTSP的方法

上面已经介绍了RTSP跟HTTP协议很像,HTTP协议也有自己的方法向post get等,RTSP也有自己的方法,如下图。

方法 方向 对象 要求 含义
DESCRIBE C->S P,S 推荐 检查演示或媒体对象的描述,也允许使用接收头指定用户理解的描述格式。DESCRIBE的答复-响应组成媒体RTSP初始阶段
ANNOUNCE C->S S->C P,S 可选 当从用户发往服务器时,ANNOUNCE将请求URL识别的演示或媒体对象描述发送给服务器;反之,ANNOUNCE实时更新连接描述。如新媒体流加入演示,整个演示描述再次发送,而不仅仅是附加组件,使组件能被删除
GET_PARAMETER C->S S->C P,S 可选 GET_PARAMETER请求检查URL指定的演示与媒体的参数值。没有实体体时,GET_PARAMETER也许能用来测试用户与服务器的连通情况
OPTIONS C->S S->C P,S 要求 可在任意时刻发出OPTIONS请求,如用户打算尝试非标准请求,并不影响服务器状态
PAUSE C->S P,S 推荐 PAUSE请求引起流发送临时中断。如请求URL命名一个流,仅回放和记录被停止;如请求URL命名一个演示或流组,演示或组中所有当前活动的流发送都停止。恢复回放或记录后,必须维持同步。在SETUP消息中连接头超时参数所指定时段期间被暂停后,尽管服务器可能关闭连接并释放资源,但服务器资源会被预订
PLAY C->S P,S 要求 PLAY告诉服务器以SETUP指定的机制开始发送数据;直到一些SETUP请求被成功响应,客户端才可发布PLAY请求。PLAY请求将正常播放时间设置在所指定范围的起始处,发送流数据直到范围的结束处。PLAY请求可排成队列,服务器将PLAY请求排成队列,顺序执行
RECORD C->S P,S 可选 该方法根据演示描述初始化媒体数据记录范围,时标反映开始和结束时间;如没有给出时间范围,使用演示描述提供的开始和结束时间。如连接已经启动,立即开始记录,服务器数据请求URL或其他URL决定是否存储记录的数据;如服务器没有使用URL请求,响应应为201(创建),并包含描述请求状态和参考新资源的实体与位置头。支持现场演示记录的媒体服务器必须支持时钟范围格式,smpte格式没有意义
REDIRECT S->C P, S 可选 重定向请求通知客户端连接到另一服务器地址。它包含强制头地址,指示客户端发布URL请求;也可能包括参数范围,以指明重定向何时生效。若客户端要继续发送或接收URL媒体,客户端必须对当前连接发送TEARDOWN请求,而对指定主执新连接发送SETUP请求
SETUP C->S S 要求 对URL的SETUP请求指定用于流媒体的传输机制。客户端对正播放的流发布一个SETUP请求,以改变服务器允许的传输参数。如不允许这样做,响应错误为”455 Method Not Valid In This State”。为了透过防火墙,客户端必须指明传输参数,即使对这些参数没有影响
SET_PARAMETER C->S S->C P,S 可选 这个方法请求设置演示或URL指定流的参数值。请求仅应包含单个参数,允许客户端决定某个特殊请求为何失败。如请求包含多个参数,所有参数可成功设置,服务器必须只对该请求起作用。服务器必须允许参数可重复设置成同一值,但不让改变参数值。注意:媒体流传输参数必须用SETUP命令设置。将设置传输参数限制为SETUP有利于防火墙。将参数划分成规则排列形式,结果有更多有意义的错误指示
TEARDOWN C->S P,S 要求 TEARDOWN请求停止给定URL流发送,释放相关资源。如URL是此演示URL,任何RTSP连接标识不再有效。除非全部传输参数是连接描述定义的,SETUP请求必须在连接可再次播放前发布

PS: P—-演示,S—-流,C—-用户端,S—-服务器端

RTSP请求格式

1
2
3
4
方法 URI RTSP版本 CR LF
消息头 CR LF
CR LF
消息体 CR LF

RTSP应答格式

1
2
3
4
RTSP版本 状态码 解释 CR LF
消息头 CR LF
CR LF
消息体 CR LF

RTSP应答码定义

  • 1xx: 已收到请求,程序继续执行
  • 2xx: 收到请求并成功出来请求
  • 3xx: 重定向
  • 4xx: 客户端请求错误,需要客户端检查请求语法是否正确
  • 5xx: 服务器错误

RTSP状态码定义

状态码 描述
“100” Continue
“200” OK
“201” Created
“250” Low on Storage Space
“300” Multiple Choices
“301” Moved Permanently
“302” Moved Temporarily
“303” See Other
“304” Not Modified
“305” Use Proxy
“400” Bad Request
“401” Unauthorized
“402” Payment Required
“403” Forbidden
“404” Not Found
“405” Method Not Allowed
“406” Not Acceptable
“407” Proxy Authentication Required
“408” Request Time-out
“410” Gone
“411” Length Required
“412” Precondition Failed
“413” Request Entity Too Large
“414” Request-URI Too Large
“415” Unsupported Media Type
“451” Parameter Not Understood
“452” Conference Not Found
“453” Not Enough Bandwidth
“454” Session Not Found
“455” Method Not Valid in This State
“456” Header Field Not Valid for Resource
“457” Invalid Range
“458” Parameter Is Read-Only
“459” Aggregate operation not allowed
“460” Only aggregate operation allowed
“461” Unsupported transport
“462” Destination unreachable
“500” Internal Server Error
“501” Not Implemented
“502” Bad Gateway
“503” Service Unavailable
“504” Gateway Time-out
“505” RTSP Version not supported
“551” Option not supported

RTSP重要字段参数

  • Accept
    用于指定客户端可以接受的媒体描述信息类型。比如:Accept:application/sdp
  • Bandwidth
    用于描述客户端可用的带宽值。
  • CSeq
    指定了RTSP请求回应对的序列号,在每个请求或回应中都必须包括这个头字段。对每个包含一个给定序列号的请求消息,都会有一个相同序列号的回应消息。
  • Rang
    用于指定一个时间范围,可以使用SMPTE、NTP或clock时间单元。
  • Session
    Session头字段标识了一个RTSP会话。Session ID 是由服务器在SETUP的回应中选择的,客户端一当得到Session ID后,在以后的对Session 的操作请求消息中都要包含Session ID.
  • Transport
    Transport头字段包含客户端可以接受的转输选项列表,包括传输协议,地址端口,TTL等。服务器端也通过这个头字段返回实际选择的具体选项。如:
    Transport: RTP/AVP;multicast;ttl=127;mode=”PLAY”,
    RTP/AVP;unicast;client_port=3456-3457;mode=”PLAY”

实践操作

通过上面的介绍,我们已经队RTSP协议有了个初步的了解,为了更一步加深理解,下面是我用原生socket写得一个客户端和RTSP流媒体服务端的交互程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
int _tmain(int argc, _TCHAR* argv[])
{
WSADATA wsdata;
int nRet = WSAStartup(MAKEWORD(2,2), &wsdata);
if (0 != nRet)
{
DWORD dwErr = WSAGetLastError();
return 0;
}
SOCKET socketTemp = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
SOCKADDR_IN serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(554);
serverAddr.sin_addr.S_un.S_addr = inet_addr("13.53.147.201");
nRet = connect(socketTemp, (SOCKADDR *)&serverAddr, sizeof(serverAddr));
if (SOCKET_ERROR == nRet)
{
DWORD dwErr = WSAGetLastError();
return 0;
}
settimeout(socketTemp, true, 10000);
char recvBuf[4096] = {0};
char command[256] = {0};
strcpy(command,"DESCRIBE rtsp://13.53.147.201:554/hikvision://13.53.147.189:8000:1:0 RTSP/1.0\r\nCseq:0\r\nAccept: application/sdp\r\nAuthorization: Basic YWRtaW46MTIzNDU=\r\nUser-Agent: StreamClient\r\n\r\n");
//strcpy(command,"OPTIONS rtsp://13.53.147.201:554 RTSP/1.0\r\nCseq:0\r\nUser-Agent: StreamClient\r\n\r\n");
int sendByte = send(socketTemp, command, strlen(command), 0);
if (SOCKET_ERROR == sendByte)
{
DWORD dwErr = WSAGetLastError();
return 0;
}
memset(recvBuf, 0, 4096);
int recvByte = recv(socketTemp, recvBuf, 4096, 0);
if (SOCKET_ERROR == recvByte)
{
DWORD dwErr = WSAGetLastError();
return 0;
}
memset(command, 0, 256);
strcpy(command,"SETUP rtsp://13.53.147.201:554/hikvision://13.53.147.189:8000:1:0/trackID=video RTSP/1.0\r\nCSeq:1\r\nTransport: RTP/AVP/TCP;unicast;interleaved=0-1;ssrc=0 User-Agent: StreamClient\r\n\r\n");
sendByte = send(socketTemp, command, strlen(command), 0);
if (SOCKET_ERROR == sendByte)
{
DWORD dwErr = WSAGetLastError();
return 0;
}
memset(recvBuf, 0, 4096);
recvByte = recv(socketTemp, recvBuf, 4096, 0);
if (SOCKET_ERROR == recvByte)
{
DWORD dwErr = WSAGetLastError();
return 0;
}
memset(command, 0, 256);
strcpy(command,"PLAY rtsp://13.53.147.201:554/hikvision://13.53.147.189:8000:1:0 RTSP/1.0\r\nCSeq: 2\r\nSession: 87Range: npt=now-\r\nUser-Agent: StreamClient\r\n\r\n");
//特别主要这力的Session字段的值是上一步SETUP得到的,我这里因为知道它是多少就没有去解析上一部答应的Session字段值。
sendByte = send(socketTemp, command, strlen(command), 0);
if (SOCKET_ERROR == sendByte)
{
DWORD dwErr = WSAGetLastError();
return 0;
}
memset(recvBuf, 0, 4096);
recvByte = recv(socketTemp, recvBuf, 4096, 0);
if (SOCKET_ERROR == recvByte)
{
DWORD dwErr = WSAGetLastError();
return 0;
}
FILE *file = fopen("e:\\rtsp.txt", "w+");
if (NULL == file)
{
return false;
}
while(true)
{
memset(recvBuf, 0, 4096);
recvByte = recv(socketTemp, recvBuf, 4096, 0);
fwrite(recvBuf, 1, recvByte, file);
}
fclose(file);
return 0;
}

更多更详细的RTSP协议可以查看rtc2326定义文档。


推荐我的微信公众号:爱做饭的老谢


上一篇:H.264码流协议解析
下一篇:kafka,redis,zookeeper,cx_Oracle在python中的应用