《电子技术应用》
您所在的位置:首页 > 通信与网络 > 设计应用 > 基于Live555的流媒体服务器设计与实现
基于Live555的流媒体服务器设计与实现
2014年微型机与应用第18期
许华滨1,2,谢维波1,2,黄 奕1,2
1.华侨大学 信息科学与工程学院,福建 厦门 361021; 2.华侨大学 厦门软件园 嵌入式技术开放实验室,福建 厦门 361008
摘要: 针对传统监控系统的不足已不能满足现代人对监控视频内容的要求,提出了一种解决方案并对其进行阐述,说明如何在Linux系统下,以IP网络摄像头为数据源,结合开源Live555库实现流媒体服务器的方法,其中涉及了视频数据的获取、编码、流化以及传输等模块。流媒体服务器的实现解决了多路客户访问摄像头的负载问题,同时若与图像处理算法结合可提供特殊的视频监控内容以满足应用需求。
Abstract:
Key words :

  摘  要: 针对传统监控系统的不足已不能满足现代人对监控视频内容的要求,提出了一种解决方案并对其进行阐述,说明如何在Linux系统下,以IP网络摄像头为数据源,结合开源Live555库实现流媒体服务器的方法,其中涉及了视频数据的获取、编码、流化以及传输等模块。流媒体服务器的实现解决了多路客户访问摄像头的负载问题,同时若与图像处理算法结合可提供特殊的视频监控内容以满足应用需求。

  关键词RTSP;流媒体服务器;Live555;网络监控

0 引言

  随着图像处理的发展,构建一个良好的视频图像处理应用平台越来越重要。目前的摄像头对多路访问的负载能力非常有限,并且现在人们对监控内容的要求已不仅仅停留在原始视频上,而大多更希望能够实时监控经过特殊处理的视频数据。为了满足这一需求,以IP摄像头作为数据源,PC端搭建流媒体服务器供多路客户进行实时监控的模式是一个很好的解决方案,这样既能减少摄像头负载能力的限制,同时又能满足图像处理后的监控需求。本文设计的流媒体服务器[1]架设在Linux操作系统的PC上,采用RTSP协议[2]进行实时传输以供客户访问。

  服务器首先登录访问IP摄像头,匹配通过后IP摄像头返回捕捉的视频数据给服务器,当客户端通过链接向服务器发送访问请求后,服务器开始向客户端传送实时视频数据,供客户进行实时监控。

1 IPC数据获取及存储

  网络摄像机对于人们来说较为重要的是如何获取其视频源数据,而海康威视的网络摄像机为人们提供了二次开发的接口以方便对IPC的功能应用进行扩展。下面对IPC视频数据获取流程进行介绍。

  由于在IPC端已经有设定好的账户与密码,因此用户在访问此IPC时就需要通过NET_DVR_Login_V30函数来进行注册:NET_DVR_Login_V30(IP地址,端口,账号,密码,&struDeviceInfo),IP摄像头匹配正确后才有访问权限。

  该流程中,启动数据流的接收是通过调用NET_DVR_RealPlay_V30来实现的。该函数中有一项参数可用来设置数据回调函数,每当有码流数据到达时,便会跳转到这个已设置的数据回调函数中,在数据回调函数中需要对接收到的数据流进行判断,若为系统头则进行一些设置,若为码流数据则可将其存入缓冲区内。其流程示意图如图1所示。

001.jpg

  在图1中,判断流数据为系统头时需要进行一些设置,其中就包括了解码回调函数的设置。解码回调函数的作用是当码流数据存入缓冲区达一帧时会跳转到该函数中,此时在解码回调函数内部便可对完整的一帧数据进行操作。

  在解码回调函数内获取到的是YV12格式帧数据,而由于所选择的是x264编码器,其输入源规范为YUV格式,因此必须在解码回调函数内将其转为YUV格式后才可供x264进行编码,之后就可以将其储入缓冲区内。本次开发过程中以循环缓冲区和链表的方式存取数据。

2 图像编码模块

  前面提到,H264编码使用的是x264编码器,x264提供了一些开发接口,但仍需进一步封装,其设计流程如下:

  (1)初始化EncoderInit函数:在其内部设置初始化结构体,调用x264_param_default及x264_encoder_open进行编码器初始化,并开辟存放编码前后图像存储空间。

  (2)编码实现Encode_frame函数:将原始YUV420P格式数据传给x264_encoder_encode函数进行编码得到nal数组,其后循环调用x264_nal_encode函数逐一将编码后nal封装成NAL单元并写入输出缓存区中,完成一帧图像数据的编码。

3 流媒体服务器模块

  服务器结合开源Live555库进行设计,提供对外实时播放。Live555是一个为流媒体提供解决方案的跨平台的C++开源项目,它包括了四个基本库,分别是:UsageEnvironment、BasicUsageEnvironment、Groupsock和LiveMedia[4]。其中LiveMedia库是最为核心的,它包含了对应各种不同流媒体类型的数据源类Source、数据接收类Sink、会话类Session及RTSPServe等。

  TaskScheduler实例是整个程序的任务调度器[5],它通过doEventLoop()方法实现程序的循环结构,并在循环中进行任务调度。

  3.1 服务器的建立及响应

  程序流程如下:

  (1)建立任务调度器

  TaskScheduler*scheduler=BasicTaskScheduler::createNew()

  (2)建立程序运行环境

  _env=BasicUsageEnvironment::createNew(*scheduler)

  (3)创建RTSP服务器绑定端口号

  RTSPServer*rtspServer=RTSPServer::createNew(*_env,9554)

  (4)创建服务器媒体对象:创建ServerMediaSession实例。

  (5)进入事件循环

  _env->taskScheduler().doEventLoop()

  服务器采用的是事件驱动机制,在这个循环中,doEventLoop()主要负责三件事:监听客户端请求并进行响应、对事件发生进行处理、对延时任务进行调度。

  RTSP协议应用于C/S模式,它本身并不传输数据,而只负责实现连接、播放、停止等操作,数据的传输则交由RTP协议来进行[6]。服务器与客户端建立连接时是通过响应客户端发送的OPTION、DESCRIBE、SETUP、PLAY、TERADOWN等请求来进行交互连接的[7]。常用的交互方法作用如下:

  OPTION:C向S端获取可提供的交互方法

  DESCRIBE:要求得到S端提供的媒体初始化信息(SDP)

  SETUP:确定传输模式并提醒S端建立会话

  PLAY:C向S发送播放请求

  TERADOWN:C向S发送关闭请求

  服务器对客户端的具体响应情况如下:

  (1)服务器端在收到客户端发送的DESCRIBE请求时,相应的处理函数根据流媒体名查找或创建ServerMediaSession,生成SDP信息作为返回响应此请求。

  (2)服务器端收到SETUP请求时,相应处理函数会对SETUP请求的传输头解析,获取流媒体发送传输参数,将这些参数组装成响应消息返回给客户端。期间subsession调用CreatNew()生成Source数据源实例及RTPSink数据接收实例。

  (3)服务器端收到PLAY请求时,RTPSink数据接收实例会开始向Source数据源索取图像数据,并将索取到的数据打包成RTP包发送出去。此时,当RTPSink开始索取数据时,就启动了对一帧图像数据的流化。

  3.2 流化过程

  当Sink向Source索取数据时服务器内便启动了流化,数据由Source流向Sink,最终再发送出去。但这一过程中经过了多个节点传递才到达Sink端,这是因为最初的Source视频数据如果直接传给Sink端,便无法直接进行流式传输,因此需要经过中间多个节点对视频数据进行“加工”才能满足流式传输的要求。下面是一个示例:

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

  filters接收到数据后也作为后者的source。对于本文H264格式的流媒体来说,图像数据经各节点传递过程如下:

  WebcamFrameSource(自定义节点)->H264VideoStreamParser->H264VideoStreamFramer->H264FUAFragmenter->H264 VideoRTPSink

  WebcamFrameSource中H264编码的视频数据传给H264VideoStreamParser,并由它分解为多个NAL单元,然后经H264VideoStreamFramer处理后由H264FUAFragmenter进行RTP封包,最后H264VideoRTPSink负责形成RTP包头并发送数据。

  在这个过程中,WebcamFrameSource类是创建的,后面的H264VideoStreamFramer类、H264FUAFragmenter类、H264VideoRTPSink类都是由Live555库定义好了的,所创建的WebcamFrameSource类负责将前期的YUV帧数据从缓冲区取出进行H264编码,然后将编码好的视频数据传给下一个节点即可。

  3.3 服务器内数据获取与打包发送

  在Live555中MediaSource类是所有Source的基类,对各种流媒体格式类型及编码的支持都是通过这个类的派生类来实现的,FrameSource派生自MediaSource,并且内部定义了一个虚函数doGetNextFrame(),用来让其子类实现各自媒体格式的帧获取。若要自定义Source的来源,则可以通过自定义一个派生自FrameSource的类来实现。前面提到的WebcamFrameSource就是继承自FrameSource类用来实现数据源获取的。

  doGetNextFrame()是FrameSource的虚函数,Sink实例在向Source实例索取数据时,会重复循环层层调用doGetNextFrame()来获取实时数据源,获取过程就是将前期的YUV帧数据从缓冲区取出进行H264编码,并将编码完成的数据间接地传递给Sink的缓冲区,最后再调用FramedSource::afterGetting()函数来通知Sink端作处理。具体流程如图2所示。

002.jpg

  数据获取后交由PackFrame()等函数进行打包,最后进行发送。若无数据,则继续向Source数据源进行索取,循环之前的步骤。

4 实验结果

003.jpg

  实验结果如图3所示,左侧PC为基于Linux的RTSP服务器,负责将IPC拍摄到的视频实时传送;右侧PC以及手机都作为客户端,通过RTSP服务器提供的URL进行链接,进而实时播放。

5 结论

  本文对IPC数据源的获取方法、编码流程、服务器内部数据流化及数据源类WebcamFrameSource的设计进行了说明。使用IPC通过路由器将数据传送至服务器,服务器端进行实时传送并提供相应的URL链接供客户端使用。客户端可使用VLC等支持RTSP协议的视频软件进行实时监控。

  参考文献

  [1] 杜哗.流媒体技术的原理和应用[J].光盘技术,2008(7):9-11.

  [2] SCHULZRINNE A, RAO R, Columbia University, et al. RFC2326-Real time streaming protocol(RTSP)[S].1998.

  [3] 樊珊.基于RTP的H264视频传输技术的研究[D].济南:山东大学,2008.

  [4] 樊承泽,陈蜀宇,杨新华.基于网络计算机的流媒体播放器的研究与实现[J].计算机技术与发展,2010,20(4):195-198.

  [5] 茅炎菲,忠东.基于RTSP协议网络监控系统的研究与实现[J].计算机工程与设计,2011,32(7):2523-2530.

  [6] 王彦丽,陈明,陈华,等.基于RTP/RTCP的数字视频监控系统的设计与实现[J].计算机工程与科学,2009,31(3):58-60.

  [7] 王路帮.RTSP协议及其分布式应用框架[J].安徽职业技术学院学报,2006,5(1):4-6.


此内容为AET网站原创,未经授权禁止转载。