文章出自:http://blog.csdn.net/imliujie/archive/2008/01/30/2072657.aspx

live555源代码简介
liveMedia项目的源代码包括四个基本的库,各种测试代码以及IVE555 Media Server。

四个基本的库分别是UsageEnvironment&TaskScheduler,groupsock,liveMedia,BasicUsageEnvironment。

UsageEnvironment 和TaskScheduler类用于事件的调度,实现异步读取事件的句柄的设置以及错误信息的输出。另外,还有一个HashTable类定义了一个通用的 hash表,其它代码要用到这个表。这些都是抽象类,在应用程序中基于这些类实现自己的子类。

groupsock类是对网络接口的封装,用于收发数据包。正如名字本身,Groupsock主要是面向多播数据的收发的,它也同时支持单播数据的收发。Groupsock定义了两个构造函数
    Groupsock(UsageEnvironment& env, struct in_addr const& groupAddr,
              Port port, u_int8_t ttl);
    Groupsock(UsageEnvironment& env, struct in_addr const& groupAddr,
              struct in_addr const& sourceFilterAddr,
              Port port);
前 者是用于SIM(source-independent multicast)组,后者用于SSM(source-specific multicast)组。groupsock库中的Helper例程提供了读写socket等函数,并且屏蔽了不同的操作系统之间的区别,这是在 GroupsockHelper.cpp文件中实现的。

liveMedia库中有一系列类,基类是Medium,这些类针对不同的流媒体类型和编码。

各种测试代码在testProgram目录下,比如openRTSP等,这些代码有助于理解liveMedia的应用。

LIVE555 Media Server是一个纯粹的RTSP服务器。支持多种格式的媒体文件:

* TS流文件,扩展名ts。
      * PS流文件,扩展名mpg。
      * MPEG-4视频基本流文件,扩展名m4e。
      * MP3文件,扩展名mp3。
      * WAV文件(PCM),扩展名wav。
      * AMR音频文件,扩展名.amr。
      * AAC文件,ADTS格式,扩展名aac。

用live555开发应用程序
基于liveMedia的程序,需要通过继承UsageEnvironment抽象类和TaskScheduler抽象类,定义相应的类来处理事件调度,数据读写以及错误处理。live项目的源代码里有这些类的一个实现,这就是“BasicUsageEnvironment”库。 BasicUsageEnvironment主要是针对简单的控制台应用程序,利用select实现事件获取和处理。这个库利用Unix或者 Windows的控制台作为输入输出,处于应用程序原形或者调试的目的,可以用这个库用户可以开发传统的运行与控制台的应用。

通过使用自定义的“UsageEnvironment”和“TaskScheduler”抽象类的子类,这些应用程序就可以在特定的环境中运行,不需要做过多的修改。需要指出的是在图形环境(GUI toolkit)下,抽象类 TaskScheduler 的子类在实现 doEventLoop()的时候应该与图形环境自己的事件处理框架集成。

先来熟悉在liveMedia库中Source,Sink以及 Filter等概念。Sink就是消费数据的对象,比如把接收到的数据存储到文件,这个文件就是一个Sink。Source就是生产数据的对象,比如通过 RTP读取数据。数据流经过多个'source'和'sink's,下面是一个示例:

'source1' -> 'source2' (a filter) -> 'source3' (a filter) -> 'sink'

从其它Source接收数据的source也叫做"filters"。Module是一个sink或者一个filter。

数据接收的终点是Sink类,MediaSink是所有Sink类的基类。MediaSink的定义如下:

class MediaSink: public Medium {
public:
    static Boolean lookupByName(UsageEnvironment& env, char const* sinkName,
                                MediaSink*& resultSink);

typedef void (afterPlayingFunc)(void* clientData);
    Boolean startPlaying(MediaSource& source,
                         afterPlayingFunc* afterFunc,
                         void* afterClientData);
    virtual void stopPlaying();

// Test for specific types of sink:
    virtual Boolean isRTPSink() const;

FramedSource* source() const {return fSource;}

protected:
    MediaSink(UsageEnvironment& env); // abstract base class
    virtual ~MediaSink();

virtual Boolean sourceIsCompatibleWithUs(MediaSource& source);
        // called by startPlaying()
    virtual Boolean continuePlaying() = 0;
        // called by startPlaying()

static void onSourceClosure(void* clientData);
        // should be called (on ourselves) by continuePlaying() when it
        // discovers that the source we're playing from has closed.

FramedSource* fSource;

private:
    // redefined virtual functions:
    virtual Boolean isSink() const;

private:
    // The following fields are used when we're being played:
    afterPlayingFunc* fAfterFunc;
    void* fAfterClientData;
};

Sink 类实现对数据的处理是通过实现纯虚函数continuePlaying(),通常情况下continuePlaying调用 fSource->getNextFrame来为Source设置数据缓冲区,处理数据的回调函数等,fSource是MediaSink的类型为 FramedSource*的类成员;

基于liveMedia的应用程序的控制流程如下:

应用程序是事件驱动的,使用如下方式的循环

while (1) {
          通过查找读网络句柄的列表和延迟队列(delay queue)来发现需要完成的任务
          完成这个任务
      }

对于每个sink,在进入这个循环之前,应用程序通常调用下面的方法来启动需要做的生成任务:

someSinkObject->startPlaying();

任何时候,一个Module需要获取数据都通过调用刚好在它之前的那个Module的FramedSource::getNextFrame()方法。这是通过纯虚函数FramedSource:oGetNextFrame()实现的,每一个Source module都有相应的实现。

Each 'source' module's implementation of "doGetNextFrame()" works by arranging for an 'after getting' function to be called (from an event handler) when new data becomes available for the caller.

注意,任何应用程序都要处理从'sources'到'sinks'的数据流,但是并非每个这样的数据流都与从网络接口收发数据相对应。
比 如,一个服务器应用程序发送RTP数据包的时候用到一个或多个"RTPSink" modules。这些"RTPSink" modules以别的方式接收数据,通常是文件 "*Source" modules (e.g., to read data from a file), and, as a side effect, transmit RTP packets.

一个简单的RTSP客户端程序
在另一个文章里,给出了这个简单的客户端的程序的代码,可以通过修改Makefile来裁剪liveMedia,使得这个客户端最小化。此客户端已经正常运行。

首先是OPTION
然后是DESCRIBE
      建立Media Session,调用的函数是 MediaSession::createNew,在文件liveMedia/MediaSession.cpp中实现。
      为这个Media Session建立RTPSource,这是通过调用 MediaSubsession::initiate来实现的的,这个方法在liveMedia/MediaSession.cpp中实现。
在然后是SETUP
最后是PLAY

rtp数据的句柄:MultiFramedRTPSource::networkReadHandler 在liveMedia/MultiFramedRTPSource.cpp中
rtcp数据处理的句柄:RTCPInstance::incomingReportHandler 在liveMedia/RTCP.cpp中

rtp数据处理的句柄的设置:MultiFramedRTPSource:oGetNextFrame 在liveMedia/MultiFramedRTPSource.cpp中, 被FileSink::continuePlaying调用在FileSink.cpp中.

rtcp数据处理的句柄设置fRTCPInstance = RTCPInstance::createNew 在/liveMedia/MediaSession.cpp中调用,
createNew调用了构造函数RTCPInstance::RTCPInstance,这个构造函数有如下调用
TaskScheduler::BackgroundHandlerProc* handler = (TaskScheduler::BackgroundHandlerProc*)&incomingReportHandler;

*********************************************************************************************************************
通过分析live库提供的例子程序OpenRTSP,可以清晰地了解客户端接收来自网络上媒体数据的过程。注意,RTP协议和RTCP协议接收的数据分别是视音频数据和发送/接收状况的相关信息,其中,RTP协议只负责接收数据,而RTCP协议除了接收服务器的消息之外,还要向服务器反馈。
A.        main函数流程main(int argc,char *argv[]){1.            创建BasicTaskScheduler对象2.            创建BisicUsageEnvironment对象3.            分析argv参数,(最简单的用法是:openRTSP rtsp://172.16.24.240/mpeg4video.mp4)以便在下面设置一些相关参数4.            创建RTSPClient对象5.            由RTSPClient对象向服务器发送OPTION消息并接受回应6.            产生SDPDescription字符串(由RTSPClient对象向服务器发送DESCRIBE消息并接受回应,根据回应的信息产生SDPDescription字符串,其中包括视音频数据的协议和解码器类型)7.            创建MediaSession对象(根据SDPDescription在MediaSession中创建和初始化MediaSubSession子会话对象)8.            while循环中配置所有子会话对象(为每个子会话创建RTPSource和RTCPInstance对象,并创建两个GroupSock对象,分别对应 RTPSource和RTCPInstance对象,把在每个GroupSock对象中创建的socket描述符置入 BasicTaskScheduler::fReadSet中,RTPSource对象的创建的依据是SDPDescription,例如对于MPEG4 文件来说,视音频RTPSource分别对应MPEG4ESVideoRTPSource和MPEG4GenericRTPSource对象。 RTCPInstance对象在构造函数中完成将Socket描述符、处理接收RTCP数据的函数 (RTCPInstance::incomingReportHandler)以及RTCPInstance本身三者绑定在一个 HandlerDescriptor对象中,并置入BasicTaskScheduler::fReadHandler中。完成绑定后会向服务器发送一条消息。)9.            由RTSPClient对象向服务器发送SETUP消息并接受回应。10.        while循环中为每个子会话创建接收器(FileSink对象),在FileSink对象中根据子会话的codec等属性缺省产生记录视音频数据的文件名,视音频文件名分别为:video-MP4V-ES-1和audio-MPEG4-GENERIC-2,无后缀名11.        while循环中为每个子会话的视音频数据装配相应的接收函数,将每个子会话中的RTPSource中的GroupSock对象中的SOCKET描述符,置入BasicTaskScheduler::fReadSet中,并将描述符、处理接收RTP数据的函数 (MultiFramedRTPSource::networkReadHandler)以及RTPSource本身三者绑定在一个 HandlerDescriptor对象中,并置入BasicTaskScheduler::fReadHandler中,并将FileSink的缓冲区和包含写入文件操作的一个函数指针配置给RTPSource对象,这个缓冲区将会在networkReadHandler中接收来自网络的视音频数据(分析和去掉RTP包头的工作由RTPSource完成),而这个函数指针在networkReadHandler中被调用以完成将缓冲区中的数据写入文件。12.        由RTSPClient对象向服务器发送PLAY消息并接受回应。13.        进入while循环,调用BasicTaskScheduler::SingleStep()函数接受数据,直到服务器发送TREADOWN消息给客户端,客户端接收到该消息后释放资源,程序退出。

}

live555源代码简介相关推荐

  1. live555源代码分析

    live555源代码下载(VC6工程):http://download.csdn.net/detail/leixiaohua1020/6374387 liveMedia 项目(http://www.l ...

  2. live555源代码概述

    live555源代码概述 2010年01月29日 星期五 13:03 liveMedia项目(http://www.live555.com/)的源代码包括四个基本的库,各种测试代码以及Media Se ...

  3. live555源代码分析与代码下载链接

    live555源代码下载(VC6工程):http://download.csdn.net/detail/leixiaohua1020/6374387 liveMedia 项目(http://www.l ...

  4. live555 源代码简单分析1:主程序

    live555是使用十分广泛的开源流媒体服务器,之前也看过其他人写的live555的学习笔记,在这里自己简单总结下. live555源代码有以下几个明显的特点: 1.头文件是.hh后缀的,但没觉得和. ...

  5. linux make 命令行 定义宏(-D)传递给C源代码 简介

    需求: 通常使用 -dname=值 从"make命令行"传递给"makefile". 该定义可在makefile中访问. 想使用 编译器选项 将宏定义从&quo ...

  6. RTSP服务器实例live555源代码分析

    1. RTSP连接的建立过程      RTSPServer类用于构建一个RTSP服务器,该类同时在其内部定义了一个RTSPClientSession类,用于处理单独的客户会话.      首先创建R ...

  7. 在windows使用vs2008编译live555

    1.live555源代码简介 liveMedia项目的源代码包括四个基本的库,各种测试代码以及IVE555 Media Server. 四个基本的库分别是UsageEnvironment&Ta ...

  8. H264 流媒体 编码汇总

    实时传输协议(RTP)和实时控制协议(RTCP) RTP是一种提供端对端传输服务的实时传输协议,用来支持在单目标广播和多目标广播网络服务中传输实时数据,而实时数据的传输则由RTCP协议来监视和控制. ...

  9. 在Livemedia的基础上开发自己的流媒体客户端

    在Livemedia的基础上开发自己的流媒体客户端V 0.01 桂堂东 一.背景... 3 二.Livemedia框架介绍... 4 1.总体框架... 4 2.客户端框架... 4 2.1 客户端o ...

最新文章

  1. 独家 | TensorFlow 2.0将把Eager Execution变为默认执行模式,你该转向动态计算图了...
  2. JAVA I/O系统。
  3. win8改win7笔记
  4. 修改图层的范围_【PS|第39期】数字绘画 使用填充图层
  5. java sleep和wait区别
  6. 摘:多线程和异步的区别
  7. win7系统mysql连接不上数据库吗_Win7系统使用数据库时mysql频繁掉线无法连接的两种解决方法...
  8. 9-n个人中选k个人的选择方法种类
  9. 我38岁,从外企技术高管到失业在家,只因为做错了这件事
  10. php mysql显示到页面上_从数据库调出数据显示到页面 PHP+Mysql+Html(简单实例)
  11. 市场研究中的数据分析知识整理 (四)-主成分分析和因子分析
  12. Kaldi:提特征报错“compute-fbank-feats: error while loading shared libraries: libkaldi-hmm.so”
  13. 数据加工(一)-------数据抽取
  14. Mysql多表联查——经典50题
  15. 为什么我劝90%的人不要转行数据分析?数据岗真没你想的那么香
  16. 用数据说话,看中国49个地方(省、市、高新区)集成电路产业实力情况
  17. spark程序消费kafka数据报错:java.lang.NoSuchMethodError: net.jpountz.util.Utils.checkRange([BII)V
  18. ff14最新服务器人数,FF14第一波转服过后 现各服务器人口状况
  19. 关于dialogbox
  20. 大数据架构及行业大数据应用

热门文章

  1. asp.net mvc webform和razor的page基类区别
  2. [你必须知道的.NET] 第七回:品味类型---从通用类型系统开始
  3. C++11 FAQ中文版:std::function 和 std::bind
  4. 图片文件夹要放在html,在网页中插入图像,若图像文件位于html文件的上两级文件夹,则在文件名之前加入()...
  5. Python3 学习系列 丨 博客目录索引
  6. PWN-PRACTICE-BUUCTF-12
  7. 【机器学习】Softmax和Sigmoid
  8. 【2019牛客暑期多校训练营(第三场)- F】Planting Trees(单调队列,尺取)
  9. 【LightOJ - 1079】Just another Robbery(概率dp,概率背包)
  10. 【牛客 - 317B】小a与204(贪心,构造,水题)