• 【miscellaneous】海康相机RTSP连接代码分析


    海康相机RTSP连接代码分析


    最近在做海康相机rtsp连接获取音视频的工作,现在介绍一下分析过程和源码。

    【源码在我上传的共享资料中: http://download.csdn.net/detail/zhouyongku/8203521

       一、基本原理

     RTSP客户端去连接服务器的最基本步骤如下:   

    (1)分析url中的端口号,创建一个与服务器[S-PORT]端口号的TCP连接用于RTSP命令交互 
    (2)执行RTSP命令请求,告诉服务器可以连接到本地的端口[C-PORT]进行数据发送 
    (3)客户端从本地[C-PORT]读取数据 
       

       二、研究步骤

     来研究一下海康相机的RTSP数据是怎么交互的

    (1)打开Wireshark,选择"抓包"->"网络接口"->选择网卡->“开始”,在"过滤“栏输入"rtsp",屏蔽不相关信息。


    (2)打开VLC播放器,输入海康相机RTSP地址

    例如:【rtsp://admin:12345@192.168.1.145:554/MPEG-4/ch2/main/av_stream】

    (3)播放几秒后再点击停止播放,退出VLC播放器。 
    (4)分析Wireshark数据 

    三、RTSP协议过程分析

    1、RTSP协议梗概

    就这几个简单的交互命令就能实现RTSP对接,C代表Client S代表Server

            例如:C1-客户端发的第一个命令 S1-服务器响应的第一个回复

    【C1】OPTIONS rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream RTSP/1.0RTSP

    【S1】Reply: RTSP/1.0 200 OK RTSP 
    【C2】DESCRIBE rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream RTSP/1.0RTSP
    【S2】Reply: RTSP/1.0 401 Unauthorized RTSP 
    【C3】DESCRIBE rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream RTSP/1.0RTSP
    【S3】Reply: RTSP/1.0 200 OK, with session descriptionRTSP/SDP 
    【C4】SETUP rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/trackID=1 RTSP/1.0RTSP 
    【S4】Reply: RTSP/1.0 200 OK RTSP 
    【C5】SETUP rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/trackID=2 RTSP/1.0RTSP 
    【S5】Reply: RTSP/1.0 200 OK RTSP 
    【C6】PLAY rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/ RTSP/1.0RTSP 
    【S6】Reply: RTSP/1.0 200 OK RTSP 
    【C7】GET_PARAMETER rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/ RTSP/1.0RTSP 
    【S7】Reply: RTSP/1.0 200 OK RTSP 
    【C8】TEARDOWN rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/ RTSP/1.0RTSP 
    【S8】Reply: RTSP/1.0 200 OK RTSP 



    2、请求OPTION

    【C1-OPTION】

     Request: OPTIONS rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream RTSP/1.0
    CSeq: 2
    User-Agent: LibVLC/2.1.3 (LIVE555 Streaming Media v2014.01.21)

    询问RTSP服务器有哪些命令可以使用

    【S1-REPLY】

    Response: RTSP/1.0 200 OK
    CSeq: 2
    Public: OPTIONS, DESCRIBE, PLAY, PAUSE, SETUP, TEARDOWN, SET_PARAMETER, GET_PARAMETER
    Date:  Thu, Nov 27 2014 11:59:41 GMT  

    服务器回应客户端的请求。这个回应第一行为OK,则表明服务器接受查询命令,并且反馈给客户端信息,可以使用的命令有:OPTIONS, DESCRIBE, PLAY, PAUSE, SETUP, TEARDOWN, SET_PARAMETER, GET_PARAMETER,则下一步就可以向服务器发送这些命令,如果没有,则服务器不接收这些命令。


    3、无验证请求资源描述DESCRIBE


    【C2-DESCRIBE】

      Request: DESCRIBE rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream RTSP/1.0
      CSeq: 3
      User-Agent: LibVLC/2.1.3 (LIVE555 Streaming Media v2014.01.21)

     Accept: application/sdp

     


    请求RTSP服务器描述自身有哪些音视频资源

    【S2-REPLY】

    Response: RTSP/1.0 401 Unauthorized  
    CSeq: 3  
    WWW-Authenticate: Digest realm="4419b727ab09", nonce="66bb9f0bf5ac93a909ac8e88877ae727", stale="FALSE"  
    WWW-Authenticate: Basic realm="4419b727ab09"

    Date:  Thu, Nov 27 2014 11:59:41 GMT


    服务器回应客户端的请求。第一行为Unauthorized,表明认证不成功服务器拒绝给出拥有的资源,因此我们需要再次发送认证的请求到服务器,则服务器才能给出拥有的资源


    4、认证请求资源描述DESCRIBE


    【C3-DESCRIBE】

    Request: DESCRIBE rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream RTSP/1.0
    CSeq: 4
    Authorization: Digest username="admin", realm="4419b727ab09", nonce="66bb9f0bf5ac93a909ac8e88877ae727", uri="rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream", response="108084646408d21aa255664781c886fc"
    User-Agent: LibVLC/2.1.3 (LIVE555 Streaming Media v2014.01.21)
    Accept: application/sdp


    发送具有认证标识的信息到服务器,去获取服务器的资源列表。怎样的格式算正确认证的信息?这个关键在于response字段。[S2-REPLY]中反馈了两个信息realm="4419b727ab09", nonce="66bb9f0bf5ac93a909ac8e88877ae727",


    **************************************response区域的计算规则如下***********************************

    (1)当password为MD5编码,则
    response = md5(<password>:<nonce>:md5(<cmd>:<url>));
    (2)当password为ANSI字符串,则
    response = md5(md5(<username>:<realm>:<password>):<nonce>:md5(<cmd>:<uri>));

    ***********************************************************************************************************

    其中 password=密码,nonce=服务器返回的nonce,cmd=当前命令(DESCRIBE、SETUP等),realm=服务器返回的reaml,uri=请求的uri地址.当服务器接收到response为108084646408d21aa255664781c886fc的时候,服务器也会用这一套公式去计算,当发现计算出的值与客户端提供的值吻合的时候,则表明用户名和密码校验成功!

    		/*MD5加密函数*/
    		int md5_hash(const void *buff, size_t len, char *hexsum);


    	<span style="white-space:pre">	</span>/*发送具有response认证的describe命令函数*/
    		
    		void RtspRequest::SendRegisterRequest(string requestType)
    		{
    			string requestCmd;
    			char cseq[256];
    			char session[256];
    			char author[500] = { 0 };
    			char acc[200] = { 0 };
    			char szInput[200] = { "" };
    			char szOutput[200] = { 0 };
    			char szMd5Pwd[200] = { 0 };
    			char szmd5methorduri[200] = { 0 };
    			
    			m_CSeq++;
    
    
    			if (m_SetupName.length())
    			{
    				requestCmd = requestType;
    				requestCmd += " ";
    				requestCmd += m_RequestsMrl;
    				requestCmd += "/";
    				requestCmd += m_SetupName;
    				requestCmd += " RTSP/1.0";
    
    
    				m_SetupName = "";
    			}
    			else
    			{
    				requestCmd = requestType;
    				requestCmd += " ";
    				requestCmd += m_RequestsMrl;
    				requestCmd += " RTSP/1.0";
    			}
    
    
    
    
    			//当password为ANSI字符串 response = md5(md5(<username>:<realm>:<password>):<nonce>:md5(<cmd>:<uri>));
    			
    			//md5(<username>:<realm>:<password>)=md5(admin:4419b727ab09:12345)=fa47d934c754db5ebebd9b42a4412073
    			sprintf_s(szInput, 200, "%s:%s:%s", m_uername.c_str(), m_realm.c_str(), m_password.c_str());
    			md5_hash(szInput, strlen(szInput), szMd5Pwd);
    			
    			//md5(<cmd>:<uri>)=md5(DESCRIBE:rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream) =0b0a4e77e852876bdfdf6ecb72ba3900
    			sprintf_s(szInput, 200, "DESCRIBE:%s", m_RequestsMrl.c_str());
    			md5_hash(szInput, strlen(szInput), szmd5methorduri);
    			
    			//md5(md5(<username>:<realm>:<password>):<nonce>:md5(<cmd>:<uri>));
    			//=md5(fa47d934c754db5ebebd9b42a4412073:66bb9f0bf5ac93a909ac8e88877ae727:0b0a4e77e852876bdfdf6ecb72ba3900)
    <span style="white-space:pre">			</span>//=108084646408d21aa255664781c886fc
    			//关于这一条,http://www.3464.com/Tools/MD5/index.asp 网站给出的结论则不一致:98f90a583e5c436f83da956c9b00767b 
    <span style="white-space:pre">			</span>//我的代码给出的值与VLC和其它工具给出的值完全匹配
    			sprintf_s(szInput, 200, "%s:%s:%s", szMd5Pwd, m_nonce.c_str(), szmd5methorduri);
    			md5_hash(szInput, strlen(szInput), szOutput);
    			m_response = szOutput;
    
    
    			_snprintf(cseq, 256, "CSeq: %u", m_CSeq);
    			_snprintf(author, 500, "Authorization: Digest username="%s", realm="%s", nonce="%s", uri="%s", response="%s"",
    				m_uername.c_str(), m_realm.c_str(), m_nonce.c_str(), m_RequestsMrl.c_str(), m_response.c_str());
    			_snprintf(acc, 500, "Accept: application/sdp");
    
    
    			if (requestType.compare("TEARDOWN") == 0)
    				m_Session = 0;
    			_snprintf(session, 256, "Session: %I64u", m_Session);
    
    
    			Write(requestCmd.c_str());
    			Write(cseq);
    			Write(author);
    			Write("User-Agent: LibVLC/2.1.3 (LIVE555 Streaming Media v2014.01.21)");
    			Write(acc);
    			if (m_Session > 0)
    				Write(session);
    
    
    			WriteFields();
    			Write("");
    		}


    【S3-REPLY】

    Response: RTSP/1.0 200 OK
    CSeq: 4
    Content-type: application/sdp
    Content-Base: rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/
    Content-length: 672
    Session Description Protocol
    Session Description Protocol Version (v): 0
    Owner/Creator, Session Id (o): - 1417089581269778 1417089581269778 IN IP4 192.168.1.145
    Session Name (s): Media Presentation
    E-mail Address (e): NONE
    Bandwidth Information (b): AS:5100
    Time Description, active time (t): 0 0
    Session Attribute (a): control:rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/
    Media Description, name and address (m): video 0 RTP/AVP 96
    Bandwidth Information (b): AS:5000
    Media Attribute (a): control:rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/trackID=1
    Media Attribute (a): rtpmap:96 H264/90000
    Media Attribute (a): fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z0KAH4iLUCgC3QgAADhAAAr8gCA=,aM44gA==
    Media Description, name and address (m): audio 0 RTP/AVP 0
    Bandwidth Information (b): AS:50
    Media Attribute (a): control:rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/trackID=2
    Media Attribute (a): rtpmap:0 PCMU/8000
    Media Attribute (a): Media_header:MEDIAINFO=494D4B48010100000400010010710110401F000000FA000000000000000000000000000000000000;
    Media Attribute (a): appversion:1.0

    首先第一行给了OK,表明上一个命令成功--DESCRIBE成功得到服务器认证
    其次,给出了服务器的媒体信息-具有两路码流--音频(audio)和视频(video) 并给出了请求两路数据的地址


    5、请求视频资源


    【C4-SETUP】

    Request: SETUP rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/trackID=1 RTSP/1.0
    CSeq: 5
    Authorization: Digest username="admin", realm="4419b727ab09", nonce="66bb9f0bf5ac93a909ac8e88877ae727", uri="rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/", response="dfd7cfc85819d15d622e4491ad12217d"
    User-Agent: LibVLC/2.1.3 (LIVE555 Streaming Media v2014.01.21)
    Transport: RTP/AVP;unicast;client_port=56732-56733


    请求获取流媒体服务器上的视频资源 并告知服务器可以往客户端56732端口发送视频数据,56733为RTCP接收端口,发送方式为单播。传输方式为UDP 

    **********************传输方式与Transport string的对应关系**********************

    UDP传输:Transport:RTP/AVP

    TCP传输:Transport:RTP/AVP/TCP

    RAW UDP传输:Transport:RAW/RAW/UDP

    ****************************************************************************************

    【S4-REPLY】

    Response: RTSP/1.0 200 OK
    CSeq: 5
    Session: 1350856257;timeout=60
    Transport: RTP/AVP;unicast;client_port=56732-56733;server_port=8208-8209;ssrc=4a3a67d5;mode="play"
    Date:  Thu, Nov 27 2014 11:59:41 GMT


    服务器同意发送视频数据给客户端 56732为视频接收端,56733为RTCP接收端口,发送方式为单播。传输方式为UDP 

    6、请求音频资源


    【C5-SETUP】

    Request: SETUP rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/trackID=2 RTSP/1.0
    CSeq: 6
    Authorization: Digest username="admin", realm="4419b727ab09", nonce="66bb9f0bf5ac93a909ac8e88877ae727", uri="rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/", response="dfd7cfc85819d15d622e4491ad12217d"
    User-Agent: LibVLC/2.1.3 (LIVE555 Streaming Media v2014.01.21)
    Transport: RTP/AVP;unicast;client_port=56734-56735
    Session: 1350856257


    请求获取服务器上的音频资源 并告知服务器可以往客户端56734端口发送视频数据,56735为RTCP接收端口,发送方式为单播。传输方式为UDP 


    【S5-REPLY】

    Response: RTSP/1.0 200 OK
    CSeq: 6
    Session: 1350856257;timeout=60
    Transport: RTP/AVP;unicast;client_port=56734-56735;server_port=8226-8227;ssrc=232306b5;mode="play"
    Date:  Thu, Nov 27 2014 11:59:41 GMT


    服务器同意发送音频数据给客户端 56734为视频接收端,56735为RTCP接收端口,发送方式为单播。传输方式为UDP 

    7、开始数据接收

    【C6-PLAY】

    Request: PLAY rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/ RTSP/1.0
    CSeq: 7
    Authorization: Digest username="admin", realm="4419b727ab09", nonce="66bb9f0bf5ac93a909ac8e88877ae727", uri="rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/", response="4c4e89a5894d2b208489fde1aeaf9e44"
    User-Agent: LibVLC/2.1.3 (LIVE555 Streaming Media v2014.01.21)
    Session: 1350856257
    Range: npt=0.000-


    告知服务器一切准备就绪,数据可以发过来了!come on baby!


    【S6-REPLY】

    Response: RTSP/1.0 200 OK
    CSeq: 7
    Session: 1350856257
    RTP-Info: url=rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/trackID=1;seq=31283;rtptime=1712470431,url=rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/trackID=2;seq=3370;rtptime=1846536290
    Date:  Thu, Nov 27 2014 11:59:41 GMT


    服务器告知客户端,朋友我已经送数据过来了,你可以接收了!
    这个时候我们打开Wireshark,在过滤栏输入rtp,可以看到如下数据,表明服务器已经向客户端的56732、56734端口发送数据

    RTP拆包到图像显示和音频播放,会在我的下一篇博客中详细解释


    8、关闭播放

    【C7-TEARDOWN】

    Request: TEARDOWN rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/ RTSP/1.0
    Method: TEARDOWN
    URL: rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/
    CSeq: 9
    Authorization: Digest username="admin", realm="4419b727ab09", nonce="66bb9f0bf5ac93a909ac8e88877ae727", uri="rtsp://192.168.1.145:554/MPEG-4/ch2/main/av_stream/", response="af15346442151a51f1478da1858778d5"
    User-Agent: LibVLC/2.1.3 (LIVE555 Streaming Media v2014.01.21)
    Session: 1350856257


    关闭数据传输 释放服务器资源 如果需要重新获取码流 则需要从1~6再来一次

    【S7-REPLY】

    Response: RTSP/1.0 200 OK
    Status: 200
    CSeq: 9
    Session: 1350856257
    Date:  Thu, Nov 27 2014 11:59:42 GMT


     服务器已经成功关闭当前链接


    本文引用:http://blog.163.com/seek_for/blog/static/1116353920116154386537/

  • 相关阅读:
    「赛后总结」Codeforces Round #680 (Div. 2)
    雲雀
    「题解」洛谷 P1494 [国家集训队]小Z的袜子
    NOIP 2020 退役记
    任务查询系统「主席树+差分」
    组合「欧拉路」
    AtCoder 123 Triangle「思维题」
    旅行(加强版)「基环树」
    一个简单的询问「莫队」
    [HNOI2012]永无乡「线段树合并」
  • 原文地址:https://www.cnblogs.com/huty/p/8517718.html
Copyright © 2020-2023  润新知