android是google公司推出的基于linux的开源手机操作系统,由于代码开源,受到很多手机厂家的青睐。可视对讲系统在android操作系统未出现之前,软件研发一般采用底层语言,容易出现功能单一、产品升级困难等情况,要在对讲系统中开发出具有3d图形效果的界面更是难上加难。鉴于此,本文利用android平台的可移植性、代码开源等优势,结合jni、ndk技术,提出了基于android平台的可视对讲系统的设计方案并加以实现。
jni[1](java native interface)是java本地调用接口,它使得运行于android平台的java程序可以使用c、c++甚至汇编语言编写的动态链接库。在需要频繁访问内存或复杂计算的情况下,使用c动态链接库比在android平台上使用java语言实现相同功能更具有效率[2]。ndk[3](native development kit)提供了一系列的工具,可以生成arm二进制码的动态库,并且能自动地将生成的动态库和java应用程序一起打包成android系统可以直接安装的apk安装包,即ndk可以将包含jni接口函数的c源程序文件编译生成动态库,供android应用程序调用,提高了对现有代码的重用性,而加快了开发进度。
本文提出一种可视对讲系统设计方案,对讲双方为门口机和室内机,并将设计方案在i.mx51硬件平台进行实现。门口机进行音视频的采集、编码、传输及音频解码、播放;室内机采用android平台,但考虑用户室内信息的保密性,室内机没有视频采集功能,室内机只进行音视频的解码、播放以及音频的采集、编码、传输。
1 可视对讲系统设计
1.1 通信流程设计
数据包传输协议使用面向无连接、资源消耗小、处理速度快的udp协议。寻址完成建立udp直连后,门口机首先对视频进行编码传输,直到被叫方按下接听键后,门口机才对音频数据进行传输。为了保证通话一直在线,室内机每隔一定的时间向门口机发送通话在线询问,如果收到在线确认应答则保持通话状态,否则就结束通话。可视对讲系统通信流程如图1所示。
表2中:包头为对讲数据包的标示符,命令类型、操作类型说明详见表3,时间戳主要是用于音视频的同步,数据类型分为音频和视频两种,帧序号为0~65 535。如果没有进行数据包分段,则总包数与当前包数均为1。音视频数据从第41位开始算起,音视频数据长度由数据包格式中的数据长度所指定。
根据系统通信流程图1、结合数据包格式,本对讲系统参数如表3所示。其中命令类型、操作类型分别与表2数据包格式相对应。
1.5 音视频编解码选择
系统音频编码选用g.711编码[4]。g.711是一种由国际电信联盟订定的音频编解码方式,拥有一倍的压缩率,是语音通信中最常用的编解码方式之一。采样和量化是音频编程及声音数字化的两个关键步骤,本系统使用的音频采样频率为8 khz、量化位数为16 bit、单声道。
ffmpeg是用于音频和视频开源方案,由于它的开源和免费以及跨平台的特点,受到开发商的青睐。ffmpeg支持包括xvid等在内的多达90种解码器,由c语言实现,不仅可以应用于pc软件平台,也可以用于嵌入式设备。本系统中视频选用xvid编解码器,视频格式为mpeg-4。(xvid是一个开放源代码的mpeg-4视频编解码器)视频标准采用ntsc制,视频尺寸为352×240,帧频为30 f/s;使用ndk提供的交叉编译工具将包含jni接口函数的音视频编解码源文件统一编译成为动态链接库,供android平台调用。
2 系统实现
2.1 系统软硬件平台
系统硬件平台为i.mx51 evk。i.mx51 evk是由freescale公司自主研发的,中央处理器基于arm cortex a8核心的i.mx51处理器;主频可扩展到1 ghz;处理器内部集成了ddr/ddr2内存控制器、opengl/openvg图形核心、ata控制器、以太网控制器等,支持720 p高清视频播放;指令缓存和数据缓存为32 kb,二级缓存为256 kb;其容量指标是之前arm11产品的2倍,可大大提高cpu的处理能力。同时处理器内部还集成了矢量运算的浮点运算及信号处理加速器,为多媒体信息娱乐终端提供了强大的处理核心支持[5]。
系统软件平台采用linux操作系统、eclipse集成开发环境。android sdk[6]版本为2.2,android ndk版本为android-ndk-r6。使用串口进行调试。
2.2 android平台在i.mx51 evk上的移植
系统采用4 gb的sd卡存放引导程序、内核、根文件系统等镜像。引导程序采用u-boot,linux内核版本为2.6.31。移植流程:android源码可以从http://source.android.com获取到,编译好u-boot、linux内核、根文件系统以及android系统镜像[7]后,设置i.mx51板上的s1 boot switch模式为1100000001,使用atk工具进行镜像的下载。下载后系统镜像在sd卡上分布图如图3所示。
图3中,mbr主要存储sd卡的分区信息表,起始地址为0 kb。引导程序、内核、根文件系统的起始地址分别为1 kb、1 mb、4 mb。system和recovery分别各占一个分区,system为android操作系统的镜像文件所占分区,recovery分区主要是用来备份和还原系统。
2.3 音视频编解码实现
2.3.1 音频编解码实现
音频编码与解码的区别仅在于调用的c库函数不一样,音频编解码调用的c库函数分别为g711encoder、g711decoder(本文以解码为例)。音频解码具体流程如下:
(1)音频java本地调用函数
在使用音频解码的类中编写java本地调用函数:
public native void g711decoder(byte[]pcm,byte[]code,int size,int lawflag);
(2)生成头文件
c库与java间需要一个后缀为“.h”的头文件来衔接,这个头文件通过javah命令生成,javah工具包含在jdk中。jdk是java的核心,包含java运行环境、java工具、java基础类库。
(3)jni接口函数
jni接口函数编写在c语言文件中,与音视频解码源码一起打包生成动态链接库。在接口函数中声明4个无符号指针变量:decode指向待解码的数据、depcm指向解码后的数据、enpcm指向待编码的数据、encode指向编码后的数据。解码代码如下:
void java_com_qsa_play_g711decoder
(jnienv*env,jobject this,jbytearray pcm,jbytearray code,jint size,jint lawflag)
{
depcm=(unsigned char*)(*env)->
getbytearrayelements(env,pcm,0);
decode=(unsigned char*)(*env)->
getbytearrayelements(env,code,0);
g711decoder(depcm,decode,size,lawflag);
(*env)->releasebytearrayelements(env, pcm,
(jbyte)depcm,0);
(*env)->releasebytearrayelements(env,code,(jbyte)
decode,0);
}
其中,depcm=(unsigned char*)(*env)->getbytearrayelements(env,pcm,0)用来获取java层传递的待解码字节数组的首地址,g711decoder()函数实现音频解码,(*env)->releasebytearrayelements(env,pcm, (jbyte)depcm,0)释放传递的数组成员,进行资源回收。
(4)使用ndk中ndk-build命令编译生成动态链接库
ndk-build命令是ndk命令工具集中的一个命令,与linux下shell编程中的make命令相似,它会查找文件夹中的后缀为“.mk”的makefile文件,根据该文件的依赖文件,将源文件编译成动态链接库。
2.3.2 视频编解码实现
视频的编解码流程与音频编解码流程基本相似,视频编解码调用的c库函数分别为avcodec_encode_video、avcodec_decode_video2。限于篇幅,在此重点介绍android平台视频的解码及显示。
在解码视频数据前,要先做一系列的准备工作:
(1)给出主要的数据结构
static avpacket avpkt;
static avframe*picture;
static avframe*pframergb;
static avcodec*codec;
static avcodeccontext*c= null;
static struct swscontext*img_convert_ctx;
androidbitmapinfo info;
void*pixels;
(2)初始化流程
①注册解码器
avcodec_init();
av_register_all();
②初始化avpacket、avcodeccontext、avframe
av_init_packet(&avpkt);
c=avcodec_alloc_context();
picture=avcodec_alloc_frame();
其中,avframe是数据流在编解码过程中用来保存数据缓存的对象,从数据流中读取到的数据首先保存到avpacket中。一个avpacket最多只包含一个avframe,而一个avframe可以包含好几个avpacket。avcodeccontext用于动态记录一个解码器的上下文信息。
③设置视频解码器
codec=avcodec_find_decoder(mpeg-4);
avcodec_open(c,codec);
④视频解码流程
视频解码流程如图4所示。图4中,androidbitmap_getinfo用于获取android平台bitmap对象的大小,androidbitmap_ lockpixels函数是对bitmap进行加锁、互斥使用资源。如果avpacket包中存在未解码完的数据,则调用函数avcodec_decode_ video2进行解码;若解码出一帧后需要调用函数sws_scale进行格式转换。视频数据解码完后颜色空间为yuv,需转换成rgb颜色空间。最后调用fill_bitmap函数进行数据填充及进行bitmap的解锁和资源的释放。
视频显示采用android平台的imageview控件进行显示。解码线程接收到视频数据后,通过jni调用,调用动态库中的视频解码接口函数进行解码,每解码完一帧后通过消息通知主线程进行显示图像的更新,这样就达到了视频数据动态显示的效果。
3 实现效果
android平台在i.mx51 evk平台上移植成功后,串口中android 操作系统启动信息如图5所示。 从图中的启动信息可以看出,android平台移植成功,启动信息也包含有cpu信息、内核版本、大小、加载地址、android文件系统版本等信息。
该软件开发完成后,在android工程的bin下生成apk文件,并复制apk文件到sd卡中,在android系统中安装该软件,使用门口机进行拨号,编码后的音视频数据通过网线进行传输。
本文将android手机操作系统应用于i.mx51 evk平台,并在该平台上提出了可视对讲的设计方案,分别进行了通信流程、应用协议、功能模块等设计,最后实现了系统的设计方案。但由于视频是使用软件解码,运行效率有待提高,且语音对讲部分回声消除存在问题,有待进一步研究。
英特尔凌动处理器
一文读懂无线充电技术的设计要点
低压断路器的分类
三极管的电流放大作用_三极管的特性曲线
典型比较器电路图分享
基于Android平台的可视对讲系统设计
iOS 12测试版抢先评测,传说中的开放NFC呢?
华为mate10发布在即:华为P10和荣耀9才是当前最值得购买的手机
如今手机是“小屏旗舰”更吸引人还是大屏幕更有诱惑力?
微软XboxOneS评测 来自国行的成功进阶值得入手
基于嵌入式CPU Smart Core实现机载飞行参数系统的设计
关于BMA456的性能分析和应用
面向医疗行业物联网有着怎样的架构
连锁店网络视频监控系统的应用方案
人脸识别性能接近极限 全球安防市场超高速增长
神盾光学指纹识别技术明年第二季就可量产出货
重磅|机智云获评工信部第五批服务型制造示范平台,助力制造业转型升级
你知道不同U盘在ARM+Linux下的读写速率吗?
“无服务器”计算兴起_AWS开启云应用库
攻螺纹的相关知识有哪些呢?