关闭

庖丁解牛-----Live555源码彻底解密(v0.78--2013.09.18)

1457人阅读 评论(0) 收藏 举报
分类:

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

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:804229次
    • 积分:12158
    • 等级:
    • 排名:第1178名
    • 原创:377篇
    • 转载:76篇
    • 译文:15篇
    • 评论:358条
    联系方式
    QQ:158---121----7277 欢迎大家发邮件交流,相互学习!邮件发到这个QQ邮箱!
    博客专栏
    最新评论