live555源码简介

live555开发库源代码包括6个部分:UsageEnviromentBasicUsageEnviromentgroupsockliveMediatestProgsmediaServer

UsageEnviroment

UsageEnviroment目录中声明一些虚类class UsageEnviromentclass HashTableclass TaskScheduler,这些类中包括各种纯虚函数,这些虚函数定义出这些类的整体轮廓。这些类的某些子类,如果想要实例化的,必须描绘出这些轮廓,即实现这些函数。

class UsageEnviroment是程序运行环境的抽象描述,通过包含TaskScheduler& fScheduler的私有变量,表示网络功能、异步事件处理等。

class TaskScheduler是定义如何设置RTSPServer端的网络功能、异步事件处理。

class HashTable是定义类似于字典的功能。

BasicUsageEnviroment

BasicUsageEnviroment目录中,主要是对UsageEnviroment目录中的class UsageEnviromentclass TaskScheduler各个部分的逐步实现,在实现的过程中逐步引入相应的成员数据。

groupsock

groupsock目录主要是对基本的socket封装,在liveMedia目录中涉及网络的部分会有使用。

liveMedia

liveMeida目录是整个live555开发库的核心部分。

class Medim class _Tables class MediaLookupTable

class Medimclass _TablesMedia.hh文件中定义,在Media.cpp文件中实现,class MediaLookupTableMedia.cpp文件中定义和实现。

liveMeida目录中最基础的类是class MediumliveMedia目录下很多class类型都是class Media的子类。class _Tablesclass MediaLookupTable主要是实现对Medium的管理。

#define mediumNameMaxLen 30

class Medium {
public:
  static Boolean lookupByName(UsageEnvironment& env,
                  char const* mediumName,
                  Medium*& resultMedium);
  static void close(UsageEnvironment& env, char const* mediumName);
  static void close(Medium* medium); // alternative close() method using ptrs
      // (has no effect if medium == NULL)

  UsageEnvironment& envir() const {return fEnviron;}

  char const* name() const {return fMediumName;}

  // Test for specific types of media:
  virtual Boolean isSource() const;
  virtual Boolean isSink() const;
  virtual Boolean isRTCPInstance() const;
  virtual Boolean isRTSPClient() const;
  virtual Boolean isRTSPServer() const;
  virtual Boolean isMediaSession() const;
  virtual Boolean isServerMediaSession() const;

protected:
  friend class MediaLookupTable;
  Medium(UsageEnvironment& env); // abstract base class
  virtual ~Medium(); // instances are deleted using close() only

  TaskToken& nextTask() {
    return fNextTask;
  }

private:
  UsageEnvironment& fEnviron;
  char fMediumName[mediumNameMaxLen];
  TaskToken fNextTask;
};


// A data structure for looking up a Medium by its string name.
// (It is used only to implement "Medium", but we make it visible here, in case developers want to use it to iterate over
//  the whole set of "Medium" objects that we've created.)
class MediaLookupTable {
public:
  static MediaLookupTable* ourMedia(UsageEnvironment& env);
  HashTable const& getTable() { return *fTable; }

protected:
  MediaLookupTable(UsageEnvironment& env);
  virtual ~MediaLookupTable();

private:
  friend class Medium;

  Medium* lookup(char const* name) const;
  // Returns NULL if none already exists

  void addNew(Medium* medium, char* mediumName);
  void remove(char const* name);

  void generateNewName(char* mediumName, unsigned maxLen);

private:
  UsageEnvironment& fEnv;
  HashTable* fTable;
  unsigned fNameGenerator;
};


// The structure pointed to by the "liveMediaPriv" UsageEnvironment field:
class _Tables {
public:
  static _Tables* getOurTables(UsageEnvironment& env, Boolean createIfNotPresent = True);
      // returns a pointer to a "_Tables" structure (creating it if necessary)
  void reclaimIfPossible();
      // used to delete ourselves when we're no longer used

  MediaLookupTable* mediaTable;
  void* socketTable;

protected:
  _Tables(UsageEnvironment& env);
  virtual ~_Tables();

private:
  UsageEnvironment& fEnv;
};

class Medium 某种媒体
class _Tables 查找表,包括void *mediaTableclass MediaLookupTable类型
class MedaLookupTable 通过HashTabel实现的Medium的查找表,包括所有在UsageEnviroment中创建的Medium实体。

上面三种类型是通过class UsageEnviroment类型中的void *liveMediaPriv成员变量联系起来。其中liveMediaPriv实际上是_Tables*类型,而在_Tables类型中有void *mediaTable成员变量,mediaTableMediaLookupTable*类型的。如果我们知道UsageEnviroment& env,给出key值,即Medium的名称,我们就可以查找相关的Medium

class RTSPServer class RTSPServer::class RTSPClientSession

class RTSPServerclass Medium的子类,是对RTSPServer的抽象描述。RTSPServer主要功能包括:

[ 1 ] RTSPServer可以接收客户端TCP连接请求,在接收客户端TCP连接请求后会创建class RTSPServer::class RTSPClientSession类。class RTSPClientSession是真正负责与客户端进行RTSP消息的接收、解包、打包、发送,是RTSP协议在RTSPServer端的具体实现。

接收客户端请求的socket和端口号,在创建RTSPServer实例时,会调用如下接口:

static int setUpOurSocket(UsageEnvironment& env, Port& ourPort);

创建RTSPServer端的非阻塞的监听socket,并且调用listen,监听网络数据。如果后续有请求消息到达,RTSPServer进行处理。这里需要特别提出RTSPServer处理网络数据采用的是Select模型。例如,在创建RTSPServer实例时源代码如下:

RTSPServer::RTSPServer(UsageEnvironment& env,  
                   int ourSocket, Port ourPort,  
                   UserAuthenticationDatabase* authDatabase,  
                   unsigned reclamationTestSeconds)  
: Medium(env),  
        fRTSPServerSocket(ourSocket), fRTSPServerPort(ourPort),  
        fHTTPServerSocket(-1), fHTTPServerPort(0), fClientSessionsForHTTPTunneling(NULL),  
        fAuthDB(authDatabase), fReclamationTestSeconds(reclamationTestSeconds),  
        fServerMediaSessions(HashTable::create(STRING_HASH_KEYS)) {  
    #ifdef USE_SIGNALS  
      // Ignore the SIGPIPE signal, so that clients on the same host that are killed  
      // don't also kill us:  
      signal(SIGPIPE, SIG_IGN);  
    #endif  
      
      // Arrange to handle connections from others:  
      env.taskScheduler().turnOnBackgroundReadHandling(fRTSPServerSocket,  
                               (TaskScheduler::BackgroundHandlerProc*)&incomingConnectionHandlerRTSP, this);  
}

通过调用TaskScheduler::turnOnBackgroundReadHandling(),开启监听SOCKET fRTSOServerSocketREAD功能,设置回调函数。

static void incomingConnectionHandlerRTSP(void*, int /*mask*/);        //RTSPServer接收到

TaskScheduler::doEventLoop( )循环中

void BasicTaskScheduler0::doEventLoop(char* watchVariable) {  
    // Repeatedly loop, handling readble sockets and timed events:  
    while (1) {  
        if (watchVariable != NULL && *watchVariable != 0) break;  
        SingleStep();  
    }  
}

会调用TaskScheduler::SingleStep()函数,在SingleStep()函数中,我们会处理网络数据的发送和接收(Select模型)、异步事件的处理、触发事件的处理。在TaskScheduler::SingleStep()函数中调用Select函数,发现监听SOCKET fRTSOServerSocket有数据需要去读,会调用如下接口:

static void incomingConnectionHandlerRTSP(void*, int /*mask*/);        //RTSPServer接收到</pre>

调用accept()函数,创建RTSPServer端与特定的Client通信的socket,获取Client的地址,之后实例化class RTSPServer::class RTSPClientSession

RTSPServer::RTSPClientSession  
    ::RTSPClientSession(RTSPServer& ourServer, unsigned sessionId, int clientSocket, struct sockaddr_in clientAddr)  
      : fOurServer(ourServer), fOurSessionId(sessionId),  
        fOurServerMediaSession(NULL),  
        fClientInputSocket(clientSocket), fClientOutputSocket(clientSocket), fClientAddr(clientAddr),  
        fSessionCookie(NULL), fLivenessCheckTask(NULL),  
        fIsMulticast(False), fSessionIsActive(True), fStreamAfterSETUP(False),  
        fTCPStreamIdCount(0), fNumStreamStates(0), fStreamStates(NULL) {  
      // Arrange to handle incoming requests:  
      resetRequestBuffer();                                                       
      envir().taskScheduler().turnOnBackgroundReadHandling(fClientInputSocket,  
         (TaskScheduler::BackgroundHandlerProc*)&incomingRequestHandler, this);  //打开int fClientInputSocket的READ功能,接收Client的RTSP消息,设置处理函数。  
      noteLiveness();  
}

赋值:

int fRTSPServerSocket;       //接收客户端TCP连接请求的SOCKET  
Port fRTSPServerPort;        //接收客户端TCP请求的端口

[ 2 ] 增加,查找,删除RTSPServer支持的ServerMediaSession集合。

void addServerMediaSession(ServerMediaSession* serverMediaSession);  
virtual ServerMediaSession* lookupServerMediaSession(char const* streamName);  
void removeServerMediaSession(ServerMediaSession* serverMediaSession);  
void removeServerMediaSession(char const* streamName);

ServerMediaSession集合的相关数据保存在HashTable中,在创建RTSPServernew HashTable

HashTable* fServerMediaSessions;          //服务器端ServerMediaSession的查找表,(Medium名称,指向ServerMediaSession的地址)

[ 3 ] 用户验证。

UserAuthenticationDatabase* fAuthDB

[ 4 ] TCP打洞。

实现在RTSPServer.hh源文件。

class RTSPServer::class RTSPClientSession是对RTSP协议在Server端的描述,主要功能是:接收客户端RTSP的Request消息、解析RTSP Request消息、封装Server端的RTSP Reply消息、发送Server端的RTSP Reply消息。

static void incomingRequestHandler(void*, int /*mask*/);   //class RTSPServer::class RTSPClientSession的整体工作流程。

参考资料

live555 media server文件播放与读内存播放

live555源码分析----SETUP命令处理流程
live555 接收rtsp视频流详细源码流程详细解析
live555源码分析—-RTP的打包与发送
live555库的rtsp服务器源码分析总结,流程详解RTSPServer - Crea
Live555源代码分析之RTSP服务器端1
live555源代码简介
live555源码分析
RTP与RTCP协议介绍