文档章节

live555 源码分析:RTSPServer 组件结构

WolfCS
 WolfCS
发布于 2017/09/06 15:51
字数 1427
阅读 31
收藏 0
点赞 0
评论 0

前面几篇文章分析了 live555 中 RTSP 的处理逻辑,RTSP 处理有关组件的处理逻辑有点复杂,本文就再来梳理一下它们之间的关系。

live555 中 RTSP 处理有关组件关系如下图:

事件和执行流程的源头在 TaskSchedulerGenericMediaServer 对象在创建的时候,会向 TaskScheduler 注册一个 server socket 及处理该 socket 上的事件的处理程序 GenericMediaServer::incomingConnectionHandler(void* instance, int /*mask*/)

当有客户端连接服务器时,触发 server socket 上的事件处理器执行。此时会基于客户端 socket 创建 ClientConnection 对象,及 RTSPClientConnectionRTSPClientConnection 对象在创建过程中,会将该客户端 socket 及 ClientConnection 中处理该 socket 上的事件的处理程序 GenericMediaServer::ClientConnection::incomingRequestHandler(void* instance, int /*mask*/) 注册给 TaskScheduler

在客户端发送的 RTSP 请求数据到达之后,GenericMediaServer::ClientConnection 会读取这些数据,并交给 RTSPServer::RTSPClientConnection::handleRequestBytes(int newBytesRead) 处理。

RTSPServer::RTSPClientConnection 解析 RTSP 请求,并处理 OPTIONSDESCRIBE 和 ``SETUP 等无需流媒体会话建立即可处理的请求。

RTSPServer::RTSPClientConnection 在处理 SETUP 请求时,会创建流媒体会话的 RTSPServer::RTSPClientSession,具体的会话建立过程都会被委托给后者处理。

需要会话建立之后才能处理的请求,也会被交给 RTSPServer::RTSPClientSession 处理。

这里来看一下 RTSPServer::RTSPClientConnection 的完整定义:

class RTSPServer: public GenericMediaServer {
. . . . . .
public: // should be protected, but some old compilers complain otherwise
  // The state of a TCP connection used by a RTSP client:
  class RTSPClientSession; // forward
  class RTSPClientConnection: public GenericMediaServer::ClientConnection {
  public:
    // A data structure that's used to implement the "REGISTER" command:
    class ParamsForREGISTER {
    public:
      ParamsForREGISTER(char const* cmd/*"REGISTER" or "DEREGISTER"*/,
			RTSPClientConnection* ourConnection, char const* url, char const* urlSuffix,
			Boolean reuseConnection, Boolean deliverViaTCP, char const* proxyURLSuffix);
      virtual ~ParamsForREGISTER();
    private:
      friend class RTSPClientConnection;
      char const* fCmd;
      RTSPClientConnection* fOurConnection;
      char* fURL;
      char* fURLSuffix;
      Boolean fReuseConnection, fDeliverViaTCP;
      char* fProxyURLSuffix;
    };
  protected: // redefined virtual functions:
    virtual void handleRequestBytes(int newBytesRead);

  protected:
    RTSPClientConnection(RTSPServer& ourServer, int clientSocket, struct sockaddr_in clientAddr);
    virtual ~RTSPClientConnection();

    friend class RTSPServer;
    friend class RTSPClientSession;

    // Make the handler functions for each command virtual, to allow subclasses to reimplement them, if necessary:
    virtual void handleCmd_OPTIONS();
        // You probably won't need to subclass/reimplement this function; reimplement "RTSPServer::allowedCommandNames()" instead.
    virtual void handleCmd_GET_PARAMETER(char const* fullRequestStr); // when operating on the entire server
    virtual void handleCmd_SET_PARAMETER(char const* fullRequestStr); // when operating on the entire server
    virtual void handleCmd_DESCRIBE(char const* urlPreSuffix, char const* urlSuffix, char const* fullRequestStr);
    virtual void handleCmd_REGISTER(char const* cmd/*"REGISTER" or "DEREGISTER"*/,
				    char const* url, char const* urlSuffix, char const* fullRequestStr,
				    Boolean reuseConnection, Boolean deliverViaTCP, char const* proxyURLSuffix);
        // You probably won't need to subclass/reimplement this function;
        //     reimplement "RTSPServer::weImplementREGISTER()" and "RTSPServer::implementCmd_REGISTER()" instead.
    virtual void handleCmd_bad();
    virtual void handleCmd_notSupported();
    virtual void handleCmd_notFound();
    virtual void handleCmd_sessionNotFound();
    virtual void handleCmd_unsupportedTransport();
    // Support for optional RTSP-over-HTTP tunneling:
    virtual Boolean parseHTTPRequestString(char* resultCmdName, unsigned resultCmdNameMaxSize,
					   char* urlSuffix, unsigned urlSuffixMaxSize,
					   char* sessionCookie, unsigned sessionCookieMaxSize,
					   char* acceptStr, unsigned acceptStrMaxSize);
    virtual void handleHTTPCmd_notSupported();
    virtual void handleHTTPCmd_notFound();
    virtual void handleHTTPCmd_OPTIONS();
    virtual void handleHTTPCmd_TunnelingGET(char const* sessionCookie);
    virtual Boolean handleHTTPCmd_TunnelingPOST(char const* sessionCookie, unsigned char const* extraData, unsigned extraDataSize);
    virtual void handleHTTPCmd_StreamingGET(char const* urlSuffix, char const* fullRequestStr);
  protected:
    void resetRequestBuffer();
    void closeSocketsRTSP();
    static void handleAlternativeRequestByte(void*, u_int8_t requestByte);
    void handleAlternativeRequestByte1(u_int8_t requestByte);
    Boolean authenticationOK(char const* cmdName, char const* urlSuffix, char const* fullRequestStr);
    void changeClientInputSocket(int newSocketNum, unsigned char const* extraData, unsigned extraDataSize);
      // used to implement RTSP-over-HTTP tunneling
    static void continueHandlingREGISTER(ParamsForREGISTER* params);
    virtual void continueHandlingREGISTER1(ParamsForREGISTER* params);

    // Shortcuts for setting up a RTSP response (prior to sending it):
    void setRTSPResponse(char const* responseStr);
    void setRTSPResponse(char const* responseStr, u_int32_t sessionId);
    void setRTSPResponse(char const* responseStr, char const* contentStr);
    void setRTSPResponse(char const* responseStr, u_int32_t sessionId, char const* contentStr);

    RTSPServer& fOurRTSPServer; // same as ::fOurServer
    int& fClientInputSocket; // aliased to ::fOurSocket
    int fClientOutputSocket;
    Boolean fIsActive;
    unsigned char* fLastCRLF;
    unsigned fRecursionCount;
    char const* fCurrentCSeq;
    Authenticator fCurrentAuthenticator; // used if access control is needed
    char* fOurSessionCookie; // used for optional RTSP-over-HTTP tunneling
    unsigned fBase64RemainderCount; // used for optional RTSP-over-HTTP tunneling (possible values: 0,1,2,3)
  };

RTSPServer::RTSPClientConnection 继承自 GenericMediaServer::ClientConnection

class GenericMediaServer: public Medium {
. . . . . .
public: // should be protected, but some old compilers complain otherwise
  // The state of a TCP connection used by a client:
  class ClientConnection {
  protected:
    ClientConnection(GenericMediaServer& ourServer, int clientSocket, struct sockaddr_in clientAddr);
    virtual ~ClientConnection();

    UsageEnvironment& envir() { return fOurServer.envir(); }
    void closeSockets();

    static void incomingRequestHandler(void*, int /*mask*/);
    void incomingRequestHandler();
    virtual void handleRequestBytes(int newBytesRead) = 0;
    void resetRequestBuffer();

  protected:
    friend class GenericMediaServer;
    friend class ClientSession;
    friend class RTSPServer; // needed to make some broken Windows compilers work; remove this in the future when we end support for Windows
    GenericMediaServer& fOurServer;
    int fOurSocket;
    struct sockaddr_in fClientAddr;
    unsigned char fRequestBuffer[REQUEST_BUFFER_SIZE];
    unsigned char fResponseBuffer[RESPONSE_BUFFER_SIZE];
    unsigned fRequestBytesAlreadySeen, fRequestBufferBytesLeft;
  };

从它们的定义,不难理解它们的职责主要在于处理网络 I/O,处理 RTSP 请求,并建立会话。

再来看 RTSPServer::RTSPClientSession 的定义:

class RTSPServer: public GenericMediaServer {
. . . . . .
  // The state of an individual client session (using one or more sequential TCP connections) handled by a RTSP server:
  class RTSPClientSession: public GenericMediaServer::ClientSession {
  protected:
    RTSPClientSession(RTSPServer& ourServer, u_int32_t sessionId);
    virtual ~RTSPClientSession();

    friend class RTSPServer;
    friend class RTSPClientConnection;
    // Make the handler functions for each command virtual, to allow subclasses to redefine them:
    virtual void handleCmd_SETUP(RTSPClientConnection* ourClientConnection,
        char const* urlPreSuffix, char const* urlSuffix, char const* fullRequestStr);
    virtual void handleCmd_withinSession(RTSPClientConnection* ourClientConnection,
        char const* cmdName,
        char const* urlPreSuffix, char const* urlSuffix,
        char const* fullRequestStr);
    virtual void handleCmd_TEARDOWN(RTSPClientConnection* ourClientConnection,
        ServerMediaSubsession* subsession);
    virtual void handleCmd_PLAY(RTSPClientConnection* ourClientConnection,
        ServerMediaSubsession* subsession, char const* fullRequestStr);
    virtual void handleCmd_PAUSE(RTSPClientConnection* ourClientConnection,
        ServerMediaSubsession* subsession);
    virtual void handleCmd_GET_PARAMETER(RTSPClientConnection* ourClientConnection,
        ServerMediaSubsession* subsession, char const* fullRequestStr);
    virtual void handleCmd_SET_PARAMETER(RTSPClientConnection* ourClientConnection,
        ServerMediaSubsession* subsession, char const* fullRequestStr);
  protected:
    void deleteStreamByTrack(unsigned trackNum);
    void reclaimStreamStates();
    Boolean isMulticast() const { return fIsMulticast; }

    // Shortcuts for setting up a RTSP response (prior to sending it):
    void setRTSPResponse(RTSPClientConnection* ourClientConnection, char const* responseStr) { ourClientConnection->setRTSPResponse(responseStr); }
    void setRTSPResponse(RTSPClientConnection* ourClientConnection, char const* responseStr, u_int32_t sessionId) { ourClientConnection->setRTSPResponse(responseStr, sessionId); }
    void setRTSPResponse(RTSPClientConnection* ourClientConnection, char const* responseStr, char const* contentStr) { ourClientConnection->setRTSPResponse(responseStr, contentStr); }
    void setRTSPResponse(RTSPClientConnection* ourClientConnection, char const* responseStr, u_int32_t sessionId, char const* contentStr) { ourClientConnection->setRTSPResponse(responseStr, sessionId, contentStr); }

  protected:
    RTSPServer& fOurRTSPServer; // same as ::fOurServer
    Boolean fIsMulticast, fStreamAfterSETUP;
    unsigned char fTCPStreamIdCount; // used for (optional) RTP/TCP
    Boolean usesTCPTransport() const { return fTCPStreamIdCount > 0; }
    unsigned fNumStreamStates;
    struct streamState {
      ServerMediaSubsession* subsession;
      int tcpSocketNum;
      void* streamToken;
    } * fStreamStates;
  };

RTSPServer::RTSPClientSession 继承自 GenericMediaServer::ClientSession

  // The state of an individual client session (using one or more sequential TCP connections) handled by a server:
  class ClientSession {
  protected:
    ClientSession(GenericMediaServer& ourServer, u_int32_t sessionId);
    virtual ~ClientSession();

    UsageEnvironment& envir() { return fOurServer.envir(); }
    void noteLiveness();
    static void noteClientLiveness(ClientSession* clientSession);
    static void livenessTimeoutTask(ClientSession* clientSession);

  protected:
    friend class GenericMediaServer;
    friend class ClientConnection;
    GenericMediaServer& fOurServer;
    u_int32_t fOurSessionId;
    ServerMediaSession* fOurServerMediaSession;
    TaskToken fLivenessCheckTask;
  };

不难理解 RTSPServer::RTSPClientSession 用于封装整个流媒体会话,处理那些要求流媒体会话已经建立的 RTSP 请求,如 PLAY 等。

具体的流媒体数据的交互,如音视频文件/数据的解析,RTP/RTCP 数据的打包及收发等,则依赖于 ServerMediaSessionServerMediaSubsession

Done。

live555 源码分析系列文章

live555 源码分析:简介 live555 源码分析:基础设施 live555 源码分析:MediaSever Wireshark 抓包分析 RTSP/RTP/RTCP 基本工作过程 live555 源码分析:RTSPServer live555 源码分析:DESCRIBE 的处理 live555 源码分析:SETUP 的处理 live555 源码分析:PLAY 的处理 live555 源码分析:RTSPServer 组件结构

© 著作权归作者所有

共有 人打赏支持
WolfCS
粉丝 79
博文 146
码字总数 505099
作品 4
杭州
高级程序员
live555学习笔记16

十六 几个重要对象的生命期 live555中很多类,类与类之间的关系复杂,从属关系不明显,层次上看起来也有些乱.所以源代码读起来比较困难,对于一些对象生命的来龙去脉也很难厘清. 但这并不能...

晨曦之光 ⋅ 2012/03/12 ⋅ 0

Live555学习笔记14

十四:live555多线程论 江湖传闻:live555如果不改为多线程,在多核心机器上效率会降低. 虽然我没做过测试,但比较相信此传闻的真实性 . 所以在我试论述一下live555如何对多核进行支持,其实就是改...

晨曦之光 ⋅ 2012/03/12 ⋅ 0

live555:RTSP实现流程记录

1、 在创建RTSPServer的时候,会预先建议一个TCP监听,端口为创建RTSPServer时传入的值,创建位置 RTSPServer::createNew- setUpOurSocket 函数,setUpOurSocket函数中 进行listen 操作,并发...

jamin-snails ⋅ 2015/08/13 ⋅ 0

RTSP学习笔记(4)LiveMediaServer流程分析

Live555MediaServer 1、初始化 BasicTaskschedular BasicUsageEnvironment RTSPServer |--------new RTSPServer |------setupOurSocket创建监听客户端连接用的socket |------turnOnBackgroun......

Sean-x ⋅ 2016/02/23 ⋅ 0

live555 --- vs2010编译

最近想研究下live555,在ubuntu下编译并运行,虽然有cgdb可以进行源码调试,但总感觉调试时不够直观和简便,于是想在vs2010下编译。 从http://live555sourcecontrol.googlecode.com/svn/trun...

长平狐 ⋅ 2012/09/20 ⋅ 0

live555 学习笔记

从程序的结构来看,live项目包括了四个基本库、程序入口类(在mediaServer中)和一些测试代码(在testProgs中)。四个基本库是UsageEnvironment、BasicUsageEnvironment、groupsock和liveMed...

icerleer ⋅ 2013/04/10 ⋅ 0

基于Hi3516A的H265 IPC LIVE555 开发基本原理

转载于http://m.blog.csdn.net/faihung/article/details/73008742,如有侵权,请告知删除。 1 系统工作原理 系统以Hi3516A开发平台(由高分辨率1080 p的AR0330摄像头模块和带千兆以太网功能的...

oqqHuTu12345678 ⋅ 01/02 ⋅ 0

经过两个多月的攻关,终于搞定了live555多线程并稳定压测通过

live555已经发展了十几年了,不得不钦佩作者坚持不懈的奉献和国外的开源生态环境,live555可以说是大部分的安防从业者的入门之选,尤其是在嵌入式或者Linux系统上,其应用还是蛮广泛的,主要...

xiejiashu ⋅ 05/04 ⋅ 0

RTSP学习笔记(1)live555

1、UsageEnvironment UsageEnvironment代表了整个程序的运行环境,其中保存了一些全局变量,定义了一些输出函数(纯虚函数)。从这些输出函数就可以看出该类主要用于充当程序的全局上下文,并...

Sean-x ⋅ 2016/02/23 ⋅ 0

live555学习笔记15

十五:RTCPInstance类小结 RTCPInstance是对rtcp通信的封装.RTCP主要是功能是统计包的收发为流量控制提供依据.RTCPInstance统计数据的取得仅依赖于RTPSink的一些函数(因为RTPSink发送RTP...

晨曦之光 ⋅ 2012/03/12 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Centos7重置Mysql 8.0.1 root 密码

问题产生背景: 安装完 最新版的 mysql8.0.1后忘记了密码,向重置root密码;找了网上好多资料都不尽相同,根据自己的问题总结如下: 第一步:修改配置文件免密码登录mysql vim /etc/my.cnf 1...

豆花饭烧土豆 ⋅ 今天 ⋅ 0

熊掌号收录比例对于网站原创数据排名的影响[图]

从去年下半年开始,我在写博客了,因为我觉得业余写写博客也还是很不错的,但是从2017年下半年开始,百度已经推出了原创保护功能和熊掌号平台,为此,我也提交了不少以前的老数据,而这些历史...

原创小博客 ⋅ 今天 ⋅ 0

LVM讲解、磁盘故障小案例

LVM LVM就是动态卷管理,可以将多个硬盘和硬盘分区做成一个逻辑卷,并把这个逻辑卷作为一个整体来统一管理,动态对分区进行扩缩空间大小,安全快捷方便管理。 1.新建分区,更改类型为8e 即L...

蛋黄Yolks ⋅ 今天 ⋅ 0

Hadoop Yarn调度器的选择和使用

一、引言 Yarn在Hadoop的生态系统中担任了资源管理和任务调度的角色。在讨论其构造器之前先简单了解一下Yarn的架构。 上图是Yarn的基本架构,其中ResourceManager是整个架构的核心组件,它负...

p柯西 ⋅ 今天 ⋅ 0

uWSGI + Django @ Ubuntu

创建 Django App Project 创建后, 可以看到路径下有一个wsgi.py的问题 uWSGI运行 直接命令行运行 利用如下命令, 可直接访问 uwsgi --http :8080 --wsgi-file dj/wsgi.py 配置文件 & 运行 [u...

袁祾 ⋅ 今天 ⋅ 0

JVM堆的理解

在JVM中,我们经常提到的就是堆了,堆确实很重要,其实,除了堆之外,还有几个重要的模块,看下图: 大 多数情况下,我们并不需要关心JVM的底层,但是如果了解它的话,对于我们系统调优是非常...

不羁之后 ⋅ 昨天 ⋅ 0

推荐:并发情况下:Java HashMap 形成死循环的原因

在淘宝内网里看到同事发了贴说了一个CPU被100%的线上故障,并且这个事发生了很多次,原因是在Java语言在并发情况下使用HashMap造成Race Condition,从而导致死循环。这个事情我4、5年前也经历...

码代码的小司机 ⋅ 昨天 ⋅ 2

聊聊spring cloud gateway的RetryGatewayFilter

序 本文主要研究一下spring cloud gateway的RetryGatewayFilter GatewayAutoConfiguration spring-cloud-gateway-core-2.0.0.RC2-sources.jar!/org/springframework/cloud/gateway/config/G......

go4it ⋅ 昨天 ⋅ 0

创建新用户和授予MySQL中的权限教程

导读 MySQL是一个开源数据库管理软件,可帮助用户存储,组织和以后检索数据。 它有多种选项来授予特定用户在表和数据库中的细微的权限 - 本教程将简要介绍一些选项。 如何创建新用户 在MySQL...

问题终结者 ⋅ 昨天 ⋅ 0

android -------- 颜色的半透明效果配置

最近有朋友问我 Android 背景颜色的半透明效果配置,我网上看资料,总结了一下, 开发中也是常常遇到的,所以来写篇博客 常用的颜色值格式有: RGB ARGB RRGGBB AARRGGBB 这4种 透明度 透明度...

切切歆语 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部