从零开始写一个RTSP服务器(一)RTSP协议讲解
从零开始写一个RTSP服务器系列
★我的开源项目-RtspServer
从零开始写一个RTSP服务器(一)RTSP协议讲解
从零开始写一个RTSP服务器(二)RTSP协议的实现
从零开始写一个RTSP服务器(三)RTP传输H.264
从零开始写一个RTSP服务器(四)一个传输H.264的RTSP服务器
从零开始写一个RTSP服务器(五)RTP传输AAC
从零开始写一个RTSP服务器(六)一个传输AAC的RTSP服务器
从零开始写一个RTSP服务器(七)多播传输RTP包
从零开始写一个RTSP服务器(八)一个多播的RTSP服务器
从零开始写一个RTSP服务器(九)一个RTP OVER RTSP/TCP的RTSP服务器
从零开始写一个RTSP服务器(一)不一样的RTSP协议讲解
文章目录
- 从零开始写一个RTSP服务器(一)不一样的RTSP协议讲解
- 前言
- 一、什么是RTSP协议?
- 二、RTSP协议详解
- 2.1 RTSP数据格式
- 2.2 RTSP请求的常用方法
- 2.3 RTSP交互过程
- 2.4 sdp格式
- 三、RTP协议
- 3.1 RTP包格式
- 3.2 RTP OVER TCP
- 四、RTCP
前言
为什么要写这个系列?
因为我自己在学习rtsp协议想自己从零写一个rtsp服务器的时候,由于rtsp比较复杂,所以觉得这个过程非常的困难,网上许多相关文章或模棱两可,或是复制粘贴。所以想写这样一个系列,来帮助想要学习rtsp协议或者想要从零写一个rtsp服务器的初学者
本系列的文章特点
并系列文章实现追求精简,能够让人明白rtsp协议的实现过程,不追求复杂和完美
如果想要实现一个比较完善的rtsp服务器,可以参考我的开源项目-RtspServer
言归正传,下面开始本系列的文章
一、什么是RTSP协议?
RTSP是一个实时传输流协议,是一个应用层的协议
通常说的RTSP包括RTSP协议
、RTP协议
、RTCP协议
对于这些协议的作用简单的理解如下
RTSP协议:负责服务器与客户端之间的请求与响应
RTP协议:负责传输媒体数据
RTCP协议:在RTP传输过程中提供传输信息
rtsp承载与rtp和rtcp之上,rtsp并不会发送媒体数据,而是使用rtp协议传输
rtp并没有规定发送方式,可以选择udp发送或者tcp发送
二、RTSP协议详解
rtsp的交互过程就是客户端请求,服务器响应,下面看一看请求和响应的数据格式
2.1 RTSP数据格式
RTSP协议格式与HTTP协议格式类似
RTSP客户端的请求格式
method url vesion\r\n CSeq: x\r\n xxx\r\n ... \r\n
method:方法,表明这次请求的方法,rtsp定义了很多方法,稍后介绍
url:格式一般为
rtsp://ip:port/session
,ip表主机ip,port表端口好,如果不写那么就是默认端口,rtsp的默认端口为554
,session表明请求哪一个会话version:表示rtsp的版本,现在为
RTSP/1.0
CSeq:序列号,每个RTSP请求和响应都对应一个序列号,序列号是递增的
RTSP服务端的响应格式
vesion 200 OK\r\n CSeq: x\r\n xxx\r\n ... \r\n
version:表示rtsp的版本,现在为
RTSP/1.0
CSeq:序列号,这个必须与对应请求的序列号相同
2.2 RTSP请求的常用方法
方法 | 描述 |
---|---|
OPTIONS | 获取服务端提供的可用方法 |
DESCRIBE | 向服务端获取对应会话的媒体描述信息 |
SETUP | 向服务端发起建立请求,建立连接会话 |
PLAY | 向服务端发起播放请求 |
TEARDOWN | 向服务端发起关闭连接会话请求 |
2.3 RTSP交互过程
有了上述的知识,我们下面来讲解一个RTSP的交互过程
OPTIONS
C–>S
OPTIONS rtsp://192.168.31.115:8554/live RTSP/1.0\r\n CSeq: 2\r\n \r\n
客户端向服务器请求可用方法
S–>C
RTSP/1.0 200 OK\r\n CSeq: 2\r\n Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY\r\n \r\n
服务端回复客户端,当前可用方法OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY
DESCRIBE
C–>S
DESCRIBE rtsp://192.168.31.115:8554/live RTSP/1.0\r\n CSeq: 3\r\n Accept: application/sdp\r\n \r\n
客户端向服务器请求媒体描述文件,格式为sdp
S–>C
RTSP/1.0 200 OK\r\n CSeq: 3\r\n Content-length: 146\r\n Content-type: application/sdp\r\n \r\nv=0\r\n o=- 91565340853 1 in IP4 192.168.31.115\r\n t=0 0\r\n a=contol:*\r\n m=video 0 RTP/AVP 96\r\n a=rtpmap:96 H264/90000\r\n a=framerate:25\r\n a=control:track0\r\n
服务器回复了sdp文件,这个文件告诉客户端当前服务器有哪些音视频流,有什么属性,具体稍后再讲解
这里只需要直到客户端可以根据这些信息得知有哪些音视频流可以发送
SETUP
C–>S
SETUP rtsp://192.168.31.115:8554/live/track0 RTSP/1.0\r\n CSeq: 4\r\n Transport: RTP/AVP;unicast;client_port=54492-54493\r\n \r\n
客户端发送建立请求,请求建立连接会话,准备接收音视频数据
解析一下
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
这两端口和这个客户端传输数据
PLAY
C–>S
PLAY rtsp://192.168.31.115:8554/live RTSP/1.0\r\n CSeq: 5\r\n Session: 66334873\r\n Range: npt=0.000-\r\n \r\n
客户端请求播放媒体
S–>C
RTSP/1.0 200 OK\r\n CSeq: 5\r\n Range: npt=0.000-\r\n Session: 66334873; timeout=60\r\n \r\n
服务器回复之后,会开始使用RTP通过udp向客户端的54492端口发送数据
TEARDOWN
C–>S
TEARDOWN rtsp://192.168.31.115:8554/live RTSP/1.0\r\n CSeq: 6\r\n Session: 66334873\r\n \r\n
S–>C
RTSP/1.0 200 OK\r\n CSeq: 6\r\n \r\n
2.4 sdp格式
我们上面避开没有讲sdp文件,这里来好好补一补
sdp格式由多行的type=value
组成
sdp会话描述
由一个会话级描述
和多个媒体级描述
组成。会话级描述的作用域是整个会话,媒体级描述描述的是一个视频流或者音频流
会话级描述
由v=
开始到第一个媒体级描述结束
媒体级描述
由m=
开始到下一个媒体级描述结束
下面是上面示例的sdp文件,我们就来好好分析一下这个sdp文件
v=0\r\n
o=- 91565340853 1 in IP4 192.168.31.115\r\n
t=0 0\r\n
a=contol:*\r\n
m=video 0 RTP/AVP 96\r\n
a=rtpmap:96 H264/90000\r\n
a=framerate:25\r\n
a=control:track0\r\n
这个示例的sdp文件包含一个会话级描述
和一个媒体级描述
,分别如下
会话级描述
v=0\r\n o=- 91565340853 1 IN IP4 192.168.31.115\r\n t=0 0\r\n a=contol:*\r\n
v=0
表示sdp的版本
o=- 91565340853 1 IN IP4 192.168.31.115
格式为 o=<用户名> <会话id> <会话版本> <网络类型><地址类型> <地址>
用户名:-
会话id:91565340853,表示rtsp://192.168.31.115:8554/live请求中的live这个会话
会话版本:1
网络类型:IN,表示internet
地址类型:IP4,表示ipv4
地址:192.168.31.115,表示服务器的地址媒体级描述
m=video 0 RTP/AVP 96\r\n a=rtpmap:96 H264/90000\r\n a=framerate:25\r\n a=control:track0\r\n
m=video 0 RTP/AVP 96\r\n
格式为 m=<媒体类型> <端口号> <传输协议> <媒体格式 >
媒体类型:video端口号:0,为什么是0?因为上面在
SETUP
过程会告知端口号,所以这里就不需要了传输协议:RTP/AVP,表示RTP OVER UDP,如果是RTP/AVP/TCP,表示RTP OVER TCP
媒体格式:表示负载类型(payload type),一般使用96表示H.264
a=rtpmap:96 H264/90000
格式为a=rtpmap:<媒体格式><编码格式>/<时钟频率>
a=framerate:25
表示帧率
a=control:track0
表示这路视频流在这个会话中的编号
三、RTP协议
3.1 RTP包格式
rtp包由rtp头部和rtp荷载构成
- RTP头部
版本号(V):2Bit,用来标志使用RTP版本
填充位§:1Bit,如果该位置位,则该RTP包的尾部就包含填充的附加字节
扩展位(X):1Bit,如果该位置位,则该RTP包的固定头部后面就跟着一个扩展头部
CSRC技术器(CC):4Bit,含有固定头部后面跟着的CSRC的数据
标记位(M):1Bit,该位的解释由配置文档来承担
载荷类型(PT):7Bit,标识了RTP载荷的类型
序列号(SN):16Bit,发送方在每发送完一个RTP包后就将该域的值增加1,可以由该域检测包的丢失及恢复
包的序列。序列号的初始值是随机的
时间戳:32比特,记录了该包中数据的第一个字节的采样时刻
同步源标识符(SSRC):32比特,同步源就是RTP包源的来源。在同一个RTP会话中不能有两个相同的SSRC值
贡献源列表(CSRC List):0-15项,每项32比特,这个不常用
rtp荷载
rtp载荷为音频或者视频数据
3.2 RTP OVER TCP
RTP默认是采用UDP发送的,格式为RTP头+RTP载荷,如果是使用TCP,那么需要在RTP头之前再加上四个字节
第一个字节:$,辨识符
第二个字节:通道,在SETUP的过程中获取
第三第四个字节: RTP包的大小,最多只能12位,第三个字节保存高4位,第四个字节保存低8位
四、RTCP
RTCP用于在RTP传输过程中提供传输信息,可以报道RTP传输情况,还可以用来音视频同步,这里就不详细讲解了
从零开始写一个RTSP服务器(一)RTSP协议讲解相关推荐
- 从零开始写一个抖音App——Apt代码生成技术、gradle插件开发与protocol协议
1.讨论--总结前两周评论中有意义的讨论并给予我的解答 2.mvps代码生成原理--将上周的 mvps 架构的代码生成原理进行解析 3.开发一款gradle插件--从 mvps 的代码引出 gradl ...
- 如何搭建python框架_从零开始:写一个简单的Python框架
原标题:从零开始:写一个简单的Python框架 Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发. 你为什么想搭建一个Web框架?我想有下面几个原因: 有一个 ...
- dotnet 从零开始写一个人工智能 从一个神经元开始
现在小伙伴说的人工智能都是弱智能,可以基于神经网络来做.而神经网络是有多层网络,每一层网络都有多个神经元.那么最简单的神经网络就是只有一层,而这一层只有一个神经元,也就是整个神经网络只是有一个神经元. ...
- 用 Node.js 手写一个 DNS 服务器
DNS 是实现域名到 IP 转换的网络协议,当访问网页的时候,浏览器首先会通过 DNS 协议把域名转换为 IP,然后再向这个 IP 发送 HTTP 请求. DNS 是我们整天在用的协议,不知道大家是否 ...
- 自己写一个Web服务器(1)
自己写一个Web服务器(1) 2016-04-13 分类:操作系统.编程开发.首页精华1人评论 分享到:更多15 本文由码农网 – 王坚原创翻译,转载请看清文末的转载要求,欢迎参与我们的付费投稿 ...
- 如何用C语言写一个web服务器的基础功能
我们都知道,学一门语言,只是单独看了就不写的话是很容易出现眼高手低的,所以,今天摩杜云要给大家分享的内容,就是如何用C语言写一个web服务器的基础功能,希望大家看完有所收获. 服务器架构 目标架构 以 ...
- 从零开始写一个武侠冒险游戏-3-地图生成
2019独角兽企业重金招聘Python工程师标准>>> 从零开始写一个武侠冒险游戏-3-地图生成 概述 前面两章我们设计了角色的状态, 绘制出了角色, 并且赋予角色动作, 现在是时候 ...
- 从零开始写一个武侠冒险游戏-6-用GPU提升性能(1)
从零开始写一个武侠冒险游戏-6-用GPU提升性能(1) ----把帧动画的实现放在GPU上 作者:FreeBlues 修订记录 2016.06.19 初稿完成. 2016.08.05 增加对 XCod ...
- api怎么写_使用Node.js原生API写一个web服务器
Node.js是JavaScript基础上发展起来的语言,所以前端开发者应该天生就会一点.一般我们会用它来做CLI工具或者Web服务器,做Web服务器也有很多成熟的框架,比如Express和Koa.但 ...
- mysql c测试程序_Linux平台下从零开始写一个C语言访问MySQL的测试程序
Linux 平台下从零开始写一个 C 语言访问 MySQL 的测试程序 2010-8-20 Hu Dennis Chengdu 前置条件: (1) Linux 已经安装好 mysql 数据库: (2) ...
最新文章
- OpenCV中OpenCL模块函数
- 华为手机文件夹android,安卓手机文件目录详解
- 大赛归来的你们,仍是那个少年--少了游移、多了自信,少了软弱、多了坚强...
- html在线转移,HTML5迁移
- 27.怎样在Swift中声明typedef?
- php重定向和伪静态,Apache301重定向和伪静态设置教程(wp程序为例)
- MyOffic(经理评分)
- Java笔记-Java通过JNI调用Linux上so文件
- 设置xy轴名称_最强干货来了:Grasshopper运算器名称总结(上篇)
- inline函数的作用
- USA 2008 Presidential Debate
- rufus下载包,exsi自启动制作工具
- swfupload 无法加载_解决SWFUpload上传控件在非IE浏览器下不好用的问题
- 【数据结构】leetcode707:python实现链表设计;leetcode142:环形链表
- 抖音sdk,抖音开发api接口
- Python安装word2vec环境依赖
- vue开发规范(单文件组件)
- 汇编总结:无符号除法,有符号除法,取余,无符号乘法,有符号乘法指令
- 网线8芯线各自作用是什么?几种常用的网线定义行业标准
- 这五个资源网站真的是非常强大 请尽快收藏