live555
開發庫源代碼包括6個部分:UsageEnviroment
、BasicUsageEnviroment
、groupsock
、liveMedia
、testProgs
、mediaServer
。html
UsageEnviroment
目錄中聲明一些虛類class UsageEnviroment
、class HashTable
、class TaskScheduler
,這些類中包括各類純虛函數,這些虛函數定義出這些類的總體輪廓。這些類的某些子類,若是想要實例化的,必須描繪出這些輪廓,即實現這些函數。服務器
class UsageEnviroment
是程序運行環境的抽象描述,經過包含TaskScheduler& fScheduler
的私有變量,表示網絡功能、異步事件處理等。網絡
class TaskScheduler
是定義如何設置RTSPServer
端的網絡功能、異步事件處理。session
class HashTable
是定義相似於字典的功能。異步
BasicUsageEnviroment
目錄中,主要是對UsageEnviroment
目錄中的class UsageEnviroment
、class TaskScheduler
各個部分的逐步實現,在實現的過程當中逐步引入相應的成員數據。socket
groupsock
目錄主要是對基本的socket
封裝,在liveMedia
目錄中涉及網絡的部分會有使用。函數
liveMeida
目錄是整個live555
開發庫的核心部分。oop
class Medim
,class _Tables
在Media.hh
文件中定義,在Media.cpp
文件中實現,class MediaLookupTable
在Media.cpp
文件中定義和實現。源碼分析
liveMeida
目錄中最基礎的類是class Medium
,liveMedia
目錄下不少class
類型都是class Media
的子類。class _Tables
和class 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 *mediaTable
,class MediaLookupTable
類型class MedaLookupTable
經過HashTabel
實現的Medium
的查找表,包括全部在UsageEnviroment
中建立的Medium
實體。
上面三種類型是經過class UsageEnviroment
類型中的void *liveMediaPriv
成員變量聯繫起來。其中liveMediaPriv
其實是_Tables*
類型,而在_Tables
類型中有void *mediaTable
成員變量,mediaTable
是MediaLookupTable*
類型的。若是咱們知道UsageEnviroment& env
,給出key
值,即Medium
的名稱,咱們就能夠查找相關的Medium
。
class RTSPServer
是class 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 fRTSOServerSocket
的READ
功能,設置回調函數。
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
中,在建立RTSPServer
時new 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協議介紹