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协议介绍