董 杰,辛吉涛,连 捷
(大连理工大学 电子信息与电气工程学部,辽宁 大连 116023)
基于Android系统的H.264视频直播技术研究
董 杰,辛吉涛,连 捷
(大连理工大学 电子信息与电气工程学部,辽宁 大连 116023)
随着智能移动设备的不断普及以及流媒体技术的不断发展,手机视频监控系统的应用日趋广泛。而Android手机又以其平台开放、种类繁多、用户体验良好等优点而被大多数人所选择。结合实际项目需求,提出一种基于Android系统的视频直播解决方案。首先基于RTP协议将H.264码流拆包,然后通过DatagramSocket(UDP协议的Socket)进行传输,最后在Windows环境下利用Cygwin将FFmpeg源解码库生成.so格式的目标库,并在Android系统中调用生成的动态代码库进行解码。重点分析了H.264码流的传输以及解码过程。实验证明该方案能很好地实现视频的实时播放,满足实际项目需求。
Android;H.264;DatagramSocket;视频解码;FFmpeg
随着多媒体技术、视频压缩技术以及网络传输技术的发展,视频监控正朝着数字化、网络化、智能化方向持续发展,并越来越广泛地渗透到政府、教育、娱乐、医疗等领域[1]。传统的视频监控系统一般采用台式机作为监控终端,需要在指定的地点并且有专用网络设备支持的情况下才能对目标现场进行监控,大大限制了监控系统的应用范围和灵活性[2]。而与传统的PC机监控终端相比,智能移动监控终端以其轻便、随机、灵活等优点能够满足用户随时随地获取监控信息的需求,因而显示出极大的优势。而Android手机又以其平台开放、价格低廉、种类繁多、用户体验良好等优点成为智能移动终端的主体。
但是由于Android智能移动终端的网络传输速度较慢以及内存较小等限制,通常服务端对视频数据按照H.264[3-4]标准进行编码后传输。这就需要Android终端对接收到的数据进行解码处理之后才能进行播放。本文提出一种基于An⁃droid系统的H.264视频直播解决方案,实践表明该方案实现的视频播放能够满足实际项目需求,具有较好的用户体验。
系统设计原理如图1所示。首先,视频采集装置进行视频数据采集,并将采集到的视频数据传送到视频编码设备;然后视频编码设备对接收到的视频数据进行H.264编码,并将编码后的数据传输至服务器;服务器和手机端通过Data⁃gramSocket(UDP协议的Socket)进行通信。当服务器接收到手机端发送的请求后,对H.264编码进行拆包并向手机端传送视频数据;最后Android手机端将接收到的数据组包后,调用解码模块进行解码,最终向用户展示解码后的视频信息。
图1 系统设计原理图
本系统通过视频采集、编码、拆包、传输、组包、解码、播放的流程实现实时视频监控。具体流程如图2所示。
图2 系统流程图
2.1 视频采集及编码
视频采集装置实时进行数据采集,并将采集到的数据信息传输至H.264编码器进行编码。
H.264是一种新的视频编解码标准,它在保留原有视频编码优点的基础上,提出了以往视频编解码技术无法比拟的一些优点,如低码率、网络适应能力强、容错能力强等[5]。H.264充分地利用了各种冗余来达到高效的数据压缩比率,同时还具备高质量流通的图形,采用高度负责的算法,使其成为当前在低码率下压缩比率最高的视频编码标准[6]。基于以上优点,本系统采用H.264编码机制对视频文件进行编码传输。
2.2 视频传输
TCP[7]协议是面向连接的传输协议,由于通信前需要建立连接,因而传输时延较大;TCP协议的流量控制机制以及确认和重发机制能够保证数据传输的可靠性,但是处理复杂,传输效率不高。而UDP[7]协议由于是无连接的传输层协议,通信前不建立连接,直接向接收方发送数据,因而节省了大量的网络状态确认和数据确认的系统资源消耗,大大提高UDP协议的传输效率,传输速度快。
视频图像传输需满足以下3点:
1)要求传输延时小,实时性高;
2)传输流量大,要求传输效率高;
3)在一定程序上允许传输错误或数据丢失。
根据以上特点可知,使用UDP协议来传输视频相对TCP协议更理想。
传输规则定义如下:
本协议以1开始定义参数类型,如通道号以1开始。
本协议采用大端模式的网络字节序传输字和双字。约定如下:
1)字节(byte,int8)按照字节流的顺序传输;
2)字(word,int16)先传输高8位,再传输低8位;
3)双字(dword,int32)先传输高8位,然后传输低8位,再传输低16位,最后传输低24位。
自定义通用消息头结构如表1所示。
表1 通用消息头结构
2.2.1 拆包
在网络传输中如果传输的IP报文大小超过最大传输单元(Maximum Transmission Unit,MTU)时就会产生IP分片情况。在以太网环境中可传输的最大IP报文(MTU)的大小为1 500 byte。除去IP头20 byte,UDP头8 byte,RTP头12 byte,RTP的最大传输量为1 460 byte。如果发送的IP数据包大于MTU,数据包就会被拆开来传送,因而产生数据包碎片,降低网络速度,增加丢包率。对于视频传输而言,若RTP包大于MTU而由底层协议任意拆包,可能会导致接收端播放器的延时播放,甚至无法正常播放。因此对于大于MTU的NALU单元,必须进行拆包处理。
RFC3984给出3种不同的RTP拆包方案:
1)Single NALU Packet(单一NAL单元模式);
2)Aggregation Packet(组合封包模式);
3)Fragmentation Unit(分片封包模式FU)。
具体拆包方法在此不再赘述。
2.2.2 传输
本系统采用DatagramSocket(UDP协议的Socket)进行数据的接收和发送。Java使用DatagramPacket来代表数据报,DatagramSocket接收和发送的数据都是通过DatagramPacket对象完成的。具体步骤如下:
1)创建DatagramSocket实例
m_sock=new DatagramSocket();
2)使用DatagramSocket类的send()和receive()方法发送和接收DatagramPacket实例
m_recvPack=new DatagramPacket
(m_byRecvbuf,m_byRecvbuf.length);
m_sock.setSoTimeout(50);
m_sock.receive(m_recvPack);
3)使用DatagramSocket类的close()方法销毁该套接字m_sock.close();
2.2.3 组包
系统根据表2定义的视频传输通用头结构进行组包,如果组包过程中出现丢包现象或者接收完当前帧所有包但不包含关键帧,则放弃当前已接收的所有数据继续接收下一帧,否则调用解码程序进行解码。具体解码流程如图3所示。
2.3 视频解码
由于Android端从服务端获得的是H.264编码数据,这就需要Android终端对接收到的数据进行解码处理之后才能进行播放。因此首先搭建Cygwin环境,然后在Windows环境下利用Cygwin把FFmpeg源解码库生成.so格式的目标库,最后在Android系统中利用JNI技术调用生成的动态代码库对视频数据流进行解码。
2.3.1 FFmpeg编译
表2 视频传输通用头结构
图3 组包流程图
首先在D盘下新建FFmpeg-1.10.7文件夹,在该文件夹下新建jni文件夹,把下载的源代码解压到该文件夹下。每次编译之前需要对参数进行配置。在jni文件夹下新建config.sh配置文件。然后打开cmd,输入bash--login-i,执行命令./ config.sh,如果配置正确的话,显示出如下两行内容:
License:nonfree and unredistributable
Creating config.mak and config.h...
进入jni目录,在刚刚生成的config.h中找到#define re⁃strict restrict。因为Android的gcc并不认得restrict这个关键字,所以把它改写成#define restrict。
将/libavutil/libm.h中所有的static函数全部注释掉。分別修改libavcodec,libavfilter,libavformat,libavutil,libpostproc和libswscale目录下的Makefile文件,将下面内容注释掉:
include$(SUBDIR)../config.mak
在jni目录下建立一个脚本文件av.mk并进行配置。
在jni目录下及其下面的jni/libavformat目录、jni/libavco⁃dec目录和其他libavfilter,libavutil,libpostproc和libswscale目录下都分別新建相应的Android.mk文件。
在jni目录下新建jni目录,并把C语言驱动程序com_act1_H264.c,com_act1_H264.h(见3.3.2JNI调用动态代码库)和Android.mk放到该目录中。在cygwin命令行窗口中,到d:ffmpeg-0.10.7目录下,执行ndk-build即可生成需要的动态链接库libmylibffmepg.so。
2.3.2 JNI调用动态代码库
JNI是Java Native Interface的缩写,中文为Java本地调用。从Java1.1开始,JNI标准成为Java平台的一部分,它允许Java代码和其他语言写的代码进行交互。JNI一开始是为了本地已编译语言,尤其是C和C++而设计的,但是它并不妨碍使用其他语言,只要调用约定受支持即可[8]。具体实现方法如下:
1)创建JNI接口类H.264
private native int InitCodec();
private native void DeleteCodec(int index);
private native byte[]FFInputFrame
(byte[]data,int iLen,int index);
private native byte[]GetBMPHeade(int index);
2)编译H.264文件,生成com_act1_H264.h文件。
3)编写com_act1_H264.c文件。
4)根据3.3.1介绍的编译方法生成.so文件。
5)调用生成的动态库
static{
System.loadLibrary("mylibffmepg");
}
mylibffmepg是要调用的库的名称。编译器会自动在前面加上lib,在后面加上.so。
2.3.3 解码
在程序中通过调用类H.264中的函数完成解码过程,解码详细过程见图4。
图4 解码详细过程
2.4 Android端显示
首先进入DetailActivity选择通道,如果选择了一个通道,则处理通道信息并执行start SingleDeviceActivity,进行单通道视频播放;如果选择了多个通道,则存储信息后并start VideoGridListActivity,进行多通道视频播放。视频播放详细界面如图5所示。
图5 单通道及多通道图像显示界面
通过实验验证,该方案能够适应不同网络环境下视频的接收和播放。其中WiFi和3G环境下视频播放流畅,丢包率较低,2G条件下也能满足基本的视频播放,但相对WiFi和3G环境下视频丢包率较高。不同网络条件下播放情况及丢包率比较如表3所示。
表3 不同网络条件下效果比较
2.5 网络异常条件下的丢包以及包的乱序处理
当网络传输不稳定时易出现丢包或包的传输乱序等情况。若不对丢包进行处理则播放画面将出现花屏现象。在组包处理时对于丢包的帧整体删除,不予播放。这就避免了由于丢包引起的花屏现象,用户体验较好。但是有时会出现当前帧的某些包在接收完下一帧的部分包之后才被传输过来的现象。此时若不做任何处理就把前一帧删除,将会浪费一帧,影响整体播放效果。笔者在处理时创建一个缓冲区,若换帧但当前帧的包没有接收完,则将前一帧放入缓冲区内等待,若组包成功则解码播放;否则若在第3帧到来时仍未组包成功,此时再删除第一帧。这样就在一定程度上避免了因包的乱序传输引起的人为丢包现象。
整个程序中对FFmpeg的编译和动态链接库的使用是解码器设计的关键,在设计解码器之前,先进行了FFmpeg的编译工作。在对FFmpeg源代码编译生成ffmpeg.so之后,还要对用C语言写成的驱动程序进行二次编译生成libffmepg.so。这样在最终程序中就需要装载两个动态库,由于两个库中相关函数的冲突,导致本地视频播放时出现崩溃。由于动态库中函数很多,排查起来工作量很大,所以需要排查函数之外的解决方案。
解决方法是把两个动态库合成一个动态库。笔者在编译过程中基于JNI机制的原理,尝试在ffmpeg目录下新建文件夹jni,把自己编写的C程序复制到该文件夹中,并修改设置使该jni目录与同层的libavcodec等目录一起被编译成为libffmepg.so的一部分,这样实现了把ffmpeg.so和libffmepg.so两个动态库合成一个动态库libffmepg.so。
通过以上的合并方法简化了编译工作,通过运行程序验证该方法是可行的。
[1]曹晓芳,王超,李杰.一种基于Android智能手机的远程视频监控的设计[J].电子器件,2011(6):709-712.
[2]李佳毅,徐晓辉,苏彦莽,等.基于Android平台的智能温室视频无线监控系统[J].农机化研究,2013(8):188-191.
[3] ITU2T Reeonunendation.H.263,Video Coding for low bit rate communieation[S].2000.
[4] 王嵩,薛全,张颖,等.H.264视频编码新标准及性能分析[J].电视技术,2003(6):25-27.
[5] SRINIVASAN K S.The effects of priority levels and buffering on the statistical multiplexing of single-layer H.264/AVC and SVC en⁃coded video streams[J].IEEE Trans.Broadcasting,2010,56(3):281-286.
[6] 罗欢,谢云,李丕杉.基于Android智能电视的视频监控的设计[J].电视技术,2013,37(22):85-87.
[7]沈兰荪,卓力.小波编码与网络视频传输[M].北京:科学出版社,2005.
[8] 农丽萍,王力虎,黄一平.Android在嵌入式车载导航系统的应用研究[J].计算机工程与设计,2010(11):2473-2476.
Study on H.264 Live Video Technology with Andriod System
DONG Jie,XIN Jitao,LIAN Jie
(School of Control Science and Engineering,Dalian University of Technology,Liaoning Dalian 116023,China)
With the popularity of smart mobile devices and the development of streaming media technology,the mobile video surveillance system is more and more popular.The Android mobile phone has been widely used because of open platforms,wide variety,good user experience,etc.In this paper,a solution for live video based on Android system is proposed.First,H.264 stream is unpacked based on the RTP protocol.Second,the generated package is transmitted via DatagramSocket(Socket of UDP protocols).Finally,dynamic library(.so)is generated from FFmpeg library by using Cygwin in the Windows system,and uses dynamic library to decode in the Android system.This paper focuses on the transmission and the decoding process of H.264 stream.The experimental results show the validity and practicability of the proposed solution and met the demand of the program.
Android;H.264;DatagramSocket;video decoding;FFmpeg
TP277
A
10.16280/j.videoe.2015.04.004
2014-08-22
【本文献信息】董杰,辛吉涛,连捷.基于Android系统的H.264视频直播技术研究[J].电视技术,2015,39(4).
国家自然科学基金项目(61374070)
董 杰(1981—),博士,硕士研究生导师,讲师,主要研究领域为智能信息处理;辛吉涛(1989—),硕士研究生,主要研究领域为智能信息处理;
连 捷(1980—),女,博士,博士生导师,副教授,主要研究领域为切换系统稳定性分析和设计。
责任编辑:许 盈