不以物喜,不以己悲

RTSP协议

RTSP协议

RTSP简述

RTSP协议是一个基于文本的多媒体播放控制协议,属于应用层。它主要用来控制具有实时特性的数据的发送,但其本身并不用于传送流媒体数据,而必须依赖下层传输协议(如RTP/RTCP)所提供的服务来完成流媒体数据的传送。RTSP负责定义具体的控制信息、操作方法、状态码,以及描述与RTP之间的交互操作。

RTSP的URL格式一般如下:

rtsp://host{:port}/{abs_path}/content_name
  • host:有效的域名或IP地址;
  • port:端口号,缺省为554,若为缺省可不填写,否则必须写明。

例如,一个完整的RTSP URL写为:

rtsp://192.168.1.55:554/test

RTSP报文

RTSP是一种基于文本的协议,用CRLF(回车换行)作为每一行的结束符(类似http协议),其好处是,在使用过程中可以方便地增加自定义仓鼠,也方便抓包分析。从消息传送方向上来分,RTSP的报文有两类:请求报文和响应报文。请求报文是指从客户端项服务器发送的请求,响应报文是指从服务器到客户端的回应。

RTSP请求报文的常用方法与作用:

方法 描述
OPTIONS 获得服务器支持的可用方法
DESCRIBE 得到会话描述信息
SETUP 客户端请求建立会话,并确立传输模式
TEARDOWN 客户端发起关闭会话请求
PLAY 客户端发起播放请求

一次基本的RTSP交互过程如下,C表示客户端,S表示服务端。

步骤 方向 信息 描述
1 C->S OPTION request Client询问Server有哪些方法可用
S->C OPTION response Server回应信息中包含所有可用的方法
2 C->S DESCRIBE request Client请求得到Server提供的媒体初始化描述信息
S->C DESCRIBE response Server回应媒体初始化信息,主要是SDP(会话描述协议)
3 C->S SETUP request 设置会话属性以及传输模式,请求建立会话
S->C SETUP response Server建议会话,返回会话标识符以及会话相关信息
4 C->S PLAY request Client请求播放
S->C PLAY response Server回应播放请求信息
5 S->C Media Data Transfer 发送流媒体数据
6 C->S TEARDOWN request Client请求关闭会话
S->C TEARDOWN response Server回应关闭会话请求

OPTIONS

示例代码如下:

static void Main(string[] args)
{
    IPAddress iPAddress = IPAddress.Parse("172.20.124.156");
    IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, 554);
    TcpClient tcpClient = new TcpClient();
    tcpClient.Connect(iPEndPoint);
    Thread thread = new Thread(Recv)
    {
        IsBackground = true,
    };
    thread.Start(tcpClient);
    const string CRLF = "\r\n";
    string options = "OPTIONS rtsp://172.20.124.156:554/Stream RTSP/1.0" + CRLF;
    options += "CSeq: 1" + CRLF;
    options += CRLF;//切记这个一定要多发送一个CRLF,否则服务器一直等待这个结束符,而不返回信息
    byte[] bys = Encoding.UTF8.GetBytes(options);
    tcpClient.GetStream().Write(bys, 0, bys.Length);
    Console.ReadKey();
}
/// <summary>
/// 接收
/// </summary>
/// <param name="sender"></param>
private static void Recv(object sender)
{
    TcpClient tcpClient = sender as TcpClient;
    NetworkStream networkStream = tcpClient.GetStream();
    StreamReader streamReader = new StreamReader(networkStream);
    while(tcpClient.Connected)
    {
        string line = streamReader.ReadLine();
        if(line == null)
        {
            break;
        }
        Console.WriteLine(line);
    }
    Console.WriteLine("连接断开了!");
}

服务端返回示例信息:

RTSP/1.0 200 OK
CSeq: 1
Session: pcNoizrGg
Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, OPTIONS, ANNOUNCE, RECORD

DESCRIBE

客户端向服务器请求媒体资源描述,服务器端通过SDP格式回应客户端的请求。资源描述中会列出所有请求媒体的媒体流及其相关信息,示例代码如下:

static void Main(string[] args)
{
    IPAddress iPAddress = IPAddress.Parse("172.20.124.156");
    IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, 554);
    TcpClient tcpClient = new TcpClient();
    tcpClient.Connect(iPEndPoint);
    Thread thread = new Thread(Recv)
    {
        IsBackground = true,
    };
    thread.Start(tcpClient);
    const string CRLF = "\r\n";
    string options = "OPTIONS rtsp://172.20.124.156:554/Stream RTSP/1.0" + CRLF;
    options += "CSeq: 1" + CRLF;
    options += CRLF;//切记这个一定要多发送一个CRLF,否则服务器一直等待这个结束符,而不返回信息
    byte[] bys = Encoding.UTF8.GetBytes(options);
    tcpClient.GetStream().Write(bys, 0, bys.Length);
    Thread.Sleep(1000);
    //请求媒体资源描述
    string describe = "DESCRIBE rtsp://172.20.124.156:554/Stream RTSP/1.0" + CRLF;
    describe += "CSeq: 2" + CRLF;
    describe += CRLF;
    bys = Encoding.UTF8.GetBytes(describe);
    tcpClient.GetStream().Write(bys, 0, bys.Length);
    Console.ReadKey();
}
/// <summary>
/// 接收
/// </summary>
/// <param name="sender"></param>
private static void Recv(object sender)
{
    TcpClient tcpClient = sender as TcpClient;
    NetworkStream networkStream = tcpClient.GetStream();
    StreamReader streamReader = new StreamReader(networkStream);
    while(tcpClient.Connected)
    {
        string line = streamReader.ReadLine();
        if(line == null)
        {
            break;
        }
        Console.WriteLine(line);
    }
    Console.WriteLine("连接断开了!");
}

服务器响应信息如下:

RTSP/1.0 200 OK
CSeq: 1
Session: pqFLiz9Mg
Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, OPTIONS, ANNOUNCE, RECORD

RTSP/1.0 200 OK
Session: pqFLiz9Mg
Content-Length: 380
CSeq: 2

v=0
o=- 0 0 IN IP4 127.0.0.1
s=EasyDarwin
i=EasyDarwin
c=IN IP4 127.0.0.1
t=0 0
a=x-qt-text-nam:EasyDarwin
a=x-qt-text-inf:EasyDarwin
a=x-qt-text-cmt:source application::EasyDarwin
a=x-qt-text-aut:
a=x-qt-text-cpy:
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;sprop-parameter-sets=,2QAH6y0AoAt0IAAAAMAgAAAHkeMGVA=
a=control:streamid=0

SETUP

SETUP请求确定了具体的媒体流如何传输,该请求必须在PLAY请求之前发送。SETUP请求包含媒体流的URL和客户端用于接收RTP数据(audio or video)的端口以及接收RTCP数据(meta information)的端口。服务器端的回复通常包含客户端请求参数的确认,并会补充缺失的部分,比如服务器选择的发送端口。每一个媒体流在发送PLAY请求之前,都要首先通过SETUP请求来进行相应的配置。

示例代码如下:

static void Main(string[] args)
{
    IPAddress iPAddress = IPAddress.Parse("172.20.124.156");
    IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, 554);
    TcpClient tcpClient = new TcpClient();
    tcpClient.Connect(iPEndPoint);
    Thread thread = new Thread(Recv)
    {
        IsBackground = true,
    };
    thread.Start(tcpClient);
    const string CRLF = "\r\n";
    string options = "OPTIONS rtsp://172.20.124.156:554/Stream RTSP/1.0" + CRLF;
    options += "CSeq: 1" + CRLF;
    options += CRLF;//切记这个一定要多发送一个CRLF,否则服务器一直等待这个结束符,而不返回信息
    byte[] bys = Encoding.UTF8.GetBytes(options);
    tcpClient.GetStream().Write(bys, 0, bys.Length);
    Thread.Sleep(1000);
    //请求媒体资源描述
    string describe = "DESCRIBE rtsp://172.20.124.156:554/Stream RTSP/1.0" + CRLF;
    describe += "CSeq: 2" + CRLF;
    describe += CRLF;
    bys = Encoding.UTF8.GetBytes(describe);
    tcpClient.GetStream().Write(bys, 0, bys.Length);
    Thread.Sleep(1000);
    //SETUP
    string setup = "SETUP rtsp://172.20.124.156:554/Stream RTSP/1.0" + CRLF;
    setup += "CSeq: 3" + CRLF;
    setup += "Transport: RTP/AVP;unicast;client__port=8000-9000" + CRLF;
    setup += CRLF;
    bys = Encoding.UTF8.GetBytes(setup);
    tcpClient.GetStream().Write(bys, 0, bys.Length);

    Console.ReadKey();
}
/// <summary>
/// 接收
/// </summary>
/// <param name="sender"></param>
private static void Recv(object sender)
{
    TcpClient tcpClient = sender as TcpClient;
    NetworkStream networkStream = tcpClient.GetStream();
    StreamReader streamReader = new StreamReader(networkStream);
    while(tcpClient.Connected)
    {
        string line = streamReader.ReadLine();
        if(line == null)
        {
            break;
        }
        Console.WriteLine(line);
    }
    Console.WriteLine("连接断开了!");
}

服务器返回信息:

RTSP/1.0 200 OK
CSeq: 1
Session: 9R52ZzrGg
Public: DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, OPTIONS, ANNOUNCE, RECORD

RTSP/1.0 200 OK
Content-Length: 380
CSeq: 2
Session: 9R52ZzrGg

v=0
o=- 0 0 IN IP4 127.0.0.1
s=EasyDarwin
i=EasyDarwin
c=IN IP4 127.0.0.1
t=0 0
a=x-qt-text-nam:EasyDarwin
a=x-qt-text-inf:EasyDarwin
a=x-qt-text-cmt:source application::EasyDarwin
a=x-qt-text-aut:
a=x-qt-text-cpy:
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;sprop-parameter-sets=,2QAH6y0AoAt0IAAAAMAgAAAHkeMGVA=
a=control:streamid=0

RTSP/1.0 200 OK
CSeq: 3
Session: 9R52ZzrGg
Transport: RTP/AVP;unicast;client__port=8000-9000

PLAY

客户端通过PLAY请求来播放一个或全部媒体流,PLAY请求可以发送一次或多次,发送一次时,URL为包含所有媒体流的地址,发送多次时,每一次请求携带的URL只包含一个响应的媒体流。PLAY请求中可指定播放的range,若未指定,则从媒体流的开始播放到结束,如果媒体流在播放过程中被暂停,则可在暂停处重新启动流的播放。

播放示例代码为:

string play = "PLAY rtsp://172.20.124.156:554/Stream RTSP/1.0" + CRLF;
play += "CSeq: 4" + CRLF;
play += CRLF;

PAUSE

PAUSE请求会暂停一个或所有媒体流,后续可通过PLAY请求恢复播放。PAUSE请求中携带所请求媒体流的URL,若参数range存在,则指明在何处暂停,若该参数不存在,则暂停立即生效,切暂停时长不确定。

暂停示例代码:

string pause = "PAUSE rtsp://172.20.124.156:554/Stream RTSP/1.0" + CRLF;
pause += "CSeq: 5" + CRLF;
pause += $"Session: {session}" + CRLF;
pause += CRLF;

TEARDOWN

结束会话请求,该请求会停止所有媒体流,并释放服务器上的相关会话数据。

string teardown = "TEARDOWN rtsp://172.20.124.156:554/Stream RTSP/1.0" + CRLF;
teardown += "CSeq: 8" + CRLF;
teardown += $"Session: {session}" + CRLF;
teardown += CRLF;
posted @ 2021-04-23 13:37  这种人  阅读(1013)  评论(0编辑  收藏  举报