rtsp协议格式解析

前言

网上关于rtsp的文章很多,但大多是抽象的理论介绍,从理论学习到实际上手开发往往还有一段距离。然而,没有实际开发经验的支撑,理论又很难理解到位。

本系列文章将从流媒体协议的基础原理开始,通过抓包分析,并结合具体的代码例程,以[原理]->[抓包]->[代码]相结合的方式,循序渐进由浅入深的介绍rtsp/rtp/rtcp开发相关的内容。

希望通过本系列内容的学习,能让大家快速入门流媒体开发需要掌握的技能。

欢迎大家关注[公众号:断点实验室]流媒体开发系列文章。
rtsp协议开发指南
rtsp协议格式解析
rtsp协议报文解析-请求行解析
rtsp协议报文解析-首部字段解析

1 RTSP与HTTP协议比较

rtsp协议在语法及一些消息参数等方面与http协议类似,这里之所以引入http的相关内容,是为了通过我们熟悉的http协议,来帮助大家快速理解rtsp协议的工作原理。

1.1 RTSP与HTTP协议的相同点

rtsp是一种基于文本的协议,在语法及消息参数等方面与http协议类似,它通过一系列格式化的文本信息,传递与实时视频流传输相关的一些控制命令及状态参数。

rtsp采用与http协议类似的报文结构,包括请求行、首部行以及实体主体三部分,因此可以通过抓包很直观的对协议内容进行分析,下图为http协议报文格式。

rtsp协议引入了大多数http1.1的状态码,来反馈当前的响应状态,客户端根据这些状态码来判断服务器状态。

static const rtsp_msg_int2str_tbl_s rtsp_msg_status_code_tbl[] = {
	{100, 0, "Continue"},
	{200, 0, "OK"},
	{201, 0, "Created"},
	{250, 0, "Low on Storage Space"},
	{300, 0, "Multiple Choices"},
	{301, 0, "Moved Permanently"},
	{302, 0, "Moved Temporarily"},
	{303, 0, "See Other"},
	{305, 0, "Use Proxy"},
	{400, 0, "Bad Request"},
	{401, 0, "Unauthorized"},
	{402, 0, "Payment Required"},
	{403, 0, "Forbidden"},
	{404, 0, "Not Found"},
	{405, 0, "Method Not Allowed"},
	{406, 0, "Not Acceptable"},
	{407, 0, "Proxy Authentication Required"},
	{408, 0, "Request Timeout"},
	{410, 0, "Gone"},
	{411, 0, "Length Required"},
	{412, 0, "Precondition Failed"},
	{413, 0, "Request Entity Too Large"},
	{414, 0, "Request-URI Too Long"},
	{415, 0, "Unsupported Media Type"},
	{451, 0, "Invalid parameter"},
	{452, 0, "Illegal Conference Identifier"},
	{453, 0, "Not Enough Bandwidth"},
	{454, 0, "Session Not Found"},
	{455, 0, "Method Not Valid In This State"},
	{456, 0, "Header Field Not Valid"},
	{457, 0, "Invalid Range"},
	{458, 0, "Parameter Is Read-Only"},
	{459, 0, "Aggregate Operation Not Allowed"},
	{460, 0, "Only Aggregate Operation Allowed"},
	{461, 0, "Unsupported Transport"},
	{462, 0, "Destination Unreachable"},
	{500, 0, "Internal Server Error"},
	{501, 0, "Not Implemented"},
	{502, 0, "Bad Gateway"},
	{503, 0, "Service Unavailable"},
	{504, 0, "Gateway Timeout"},
	{505, 0, "RTSP Version Not Supported"},
	{551, 0, "Option not support"},
};

1.2 RTSP与HTTP协议的不同点

http协议是无状态的协议,它的每个请求都是完全独立的,每个请求包含了处理这个请求所需的完整的数据,发送请求不涉及状态变更

例如,当浏览器第一次发送请求给服务端时,服务端响应了,如果同一浏览器向服务端再次发送相同请求时,服务端还是会执行相同的响应(当然服务端可以通过cookie记录与客户端通信的状态信息,这是另一个问题)。

与http服务端不同的是,rtsp服务端几乎在所有情况下都需要默认维护状态,这与http的无状态性质相反。

此外,rtsp与http的根本不同在于,http的数据传输(如照片等)是通过http协议本身实现的,客户端发出资源请求,服务端在响应中传递数据。在rtsp中,视频流是通过rtp协议传输的,rtsp可以设置参数并在传输结束后很长时间内继续控制媒体流。

2 RTSP协议报文格式解析

与http协议类似,rtsp协议也是面向文本的(text-oriented)协议,报文内容可以看作是由ASCII码组成字符缓存,对协议的封装与解析,就是按照协议的报文格式,组装或解析对应的字符缓存。

2.1 RTSP协议报文结构

rtsp报文由三部分组成,即开始行、首部行和实体主体。在请求报文中,开始行就是请求行。rtsp请求报文的结构如下图所示。

rtsp响应报文的结构如下图所示。

报文中的部分字段(如url字段等)长度是不固定的,首部行包含的首部字段个数也不是固定的,因此,协议通过空格及CRLF将各个字段内容信息分割开来,用空格作为一个字段结束的标识,用CRLF作为一行结束的标识,协议的封装解析可以以此为依据进行设计。

2.2 RTSP协议报文方法

协议报文方法包括OPTIONS,DESCRIBE,SETUP,PLAY,TEARDOWN等,具体含义如下表所示,其中C标识客户端,S标识服务器。

方向 方法 描述 作用
C->S OPTION request 询问对端有哪些可用方法 OPTION用于查询服务器端可用方法
S->C OPTION response 回应S所有可用方法
C->S DESCRIBE request 取得S媒体描述信息 DESCRIBE用于取得媒体描述信息
S->C DESCRIBE response 回应媒体描述信息
C->S SETUP request 请求建立会话连接 SETUP用于建立RTSP会话连接
S->C SETUP response 建立会话连接
C->S PLAY request C请求S开始发送数据 PLAY用于请求开始发送数据
S->C PLAY response S回应该请求的信息
C->S TEARDOWN request 请求关闭会话 TEARDOWN用于结束RTSP会话
S->C TEARDOWN response S回应退出请求

2.3 RTSP协议首部行

与http协议类似,rtsp协议的首部字段是构成rtsp报文的要素之一,它为客户端和服务端提供报文交互所需的报文序列号、使用的语言、报文日期等内容,如:

  • Accept字段告诉服务端,客户端在rtsp请求与响应中能够接受的数据内容或数据类型。
  • User-Agent字段告诉服务端,发起请求客户端的描述信息。

下表列出了rtsp协议使用的首部行字段,在type列中类型"g"表示在请求和响应报文中都会用到的通用字段,"R"表示请求报文字段,"r"表示响应报文字段,"e"表示实体主体字段。

support列中的"req."字段表示对应的首部行字段,在相关类型的报文中必须要包含的,而标记为"opt."的字段是可选的,如:

  • CSeq为报文序列号,所有请求/响应报文都需要包含该首部行字段。

methods列中列出的方法为各个首部行字段实际使用的报文场景,如Range字段一般应用于PLAY, PAUSE, RECORD这三个报文中,表示视频流在PLAY, PAUSE, RECORD这三个操作中的作用范围。

Header type support methods
Accept R opt. entity
Accept-Encoding R opt. entity
Accept-Language R opt. all
Allow r opt. all
Authorization R opt. all
Bandwidth R opt. all
Blocksize R opt. all but OPTIONS, TEARDOWN
Cache-Control g opt. SETUP
Conference R opt. SETUP
Connection g req. all
Content-Base e opt. entity
Content-Encoding e req. SET_PARAMETER
Content-Encoding e req. DESCRIBE, ANNOUNCE
Content-Language e req. DESCRIBE, ANNOUNCE
Content-Length e req. SET_PARAMETER, ANNOUNCE
Content-Length e req. entity
Content-Location e opt. entity
Content-Type e req. SET_PARAMETER, ANNOUNCE
Content-Type r req. entity
CSeq g req. all
Date g opt. all
Expires e opt. DESCRIBE, ANNOUNCE
From R opt. all
If-Modified-Since R opt. DESCRIBE, SETUP
Last-Modified e opt. entity
Proxy-Require R req. all
Public r opt. all
Range R opt. PLAY, PAUSE, RECORD
Range r opt. PLAY, PAUSE, RECORD
Referer R opt. all
Require R req. all
Retry-After r opt. all
RTP-Info r req. PLAY
Scale Rr opt. PLAY, RECORD
Session Rr req. all but SETUP, OPTIONS
Server r opt. all
Speed Rr opt. PLAY
Transport Rr req. SETUP
Unsupported r req. all
User-Agent R opt. all
Via g opt. all
WWW-Authenticate r opt. all

以上内容对报文首部行字段做了简要的介绍,限于篇幅的原因无法对每个字段进行深入的介绍,感兴趣的读者可以参考rtsp协议规范RFC2326中[12. Header Field Definitions]中的相关内容,也可直接参考http协议中关于这部分内容的相关描述,网上应该很容易找到,后续文章会对代码中涉及的相关信息再做进一步的解读。

3、RTSP协议会话流程抓包分析

协议的基本原理讲完了了,下面带大家分析协议的交互过程及抓包分析。

3.1 RTSP协议会话流程

一个基本的rtsp会话流程,包括客户端向服务端请求支持的操作类型,发送建立会话请求,请求发送流媒体数据等,会话流程如下图所示。

下面的抓包截图反映了客户端与服务端的实际交互过程。

3.2 RTSP协议抓包分析

  • 向服务端请求媒体描述信息

C->S:DESCRIBE request //请求S提供的媒体描述信息

S->C:DESCRIBE response //S回应媒体描述信息,一般是sdp格式信息

  • 建立RTSP会话

C->S:SETUPrequest //通过Transport头字段列出可接受的传输选项,请求S建立会话

S->C:SETUPresponse //S建立会话,通过Transport头字段返回选择的具体转输选项,并返回建立的Session ID;

  • 请求开始传送数据

C->S:PLAY request //C请求S开始发送数据

S->C:PLAYresponse //S回应该请求的信息

  • 视频推流

S->C:发送流媒体数据 //通过RTP协议传送数据

4、RTSP协议代码实现

前面内容介绍了协议的基础原理及抓包分析,下面我们来结合代码继续讲解。

这里我们以[公众号:断点实验室]流媒体开发系列文章rtsp协议入门指南中引入的推流端代码为例,讲述rtsp协议报文的解析及封装过程。

4.1 RTSP协议数据结构

推流端代码按照rtsp协议报文格式,设计一个存储协议各格式化信息的数据结构,数据结构中的各个结构分别描述了格式化报文信息中的相应内容。

报文的解析及组装过程,可以看作在依照协议文本格式及语法规则的情况下,在报文文本信息与协议数据结构之间相互转换,即

  • 报文解析:从网络接口读报文信息到缓存,将缓存中的文本信息按照不同报文格式提取出来,存储到协议数据结构中,即字符串码->协议数据结构

  • 报文组装:创建报文缓存,根据服务端当前的状态将待发送的报文内容存储到协议数据结构中,最后将协议数据结构中的内容,按照报文格式组装到报文字符串码缓存中并发送,即协议数据结构->字符串码

4.2 RTSP协议请求行数据结构

下面我们来看下协议请求行响应行数据结构具体实现。

代码通过一系列的枚举类型,定义了协议的操作类型、传输方式、版本信息、报文类型等信息,并以此为基础定义了请求行、响应行数据结构。

服务端支持的操作类型

typedef enum __rtsp_msg_method_e {
	RTSP_MSG_METHOD_OPTIONS = 0,//用于查询服务器端可用方法
	RTSP_MSG_METHOD_DESCRIBE,//用于取得媒体描述信息
	RTSP_MSG_METHOD_SETUP,//用于指定建立RTSP会话连接的传输机制
	RTSP_MSG_METHOD_PLAY,//用于请求开始发送数据
	RTSP_MSG_METHOD_RECORD,//用于请求服务端录制指定时间范围媒体数据
	RTSP_MSG_METHOD_PAUSE,//用于暂停RTSP会话
	RTSP_MSG_METHOD_TEARDOWN,//用于结束RTSP会话
	RTSP_MSG_METHOD_ANNOUNCE,//用于把要推送的音视频信息通过sdp格式传给对端
	RTSP_MSG_METHOD_SET_PARAMETER,//用于设置流参数
	RTSP_MSG_METHOD_GET_PARAMETER,//用于获取流参数
	RTSP_MSG_METHOD_REDIRECT,//用于重定向
	RTSP_MSG_METHOD_BUTT,//未匹配到类型
} rtsp_msg_method_e;

RTSP传输方式

typedef enum __rtsp_msg_uri_scheme_e {
	RTSP_MSG_URI_SCHEME_RTSP = 0,//TCP传输
	RTSP_MSG_URI_SCHEME_RTSPU,//UDP传输
	RTSP_MSG_URI_SCHEME_BUTT,//未匹配到类型
} rtsp_msg_uri_scheme_e;

协议url地址

typedef struct __rtsp_msg_uri_s {
	rtsp_msg_uri_scheme_e scheme;//RTSP传输方式
	uint16_t port;//端口号
	char ipaddr[32];//ip地址
	char abspath[64];//url <path>
} rtsp_msg_uri_s;

协议版本

typedef enum __rtsp_msg_version_e {
	RTSP_MSG_VERSION_1_0 = 0,
	RTSP_MSG_VERSION_BUTT,
} rtsp_msg_version_e;

请求行结构

typedef struct __rtsp_msg_request_line_s {
	rtsp_msg_method_e method;//方法
	rtsp_msg_uri_s    uri;//url
	rtsp_msg_version_e version;//版本
} rtsp_msg_request_line_s;

响应行结构

typedef struct __rtsp_msg_response_line_s {
	rtsp_msg_version_e version;//版本
	uint32_t status_code;//状态码
} rtsp_msg_response_line_s;

这里的报文类型增加了RTSP_MSG_TYPE_INTERLEAVED这种类型,表示复用rtsp链路,将rtp/rtcp报文发送到rtsp链路中进行传输,rtp/rtcp不再新建通信链路。

rtsp报文类型

typedef enum __rtsp_msg_type_e {
	RTSP_MSG_TYPE_REQUEST = 0,//rtsp请求报文
	RTSP_MSG_TYPE_RESPONSE,//rtsp应答报文
	RTSP_MSG_TYPE_INTERLEAVED,//rtp/rtcp over rtsp
	RTSP_MSG_TYPE_BUTT,//未匹配到类型
} rtsp_msg_type_e;

rtsp interleaved frame,用于将rtp/rtcp报文发送到rtsp链路中进行传输

typedef struct __rtsp_msg_interleaved_line_s {
	uint8_t  channel;//channel identifier(rtp/rtcp)
	uint16_t length;//the length of rtp/rtcp packet
	uint8_t  reserved;
} rtsp_msg_interleaved_line_s;

4.3 RTSP协议首部行数据结构

rtsp请求-应答序列号

typedef struct __rtsp_msg_cseq_s {
	uint32_t cseq;
} rtsp_msg_cseq_s;

日期

typedef struct __rtsp_msg_date_s {
	char http_date[32];
} rtsp_msg_date_s;

会话id

typedef struct __rtsp_msg_session_s {
	uint32_t session;
} rtsp_msg_session_s;

rtp传输层类型

typedef enum __rtsp_msg_transport_type_e {
	RTSP_MSG_TRANSPORT_TYPE_RTP_AVP = 0,//RTPoverUDP
	RTSP_MSG_TRANSPORT_TYPE_RTP_AVP_TCP,//RTPoverTCP
	RTSP_MSG_TRANSPORT_TYPE_BUTT,
} rtsp_msg_transport_type_e;

header Transport字段

typedef struct __rtsp_msg_transport_s {
	rtsp_msg_transport_type_e type;//rtp传输层类型(tcp/udp)
	uint32_t flags;//以下flag列表实际取值
#define RTSP_MSG_TRANSPORT_FLAG_SSRC			(1<<0)
#define RTSP_MSG_TRANSPORT_FLAG_UNICAST			(1<<1)
#define RTSP_MSG_TRANSPORT_FLAG_MULTICAST		(1<<2)
#define RTSP_MSG_TRANSPORT_FLAG_CLIENT_PORT		(1<<3)
#define RTSP_MSG_TRANSPORT_FLAG_SERVER_PORT		(1<<4)
#define RTSP_MSG_TRANSPORT_FLAG_INTERLEAVED		(1<<5)
	uint32_t ssrc;//rtp ssrc
	uint16_t client_port;//rtcp is rtp + 1
	uint16_t server_port;
	uint8_t interleaved;//rtp/rtcp channel range in rtsp interleaved frame
} rtsp_msg_transport_s;

服务端时间类型结构

typedef enum __rtsp_msg_time_type_e {
	RTSP_MSG_TIME_TYPE_SMPTE = 0,//SMPTE timecode
	RTSP_MSG_TIME_TYPE_NPT,//network time protocol 
	RTSP_MSG_TIME_TYPE_UTC,//Coordinated Universal Time
	RTSP_MSG_TIME_TYPE_BUTT,//未匹配到类型
} rtsp_msg_time_type_e;

SMPTE时间码,主要参数格式是:Hours:Minutes:Second:frames,通常用时间码来识别和记录视频数据流中的每一帧,从一段视频的起始帧到终止帧,其间的每一帧都有一个唯一的时间码地址

typedef struct __rtsp_msg_time_smpte_s {
	//10:07:33:05.01
	uint32_t seconds;	//10*3600 + 07*60 + 33
	uint32_t subframes;	//05*100 + 01
} rtsp_msg_time_smpte_s;

网络时间结构

typedef struct __rtsp_msg_time_npt_s {
	//123.45
	uint32_t secords;//123
	uint32_t usecords;//45
} rtsp_msg_time_npt_s;

协调世界时结构

typedef struct __rtsp_msg_time_utc_s {
	//19961108T142730.25Z
	uint32_t secords;//1996/11/08 14:27:30 - 1900/1/1 0:0:0
	uint32_t usecords;//25 
} rtsp_msg_time_utc_s;

Range Rr opt. PLAY,PAUSE,RECORD 时间范围

typedef struct __rtsp_msg_range_s {
	rtsp_msg_time_type_e type;//服务端时间类型结构
	union __start_u {
		rtsp_msg_time_smpte_s smpte;//SMPTE时间码
		rtsp_msg_time_npt_s npt;//网络时间结构
		rtsp_msg_time_utc_s utc;//协调世界时结构
	} start;//开始时间
	union __end_u {
		rtsp_msg_time_smpte_s smpte;//SMPTE时间码
		rtsp_msg_time_npt_s npt;//网络时间结构
		rtsp_msg_time_utc_s utc;//协调世界时结构
	} end;//结束时间
} rtsp_msg_range_s;

Content-Type类型

typedef enum __rtsp_msg_content_type_e {
	RTSP_MSG_CONTENT_TYPE_SDP = 0,//sdp格式
	RTSP_MSG_CONTENT_TYPE_RTSL,//rtsl格式
	RTSP_MSG_CONTENT_TYPE_MHEG,//mheg格式(Multimedia and Hypermedia Expert Group)
	RTSP_MSG_CONTENT_TYPE_BUTT,
} rtsp_msg_content_type_e;

Accept字段

typedef struct __rtsp_msg_accept_s {
	uint32_t accept;//Accept取值
#define RTSP_MSG_ACCEPT_SDP		(1<<RTSP_MSG_CONTENT_TYPE_SDP)//1<<0
#define RTSP_MSG_ACCEPT_RTSL	(1<<RTSP_MSG_CONTENT_TYPE_RTSL)//1<<1
#define RTSP_MSG_ACCEPT_MHEG	(1<<RTSP_MSG_CONTENT_TYPE_MHEG)//1<<2
} rtsp_msg_accept_s;

Authorization字段

typedef struct __rtsp_msg_authorization_s {
	char authorization[128];
} rtsp_msg_authorization_s;

User-Agent字段

typedef struct __rtsp_msg_user_agent_s {
	char user_agent[64];
} rtsp_msg_user_agent_s;

header public字段

typedef struct __rtsp_msg_public_s {
	uint32_t public_;//header public字段取值
#define RTSP_MSG_PUBLIC_OPTIONS		(1<<RTSP_MSG_METHOD_OPTIONS)//1<<0
#define RTSP_MSG_PUBLIC_DESCRIBE	(1<<RTSP_MSG_METHOD_DESCRIBE)//1<<1
#define RTSP_MSG_PUBLIC_SETUP		(1<<RTSP_MSG_METHOD_SETUP)//1<<2
#define RTSP_MSG_PUBLIC_PLAY		(1<<RTSP_MSG_METHOD_PLAY)//1<<3
#define RTSP_MSG_PUBLIC_RECORD		(1<<RTSP_MSG_METHOD_RECORD)//1<<4
#define RTSP_MSG_PUBLIC_PAUSE		(1<<RTSP_MSG_METHOD_PAUSE)//1<<5
#define RTSP_MSG_PUBLIC_TEARDOWN	(1<<RTSP_MSG_METHOD_TEARDOWN)//1<<6
#define RTSP_MSG_PUBLIC_ANNOUNCE	(1<<RTSP_MSG_METHOD_ANNOUNCE)//1<<7
#define RTSP_MSG_PUBLIC_SET_PARAMETER	(1<<RTSP_MSG_METHOD_SET_PARAMETER)//1<<8
#define RTSP_MSG_PUBLIC_GET_PARAMETER	(1<<RTSP_MSG_METHOD_GET_PARAMETER)//1<<1
#define RTSP_MSG_PUBLIC_REDIRECT	(1<<RTSP_MSG_METHOD_REDIRECT)//1<<10
} rtsp_msg_public_s;

RTP-Info字段结构

typedef struct __rtsp_msg_rtp_subinfo_s {
	rtsp_msg_uri_s url;//__param_u对应的url地址
	uint32_t isseq;
	union __param_u {
		uint32_t rtptime;//rtp时间戳
		uint32_t seq;//rtp流数据包序列号
	} param;
} rtsp_msg_rtp_subinfo_s;

RTP-Info结构队列

typedef struct __rtsp_msg_rtp_info_s {
	uint32_t ninfos;//队列序号
	rtsp_msg_rtp_subinfo_s **info_array;//RTP-Info结构队列指针
} rtsp_msg_rtp_info_s;

Server字段

typedef struct __rtsp_msg_server_s {
	char server[64];
} rtsp_msg_server_s;

Content-Length 实体主体长度

typedef struct __rtsp_msg_content_length_s {
	uint32_t length;
} rtsp_msg_content_length_s;

Content-Type 实体主体类型

typedef struct __rtsp_msg_content_type_s {
	rtsp_msg_content_type_e type;//Content-Type类型类型
} rtsp_msg_content_type_s;

4.3 RTSP协议报文数据结构

将协议请求行、响应行、首部行等数据结构再进一步封装,就得到了用于描述rtsp报头信息的rtsp_msg_hdr_s、描述rtsp报文实体主体的rtsp_msg_body_s,以及最终描述rtsp报文信息的rtsp_msg_s结构。

rtsp报头结构 message header

typedef struct __rtsp_msg_hdr_s {
	union __start_line_u {
		rtsp_msg_request_line_s reqline;//请求行
		rtsp_msg_response_line_s resline;//响应行
		rtsp_msg_interleaved_line_s interline;//rtsp interleaved frame
	} startline;//开始行

	//general-headers field 通用首部字段
	rtsp_msg_cseq_s *cseq;//序列号
	rtsp_msg_date_s *date;//日期
	rtsp_msg_session_s *session;//会话id
	rtsp_msg_transport_s *transport;//header Transport字段
	rtsp_msg_range_s *range;//时间范围

	//request-headers field 请求首部字段
	rtsp_msg_accept_s *accept;//header Accept字段
	rtsp_msg_authorization_s *authorization;//header Authorization字段
	rtsp_msg_user_agent_s *user_agent;//header User-Agent字段

	//response-headers field 响应首部字段
	rtsp_msg_public_s *public_;//header public字段
	rtsp_msg_rtp_info_s *rtp_info;//header RTP-Info字段
	rtsp_msg_server_s *server;//header Server字段

	//entity-headers field 实体主体首部字段
	rtsp_msg_content_length_s *content_length;//header Content-Length 实体主体长度
	rtsp_msg_content_type_s *content_type;//header Content-Type 实体主体类型
} rtsp_msg_hdr_s;

rtsp报文实体主体

typedef struct __rtsp_msg_body_s {
	void *body;//报文实体主体指针
} rtsp_msg_body_s;

rtsp报文结构

typedef struct __rtsp_msg_s {
	rtsp_msg_type_e type;//报文类型
	rtsp_msg_hdr_s  hdrs;//报头结构
	rtsp_msg_body_s body;//实体主体
} rtsp_msg_s;

至此,我们通过一系列的结构体,完成了对协议报文结构的描述。通过下面的方法,从网络接口中读取报文并解析到报文结构体对象中,或从报文结构体对象中提取报文信息并组装发送到网络接口,完成与客户端的交互。

int rtsp_msg_set_request (rtsp_msg_s *msg, rtsp_msg_method_e mt, const char *ipaddr, const char *abspath);
int rtsp_msg_set_response (rtsp_msg_s *msg, int status_code);
int rtsp_msg_get_cseq (const rtsp_msg_s *msg, uint32_t *cseq);
int rtsp_msg_set_cseq (rtsp_msg_s *msg, uint32_t cseq);
int rtsp_msg_get_session (const rtsp_msg_s *msg, uint32_t *session);
int rtsp_msg_set_session (rtsp_msg_s *msg, uint32_t session);
int rtsp_msg_get_date (const rtsp_msg_s *msg, char *date, int len);
int rtsp_msg_set_date (rtsp_msg_s *msg, const char *date);
int rtsp_msg_set_transport_udp (rtsp_msg_s *msg, uint32_t ssrc, int client_port, int server_port);
int rtsp_msg_set_transport_tcp (rtsp_msg_s *msg, uint32_t ssrc, int interleaved);
int rtsp_msg_get_accept (const rtsp_msg_s *msg, uint32_t *accept);
int rtsp_msg_set_accept (rtsp_msg_s *msg, uint32_t accept);
int rtsp_msg_get_user_agent (const rtsp_msg_s *msg, char *user_agent, int len);
int rtsp_msg_set_user_agent (rtsp_msg_s *msg, const char *user_agent);
int rtsp_msg_get_public (const rtsp_msg_s *msg, uint32_t *public_);
int rtsp_msg_set_public (rtsp_msg_s *msg, uint32_t public_);
int rtsp_msg_get_server (const rtsp_msg_s *msg, char *server, int len);
int rtsp_msg_set_server (rtsp_msg_s *msg, const char *server);
int rtsp_msg_get_content_type (const rtsp_msg_s *msg, int *type);
int rtsp_msg_set_content_type (rtsp_msg_s *msg, int type);
int rtsp_msg_get_content_length (const rtsp_msg_s *msg, int *length);
int rtsp_msg_set_content_length (rtsp_msg_s *msg, int length);
uint32_t rtsp_msg_gen_session_id (void);

小结

本篇为流媒体开发系列文章的第二篇,通过引入http协议,介绍了rtsp协议报文格式,通过抓包分析了报文交互流程,并最终结合代码探讨背后的实现机制。

在下一篇文章中,我们会结合rtsp报文数据结构以及4.3节中提到的方法,讲述如果对请求报文进行解析,以及如何根据报文数据结构组织应答报文,欢迎大家继续关注。

往期推荐

ffmpeg播放器实现详解 - FFmpeg编译安装
ffmpeg播放器实现详解 - FFPlay源码编译
ffmpeg播放器实现详解 - 框架搭建
ffmpeg播放器实现详解 - 视频显示
ffmpeg播放器实现详解 - 音频播放
ffmpeg播放器实现详解 - 创建线程
ffmpeg播放器实现详解 - 视频同步控制
ffmpeg播放器实现详解 - 音频同步控制
ffmpeg播放器实现详解 - 快进快退控制


// 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
// 公众号:断点实验室
// 扫描二维码,关注更多优质原创,内容包括:音视频开发、图像处理、网络、
// Linux,Windows、Android、嵌入式开发等

posted @ 2022-08-23 22:53  断点实验室  阅读(1260)  评论(0编辑  收藏  举报