从零开始写一个发送h264的rtsp服务器(上)
转自:http://blog.csdn.net/jychen105/article/details/47006345
一、什么是RTSP
通常所说的rtsp协议其实包含三个协议: rtsp协议, rtp协议, rtcp协议
各协议运作流程概要:
第一阶段:rtsp协议负责沟通传输什么数据,传的是图像还是声音,还是两者混合?图像的话传是h264流,还是h265流,还是jpeg流?后续的rtp,rtcp协议是采用tcp还是udp,端口号是多少都是通过第一阶段的rtsp协议确定的。
第二阶段:通过rtp协议传输数据,rtcp进行网络传输质量的监控
第三阶段:通过rtsp协议中断整个协议的传输
二、RTSP协议详解
rtsp协议是个文本协议,运行于tcp协议之上,服务器默认监听端口554,当然也可以修改成其他端口,一般不改。
协议包格式
- 客户端协议格式
第一行:方法名:XXX\r\n
第二行:CSeq:XXX\r\n
第N行:XXX\r\n
\r\n
- 服务器端协议格式
第一行:RTSP/1.0 XXX\r\n
第二行:CSeq:XXX\r\n
第N行:XXX\r\n
\r\n
协议最终都是以两个\r\n分隔
rtsp通信精简版
| 步骤 | 客户端 | 服务端 | 含义 |
|---|---|---|---|
| 1 | 请求OPTIONS | 回应OPTIONS | 查询服务器支持哪些命令或者方法 |
| 2 | 请求DESCRIBE | 回应DESCRIBE | 查询服务器发送流的描述信息 |
| 3 | 请求SETUP | 回应SETUP | 告诉服务器以TCP or UDP建立RTP,RTCP连接,并告诉端口号 |
| 4 | 请求PLAY | 回应PLAY | 告诉服务器可以用RTP协议发送数据过来了 |
| 最后一步 | 请求TEARDOWN | 关闭连接 | 告诉服务器关闭连接 |
rtsp通信详细版本
客户端:192.168.1.109
服务端:192.168.1.188
1. OPTIONS
客户端请求:
OPTIONS rtsp://192.168.1.188/h264 RTSP/1.0
CSeq: 2
User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
服务端回应:
RTSP/1.0 200 OK
CSeq: 2
Date: Mon, Jul 21 2014 09:07:56 GMT
Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER
需注意的点:
回应的CSeq与请求的CSeq必须一致,后续rtsp命令下同。
PAUSE, GET_PARAMETER, SET_PARAMETER这几个命令可无,也就是一些命令服务器可以不实现。OPTIONS, SETUP, PLAY是一定要有的,其他的未认真调查。
2. DESCRIBE
客户端请求:
DESCRIBE rtsp://192.168.1.188/h264 RTSP/1.0
CSeq: 3
User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
Accept: application/sdp
服务端回应:
RTSP/1.0 200 OK
CSeq: 3
Date: Mon, Jul 21 2014 09:07:56 GMT
Content-Base: rtsp://192.168.1.188/h264/
Content-Type: application/sdp
Content-Length: 547
v=0
o=- 1405932398518315 1 IN IP4 192.168.1.188
s=Session streamed by "hua_an"
i=h264
t=0 0
a=tool:LIVE555 Streaming Media v2012.10.24
a=type:broadcast
a=control:*
a=range:npt=0-
a=x-qt-text-nam:Session streamed by "hua_an"
a=x-qt-text-inf:h264
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:500
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=64002A;sprop-parameter-sets=J2QAKq2EBUViuKxUcQgKisVxWKjiECSFITk8nyfk/k/J8nm5s00IEkKQnJ5Pk/J/J+T5PNzZpsqAUAW6bIAAAfQAAGGocAAABbjYAAD0JBe91lA=,KP4Briw=
a=control:track1
注意的点:
服务端回应了两个协议,一个是rtsp的回应,还回应了一个sdp协议(Session Description Protocol),sdp协议最后一个只有一个\r\n。 rtsp协议是两个\r\n结尾。
sdp协议中描述了发送的流为h264,采样率为90000Hz (h264的采样率为90000HZ,因此时间戳的单位为1(秒)/90000,因此如果当前视频帧率为25fps,那时间戳间隔或者说增量应该为3600, 即每个naul单元的时间间隔为3600。此句话可以放在rtp协议封装h264时理解。)
sprop-parameter-sets为sps跟pps的base64编码组合。(sps,pps为h264 nalu单元的Sequence Parameter Sets (SPS) 和Picture Parameter Set (PPS), 后续会介绍)
3. SETUP
客户端请求:
SETUP rtsp://192.168.1.188/h264/track1 RTSP/1.0
CSeq: 4
User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
服务端回应:
RTSP/1.0 200 OK
CSeq: 4
Date: Mon, Jul 21 2014 09:07:56 GMT
Transport: RTP/AVP/TCP;unicast;destination=192.168.1.109;source=192.168.1.188;interleaved=0-1
Session: 5C01EACE
此处为TCP建立RTP跟RTCP。RTP,RTCP都是利用此路连接,不再建立新连接,只是数据包格式不一样而以。
注意interleaved=0-1, 0为传送RTP数据,1为RTCP数据
4. PLAY
客户端请求
PLAY rtsp://192.168.1.188/h264/ RTSP/1.0
CSeq: 5
User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
Session: 5C01EACE
Range: npt=0.000-
服务端回应
RTSP/1.0 200 OK
CSeq: 5
Date: Mon, Jul 21 2014 09:07:56 GMT
Range: npt=0.000-
Session: 5C01EACE
RTP-Info: url=rtsp://192.168.1.188/h264/track1;seq=28626;rtptime=98136845
播放,开始传输rtp数据。同时告知开始序号为28626, 开始时间戳为98136845
5. 最后一步
客户端请求:
TEARDOWN rtsp://192.168.1.188/h264/ RTSP/1.0
CSeq: 7
User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
Session: 5C01EACE
服务端回应:
关闭RTSP连接
三、RTP协议
根据之前rtsp的协议,rtp即可以通过tcp,也可以通过udp传输。但是数据包协议格式是一样的。
- tcp传输
| 协议格式 | ‘$’ | 0 | 长度(=RTP协议头长度+RTP数据长度) | RTP协议头 | RTP数据 |
|---|---|---|---|---|---|
| 长度信息 | 1字节 | 1字节 | 2字节 | sizeof(RTP协议头) | N |
- udp传输
| 协议格式 | RTP协议头 | RTP数据 |
|---|---|---|
| 长度信息 | sizeof(RTP协议头) | N |
– 数据传输采用网络字节序
– RTP数据长度小于MTU长度, 一般是1500, 目的是为了网络传输避免分片,未深究如何避免分片的。
– 传输的流媒体数据就是封装在RTP数据部分
RTP协议头
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X| CC |M| PT | sequence number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| timestamp |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| synchronization source (SSRC) identifier |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
| contributing source (CSRC) identifiers |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//set CC = 0, so there is no CSRC
转成c语言结构体(小端字节序):
typedef struct
{
/* byte 0 */
unsigned char csrc_len:4; /* CC expect 0 */
unsigned char extension:1; /* X expect 1, see RTP_OP below */
unsigned char padding:1; /* P expect 0 */
unsigned char version:2; /* V expect 2 */
/* byte 1 */
unsigned char payload:7; /* PT RTP_PAYLOAD_RTSP */
unsigned char marker:1; /* M expect 1 */
/* byte 2,3 */
unsigned short seq_no; /*sequence number*/
/* byte 4-7 */
unsigned long timestamp; /*time stamp*/
/* byte 8-11 */
unsigned long ssrc; /* stream number is used here. */
} RTPHeader;/*12 bytes*/
四、RTCP
rtcp主要是用来解决网络流控的,如果是自实现rtsp服务器传输实时流,可以不实现此部分。
如果是实现rtsp客户端,建立实现一个Recvive Report包就行了,此包主要是报告丢包率,网络延迟是多少,方便服务器端调节。
因为发的都是实时流,简单起见,recvive report封包时,丢包率为0,延迟也为0
五、h264是如何通过rtsp发送的
下篇
从零开始写一个发送h264的rtsp服务器(上)的更多相关文章
- 从零开始写一个发送h264的rtsp服务器(下)
转自:http://blog.csdn.net/jychen105/article/details/47012099 一.H264是如何通过rtsp发送的 简单来说,H264就是通过打包到rtp协议的 ...
- 从零开始写一个Tomcat(贰)--建立动态服务器
上文书说道如何通过http协议建立一个静态的服务器来访问静态网页,但我们选择tomcat最主要的原因还是因为它能动态的执行servlet,这边文章将引导你实现一个能够运行servlet的服务器,这个简 ...
- 从零开始写一个Tomcat(叁)--请求解析
挖坑挖了这么长时间也该继续填坑了,上文书讲到从零开始写一个Tomcat(贰)--建立动态服务器,讲了如何让服务器解析请求,分离servlet请求和静态资源请求,读取静态资源文件输出或是通过URLCla ...
- 深入浅出React Native 3: 从零开始写一个Hello World
这是深入浅出React Native的第三篇文章. 1. 环境配置 2. 我的第一个应用 将index.ios.js中的代码全部删掉,为什么要删掉呢?因为我们准备从零开始写一个应用~学习技术最好的方式 ...
- 用ASP.Net写一个发送ICQ信息的程序
用ASP.Net写一个发送ICQ信息的程序 这里我给大家提供一个很实用的例子,就是在线发送ICQ信息.想一想我们在网页上直接给朋友发送ICQ信息,那是多么美妙的事情啊.呵呵,在吹牛啊,其实ICQ本来就 ...
- 从零开始写一个武侠冒险游戏-0-开发框架Codea简介
从零开始写一个武侠冒险游戏-0-开发框架Codea简介 作者:FreeBlues 修订记录 2016.06.21 初稿完成. 2016.08.03 增加对 XCode 项目文件的说明. 概述 本游戏全 ...
- 2019-5-24-WPF-源代码-从零开始写一个-UI-框架
title author date CreateTime categories WPF 源代码 从零开始写一个 UI 框架 lindexi 2019-05-24 15:54:36 +0800 2018 ...
- 从零开始写一个武侠冒险游戏-8-用GPU提升性能(3)
从零开始写一个武侠冒险游戏-8-用GPU提升性能(3) ----解决因绘制雷达图导致的帧速下降问题 作者:FreeBlues 修订记录 2016.06.23 初稿完成. 2016.08.07 增加对 ...
- 从零开始写一个武侠冒险游戏-7-用GPU提升性能(2)
从零开始写一个武侠冒险游戏-7-用GPU提升性能(2) ----把地图处理放在GPU上 作者:FreeBlues 修订记录 2016.06.21 初稿完成. 2016.08.06 增加对 XCode ...
随机推荐
- C/C++的64位整型
在C/C++中,64为整型一直是一种没有确定规范的数据类型.现今主流的编译器中,对64为整型的支持也是标准不一,形态各异.一般来说,64位整型的定义方式有long long和__int64两种(VC还 ...
- Android应用--QR的生成(二维码)
二维码的定义: 二维码(2-dimensional bar code),是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的. 在许多种类的二维条码中,常用的码制 ...
- Ubuntu 下 vi 输入方向键会变成 ABCD 的解决方法
Ubuntu 下 vi 输入方向键会变成 ABCD,这是 Ubuntu 预装的是 vim tiny 版本,安装 vim full 版本即可解决. 先卸载vim-tiny: $ sudo apt-get ...
- 一份可以发布jar包到MAVEN中央仓库的POM
[2017-01-03 更新]将基础的pom抽离成一个项目无关的parent pom,euler-framework的pom继承这个parent pom 今天在家折腾了一下怎么把Jar包发布到Mave ...
- Divide by Zero 2018 and Codeforces Round #474 (Div. 1 + Div. 2, combined)
思路:把边看成点,然后每条边只能从下面的边转移过来,我们将边按照u为第一关键字,w为第二关键字排序,这样就能用线段树维护啦. #include<bits/stdc++.h> #define ...
- Windows 下 MySql 5.7.20安装及data和my.ini文件的配置(转)
Windows 下 MySql 5.7.20安装及data和my.ini文件的配置 本文通过图文并茂的形式给大家介绍了MySql 5.7.20安装及data和my.ini文件的配置方法. my ...
- 008.KVM-VNC管理
一 VNC管理 1.1 修改配置 [root@kvm-host ~]# vi /etc/libvirt/qemu.conf …… vnc_listen = "0.0.0.0" 说明 ...
- excel导入及注意事项
在Excel导入过程中经常遇到单元格数据格式不正确引发的错误,在赋值前需要做下类型转换. 提供一个类型转换工具类: /** * 单元格类型转化工具类 * @param cell * @return * ...
- bzoj 2809 可并堆维护子树信息
对于每个节点,要在其子树中选尽量多的节点,并且节点的权值和小于一个定值. 建立大根堆,每个节点从儿子节点合并,并弹出最大值直到和满足要求. /***************************** ...
- Nginx增加模块
http://blog.csdn.net/loyachen/article/details/50902667