从零开始写一个发送h264的rtsp服务器(上)「建议收藏」

从零开始写一个发送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发送的

下篇

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107634.html原文链接:https://javaforall.net

(1)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • es6 模板字符串_模板字符串如何实现

    es6 模板字符串_模板字符串如何实现es6的模板字符串个人觉得是很好用的,尤其简化了字符串拼接这块,下面说下它是如何使用的首先,模板字符串是增强版的字符串,使用反引号“来包括字符串,如果需要拼接上变量,那拼接的格式是使用${}包裹变量即可举个例子看下最基本的用法,可以看出来跟普通字符串拼接比较起来简洁容易了很多2:模板字符串的另一优点是,空格和缩进都会保留在输出中,之前的字符串换行的话需要拼接换行符,缩进需要使用缩…

    2022年8月21日
    9
  • android autosize原理,(原创)AndroidAutoSize屏幕适配工具介绍[通俗易懂]

    android autosize原理,(原创)AndroidAutoSize屏幕适配工具介绍[通俗易懂]屏幕适配是我们在开发中经常会遇到的一个问题不同的机型有不同的屏幕尺寸和密度现在市场上已经有不少屏幕适配的解决方案今天就来介绍一个我自己觉得不错的AutoSize这是是一个Android端可以根据设备不同屏幕尺寸自动适配宽高的工具特点是使用起来非常简单。作者写的介绍它网站有:https://www.jianshu.com/p/4aa23d69d481代码位置:https://github.com/J…

    2022年6月6日
    383
  • 电阻和电容的识别_电容电阻怎么区分

    电阻和电容的识别_电容电阻怎么区分一、贴片电阻阻值的读法贴片电阻的阻值通常以数字形式直接标注在电阻的表面,所以读电阻的阻值直接看电阻表面的数字即可。通常情况下有三种表示方法:(1)、由三个数字组成,表明电阻的误差是±5%。前面两位是有效数字,第三位数字表示乘零的倍数,即10的几次方,基本单位是Ω。例如:103,1和0是有效数字直接写下来即可,3表示乘零倍率,也就是10的2次方,所以103表示的阻值就是1010^3=1010…

    2022年8月21日
    7
  • (RegionProposal Network)RPN网络结构及详解[通俗易懂]

    (RegionProposal Network)RPN网络结构及详解[通俗易懂]RPN(RegionProposalNetwork)区域生成网络Faster-RCNN的核心。在这里整理。1.anchors。特征可以看做一个尺度51*39的256通道图像,对于该图像的每一个位置,考虑9个可能的候选窗口:三种面积{128,256,512}×{128,256,512}×三种比例{1:1,1:2,2:1}{1:1,1:2,2:1}。这些候选窗口称为anchors…

    2022年6月23日
    115
  • se3948_30.03.23

    se3948_30.03.23题目描述题解好仙的题啊考虑设交集大小至少为xxx的个数为axa_xax​,则ax=(xn)(22n−x−1)a_x=(_x^n)(2^{2^{n-x}}-1)ax​=(xn​)(22n−x−1)然后我们考虑构造容斥系数fxf_xfx​,使得ans=∑x=0nfxaxans=\sum_{x=0}^nf_xa_xans=∑x=0n​fx​ax​然后我们考虑到如果交集大小恰好为…

    2022年10月8日
    2
  • python3.4的pygame安装

    python3.4的pygame安装确定你的python版本后,才能进行下面的步骤:1.进入官网http://www.lfd.uci.edu/~gohlke/pythonlibs/#pygame 下载对应版本的pygame,注意区分32位与64位。  这里wheel是一种便于python安装的压缩格式。2.进入cmd模式下安装p

    2022年5月10日
    44

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

评论列表(1条)

  • 匿名的头像
    匿名 2022年5月13日 下午4:53

    下篇呢

关注全栈程序员社区公众号