庖丁解牛-----Live555原始碼徹底解密(v0.78--2013.09.18)
#define LIVEMEDIA_LIBRARY_VERSION_STRING "2013.09.18"
live555中主要包括以下幾個庫:UsageEnvironment ,BasicUsageEnvironment,groupsock,LiveMedia;其中
UsageEnvironment包括抽象類UsageEnvironment和抽象類TaskScheduler,這兩個類用於事件排程,其中包括實現了對事件的非同步讀取、對事件控制代碼的設定及對錯誤資訊的輸出等;該庫中還有一個HashTable,這是一個通用的HashTable,在整個專案中都可以使用它,當然該HashTable也是一個抽象類。
BasicUsageEnvironment中的類主要是對UsageEnvironment中對應類的實現。
groupsock,顧名思義,用於資料包的接收和傳送,其同時支援多播和單播。groupsock庫中包括了GroupEId、Groupsock、GroupsockHelper、NetAddress、NetInterface等類,其中Groupsock類有兩個建構函式,一個是“for a source-independent multicast group”,另一個是“for a source-specific multicast group”;而GroupsockHelper類主要用於讀寫Socket。
liveMedia是很重要的一個庫,其不僅包含了實現RTSP Server的類,還包含了針對不同流媒體型別(如TS流、PS流等)編碼的類。在該庫中,基類是Medium,層次關係非常清晰。在該庫中,有幾個很重要的類,如RTSPServer、ServerMediaSession、RTPSink、RTPInterface、FramedSource等。
下面直接上原始碼:
class TaskScheduler; // forward
// An abstract base class, subclassed for each use of the library
class UsageEnvironment
public:
void reclaim();
// task scheduler:
TaskScheduler& taskScheduler() const {returnfScheduler;}
// result message handling:
typedef char const* MsgString;
virtual MsgString getResultMsg() const = 0;
virtual void setResultMsg(MsgStringmsg) = 0;
virtual void setResultMsg(MsgStringmsg1,MsgStringmsg2) = 0;
virtual void setResultMsg(MsgStringmsg1,MsgStringmsg2,MsgStringmsg3) = 0;
virtual void setResultErrMsg(MsgStringmsg,interr = 0) = 0;
// like setResultMsg(), except that an 'errno' message is appended. (If "err == 0", the "getErrno()" code is used instead.)
virtual void appendToResultMsg(MsgStringmsg) = 0;
virtual void reportBackgroundError() = 0;
// used to report a (previously set) error message within
// a background event
virtual void internalError(); // used to 'handle' a 'should not occur'-type error condition within the library.
// 'errno'
virtual int getErrno() const = 0;
// 'console' output:
virtual UsageEnvironment& operator<<(charconst*str) = 0;
virtual UsageEnvironment& operator<<(inti) = 0;
virtual UsageEnvironment& operator<<(unsignedu) = 0;
virtual UsageEnvironment& operator<<(doubled) = 0;
virtual UsageEnvironment& operator<<(void*p) = 0;
// a pointer to additional, optional, client-specific state
void* liveMediaPriv;
void* groupsockPriv;
protected:
UsageEnvironment(TaskScheduler&scheduler);// abstract base class
virtual ~UsageEnvironment();// we are deleted only by reclaim()
private:
TaskScheduler& fScheduler;
};
1.1)UsageEnvironment中包含TaskScheduler的引用,可以通過fScheduler呼叫TaskScheduler類中的函式;
private:
TaskScheduler& fScheduler;
UsageEnvironment類中的建構函式式保護的,TaskScheduler類中的建構函式是私有的;因為它們都是一個抽象的基類,不能生成物件,所以不需要呼叫建構函式;因為UsageEnvironment的建構函式是保護的,所以在派生類中可以呼叫該建構函式,比如在派生類的建構函式中就可以呼叫它。
UsageEnvironment類中有2個指標liveMediaPriv和groupsockPriv;
// a pointer to additional, optional, client-specific state
void* liveMediaPriv;
void* groupsockPriv;
1.2) BasicUsageEnvironment0類和BasicUsageEnvironment類
為什麼要增加中間的一層繼承類呢;BasicUsageEnvironment0中實現了setResultMsg等函式,而BasicUsageEnvironment中實現了'console' output,<<運算子過載;
class BasicTaskScheduler: public BasicTaskScheduler0 {
public:
static BasicTaskScheduler* createNew(unsignedmaxSchedulerGranularity = 10000/*microseconds*/);
// "maxSchedulerGranularity" (default value: 10 ms) specifies the maximum time that we wait (in "select()") before
// returning to the event loop to handle non-socket or non-timer-based events, such as 'triggered events'.
// You can change this is you wish (but only if you know what you're doing!), or set it to 0, to specify no such maximum time.
// (You should set it to 0 only if you know that you will not be using 'event triggers'.)
virtual ~BasicTaskScheduler();
protected:
BasicTaskScheduler(unsignedmaxSchedulerGranularity);
// called only by "createNew()"
static void schedulerTickTask(void*clientData);
void schedulerTickTask();
protected:
// Redefined virtual functions:
virtual void SingleStep(unsignedmaxDelayTime);
virtual void setBackgroundHandling(intsocketNum,intconditionSet,BackgroundHandlerProc*handlerProc,void*clientData);
virtual void moveSocketHandling(intoldSocketNum,intnewSocketNum);
protected:
unsigned fMaxSchedulerGranularity;
// To implement background operations:
int fMaxNumSockets;
fd_set fReadSet;
fd_set fWriteSet;
fd_set fExceptionSet;
};
BasicTaskScheduler中包含有讀寫sokcet的操作 int fMaxNumSockets; fReadSet,fWriteSet,fExceptionSet。
1) socket類(groupsock)的繼承關係圖如下:
Groupsock有一個讀的函式:
Boolean Groupsock::handleRead(unsignedchar*buffer,unsignedbufferMaxSize,
unsigned& bytesRead,
struct sockaddr_in& fromAddress) {
// Read data from the socket, and relay it across any attached tunnels
//##### later make this code more general - independent of tunnels
bytesRead = 0;
int maxBytesToRead = bufferMaxSize - TunnelEncapsulationTrailerMaxSize;
int numBytes = readSocket(env(),socketNum(),
buffer, maxBytesToRead, fromAddress);
if (numBytes < 0) {
if (DebugLevel >= 0) {// this is a fatal error
env().setResultMsg("Groupsock read failed: ",
env().getResultMsg());
}
return False;
}
// If we're a SSM group, make sure the source address matches:
if (isSSM()
&& fromAddress.sin_addr.s_addr !=sourceFilterAddress().s_addr) {
return True;
}
// We'll handle this data.
// Also write it (with the encapsulation trailer) to each member,
// unless the packet was originally sent by us to begin with.
bytesRead = numBytes;
int numMembers = 0;
if (!wasLoopedBackFromUs(env(),fromAddress)) {
statsIncoming.countPacket(numBytes);
statsGroupIncoming.countPacket(numBytes);
numMembers =
outputToAllMembersExcept(NULL,ttl(),
buffer, bytesRead,
fromAddress.sin_addr.s_addr);
if (numMembers > 0) {
statsRelayedIncoming.countPacket(numBytes);
statsGroupRelayedIncoming.countPacket(numBytes);
}
}
if (DebugLevel >= 3) {
env() << *this <<": read " <<bytesRead <<" bytes from " <<AddressString(fromAddress).val();
if (numMembers > 0) {
env() << "; relayed to " << numMembers << " members";
}
env() << "\n";
}
return True;
}
groupsock 支援tcp操作嗎?
4)LiveMedia
LiveMedia是一個相當複雜的庫,包括流媒體的傳輸等操作;下次單獨講解;