出租车行业的发展给人们的出行带来了极大的便利,伴随租出车数量的增多一些针对出租车的强盗案件也逐年上升,出租车公司对车辆状态的监测也成为紧迫的需求。针对此种情况开发了基于MPEG-4的出租车无线视频监控解决方案,本文主要介绍方案的软件系统。本系统同已有的局域网监控相比具有明显的优势。不受地域、距离限制无须布线,非常适合出租车分布范围广,移动范围大,终端数量多的特性。
MPEG-4(ISO/IEC14496)通过帧重建技术来压缩和传输数据,以极少的数据量获得了极佳的图像效果,已成为目前市场上数字视频编解码技术的主流。
本文结合出租车实际情况设计了整体架构,硬件电路,软件框架和具体实现的整套解决方案。硬件设计划分为基于TMS320DM270双核处理器的视频采集处理模块、CDMA传输模块和GPS接收模块。软件设计划分为整体调度模块、采用完IOCP技术的网络传输模块、采用XviD开放源码构造的MPE-4视频解压播放模块、基于MySQL的数据库存储模块。整个系统模型具有很高的扩展性,各部分功能方便重用和替换,经测试是一套实用可靠的高效方案。
系统总体结构
网络拓扑结构
网络拓扑结构图如图1所示,整个系统分为3部分。
每一台出租车装有一个嵌入式设备,包括CDMA通讯模块、GPS采集模块、视频输入输出模块和基于TMS320DM270的MPEG-4编码、控制模块,在出租车终端完成视频信号的采集、转换和压缩。从CDMA内网发起对服务器的连接,进行通讯。
·CDMA网中的出租车终端
高性能服务器架设在公网,通过出租车终端的IP和ID管理各个终端,所有监控终端与出租车终端通讯的命令和请求也都通过服务器进行转发,可以通过服务器设置不同监控终端的访问权限,出租车报警后发送的视频和图片数据都在服务器备份,实时GPS数据通过数据库保存。
·客户端
采用C/S模式,在普通PC机上安装客户端软件,在Internet上的任意位置,使用经过授权的用户名及密码可访问有固定IP地址的服务器实现实时监控。
·软件体系结构
软件的体系结构及各个部分之间的数据流和控制流的交互如图2。
1)服务器主控制模块:完成整个服务器系统的初始化,解析网络模块接收到的数据和命令,调用其他模块进行相应的处理,实现具体功能
2)网络传输模块:所有的数据流和控制命令都通过调用网络传输模块的接收和发送功能来实现。
3)用户管理模块:对登录到服务器的用户进行身份和权限认证。根据设定的权限和分组规则,为用户提供对应的服务。可修改管理员和个人用户密码。保证系统的安全性和保密要求。
4)文件操作模块:增加、删除、修改、查询文件。对接收到需要保存的图片和图像数据写文件保存,为客户端的请求提供文件。
5)数据库模块:增加、修改、查询和删除,GPS信息、错误记录和日志记录。
客户端有3个模块
1)视频显示模块:调用sPlayer.ocx解压显示图像。
2)地图显示模块:通过对sinomaps的地图控件二次开发生成mapspeed.ocx,实时显示出租车的位置。
3)文件操作模块和网络模块与服务器端的功能基本相同。
系统主要技术
MPEG-4视频压缩技术
测试表明,MPEG-4视音频全同步时数据流量为36Kb~336Kb,仅为MJPG或MPEG1的1/10,画面质量可以达到近似DVD的效果。
XviD编解码技术
·多种编码模式
除了最原始单重估定码流压缩(1一passCBR)之外,XviD提供了包括:单重质量模式动态码流压缩、单重量化(Quantization)模式动态码流压缩、和包括外部控制和内部控制的两种双重(2一pass)动态码流压缩模式。XviD显然是目前PC上的MPEG4编码内核中,可选模式最多的视频编码。
·量化方式和范围控制
XviD不仅提供了标准的MPEG量化方式,还特地提供了更适合低码流压缩的H.263量化方式。并且XviD还可以在双重(2-pass)运算时,根据对画面信息的综合分析,动态的决定某段场景的画面量化方式。除了量化方式选择,XviD还提供了强大的对压缩过程中的量化幅度的范围控制。
XviD提供了多极运动侦测精度。包括半像素插值(half pixel interpolation)的技术以l6x16像素的微区块为单元标示上运动矢量;以及4分运动矢量(inter4v motion vectors)的方式,以8x8的像素区块为单元更细致的纪录运动向量以供二重分析。
·动态关键帧距
在视频压缩中,I帧记录全部的画面信息,而后续插入的P帧(P—Frame)仅记录下与之前一帧的差值。因此根据画面镜头切换和运动幅度变换关键帧I帧的位置,对于视频压缩下的画面质量提高,有明显效果。
·人类视觉系统HVS(Human Visual System)
完成端口(IOCP)机制
IOCP(I/O Completion Port,输入/输出完成端口)是一种能够合理利用与管理多线程的机制。该机制使用完成端口,用一定数量的线程处理重叠I/O(Overlapped I/O)技术,帮助处理大量客户端请求,并使系统的性能达到较佳状态 。从性能上考虑,与采用Select模型和Overlapped模型相比,采用完成端口模型在请求响应的并行性上更胜一筹,I/O完成端口提供的多线程特性是一般异步模型所无法达到的。而且IOCP尤其适合为大量I/O请求提供服务,对于提高服务器效率大有裨益。
系统分析与实现
本解决方案的开发基础为Windows Server2003,开发工具为VC.NET2003。
数据包装和解析的实现
网络传输数据包通过自加包头进行解析,通过不同通道传送视频数据/控制命令。加载过程如图3。
服务器的网络传输部分的实现
1.启动监听线程并初始化完成端口(IOCP)核心对象,进入对CDMA终端喝监控终端的监听状态,主要通过CreateIoCompletionPort函数实现,此函数主要实现两个功能1)建立IOCP对象,2)将接受到的套接字(SOCKET)同IOCP关联。
HANDLE CreateIoCompletionPort(
HANDLE FileHandle,//功能1时为INVALID_HANDLE_VALUE,功能2时为接受的SOCKET
HANDLE ExistingCompletionPort,,//功能1时赋值NULL,功能2时输入已建立的IOCP对象
ULONG_PTR CompletionKey,//完成键自设的数据结构,功能1时为NULL,功能2时完成键
DWORD NumberOfConcurrentThreads ) //同时可操作IOCP对象的线程数,设为CPU数×2+2
2.调用异步接收函数WSARecv()发起接收 SAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
3.查看完成端口的通讯队列,异步接收出租车终端发送的数据和通讯命令,通过调用GetQueuedCompletionStatus( )函数实现,
BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort,//查看的完成端口对象
LPDWORD lpNumberOfBytes,,// 期望读入的字节数
PULONG_PTR lpCompletionKey,// 完成键,自设的数据结构
LPOVERLAPPED* lpOverlapped,// 重叠IO标志,每次查询时需事先清零复位
DWORD dwMilliseconds) // 设置查询超时时间
4.自设完成键数据结构如下,包含
struct CMD_CDMA_LINK_INFO
{ SOCKET m_hSocket; // 通讯套接字SOCKET
UINT m_uiCDMAId; //无符号整型变量保存出租车终端ID
CString m_strCDMAIP; //字符串变量保存出租车终端IP地址
bool m_bCmdCDMALinkState; //布尔型变量保存连接状态
int m_nNumberOfPendlingIO; //整型变量保存挂起I/O数
bool m_bAlarm; //布尔型变量保存报警标志
CCriticalSection m_cmdCDMALinkInfoLock; };//临界区变量,作线程同步
客户端的解压实现
客户端也采用多个线程并行处理的模式,分别负责数据通讯、数据处理、解压显示和地图刷新,MPEG-4的解码主要采用XviD解压库。MPEG-4协议有非对称性的特点,即压缩运算量大,复杂性高,为保证视频信息的实时性,视频采集压缩由硬件完成;而解压运算量较小,可以借鉴XviD编解码技术来实现。如前所述,XviD编解码技术有很多突出的优点。在解码过程中解压主函数实现如下
int CDecThread::dec_main(BYTE* istream, BYTE* ostream,int istream_size,
xvid_dec_stats_t * xvid_dec_stats)
{int ret=XviD_ERR_FAIL; //默认值-1
/* Reset all structures */
memset(&xvid_dec_frame, 0, sizeof(xvid_dec_frame_t));
memset(xvid_dec_stats, 0, sizeof(xvid_dec_stats_t)); //初始化所有数据结构
/* Set version设置解压版本*/
xvid_dec_frame.version = XviD_VERSION;
xvid_dec_stats->version = XviD_VERSION;
/* No general flags to set //设置主标志位*/
xvid_dec_frame.general = 0;
/* Input stream输入解压数据流*/
xvid_dec_frame.bitstream = istream;
xvid_dec_frame.length = istream_size;
/* Output frame structure输出帧结构 */
xvid_dec_frame.output.plane[0] = ostream;
xvid_dec_frame.output.stride[0] = m_nXDIM*m_nBPP;
xvid_dec_frame.output.csp = m_nCSP;
ret = xvid_decore(dec_handle, XviD_DEC_DECODE, &xvid_dec_frame, xvid_dec_stats);
return(ret);
结语