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);
结语