zoukankan      html  css  js  c++  java
  • 2012.02.13(rtsp)

    RTSP:Read network & Netscape共同提出的如何有效的在IP网路上传输流媒体数据的应用协议。

    RTSP建立并控制一个或几个时间同步的连续流媒体,如音频和视频。

    按需传送,提供了选择发送通道(UDP,组播UDP与TCP),并提供基于RTP的发送机制方法。RTSP控制的流可能用到RTP.

    RTSP中客户端和服务器口可以发送请求。

    RTSP是一种文本协议,采用UTF-8编码中的ISO 10646字符集。

    RTSP的消息有两大类:请求消息,回应消息:

    请求消息:

    简单的rtsp交互过程:

    C表示rtsp客户端;S表示rtsp服务器端:

    1、C->S:OPTION request;//询问s有哪些方法可用

    BOOL RtspRequest::RequestOptions()
    {
     if (m_State < stateConnected)
      return FALSE;

     SendRequest("OPTIONS");

     printf("\n");

     if ( !GetResponses() )
      return FALSE;

     return TRUE;
    }

    1、S->C:OPTION response;//S回应信息中包括提供的所有可用方法

    void RtspResponse::ResponseOptions()
    {
     AddField("Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE");
     SendResponse("");

     printf("\n");
    }

    2、C->S:DESCRIBE request//要求得到S提供的媒体初始化描叙信息

    BOOL RtspRequest::GetDescribe(string* pDescribe)
    {
     BYTE* pDescribeBuffer = NULL;
     int describeSize;
     string describe;
     string searchField;

     if ( !SearchResponses(&searchField, "Content-Length") )
      return FALSE;

     describeSize = atoi( searchField.c_str() );
     pDescribeBuffer = new BYTE[describeSize + 1];
     if (!pDescribeBuffer)
      return FALSE;
     memset(pDescribeBuffer, 0, describeSize);

     describeSize = Tcp::Read(pDescribeBuffer, describeSize);
     if (describeSize != describeSize)
     {
      delete []pDescribeBuffer;
      return FALSE;
     }
     pDescribeBuffer[describeSize] = '\0';

     *pDescribe = (char*)pDescribeBuffer;

     delete []pDescribeBuffer;

     printf("%s\n\n", pDescribe->c_str());

     return TRUE;
    }

    2、S->C:DESCRIBE response//S回应媒体初始化描叙信息,主要是sdp

    void RtspResponse::ResponseDescribe(PCSTR sdp, UINT sdpLength)
    {
     string contentBase;
     string contentType;
     string contentLength;
     string server;

     char temp[20];
     string requestMrl;

     server = "Server: RTSP Service";
     
     contentType = "Content-Type: application/sdp";

     _snprintf(temp, 20, "%lu", sdpLength);
     contentLength = "Content-Length: ";
     contentLength += temp;

     GetRequestMrl(&requestMrl);
     contentBase = "Content-Base: ";
     contentBase += requestMrl;

     AddField(server);
     AddField(contentBase);
     AddField(contentType);
     AddField(contentLength);
     SendResponse("");

     printf("\n");

     Tcp::Write((PBYTE)sdp, sdpLength);

     printf("Content:\n");
     printf(sdp);
     printf("\n\n");
    }

    3、C->S:SETUP request//设置会话的属性,以及传输模式,提醒S建立会话

    BOOL RtspRequest::RequestSetup(PCSTR setupName, INT transportMode, INT clientPort, INT clientRtcpPort, INT64* pSession)
    {
     if (m_State < stateConnected)
      return FALSE;

     string transportField;

     if (setupName == NULL)
      m_SetupName = "";
     else
      m_SetupName = setupName;

     if ( !GenerateTransportField(&transportField, transportMode, clientPort, clientRtcpPort) )
      return FALSE;

     AddField(transportField);
     SendRequest("SETUP");

     printf("\n");

     if ( !GetResponses() )
      return FALSE;

     m_State = stateReady;

     if (pSession)
      *pSession = m_Session;

     return TRUE;
    }

    3、S->C:SETUP response//S建立会话,返回会话标识符,以及会话相关信息

    void RtspResponse::ResponseSetup( PCSTR serverIp, INT serverRtpPort,
             PCSTR targetIp, INT targetRtpPort,
             INT32 ssrc)
    {
     string transport;
     string client_port;
     string server_port;
     string ssrc_;
     char temp[100];

     if (!m_Session)
      m_Session = GenerateOneNumber();

     _snprintf(temp, 100, "server_port=%u-%u", serverRtpPort, serverRtpPort+1);
     server_port = temp;

     _snprintf(temp, 100, "client_port=%u-%u", targetRtpPort, targetRtpPort+1);
     client_port = temp;

     _snprintf(temp, 100, "ssrc=%u", ssrc);
     ssrc_ = temp;

     transport += "Transport: RTP/AVP;unicast;";
     transport += "source=";
     transport += serverIp;
     transport += ';';
     transport += server_port;
     transport += ';';
     transport += client_port;
     transport += ';';
     transport += ssrc_;
      
     AddField(transport);
     SendResponse("");

     printf("\n");
    }

    4、C->S:PLAY request//C请求播放

    BOOL RtspRequest::RequestPlay()
    {
     if (m_State < stateReady)
      return FALSE;

     SendRequest("PLAY");

     printf("\n");

     if ( !GetResponses() )
      return FALSE;
     
     m_State = statePlaying;

     return TRUE;
    }

    4、S->C:PLAY request//S回应请求信息

    void RtspResponse::ResponsePlay(PCSTR setupUrl)
    {
     string rtpinfo = "RTP-Info: ";
     rtpinfo += setupUrl;

     //string range = "Range: npt=now-";
     //AddField(range);
     AddField(rtpinfo);
     SendResponse("");

     printf("\n");
    }

    S->C:发送流媒体数据

    5、C->S:TEARDOWN request//C 请求关闭会话

    BOOL RtspRequest::RequestTeardown()
    {
     if (m_State < stateConnected)
      return FALSE;

     SendRequest("TEARDOWN");

     printf("\n");

     if ( !GetResponses() )
      return FALSE;

     m_State = stateInit;

     return TRUE;
    }

    5、S->C:TEARDOWN response//S回应请求

    void RtspResponse::ResponseTeardown()
    {
     AddField("Connection: Close");
     SendResponse("");

     printf("\n");
    }

    上面的过程是标准的,友好的rtsp流程。其中3、4步时必须的;

     1、OPTION

    目的是得到服务器提供的可用方法:

    OPTION rtsp://192.168.20.136:5000/xxx666 RTSP/1.0

    CSeq:1 //每个消息都有序号来标记,第一个包通常是option请求消息

  • 相关阅读:
    我再说一遍-微软官方文档查询技巧分享
    你听我说-HandyControl多语言包处理
    太阳当空照-Windows服务化方式脚本封装sc指令
    你听我说-HandyControl源码编译
    太阳当空照-知识分享
    Mac多屏dock切换
    [转]浅析线性表(链表)的头插法和尾插法的区别及优缺点
    点击按钮,在textarea光标位置插入值
    优秀学习笔记汇总>o<
    解决excel文件上传时更改选中的文件出现错误net::ERR_UPLOAD_FILE_CHANGED
  • 原文地址:https://www.cnblogs.com/itxiaocaiyidie/p/2348653.html
Copyright © 2011-2022 走看看