zoukankan      html  css  js  c++  java
  • vlc客户端rtsp播放live555的.264文件

         服务端只调用GenericMediaServer::ClientConnection类构造函数一次,在RTSPServer的基类GenericMediaServer的构造函数中,调用了turnOnBackgroundReadHandling并将其静态函数incomingConnectionHandler关联到fServerSocket。这样当有VLC客户端通过rtsp播放的时候,由于BasicTaskScheduler0::doEventLoop循环调用BasicTaskScheduler::SingleStep函数,执行刚刚关联的静态函数并继而调用同名函数进而调用GenericMediaServer::incomingConnectionHandlerOnSocket函数,在该函数中会调用createNewClientConnection函数。由于createNewClientConnection函数是GenericMediaServer类的虚函数,所以最终调用RTSPServerSupportingHTTPStreaming::createNewClientConnection函数创建RTSPServerSupportingHTTPStreaming::RTSPClientConnectionSupportingHTTPStreaming类对象,这个类继承自RTSPServer::RTSPClientConnection,而这个类又继承自GenericMediaServer::ClientConnection类。所以执行该构造函数一次。

          在GenericMediaServer::ClientConnection类的构造函数中,和GenericMediaServer构造函数中一样,将ClientConnection类的静态函数incomingRequestHandler关联给这个客户连接socket。这样当客户端发送rtsp消息后,服务端就可以通过该静态函数作为响应入口来响应。该静态函数会调用同名函数即GenericMediaServer::ClientConnection::incomingRequestHandler,在该函数中先读取客户端发来的rtsp消息,然后调用handleRequestBytes函数响应,该函数为虚函数,实际调用的是RTSPServer::RTSPClientConnection::handleRequestBytes。

          当用vlc来请求一个Live555的264文件时,如果能正常播放则流程如下。其中在Live555服务端共调用RTSPServer::RTSPClientSession类构造函数一次,是在RTSPServer::RTSPClientConnection::handleRequestBytes函数中处理客户端发来的"Setup"消息的过程中,然后调用RTSPServer::RTSPClientSession::handleCmd_SETUP函数。在响应"Setup"消息过程中创建RTSPServer::RTSPClientSession对象,调用GenericMediaServer::createNewClientSessionWithId函数,在该 函数中首先生成一个随机值,然后以该随机值作为参数调用虚函数createNewClientSession,即执行RTSPServer::createNewClientSession来创建RTSPServer::RTSPClientSession对象。 

          其中在Live555服务端共调用ServerMediaSession类构造函数两次,第一次是在响应"Describe"消息的过程中,RTSPServer::RTSPClientConnection::handleCmd_DESCRIBE函数中首先调用GenericMediaServer::lookupServerMediaSession,该函数为虚函数所以会调用DynamicRTSPServer::lookupServerMediaSession函数,在该函数中首先用streamName作为参数调用基类的函数,如果没有找到就构造ServerMediaSession类对象并以streamName保存到基类的hash表fServerMediaSessions中,这样下次调用lookupServerMediaSession即可以查到。

          在DynamicRTSPServer::lookupServerMediaSession函数中调用同文件中的静态函数createNewSMS,该函数调用ServerMediaSession类的构造函数,然后调用H264VideoFileServerMediaSubsession::createNew创建对象并作为参数调用ServerMediaSession::addSubsession函数。 

          第二次调用ServerMediaSession类构造函数是在响应"Setup"消息的过程中,在创建了RTSPServer::RTSPClientSession对象后,调用该对象的handleCmd_SETUP函数,即RTSPServer::RTSPClientSession::handleCmd_SETUP函数中,同样首先调用GenericMediaServer::lookupServerMediaSession,由于在响应"Describe"消息已经创建了ServerMediaSession类对象,所以DynamicRTSPServer::lookupServerMediaSession函数中是可以获取到这个对象的,但是在该函数中首先将之前的这个ServerMediaSession类对象移除,然后再调用静态函数createNewSMS,同在处理"Describe"消息中的流程一样,最终会调用ServerMediaSession类构造函数并保存到基类GenericMediaServer的hash表fServerMediaSessions中。之所以要先删除再添加的注释为"Remove the existing "ServerMediaSession" and create a new one, in case the underlying file has changed in some way"。

          这第二次调用ServerMediaSession类构造函数产生的对象在RTSPServer::RTSPClientSession::handleCmd_SETUP函数中赋值给RTSPServer::RTSPClientSession的基类GenericMediaServer::ClientSession中的成员ServerMediaSession* fOurServerMediaSession;而且注释为"We're accessing the "ServerMediaSession" for the first time."。然后根据ServerMediaSession对象包含的ServerMediaSubsession对象个数fSubsessionCounter来初始化RTSPServer::RTSPClientSession类的成员变量fStreamStates。这是一个指针对象,指向一个结构体数组,其中数组的每个元素代表一个子会话即ServerMediaSubsession对象。然后又会调用getStreamParameters,又因为该函数为虚函数,所以执行OnDemandServerMediaSubsession::getStreamParameters,该函数中首先创建继承自FramedSource类的H264VideoStreamFramer对象,然后又创建继承自RTPSink类的H264VideoRTPSink对象,然后以这两个对象创建StreamState对象来作为RTSPServer::RTSPClientSession类的成员fStreamStates所指的数组中子session的关联的void* streamToken;。然后将目的地址保存在子session的成员变量中,即OnDemandServerMediaSubsession类中的保护成员HashTable* fDestinationsHashTable;中。 

         下图所示为一次正常的客户端申请播放264视频所交互的rtsp消息及部分类的继承关系:

      

  • 相关阅读:
    强大的Resharp插件
    配置SPARK 2.3.0 默认使用 PYTHON3
    python3 数据库操作
    python3 学习中的遇到一些难点
    log4j的一个模板分析
    MYSQL内连接,外连接,左连接,右连接
    rabbitmq实战记录
    领域模型分析
    分布式系统学习笔记
    阿里开发规范 注意事项
  • 原文地址:https://www.cnblogs.com/wongdu2014/p/6204106.html
Copyright © 2011-2022 走看看