前面几篇文章分析了 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; // forwardclass 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 servervirtual void handleCmd_SET_PARAMETER(char const* fullRequestStr); // when operating on the entire servervirtual 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 tunnelingstatic 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 ::fOurServerint& fClientInputSocket; // aliased to ::fOurSocketint fClientOutputSocket;Boolean fIsActive;unsigned char* fLastCRLF;unsigned fRecursionCount;char const* fCurrentCSeq;Authenticator fCurrentAuthenticator; // used if access control is neededchar* fOurSessionCookie; // used for optional RTSP-over-HTTP tunnelingunsigned 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 WindowsGenericMediaServer& 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 ::fOurServerBoolean fIsMulticast, fStreamAfterSETUP;unsigned char fTCPStreamIdCount; // used for (optional) RTP/TCPBoolean 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 组件结构

live555 源码分析:RTSPServer 组件结构相关推荐

  1. live555源码分析(四)RTSPServer分析

    live555源码分析系列 live555源码分析(一)live555初体验 live555源码分析(二)基本组件上 live555源码分析(三)基本组件下 live555源码分析(四)RTSPSer ...

  2. live555 源码分析:RTSPServer

    live555 使用 RTSP/RTP/RTCP 协议来实现流媒体的传输,其中使用 RTSP 来建立流媒体会话,并对流媒体会话进行控制.在 live555 中,通过类 RTSPServerSuppor ...

  3. live555 源码分析:播放启动

    本文分析 live555 中,流媒体播放启动,数据开始通过 RTP/RTCP 传输的过程. 如我们在 live555 源码分析:子会话 SETUP 中看到的,一个流媒体子会话的播放启动,由 Strea ...

  4. live555 源码分析:子会话 SDP 行生成

    如我们在前文 live555 源码分析:ServerMediaSession 中看到的,H264VideoFileServerMediaSubsession 的继承层次体系如下图: 在这个继承层次体系 ...

  5. live555 源码分析:ServerMediaSession

    在 live555 中,用一个 ServerMediaSession 表示流媒体会话,它连接了 RTSPServer 和下层流媒体传输逻辑.ServerMediaSession 和 ServerMed ...

  6. live555 源码分析: SETUP 的处理

    SETUP 请求在 RTSP 的整个工作流程中,用于建立流媒体会话.本文分析 live555 对 SETUP 请求的处理. 在 RTSPServer::RTSPClientConnection::ha ...

  7. live555 源码分析: DESCRIBE 的处理

    前面在 live555 源码分析:RTSPServer 中分析了 live555 中处理 RTSP 请求的大体流程,并分析了处理起来没有那么复杂的一些方法,如 OPTIONS,GET_PARAMETE ...

  8. live555源码分析(一)live555初体验

    live555源码分析系列 live555源码分析(一)live555初体验 live555源码分析(二)基本组件上 live555源码分析(三)基本组件下 live555源码分析(四)RTSPSer ...

  9. live555 源码分析: PLAY 的处理

    在 SETUP 请求之后,客户端会发起 PLAY 请求,以请求服务器开始传输音视频数据.在 PLAY 请求执行时,一定是已经执行过 SETUP 请求,建立好了客户端会话,因而会与其它要求客户端会话已经 ...

最新文章

  1. 在R中子集化数据框的5种方法
  2. 与跨国巨头合作,做羊还是做狼? --- 我看SAP取消HAND合作伙伴资格
  3. 开发者进阶之路 |UIBPlayer (视频播放)demo分享
  4. Java实现二叉树的创建、递归/非递归遍历
  5. nginx+web.py+fastcgi(spawn-fcgi)的session失效問題
  6. java 数组合并_数组与链表
  7. SQLSERVER对加密的存储过程、视图、触发器进行解密
  8. 2019年春季第七周 编程总结
  9. C 线程同步的四种方式(Linux)
  10. Swift学习几天就会写项目
  11. 程序员能考哪些证书?这个几个不能少
  12. 小区报修管理系统c语言,小区物业报修管理系统的设计与实现.pdf
  13. JAVACC使用总结(四):LOOKAHEAD解决语法选择冲突的利刃
  14. java提取富文本文字_富文本中文字部分提取
  15. 蓝牙sbc怎么解决_蓝牙耳机不会挑?蓝牙编解码器了解一下
  16. 记录一次对学校考试系统的漏洞挖掘
  17. 新用户注册之验证码短信、语音解决方案
  18. Sentinel Dubbo 适配器看限流与熔断(实战思考篇)
  19. Perl特殊变量(flw等翻译)
  20. 关于Linux中的docker-compose.yml配置文件

热门文章

  1. 初始化方法-使用参数设置属性初始值
  2. 64位计算机安装32位,64位电脑装32位系统,小编教你64位电脑怎么装32位系统
  3. 华为云DevCloud重金悬赏,开发者大赛等你来战!
  4. jQuery Css方法
  5. 4.19. 在线用户表
  6. 洗礼灵魂,修炼python(54)--爬虫篇—urllib2模块
  7. Ixia张林辉:测试系统让SDN更“迷人”
  8. 使用git推送代码到开源中国以及IDEA环境下使用git
  9. CodeSmith 基础用法和例子
  10. 第一个冲刺期的第九天