基于ARM11的H.264硬编解码视频传输系统设计
2018-05-23,,,
, , ,
(1.江南大学 物联网工程学院,江苏 无锡 214122; 2.沈阳航空航天大学 自动化学院,沈阳 110000;3.江苏联合职业技术学院 无锡机电分院,江苏 无锡 214000)
0 引言
由于视频原始数据中存在着各种冗余信息,如时间冗余、空间冗余等,故对视频原始数据进行压缩编码十分重要[1]。当前,市场上的嵌入式采集方案大多采用ASIC、FPGA等专用方案,虽然这种方案有高可靠性,高效率的优点,但其灵活性较差,整体设计周期较长,系统开发成本高[2-3];目前,市场上也有采用双核DSP处理器或者是ARM和DSP双处理器的方案,这两种方案都使用了DSP,系统编解码速度快,但系统功耗较大,成本也比较高[4-5]。
采用包含多媒体硬件编解码器的高性能单片嵌入式处理器来进行硬件编解码和智能控制,则既降低了系统的功耗和成本,同时也使得系统具有更易维护和升级的优点,若根据系统的硬件体系结构对软件作进一步地优化,便可实现高效运算[6]。通过对嵌入式技术的深入学习和研究,本文提出了一种基于S3C6410单核嵌入式处理器的视频传输系统解决方案。
1 视频传输系统总体设计
本视频传输系统主要由流媒体服务器、网络传输模块和PC机三部分组成。流媒体服务器采用以S3C6410为处理器的Tiny6410开发板。首先Tiny6410开发板上需要移植Linux操作系统,然后在操作系统上部署live555流媒体服务器,采用最新一代编解码方式H.264对采集的视频数据进行硬编码,使用RTP对数据包进行封装,然后发送给live555流媒体服务器等待传输;使用RTP/RTCP协议将视频流传输给PC,PC端对视频流解码后可进行视频的回放。系统总体结构如图1所示。
图1 系统总体结构图
2 视频传输系统硬件开发平台
系统使用的Tiny6410开发板采用Samsung公司生产的S3C6410处理器,S3C6410是基于ARM1176JZF-S核的高性能处理器,主频667 Mhz,其内部总线结构由APB、AHB和AXI组成,外围模块通过这些总线与处理器相连[7]。S3C6410中包含内存管理器MMU、LCD控制器、摄像头控制器、4路UART和1路IIC等丰富资源,内部集成的多媒体编解码器MFC支持H.264等多种音视频格式的编解码,在视频监控、可视电话等开发应用中使用十分广泛,具有体积小、功耗低、处理能力强、速度快等优点。系统硬件框图如图2所示。
图2 系统硬件框图
3 视频传输系统软件设计
系统软件设计主要由视频采集、视频编码、视频网络传输以及流媒体服务器四个模块组成,四个模块的设计如下。
3.1 视频采集模块的设计
设备驱动程序是Linux内核中的重要组成部分,它主要负责协调操作系统和硬件设备的关系,并提供由操作系统到硬件设备的接口。设备驱动程序为处于用户态的程序屏蔽了硬件的细节,从用户态程序的角度来看,通过类似于系统调用的方式即可实现对设备进行访问和操作。V4L2(Video For Linux two)是内核下编写视频设备驱动程序的规范。通过将视频应用函数封装,V4L2简化了视频采集程序的开发,提高了系统开发与维护的效率[8]。
图3 视频采集流程图
V4L2视频采集的流程如上图3所示。视频采集中的关键步骤代码如下:
(1)打开设备文件并查看设备功能
intfd=open("/dev/video0,O_RDWR);
{mathop{ m ret} olimits} = ioctl(fd, VIDIOC—QUERYSTD,& std);
(2)设置视频帧格式及制式
{mathop{ m if} olimits}(ioctl(fd, VIDIOC—S—FMT,& fmt) < 0){
{mathop{ m return} olimits} 0;
}
(3)向驱动申请帧缓冲
{mathop{ m struct} olimits} v4l2—requestbuffers req;
{mathop{ m memset} olimits} (& req, 0, sizeof (req));
{mathop{ m ioctl} olimits} (fd,VIDIOC—REQBUFS,& req)
(4)帧缓冲映射并采集数据
{mathop{ m buffers} olimits} = calloc( req.count, sizeof(Video Buffer));{mathop{ m buffers} olimits} [numBufs].start = mmap(NULL,buf.length,PROT—{mathop{ m READ} olimits} |PROT\_WRITE,MAP\_SHARED,fd,buf.m.offset);{mathop{ m enum} olimits} v4l2\_buf\_type type;
{mathop{ m type} olimits} = V4L2\_BUF\_TYPE\_VIDEO\_CAPTURE;
{mathop{ m f} olimits} (ioctl(fd, VIDIOC\_STREAMON, & type) < 0){
{mathop{ m return} olimits} - 1;
}
(5)采集结束,关闭摄像头
{mathop{ m ret} olimits} = ioctl(fd, VIDIOC\_STREAMOFF,& std);
{mathop{ m close} olimits} (fd);
3.2 视频编码模块的设计
视频编码主要是将摄像头采集的图像经过压缩编码,形成特定的文件格式或视频数据流。通过对视频数据进行H.264编码,既提高了编码效率,同时也增强了网络传输的鲁棒性[9]。
3.2.1 视频编码模型
MFC主要对存放在缓存中的摄像头数据进行编码。MFC硬件部分分为BIT processor模块和视频编解码核心模块,BIT processor模块主要负责接硬件加速、编解码速率控制以及接收处理器信号;视频编解码核心模块主要负责运动估算、帧间预测以及帧内预测,并通过BIT processor将数据存放到MFC的输出缓存中。通过模块的共享,MFC既能支持多种格式的编解码,又大大降低了硬件的冗余。
MFC library、MFC driver和用户程序共同组成了视频编码的软件部分。其中,MFC driver通过在内核中注册一个misc设备,在文件系统中生成/dev目录下的s3c-mfc设备文件,进而可以对该设备文件进行iotcl操作。MFC driver在初始化时先后完成:进行设备注册、打开系统时钟、进行寄存器物理地址映射、注册中断interrupt、获取显存framebuffer、设置位处理器缓存、对MFC硬件进行初始化。MFC硬编解码模型框图4所示。
图4 MFC硬编解码模型框图
3.2.2 视频编码程序设计
使用MFC进行视频的编解码可以通过调用MFC library中的函数实现,使得开发人员更多地专注于多媒体应用开发。使用MFC进行视频编码的简要步骤如下:
(1)打开输入设备video
defineCODEC_NODE"/dev/video0"
{mathop{ m dev} olimits} \_fp = open(CODEC\_NODE, O\_RDWR);
(2)获取设备的capability属性
{mathop{ m ret} olimits} = ioctl(cam\_c\_fp , VIDIOC\_QUERYCAP, & cap);
(3)设置设备参数
{mathop{ m codec} olimits} \_fmt.type = V4L2\_BUF\_TYPE\_VIDEO\_CAPTURE;{mathop{ m codec} olimits} \_fmt.fmt.pix.width = LCD\_WIDTH;
{mathop{ m codec} olimits} \_fmt.fmt.pix.height = LCD\_HEIGHT;
{mathop{ m codec} olimits} \_fmt.fmt.pix.pixelformat = V4L2\_PIX\_FMT\_YUV420; {mathop{ m ret} olimits} = ioctl(cam\_c\_fp , VIDIOC\_S\_FMT, & codec\_fmt);
(4)MFC初始化
{mathop{ m handle} olimits} = mfc\_encoder\_init(LCD\_WIDTH,LCD\_HEIG{mathop{ m HT} olimits} , framerate, 1000, 30); /* Codec start */
(5)设置MFC的状态
{mathop{ m start} olimits} = 1;
{mathop{ m ret} olimits} = ioctl(cam\_c\_fp, VIDIOC\_STREAMON, & start);
(6)循环读取数据
{mathop{ m while} olimits} (1){
{mathop{ m read} olimits} (cam\_c\_fp,g\_yuv,YUV\_FRAME\_BUFFER\_SIZE);{mathop{ m f} olimits} (frame\_count = = 1) {
{mathop{ m encoded} olimits} \_buf = (unsignedchar*)mfc\_encoder\_exe(handl{mathop{ m e} olimits} ,g\_yuv,YUV\_FRAME\_BUFFER\_SIZE,1,& encoded\_size);}else
{mathop{ m encoded} olimits} \_buf = (unsignedchar*)mfc\_encoder\_exe(h
{mathop{ m andle} olimits} ,g\_yuv, YUV\_FRAME\_BUFFER\_SIZE, 0,
&encoded_size);
}
其中,MFC编码初始化函数mfc_encoder_init通过调用SsbSipH264EncodeInit函数对MFC进行初始化;mfc_encoder_exe则调用MFClibrary中的SsbSipH264EncodeGetInBuf函数将要编码的数据放入MFC的输入缓存,再通过SsbSipH264EncodeExe函数对帧数据进行编码,最后通过SsbSipH264EncodeGetOutBuf函数获得编码后帧的地址。
3.3 视频网络传输模块的设计
3.3.1 H.264的RTP封装
NALU(NAL unit)数据流是由网络适配层对H.264的原始数据进行处理后形成的。下面对H.264视频流三种RTP负载格式进行介绍:当一个RTP包能放置一个NALU而不能放置两个NALU的时候,采用单个NAL单元包封装方式;聚合包主要是在RTP负载包能够放置两个或两个以上的NALU的时候,为了提高网络的传输效率,将多个NALU打包到一个RTP包中。当RTP负载包无法装载一个NALU时,则需要对NALU进行分片。H.264数据包分片步骤可见于图5,其分片规则如下:
图5 H.264数据包的分片步骤框图
1) 聚合包无法分片,只有单个NALU可进行分片。
2) NALU字节是连续的,且整数个NALU字节构成一个NALU。
3) 发送时,NALU不同分片的RTP序列号是递增有序排列的;接收时,则必须按照与发送时相同的序列号排列合并。
3.3.2 JRTPLIB库的移植与使用
JRTPLIB内部用C++实现了RTCP机制,为视频的网络传输提供了一个可靠的RTP协议库[11]。JRTPLIB 库的移植步骤如下:
1)下载并解压jthread、jrtplib 的源代码
2)配置编译环境,对jthread进行编译
./configure-host=arm-linuxCC=arm-linux-gccCX{mathop{ m X} olimits} = arm - linux - g + +
make
makeinstall
3)对JRTPLIB进行编译
./configure-host=arm-linuxCC=arm-linux-gcc{mathop{ m CXX} olimits} = {mathop{ m arm} olimits} - {mathop{ m linux} olimits} - {mathop{ m g} olimits} + + - {mathop{ m with} olimits} - {mathop{ m jthread} olimits} - {mathop{ m includes} olimits} = /usr/local/{mathop{ m include} olimits} /jthread CPPFLAGS = - I/usr/local/include/jth{mathop{ m read} olimits} LDFLAGS = - L/usr/local/lib - ljthread
make
makeinstall
4)在库目录中添加编译生成的.a文件和.so文件,完成JRTPLIB的移植。
在使用JRTPLIB库之前,先要对一些参数进行相应的设置。初始化RTP会话中的一个重要工作是设置合适的时间戳,通过调用RTPSession类中的SetTimestampUnit()函数可实现以秒为单元的时戳单元的设置;RTP 会话的实例可通过RTPSession类中的Create()函数来实现初始化;会话的通信端口和通信地址则可通过AddDestination()函数实现。最后,应用程序在传输RTP数据包时可通过调用SendPacket函数实现。
3.4 基于live555的流媒体服务器构建
本文在嵌入式Linux操作系统上部署live555服务器,完成了流媒体服务器的构建。live555是一个针对流媒体服务而提出的C++解决方案,它支持多种多媒体传输协议。该服务器框架中主要包含四个模块:UsageEnvironment模块包含抽象类TaskScheduler,主要是对系统环境进行抽象;BasicUsageEnvironment模块主要完成对输入输出信号响应的实现;而GroupSock模块则主要用于数据包的接收和发送;最重要的是GroupSock模块,其包含了RTCPInstance、RTSPClient、Sink、MediaSession和 Source众多派生类。
该流媒体服务器工作在阻塞模式,服务器初始化时,首先需要进行RTSP端口的绑定,然后进行RTSP监听,当有用户连接时,服务器会先通知RTP打包模块对数据进行打包,接着服务器再将RTP打包好的数据包转发。live555服务器运行流程如图6所示。
图6 live555服务器运行流程图
4 系统测试
在PC上安装支持多种流协议的VLC播放器,在VLC播放器中打开流文件并选择RTP协议,即可接受解码并播放tiny6410开发板通过局域网传送过来的RTP流。设置流媒体服务器IP为192.168.1.230,端口为8000。在PC端进行如下测试:
先运行tiny6410上的流媒体服务器,SecureCRT显示“The server is running”,在PC端运行VLC播放器,输入URL:RTSP://192.168.1.230:8000/,点击播放。视频传输实时性良好,系统实物测试和VLC端显示如图7所示。
图7 系统实物测试和VLC端显示图
由于时间及条件等方面的限制,该视频传输系统存在一定的时延问题。根据系统测试环境,预先在系统接收端设置500 ms的缓冲区域,但系统播放的实际时延高于500 ms,在1~1.5 s之间。VLC视频播放统计信息如图8所示。系统运行2小时,平均传输速率为165 kb/s,平均丢包率为2.2%,满足国家视频监控的标准。由于视频数据是经压缩编码后再进行传输的,这极大地提高了数据传输的效率,同时也降低了网络的压力。
图8 VLC统计信息
5 结论
本文分别从硬件和软件两个角度出发,阐述了基于ARM11的H.264硬编解码视频传输系统的设计与实现。本系统采用以ARM11为核心的S3C6410作为处理器,使用外设摄像头获取实时视频数据;在Tiny6410上移植Linux操作系统并构建live555流媒体服务器,监听用户请求;采用处理器内置的多媒体硬编解码器MFC对视频数据进行H.264编码,使编码效率得到了有效的提高;使用RTP对数据包进行封装,然后经由live555流媒体服务器转发至PC机;经测试,视频还原流畅,传输实时性良好,满足实际应用需求。
参考文献:
[1] 高 敏. 视频图像压缩中熵编码技术研究[D].哈尔滨:哈尔滨工业大学,2016.
[2] 郭诚欣,陈 红,孙 辉,等. 基于现代硬件的并行内存排序方法综述[J]. 计算机学报,2016(1):24.
[3] 杜晓婧,李树国. SHA-1算法的高速ASIC实现[J]. 微电子学与计机,2016(10):19-23.
[4] 任志玲,朱光泽.基于嵌入式和运动检测的井下视频监控系统[J].计算机测量与控制, 2014,22(5):1398-1400.
[5] 何登平,黄凌云,何 策. 基于DM3730的高清智能视频采集处理系统的设计与应用[J]. 光电子技术,2015(4):283-288.
[6] Xia T, Prevotet J C, Nouvel F. Mini-NOVA: A Lightweight ARM-based Virtualization Microkernel Supporting Dynamic Partial Reconfiguration[A].Parallel and Distributed Processing Symposium Workshop[C]. IEEE, 2015:71-80.
[7] Yin Q, Zhang J. Development of remote video monitoring system based on TCP/IP[A]. International Conference on Computer Science & Education[C]. IEEE, 2015:596-600.
[8] 田时舜,章明朝,周 跃,等. 基于DM8148的嵌入式网络视频服务器设计[J]. 计算机工程与设计,2015(5):1192-1196.
[9] Zeng B, Yeung S K A, Zhu S, et al. Perceptual Encryption of H.264 Videos: Embedding Sign-Flips Into the Integer-Based Transforms[J]. IEEE Transactions on Information Forensics & Security, 2014, 9(2):309-320.
[10] 张纪宽,彭 力,陈志勇.动态复杂背景下的智能视频监控系统设计与实现[J].计算机测量与控制,2016,24(7):100-104.
[11] Belyaev E, Vinel A, Surak A, et al. Robust Vehicle-to-Infrastructure Video Transmission for Road Surveillance Applications[J]. IEEE Transactions on Vehicular Technology, 2015, 64(7):2991-3003.