基于Android平台的实时监控系统客户端设计

2015-06-22 14:40赵红超
电视技术 2015年20期
关键词:音视频线程解码

赵红超,李 琦,韩 瑾,李 鼎

(河北工业大学 电子信息工程学院,天津 300401)

基于Android平台的实时监控系统客户端设计

赵红超,李 琦,韩 瑾,李 鼎

(河北工业大学 电子信息工程学院,天津 300401)

提出了一种基于Android手机平台的远程监控系统客户端的设计方案。对系统中的各个模块做了详细地研究,并针对Android平台设计了基于FFmpeg的解码方案。系统采用P2P技术、多线程机制,并对数据做了缓存处理,从而实现了实时的监视与控制性能。采用OpenGL ES渲染技术,大大提高了绘图效率。

实时监控;H.264;FFmpeg;AAC;GLSurfaceView;OpenGL;多线程

随着4G时代的到来,移动终端设备的高速智能化发展,各类智能手机操作系统性能不断提高。由Google开发的Android操作系统基于开源Linux系统实现,其中底层采用C语言设计,而应用层采用简便的Java语言进行开发[1]。其免费开源特性促进了智能手机以及平板电脑的快速发展[2],也为无线视频监控提供了很好的软、硬件平台。

视频监控具有悠久的发展历史,在安防领域拥有重要角色,对人身安全和家庭财产安全的保护起到了关键的作用[3]。近年来,随着网络技术的快速发展[4],以网络、移动通信技术为平台的移动视频监控,已经越来越成熟,应用范围也越来越广阔。移动实时视频监控不受空间上的制约,实现了远程实时监控。随着“Any Time,Any Where,Any Device”等目标[5]的提出,旧式的网络视频监控系统已经满足不了公民对生活质量日益增长的需求。基于Android平台的移动实时视频监控使这个问题得到了解决,这项应用在安防领域得到推广后,很快将会在人民大众家庭中得到普及。

本文在Android平台下提出了实时监控客户端的设计与实现方法。通过Google提供的NDK开发工具编译生成可供Java调用的动态链接库,利用JNI机制实现Java与C的交互和相互调用,从而实现高效的系统性能。通过调用开源的功能强大的FFmpeg多媒体编解码框架[6]以及OpenGL ES图像库来对媒体数据进行解码和播放,实现了实时高清的监控系统性能。

1 系统结构

1.1 系统设计

本系统采用P2P技术,与传统的客户端——服务器模式不同,在P2P工作方式中每个客户终端既是客户机又是服务器。因此本系统不单单具有普通的客户端监视功能,还有对设备的控制功能,从而真正实现了实时的监视与控制。本系统有两个角色,分别是Client与Server。在Client模式下,手机作为Client来实时接收和显示媒体数据,完成监视视频画面、音频播放、拍照及录像功能;在Server模式下,手机又可以充当Server角色来实现对设备的控制功能,包括视频画质控制、灯的开关控制、报警开关控制、对摄像头的方向调整控制以及与设备的对讲。总体功能框架如图1所示。

图1 系统功能框架

1.2 系统Client模式

本视频监控系统的Client模式整体分为4个模块,分别是数据接收模块、数据解码模块、数据播放模块和数据存储模块。接收模块主要是利用LinkedList对音视频数据进行接收与缓存,解码模块负责对接收到的多媒体数据进行相应的解码,数据播放模块则根据一定的同步原则进行音视频的同步播放,存储模块即对拍照所获图片与录像所得视频进行保存。系统Client模式流程如图2所示。

图2 系统Client模式流程

Android中的一个应用程序对应着一个进程,一个进程中有一个主线程(UI Thread),主要负责UI界面的渲染、更新和控件间的交互,所以在主线程中执行任务所需时间越短越好,为了避免阻塞,主线程应将耗时较长的事件交由子线程来处理。

由于对媒体数据的接收和解码以及播放都是非常耗时的复杂和持续过程,若其中有一个过程阻塞就会影响整体程序的运行,从而导致视频卡顿不连续的现象,所以本系统使用多线程来并行处理对数据的接收、解码和播放。本系统中共有6个子线程在同时工作,包括视频接收子线程VideoThread、视频解码子线程VideoDecodeThread、视频渲染子线程RenderThread、音频接收子线程AudioThread、音频解码子线程AudioDecodeThread以及音频播放子线程AudioWriteThread,从而使对音视频数据的接收、解码与播放分别处于不同的子线程,并将结果交由主线程来处理,有效地解决了主线程阻塞问题。

1.2.1 数据接收模块

数据接收模块主要与远程服务会话,然后根据会话结果接收远程摄像头所监控的视频数据。由于受到网络不稳定性的影响,到达客户端的数据包会出现抖动或时延,为了避免这种现象的发生,接收模块采用缓冲机制。首先为了能够完成保存每一帧数据和信息,创建VideoData类和AudioData类,其中VideoData类中保存着编码类型、帧数据、帧类型、帧大小、时间戳和帧编号,同样AudioData类中保存着编码类型、帧数据、帧大小、时间戳和帧编号;然后利用Java中的LinkedList对数据进行缓冲,缓冲示意图如图3所示。

图3 缓冲示意图

LinkedList是Java中的双向列表,是基于链表的数据结构。LinkedList列表中的每个节点都包含了对前一个和后一个元素的引用,可以被当作堆栈、队列或双端队列进行操作,以方便在内存区域的队尾插入(add)数据以及在队头进行读取删除(remove)数据。本系统中的缓冲机制即利用LinkedList的size()方法进行实时观测缓冲区中的数据长度,当缓冲区的数据达到所设定的值时,人为进行remove操作,经实验测试当缓冲区最大长度设为10帧的时候既能起到缓冲的效果又不至于给手机内存造成太大负担。

1.2.2 数据解码模块

Android自带的Media Player支持的媒体格式仅局限于OpenCore中所支持的媒体格式。FFmpeg是一种包含音视频录制、转换以及编解码等功能的开源解决方案,其支持包括H.264在内的多种编码格式的编解码,具有较高的执行效率。Android平台的应用程序是由Java来实现的运行效率较慢,为了满足速度的要求,本系统在C层采用FFmpeg开源方案对H.264视频和AAC音频进行解码。

1.2.3 数据播放模块

播放媒体数据就是对视频画面的渲染和音频数据的播放。为了提高画面渲染效率,本系统使用OpenGL ES来渲染实时视频图像。OpenGL ES是为了充分利用硬件加速,专门针对手机、PDA和游戏主机等嵌入式设备而设计的,适合复杂的、图形密集的程序。

Android中使用GLSurfaceView来显示OpenGL视图,该类继承SurfaceView并包含了一个专门用于渲染3D的接口Renderer,主要通过实现onSurfaceCreated、onSurfaceChanged及onDrawFrame等函数来完成图像渲染。

1.2.4 数据存储模块

在视频监控过程中有时会检测到异常情况,而为了现实生活中的现取留证有时需要拍照或者录像功能,从而保存数据以待以后查询调取。因本系统是实时监控系统,若像普通视频监控系统一样将数据保存到本地,当长时间录制视频时则需要很大的内存空间,从而给设备带来很大的内存负担。为此,本系统的解决方法是将拍照和录像后得到的媒体数据保存到云上,而在手机上保存的仅是在云上的链接地址,当用户想要查看时则可直接从云上调取数据并进行播放。

该模块以保存存储路径来代替传统的本地保存数据,能够给用户设备节省很多内存,从而解决了因占用内存过多导致设备性能差的问题。但是存在的缺点是如果用户想翻看录制的视频或者是所拍的照片则都必须连接网络,不过这比起占用内存来说是可以接受的。

1.3 系统Server模式

本视频监控系统的Server模式即客户端给设备发送控制命令或音频数据,从而控制设备进行相应的操作以及与设备进行对讲。

系统中灯的设置是为了方便用户在晚上或者光线不好的情况下对所关心区域进行监控;远程控制警报的开关能够很好地避免因误判而造成的长时间扰民的警报声;视频质量的选择能够避免在网络状况不佳的状态下因进行高质量的传输而造成视频的卡顿;云台控制摄像头的转动能够方便用户查看所监控区域每个方向的状况。综上所述本系统的Server模式的设计给用户带来了很大的便利,使用户不仅仅是被动地接收和显示数据,还可以操作控制设备,方便地控制设备监测用户所想要看到的区域。

2 FFmpeg音视频解码

Android应用层程序是由Java高级语言来实现的,每个应用程序都对应存在着一个独立的驻留在一个由Linux内核管理的进程中的Dalvik虚拟机实例。Dalvik虚拟机支持Java Native Interface编程方式,JNI即连接Java与C或C++之间通信的桥梁,Android应用层可以通过JNI实现Java与C的交互。Java与C/C++之间的通信实质上最终是通过生成库来实现的,所以要想调用Native方法就要利用NDK来编译C文件并生成相应的动态链接库[7]。

Android NDK与Linux系统有一定的差异,在跨平台编译FFmpeg源代码时不能采用原有makefile文件,而要通过编写Android.mk文件来指定所要编译生成的so库名、引用的头文件目录、需要编译的.c或.cpp文件以及.a静态库文件等,通过编写Application.mk来描述在应用程序中所需要的静态库或动态库。

2.1 音视频解码

FFmpeg拥有庞大的功能体系,在解码方面其包含多种格式解码器,所以利用FFmpeg能够解码多种格式的媒体数据,并且在解码后可以对媒体数据进行相应的转码,从而得到想要的数据格式,故而可以灵活方便地对多媒体进行解码。解码主要流程如图4所示。

图4 视频解码流程

由于本系统是实时的,所以要不断接收媒体数据并对其进行解码,所以将整个解码流程封装成3个接口,分别是初始化init、解码decode和关闭close。这样系统只需在开始和结束时分别执行一次init和close,中间循环调用decode来解码,避免了因频繁初始化和开启释放内存空间带来的不必要操作,提高代码执行效率。

具体工作流程是:首先在init中,要用av_register_all来注册所有容器格式和CODEC,以备后面进行相应的调用,然后要用av_init_packet来使用默认值初始化AVPacket,其中AVPacket是存储压缩编码数据相关信息的结构体,调用avcodec_find_decoder来查找特定的解码器,并调用avcodec_open来打开该解码器,并用av_frame_alloc来为解码帧分配内存空间。然后在decode中要利用avcodec_decode_video2和avcodec_decode_audio4分别进行解码视频和音频数据,并将结果返回。最后在close中要调用av_free_packet和av_free来分别释放AVPacket与AVFrame对象,并关闭初始化时所开辟的内存。

2.2 视频转码

调用avcodec_decode_video2解码出的视频数据格式是YUV420P,而Android中不支持直接渲染YUV数据,故需要将解码后的YUV420P格式数据转码成在Android中可渲染的RGB格式。

调用FFmpeg中的函数可以很容易地将视频转换成某一格式,而Android中的Bitmap配置中支持的ARGB_8888数据格式在pixmft.h中并没有定义,所以要想渲染ARGB_8888格式的数据则需要自己研究转码方法。本文采用的方法是先将byte类型RGB数据当作无符号数转换成int类型RGB数据,再按位操作转换成ARGB数据,按位操作大大提高了计算效率,从而节省解码时间。其中涉及到的数学转换公式为

R=Y+(360(V-128))>>8

(1)

G=Y-(88(U-128)>>8)

(2)

B=Y+(455(U-128))>>8

(3)

3 音视频同步

对媒体数据的播放最关键的就是音视频的同步问题,而解决同步问题的最好方法就是时间戳,在生成媒体数据时给其分别添加时间戳,播放时将音视频数据都参考某一特定的时间来播放。音视频基于时间戳的同步有三种方案,第一种是以外部时钟为参考,第二种是以音频时间戳为参考,第三种是以视频时间戳为参考。以外部时钟为参考需要设立一个满足要求的外部时钟比较浪费资源,故不采纳。由于人对影像的敏感度比对声音的敏感度要高,所以本文采用第二种方案,以音频时间为参考,将视频同步于音频。

本系统中的音频播放是需要用户控制的,当用户按下音频按钮,该客户端将给设备发送音频请求指令。当系统接收到音频数据并解码完成等待播放时,要将该AudioData对象的时间戳apts与此时将要播放的VideoData对象时间戳vpts作对比,vpts大于apts则将当前AudioData对象丢弃,否则正常播放。

4 媒体播放

视频渲染采用GLSuerfaceView渲染器进行,通过实现GLSurfaceView中Renderer接口中的3个方法onSurfaceCreated、onSurfaceChanged、onDrawFrame来完成持续渲染。onDrawFrame在渲染的过程中起主要作用,系统每一次重画GLSurfaceView都要调用onDrawFrame方法并在其中绑定纹理,使用这个方法去作为主要的绘制和重新绘制graphic对象的执行点。传统的ImageView渲染方法只能在UI主线程操作,会经常造成UI线程的阻塞,而GLSuerfaceView则是直接在子线程进行渲染,不用回到主线程,从而提高了系统性能。

由于MediaPlayer只能播放文件流,而监控系统是实时的,所以音频播放采用的是AudioTrack,其中的play()与write()方法均调用由C编写的Native方法,大大提高了执行效率。

通过实际测试,本系统有效地解决了视频延迟等问题,达到了实时监控的要求。图5为实时监控系统界面图。

5 结束语

随着生活质量的提高,实时监控越来越受大众欢迎,同时对监控系统的性能要求也越来越高,流畅清晰的画面也是必须实现的功能。本文采用GLSuerfaceView来对视频画面进行渲染,采用AudioTrack来完成声音的播放,并利用多线程分别处理音视频的接收、解码和播放,通过缓冲机制有效地解决了视频延迟卡顿现象,达到了实时性的要求。

[1] 李向军,张小菲,王书阵.一种基于Android平台的移动终端多媒体播放器的扩展设计[J].微电子学与计算机,2014,31(2):118-121.

图5 实时监控系统界面(截图)

[2] 胡顾飞,汤文兵,朱成亮.基于Android平台的纹理映射分析与实现[J].中国新技术新产品,2011(12):33.

[3] 王咸锋,林华.手机远程视频实时监控系统的设计与实现[J].微计算机信息,2007,23(34):111-112.

[4] 郝明磊.基于Android实时视频监控客户端设计与实现[D].宁波:宁波大学,2014.

[5] 杨明极,毕晶.基于Android视频客户端的设计[J].电视技术,2012,36(3):43-47.

[6] 马洪堂.基于FFmpeg的视频转换系统的模块研究[J].电脑知识与技术,2009(5):3545-3546.

[7] 李炜锋,于鸿洋.基于Android的视频软硬解码及渲染的对比研究与实现[J].电视技术,2014,38(9):67-70.

[8] 刘云粼,王树东.基于SSE2的YUV与RGB色彩空间转换[J].中国图象图形学报,2010,15(1)45-49.

赵红超(1989— ),女,硕士生,主研嵌入式系统开发、视频处理;

李 琦(1974— ),教授,硕士生导师,主要研究方向为无线通信、嵌入式系统;

韩 瑾(1991— ),女,硕士生,主研无线网络技术;

李 鼎(1987— ),硕士生,主研无线通信与网络。

责任编辑:许 盈

Design of Real-time Monitoring System Client Based on Android Platform

ZHAO Hongchao, LI Qi, HAN Jin, LI Ding

(School of Electronic and Information Engineering, Hebei University of Technology, Tianjin 300401,China)

A design scheme of remote monitoring system client based on Android mobile platform is proposed in order to realize mobile real-time monitoring system. Every module of this system is researched in detail, and the decoding scheme based on FFmpeg is designed on Android platform. The P2P technology, multi-thread mechanism and data processing cache are used to realize the real-time performance. The efficiency of drawing image is improved greatly by OpenGL ES rendering technique.

real-time monitoring; H.264; FFmpeg; AAC; GLSurfaceView; OpenGL; multithread

河北省自然科学基金项目(F2012202116)

TN919.85

A

10.16280/j.videoe.2015.20.026

2015-05-08

【本文献信息】赵红超,李琦,韩瑾,等.基于Android平台的实时监控系统客户端设计[J].电视技术,2015,39(20).

猜你喜欢
音视频线程解码
《解码万吨站》
基于C#线程实验探究
Microchip推出首款车载以太网音视频桥接(AVB)全集成解决方案
基于国产化环境的线程池模型研究与实现
解码eUCP2.0
3KB深圳市一禾音视频科技有限公司
NAD C368解码/放大器一体机
Quad(国都)Vena解码/放大器一体机
WIFI音视频信号传输的关键问题探究
高速公路整合移动音视频系统应用