嵌入式 live555源码详解

原创 2013年12月02日 14:43:10

live555 类之间的依属关系和功能分析

首先呢,不要指望一口气把live555能够肯下,那样代码你看着看着你就会发现涉及到的类越来,很快你自然的就投入很多时间去分析作者的设计架构.

再坚固的堡垒,只要咱们保持着恒心,强攻总有一天可以攻下。

今天就来分析下live555中设计的几个核心类.

在接收到客户端发送的Descripture命令后,服务器会创建ServerMediaSession和ServerMediaSubSession,创建了ServerMediaSession后会添加进RtspServer的HashTable:fServerMediaSessions中。

但是这里有一个问题,困扰了我很长时间.

ServerMediaSession里面以链表的形式存储ServerMediaSubSession,但是我看代码觉得始终ServerMediaSession里面只可能会存在一个ServerMediaSubSession,还有访问的资源,比如tv.264,跟ServerMediaSession和ServerMediaSubSession的对应关系是如何的?

在RtspClientSession中:

    unsigned fNumStreamStates;//有什么意义?
    struct streamState {
      ServerMediaSubsession* subsession;
      void* streamToken;//streamState
    } * fStreamStates;

fNumStreamStates的意义何在,是专门用于处理什么情况的?

第二部分接受到了Setup命令,客户端和服务器基本就已经协商好了,双边通信的端口,这个时候引入的主要类是;

FramedSource,RTPSink,GroupSock,BasicUDPSink,StreamState.

但是根据面向对象的设计原则,RtspClientSession肯定不会跟上面这么多类通信,这样RtspClientSession抗的风险就太大了.


它只需要与StreamState沟通就好了,最后借助ServerMediaSession::getStreamParameters,fStreamStates结构体的成员void* streamToken = StreamState.

StreamState拥有一个参数RTPSink,RTPSink拥有2个参数:FramedSource,GroupSocket,这样基本上他们的功能就理清了.


第三部分在接收到了Play命令后,主要调用ServerMediaSubSession的startStream来完成,而ServerMediaSubSession的主要调用的StreamState::startPlaying

咱门看下StreamState::startPlaying的核心代码:

fRTPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this);
fRTCPInstance
      = RTCPInstance::createNew(fRTPSink->envir(), fRTCPgs,
    fTotalBW, (unsigned char*)fMaster.fCNAME,
    fRTPSink, NULL );


看代码意图很明显:

开发RTP数据包,处理RTCP数据包完成和客户端交互.


好,那么通过上面的分析,基本上可以猜测出设计到的类的意图:

FrameSource:
完成对访问的资源的解析,提取出H264NALUE单元,并通过函数指针回调给RTPSink.
RTPSink对FramedSource传递过来的H264 NALU单元根据RFC3984的协议进行封包处理,封包处理好后,然后借助GroupSocket将数据推送出去.

StreamState的主要功能控制数据的发送,暂停,停止。

那么既然StreamState已经实现了这些最核心的功能,那么为何还需要ServerMediaSubSession和ServerMediaSession.

对于这2个类我存在的疑惑还真不少。

不过可以肯定得是,他们的存在应该与N个用户请求同一个资源文件有关。

比如N个用户同事请求:rtsp://127.0.0.1/tv.264,这样的有关。

作者的设计意图很可能是想复用相关的数据.


初步画了张设计图:


live555源码分析-live555大致流程

今天大致分析了下live555的流程,以H264为例子进行的分析.

从连接到发送RTP/RTCP数据包。

首先分析呢,不能太关注细节,先整体再局部。

在分析的过程中,设计到live555自己封装的一个高级类:比如迭代器,哈希表,而且这2个类在live555中运用的范围还非常的广,但是无不例外都是用链表进行实现的。
后面我们会专门花时间来分析live555是如何实现迭代器和哈希表的.


接着二的分析,这个时候客户端会发送Options,Descriptur,Setup等命令过来,还会发送,快进,暂停,停止等信息过来,完成后,服务器就开始发送RTP/RTCP数据包.

阐述下RTP包和RTCP包得关系.

RTP/RTCP数据包的传输是基于UDP,这是一种无连接的传输方式,也就是说服务器无法判断出客户端和服务器是否依然还在保持联系中,rtcp包就是专门解决这个问题的. rtcp包含了双边发送rtp数据包的信息,包括发送了多少数据包等信息。

那么客户端和服务器就可以通过对RTCP包得分析来统计传输过程中丢了多少包,还有如果超过一定时间没有接收到RTCP数据包,那么客户端和服务器就会终止双边的连接。


说了这么多,分析下live555处理的业务流程.

客户端发送Descripture命令过来后,服务器会创建一个ServerMediaSession,SeerverMediaSession本身会放到一张哈希表中,这张哈希表的作用其实就是绑定后缀名和具体的MediaSession.
比如:rtsp://127.0.0.1:554/tv.264 ,所有的264文件都有一个ServerMediaSession对应,同理,所有的aac,mp3....对会有一个对应的ServerMediaSession.
ServerMediaSession自己也是一个链表(单向还是双向没分析),里面的元素为ServerMediaSubSession。

ServerMediaSubSession的子类很多,比如:H264FileMediaSubSession,AACFileMediaSubSession,光看这些个类的命名,大家也基本猜测出这部分的设计思路.

比如用户同时访问:
rtsp://127.0.0.1:554/tv.264
rtsp://127.0.0.1"554/tv2.264


那么live555,就会分配一个ServerMediaSession,然后再ServerMediaSession中包含2个H264FileMediaSubSession,这2个H264FileMediaSubSession一个对应tv.264,另一个对应tv2.264.


H264FileMediaSubSession的功能猜测应该是解析文件,并从中提取H264 NALU单元,并封装为RTP包.(这个类的设计也很复杂,主要是细节多.)


Descriptur完成后,客户端就知道了服务器传递过来的数据的很多信息呢,比如SPS,PPS,这个时候客户端会进行解码器的初始化等操作。

然后完成相关操作后,便会发送Setup,告诉服务器RTP/RTCP的传递端口,让服务器知道数据包具体传到哪个端口.


然后客户端发送PLAY,服务器边开始发送数据包:

  fStreamStates[i].subsession->startStream(fOurSessionId,
            fStreamStates[i].streamToken,
            (TaskFunc*)noteClientLiveness, this,
            rtpSeqNum, rtpTimestamp,
            handleAlternativeRequestByte, this);
      const char *urlSuffix = fStreamStates[i].subsession->trackId();



  if (!fAreCurrentlyPlaying && fMediaSource != NULL) {
    if (fRTPSink != NULL) {
      fRTPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this);
      fAreCurrentlyPlaying = True;
    } else if (fUDPSink != NULL) {
      fUDPSink->startPlaying(*fMediaSource, afterPlayingStreamState, this);
      fAreCurrentlyPlaying = True;
    }
  }


因为里面的设计的类过多,截取一下一些比较重要的代码.

简单说就是接收到PLAY命令后,就开始发送RTP数据包和定时接受/发送RTCP数据包了。

相关文章推荐

live555源代码分析

live555源代码概述 liveMedia 项目(http://www.live555.com/)的源代码包括四个基本的库,各种测试代码以及 Media Server。四个基本的库分别是: Usag...

live555源代码详细分析解析,教你如何使用live555接收rtsp数据

最近继续看了看live555的代码,进行了一些具体的实验。 对live555的部分特性有了一定的了解。 稍微看了网上的一些关于live555的文章,千篇一律。 大部分都是转载自一个人的博客。 ...

live555源码分析----RTP的打包与发送

这里主要分析一下,live555中关于RTP打包发送的部分。在处理完PLAY命令之后,就开始发送RTP数据包了(其实在发送PLAY命令的response包之前,就会发送一个RTP包,这里传输就已经开始...
  • gavinr
  • gavinr
  • 2011年12月02日 17:10
  • 17231

live555 源码分析

1.live555 开发库源代码包括6个部分:UsageEnviroment、BasicUsageEnviroment、groupsock、liveMedia、testProgs、mediaServe...

live555 源码架构分析

live555源代码分析   , 写的不错 转载备忘 源代码下载(VC6工程):http://download.csdn.net/detail/leixiaohua1020/6374...
  • mtour
  • mtour
  • 2014年10月13日 16:28
  • 1189

live555源码分析-live555大致流程

今天大致分析了下live555的流程,以H264为例子进行的分析. 从连接到发送RTP/RTCP数据包。 首先分析呢,不能太关注细节,先整体再局部。 在分析的过程中,设计到live5...

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

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

live555源码分析----H264的数据处理

现在来分析live555中关于H264的处理部分,主要包括从文件中读取数据进行并进行frame(NALU)的分割,然后对frame进行分片,这些工作都是在frame交给RTP sink之前完成的。接着...
  • gavinr
  • gavinr
  • 2011年12月05日 14:56
  • 25942

LIVE555源码研究之四:MediaServer (一)

LIVE555源码研究之四:MediaServer (一)      从本篇文章开始我们将从简单服务器程序作为突破点,深入研究LIVE555源码。     从前面的文章我们知道,任何一个基于LIVE5...

基于live555实现实时视频监控

目录 1 所需软件、源码及下载地址----------------------------------------------------------------------------------...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:嵌入式 live555源码详解
举报原因:
原因补充:

(最多只允许输入30个字)