live555源碼簡介

live555開發庫源代碼包括6個部分:UsageEnviromentBasicUsageEnviromentgroupsockliveMediatestProgsmediaServerhtml

UsageEnviroment

UsageEnviroment目錄中聲明一些虛類class UsageEnviromentclass HashTableclass TaskScheduler,這些類中包括各類純虛函數,這些虛函數定義出這些類的總體輪廓。這些類的某些子類,若是想要實例化的,必須描繪出這些輪廓,即實現這些函數。服務器

class UsageEnviroment是程序運行環境的抽象描述,經過包含TaskScheduler& fScheduler的私有變量,表示網絡功能、異步事件處理等。網絡

class TaskScheduler是定義如何設置RTSPServer端的網絡功能、異步事件處理。session

class HashTable是定義相似於字典的功能。異步

BasicUsageEnviroment

BasicUsageEnviroment目錄中,主要是對UsageEnviroment目錄中的class UsageEnviromentclass TaskScheduler各個部分的逐步實現,在實現的過程當中逐步引入相應的成員數據。socket

groupsock

groupsock目錄主要是對基本的socket封裝,在liveMedia目錄中涉及網絡的部分會有使用。函數

liveMedia

liveMeida目錄是整個live555開發庫的核心部分。oop

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的管理。this

#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協議介紹

相關文章
相關標籤/搜索