随着网络视频直播技术的发展,人们对视频直播提出了更高要求,由于多媒体网络传输具有高带宽、高实时性特点,而当前网络带宽不够高,在广域网传播传输多媒体数据时还普遍存在延迟和丢包现象,因此对于视频的压缩和编码[1]、传输信道选取、不同网络协议之间的的选择、组播技术、媒体流帧率控制技术已经成为了视频直播系统中的关键技术,文中提出了“Internet+DirectShow+RTMP+H.264+Nginx”的方式来进行视频传输系统的构建。利用了Internet的广泛性[2]和DirectShow内在的可扩展性以及H.264[3]的高压缩比即在低带宽情况下高效的传输数据特性和RTMP协议对有网络缺陷的补偿性,使得实时多媒体信息在网络中的传输更为高效。本系统为纯软件实现,对硬件要求低,具有稳定性的Nginx服务器[4]、丰富的模块库配置、配置灵活和低系统资源的消耗等优点降低了系统成本的同时又满足了项目的需求。本系统可用于学校和企业的视频会议、视频监控,能够满足不同层次的实时视频直播的要求。
1 DirectShow技术和RTMPDirectShow是Windows平台上的流媒体体系结构,是一个开放性的应用框架。是DirectX家族一员,是基于COM(component object model)的编程接口。DirectShow在Windows平台上数字媒体程序的开发并负责系统总体任务和底层工作大大降低了开发的难度并且有很好的兼容性能够支持多种硬件设备在Windows平台上的音视频采集。典型的DirectShow系统如图 1所示。
![]() |
| 图 1 DirectShow系统框图 |
在DirectShow使用中构建Filter Graph 模型成了DirectShow视频捕获技术的关键,在Filter Graph 中包含了各个能够处理数据模块的Filter[5] ,各个Filter按照特定的顺序连接为一条线就能够完成处理数据等功能,各个过滤器Filter 通过针脚Pin[6] 连接,针脚Pin通过 GetMediaType()、CheckMediaType()和SetMediaType()3种方法来协商各个Filter之间传输数据的多媒体类型。
RTMP是由 Adobe 公司提出的一种在Flash平台进行实时数据传输的网络协议,RTMP 协议使用的是TCP 协议作为其传输层的网络协议[7]。TCP协议是一种面向连接的、可靠的、基于字节流的传输层通信协议,在网络传输的过程中没有丢包的现象,从而使用户能够收看更加清晰流畅的视频。 RTMP协议可以进行实时视频流的传输和控制他的播放。因此本系统采用RTMP协议作为数据传输协。
2 系统总体设计方案本系统采用H.264编码进行视频流的的实时播出,主要有4大部分组成:视频数据的捕获、视频编码、视频RTMP打包与传输及流媒体服务器的转播。视频捕获部分负责实时捕获视频数据;视频编码部分负责将捕获的视频数据进行实时H.264编码压缩,并可以选择保存为本地文件;视频播出部分负责将编码完的数据进行RTMP包封装,然后发送到Nginx服务器,最后由Nginx服务器向申请观看的客户端实时转播视频数据。工作原理如图 2所示。
![]() |
| 图 2 系统整体结构 |
在系统中正确安装视频采集卡后通过GraphEdit就能够在“VideoCaptureSources”目录下找到各个捕捉设备的Filter,一般以CaptureFilter形式出现,1个Capture Filter至少有1个Capture Output Pin。选择系统使用的捕捉卡后然后调用AddFilter把Capture Filter添加到Filter Graph。
本系统通过DirectShow实现视频捕获,具体分为以下4个步骤。
1)采集设备枚举
在构造Video Capture Filter前,需要列举出系统的所有采集设备,根据列举的设备名称创建需要的Video Capture Filter。核心代码如下:
IID_ICreateDevEnum,(LPVOID *)&pDevEnum);
2)创建Video Capture Filter
由上一步骤得到采集设备,建立Video Capture Filter。具体代码如下:
hr=pMoniker->BindToObject(0,0,IID_IBaseFilter,(void **)&m_pCapture);//创建采集Filter 实例[8]
3)创建视频采集过滤器图表[9]
使用ICaptureGraphBuilder2接口,创建视频采集过滤器图表,然后再将它添加到IGraphBuilder图表管理器中。
4)将所有的的Smart Tee和Video Renderer Filter连接成完整的图表。
利用ICaptureGraphBuilder2提供的RenderStream函数,构建Smart Tee和Video Renderer Filter[10]并将它们连接成一个完整的图表,从而完成视频采集的功能。核心代码如下;
pBuild->RenderStream(&PIN_CATEGORY_PREVIEW,&MEDIATYPE_Video,pCap,NULL,NULL);
该系统的发送端实现思路如下,用USB摄像头采集数据,用FFmpeg 支持的X264编码对采集到的数据进行H.264编码 ,对编码好的数据连接到发送Filter并以RTMP协议打包,将打包好的数据发送至Nginx服务器。其中滤波图如图 3所示。
![]() |
| 图 3 发送端的Filter Graph |
在本系统中利用DirectX SDK 将视频编码模块封装为H.264Filter,将视频传输模块封装为H.264SenderFilter。利用开源的X264编码器进行H.264的视频编码,使用librtmp进行对H.264数据进行RTMP协议的封装和传输[11]。H.264编码Filter重写了函数CheckinputType(eonsteMediaType*mtln)该函数检测Filter对输入的媒体是否支持。DecideBuffersize()根据输入媒体类型给出需要分配的缓冲区大小,给函数分配缓冲区。CompleteConnect(pINesDIRECTION direetion,Ipin*pReeeivepin)当输入Pin连接成功后,会调用该函数对X264编码器进行初始化,参数设置,编码器打开,编码空间分配。在本项目中使用的摄像头采集到的视频数据格式是RGB24,而X264支持的是标准的YUV420格式,因此编码前要对采集模块传送过来的RGB格式的图像进行格式转换,在编码前对RGB格式的图像转换为YUV420格式,然后用X264编码进行编码,X264编码过程如下:
1)x264_param_default( x264_param_t *param )。对编码器进行参数设定分配编码器所需结构体。检测参数有效性,初始化sps和pps,分配编码器所需memory空间,包括参考帧和缓冲帧,初始化macroblock cache相应空间。根据cpu类型,初始化各指令集加速函数。
2)以宏块为单位对视频数据进行编码,x264_macroblock_cache_load()函数将相关数据载入缓存。然后利用x264_macroblock_analyse()函数分析参数,确定最佳编码模式。确定好编码模式后,首先用x264_macroblock_encode()函数对宏块进行编码,然后用x264_encoder_encode( h,&nal,&i_nal,pic,&pic_out )对帧进行编码。
3)i_size = x264_nal_encode( data,&i_data,1,&nal[i] ) 网络打包编码i_file += p_write_nalu( hout,data,i_size ) 把网络包写入到输出文件中去返回对下一帧进行编码。视频编码流程如图 4所示。
![]() |
| 图 4 视频编码流程 |
将编码好的数据通过Output pin 输入到H.264 RTMP SenderFilter,首先要将H.264数据进行RTMP协议封包,RTMP协议封包组成与含义如表 1所示。
| 用途 | 大小/Byte | 含义 |
| Head_Type | 1 | 包头 |
| TiMMER | 3 | 时间戳 |
| AMFSize | 3 | 数据大小 |
| AMFType | 1 | 数据类型 |
| StreamID | 4 | 流ID |
将封装好的数据包利用网络传输到流媒体服务器。数据包是使用librtmp库进行传输的。首先初始化RTMP结构,建立和流媒体服务器的RTMP连接,并设置输入的RTMP连接的URL,然后将封装好的RTMPPacket 调用RTMP_SendPacket()函数,循环往流媒体服务器Nginx发送数据。这里RTMP Packet是已经封装好的加了时间戳的H264或者AAC数据流。发送端流程如图 5所示。
![]() |
| 图 5 视频发送端流程 |
在众多的流媒体服务器中选择Nginx ,Nginx是一个高性能的HTTP服务器,Nginx并发性比较好,CPU内存占用低,适合作为本项目的流媒体服务器。在本项目中使用nginx rtmp模块来完成音视频在线直播,使用upstream模块完成网络数据的接收、处理和转发。Nginx进行数据转发的流程: Nginx服务器等待客户端http请求,搜索上游服务器。当与上游服务器建立连接,Nginx会建立两个handler分别为Upstream,Downstream,Upstream接收发来的数据,转发给已连接的客户端。
nginx rtmp模块能够支持外部程序调用。本系统使用了nginx rtmp模块,调用FFmpeg实现了对实时视频流h.264编码的功能。在nginx服务器上配置rtmp模块具体步骤为首先安装依赖包,然后安装git工具,最后安装FFmpeg及其依赖包。
1)安装和编译nginx rtmp模块代码如下./configure-add-module=/path/to/nginx-rtmp-module。
2)安装对于HLS(HTTP Live Streaming)支持模块的配置,./configure-add-module=/path/to/nginx-rtmp-module-add-module=/path/to/nginx-rtmp-module/hls。
对于HLS支持模块的配置利用了Apple的动态码率自适应技术,主要用于PC和Apple终端的音视频服务。包括一个m3u(8)的索引文件、TS媒体分片文件和key加密串文件。使用FFmpeg转流如下
exec/opt/ffmpeg/bin/ffmpeg-irtmp://localhost/myapp/$name-c:acopy-c:vlibx264-b:v512K-g30-fflvrtmp://localhost/hls/$name_low。
将视频流转推到hls,hls_variant会生成一个多码率的m3u8文件,同时把切片文件存放到test_low目录下,在观看视频时,访问http://yourip/hls/test.m3u8,本系统中使用的实际码流的URL http://IP /hls /livestream.m3u8为其中IP为服务器Nginx的IP地址,Nginx服务器对于RTMP直播配置在配置文件nginx.conf中加入rtmp直播配置代码如下:
rtmp {
server {
listen 1935;
chunk_size 4000;
application live {
live on;
}
}
}
配置好直播模块以后启动Nginx服务器就可完成流媒体服务器的搭建和转播的配置。
4 系统测试完成jwplayer下载后,解压到/usr/local/nginx/html/,建立测试页面player.html,也放到上面目录下。系统采集视频界面如图 6所示。
![]() |
| 图 6 视频采集界面 |
其中视频设备采用摄像头Gsou USB2.0 Camera 帧率为25 ,可根据项目需要自己选取帧率、分辨率和波特率,本系统也可以把本地保存的视频文件推流到Nginx服务器,可以把摄像头采集的实时视频保存为本地文件。rtmp://111.117.58 .223 /mytv/livestream 为流媒体链接。其中111.117.58.223为Nginx服务器的IP地址录制实时视频之前需要启动Nginx服务器然后点击开始录制,开始录制界面如图 7所示。
![]() |
| 图 7 录制开始界面 |
实时视频录制系统启动以后,需要查看服务器和客户端的1955端口是否打开,因为1935通信的是RTMP协议。如果的1935端口没有打开,需要在对应的TCP端口设置项中选中全部允许就可以了。设置完毕后,点确定按钮使设置生效。打开PC机浏览器输入111.117.58.223:9091/player.html 实时视频可以清晰流畅地观看,如图 8。同时通过长时间的视频系统的运行和实时视频网页和手机客户端播放,可以很直观地测试系统的准确性、稳定性和可靠性。
![]() |
| 图 8 浏览器收看界面 |
文中通过对实时视频直播系统的介绍,详细的描述了实现软件系统的步骤和方法,主要包括DirectShow进行视频数据的捕获,H.264编码器进行实时编码,使用RTMP协议作为视频网络传输协议,配置稳定高效的Nginx作为本系统的流媒体服务器,用户不需要使用任何客户端仅仅在装过Flash的浏览器就可以观看视频直播,本系统完美解决多平台的兼容问题RTMP解决PC端,HLS解决Android、Apple终端,使用RTMP协议保证了实时视频数据质量避免了在广域网传播中丢包现象,经过测试系统性能可靠稳定,很好地满足了复杂场景和网络带宽低的情况下视频直播系统的要求。
| [1] | 王洪伟. 基于DM3730和GStreamer的网络视频传输技术设计与实现[J]. 应用科技, 2014, 41(3): 19-22. |
| [2] | SERGIO S. The embedded internet: TCP/IP basics, implementation and applications[M]. Buenos Aires: Addison Wesley Professional, 2008: 47-59. |
| [3] | KIM W J, CHO K, CHUNG K S. Stage-based frame-partitioned parallelization of H. 264/AVC decoding[J]. IEEE Transactions on Consumer Electronics, 2010, 56(2): 3-10. |
| [4] | 林志伟. 面向移动终端的流媒体实时通信服务器关键技术研究[D]. 厦门: 厦门大学, 2012: 72-73. |
| [5] | 杨晨. 移动流媒体服务器设计和性能分析[D]. 武汉: 华中科技大学, 2006: 57-58. |
| [6] | 曾华山, 宋钰. 基于Directshow的VMR视频捕获的实现[J]. 电脑知识与技术, 2010, 6(25): 7110-7111. |
| [7] | 于洋. 基于DirectShow的多线程AVS转码器的研究与实现[D]. 哈尔滨: 哈尔滨工业大学, 2009: 53-54. |
| [8] | 章洪兵, 于永彦, 赵欢, 等. 基于DirectX的视频采集与处理系统[J]. 电脑知识与技术, 2008, 4(5): 1204-1207. |
| [9] | 余永胜. 探究基于TCP协议的网络应用设计与开发[J]. 电子制作, 2013, (22): 58. |
| [10] | 姜浩然, 徐林. 基于RTMP的流媒体服务器的研究[J]. 计算机与数字工程, 2011(10): 104-108. |
| [11] | 叶秀芬, LIU Peter Xiaoping, 冯伟兴, 等. 用于互联网遥操作的基于速率的点对点传输协议的研究[J]. 哈尔滨工程大学学报, 2003, 24(3): 273-277. |











