#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是一个相当复杂的库,包括流媒体的传输等操作;下次单独讲解;