摘 要:將嵌入式Linux和無線網絡引入到視頻監控系統,闡述了系統的硬件組成;介紹了USB無線網卡驅動實現的過程;從嵌入式Linux開發環境的搭建、嵌入式流媒體服務器的設計和動態網頁的設計等方面介紹了軟件系統的具體實現過程;對動態網頁設計所涉及到的雙緩沖技術進行了詳細介紹。實現結果表明,該系統具有可靠性高、體積小、成本低和使用便利等特點,適用于移動視頻監控等實際場合。
關鍵詞:嵌入式Linux;USB無線網卡;流媒體服務器;雙緩沖;移動視頻監控
中圖分類號:TP29文獻標識碼:A
文章編號:1004-373X(2010)01-148-05
Mobile Video Surveillance System Based on ARM
HUANG Qian1,MIN Huasong1,2
(1.School of Computer Science and Technology,Wuhan University of Science and Technology,Wuhan,430065,Hubei,China;
2.Institute of Robot,Beijing University of Aeronautics and Astronautics,Beijing,100083,china)
Abstract:Embedded Linux and wireless network are adopted to video surveillance system,the construct of the system hardware is explained,the realization of USB wireless network adapter driver is presented.The implementation of software is indicated on the several aspects of Embedded Linux development environment configuration,an embedded streaming media server design and dynamic Web page design in details.In addition,the double buffering feature involved in the dynamic Web page design is introduced.Experimental result shows that the system can achieve high reliability,small size,low cost and convenience,and it can be applied to mobile video surveillance and other practical applications.
Keywords:embedded Linux;USB wireless network adapter;streaming media server;double buffering;mobile video surveillance
0 引 言
傳統的視頻監控系統[1]一般采用PC服務器的C/S(Client/Server)結構,視頻服務器由計算主機和許多存放視頻的磁盤陳列組成,專門用于視頻的存儲和傳輸。流式傳輸采用的是邊接收邊播放的原則,這需要將多媒體的編、解碼和傳輸技術很好地結合在一起。目前多媒體的編解碼技術如MPEG-4,H.264等,可以以較小的帶寬開銷來實現較高質量的視頻傳輸,然而目前的傳輸技術卻無法滿足移動視頻監控的需求[2],因為設備的移動速度和所在位置都會嚴重影響到傳輸。傳統流媒體系統體積大、成本高、可靠性低且移植性差,不能滿足這種特殊場合的應用要求。
針對傳統監控技術的不足,本文提出了基于ARM的移動視頻監控的設計與實現,設計了一種專門功能、結構簡單的流媒體服務器;采用Boa作為Web服務器,并通過瀏覽器來監控,實現跨平臺監視;采用雙緩沖技術,確保用戶能夠得到較好、較穩定的播放質量;利用USB無線網卡實現無線上網,免去布線的煩惱,方便地實現了移動視頻監控的功能。
1 系統硬件設計
硬件平臺是整個系統運作的基礎。本系統主要由流媒體服務單元、USB無線網卡、無線路由、攝像頭和監控端組成。流媒體服務單元是整個系統的核心,主要由嵌入式Linux、嵌入式處理器和外圍器件組成。
嵌入式處理器采用Intel XScale結構的PXA270[3]嵌入式微處理器,最高主頻可達624 MHz;加入wireless MMX技術,大大提升了多媒體處理能力;加入Intel SpeedStep動態管理電源技術,在保證CPU性能的情況下,最大限度地降底移動設備的功耗。在處理器豐富資源的基礎上,本系統擴展了64 MB Nand FLASH,64 MB SDRAM,16 MB Nor FLASH,4個USB主接口以及一個從接口。USB一主接口接攝像頭,用于采集視頻數據;USB一主接口接無線網卡[4],用于發送視頻數據。無線網卡采用了TCP/IP、NETBEUI傳輸協議,傳輸速率為11 Mb/s,5.5 Mb/s,2 Mb/s,1 Mb/s。其最大覆蓋范圍為35~100 m(室內)、100~300 m(室外),能較好地滿足移動視頻監控的要求。本系統硬件組成圖如圖1所示。
圖1 系統硬件結構
以PXA270為核心接收攝像頭采集到的視頻數據,經過編碼后通過無線網卡發送,再經由無線路由接入以太網,用戶通過Internet接收到視頻信息。
2 USB無線網卡驅動
在Linux系統中,提供了主機側和設備側視角的USB驅動框架[5]。從主機側角度而言,需要編寫的USB驅動程序包括主機控制器驅動和設備驅動兩大類。主機控制器驅動程序屬于USB驅動程序的核心,這部分在Linux內核源碼中已經有很好的支持。本節將重點介紹USB無線網卡設備驅動的實現[6]。
2.1 USB驅動的注冊和注銷
usbids描述了這個USB驅動所支持的USB設備列表。
static struct usbdeviceid usbids[]={
/* ZD1211 */
…
}
MODULEDEVICETABLE(usb,usbids);
usbdriver連接了USB總線與USB無線網卡,定義usbdriver并編寫注冊和注銷函數。
static struct usbdriver driver={
.name=″zd1211rw″,
.idtable=usbids,
.probe=probe,
.disconnect= disconnect,
};
static int init usbinit(void)
{
int r ;
…
zdworkqueue=createsinglethreadworkqueue(driver.name);
//創建等待隊列線程
…
r=usbregister(driver);//注冊USB子系統
…
}
static void exit usbexit(void)
{
…
usbderegister(driver);//注銷USB子系統
destroyworkqueue(zdworkqueue);//銷毀等待隊列線程
}
2.2 探測和斷開函數
在編寫USB無線網卡設備驅動時,很重要的一步是probe()和disconnect()函數,即探測和斷開函數,它們分別在設備被插入和拔出的時候被調用,用于初始化和釋放硬件資源。
static int probe(struct usbinterface *intf,const struct usbdeviceid *id)
{
…
struct usbdevice *udev=interfacetousbdev(intf);
struct netdevice *netdev=NULL;
printid(udev);
…
netdev=zdnetdevalloc(intf);//分配資源
r=registernetdev(netdev);//注冊無線網卡設備
…
error:
usbresetdevice(interfacetousbdev(intf));
zdnetdevfree(netdev);//釋放資源
return r;
}
static void disconnect(struct usbinterface *intf)
{
struct netdevice *netdev=zdintftonetdev(intf);
…
zdnetdevdisconnect(netdev);//注銷無線網卡設備
…
usbresetdevice(interfacetousbdev(intf));
zdnetdevfree(netdev);//釋放資源
…
}
2.3 USB請求塊(URB)
USB無線網卡本身的驅動部分的讀寫等操作流程有其特殊性,即以USB請求塊(URB)來貫穿始終。URB是USB主機與無線網卡設備通信的電波。
int zdusbenableint(struct zdusb *usb)
{
…
urb=usballocurb(0,GFPKERNEL);//創建URB結構體
…
usbfillinturb(urb,udev,usbrcvintpipe(udev,EPINTIN),transferbuffer,USBMAXEPINTBUFFER,inturbcomplete,usb,intr->interval);
//初始化,被安排給USB無線網卡設備
…
r=usbsubmiturb(urb,GFPKERNEL);
//被USB無線網卡設備驅動提交給USB核心
…
}
static int uploadcode(struct usbdevice *udev,const u8 *data,sizet size,u16 codeoffset,int flags)
{
…
r=usbcontrolmsg(udev,usbsndctrlpipe(udev,0),
USBREQFIRMWAREDOWNLOAD,
USBDIROUT | USBTYPEVENDOR,codeoffset,
0,p,transfersize,1000 /* ms */);
//USB驅動與USB無線網卡傳輸控制信息
…
}
3 系統軟件設計
基于ARM的移動視頻監控的軟件設計包括嵌入式Linux系統開發環境的搭建與移動視頻監控軟件設計兩大部分。
3.1 基于ARM的嵌入式Linux開發平臺
本方案采用了Linux嵌入式操作系統,以Linux 2.6.24為基礎進行裁減定制自己的內核,在編譯內核時保留必須的文件系統、存儲器、串口、USB、以太網驅動,將攝像頭、USB無線網卡驅動以模塊的形式編譯,以減少編譯后內核的大小[7,8]。Bootloader 采用blob,燒寫blob后利用tftp協議實現Linux內核和文件系統在Flash上的燒寫。在Redhat 9 安裝Arm-linux-gcc,建立交叉編譯環境,實現流媒體服務器和Boa在PAX270上的搭建。鑒于現在燒寫技術已經很成熟,故不詳細討論。
3.2 移動視頻監控軟件的設計
移動視頻監控軟件完成的主要功能有:設計流媒體服務器采集并傳輸攝像頭拍攝的視頻信息;構建嵌入式Web服務器Boa;動態網頁的設計以及流媒體服務器、Web服務器與瀏覽器之間的通信等任務。因此系統軟件框架如圖2所示。
圖2 系統軟件框架
3.2.1 流媒體服務器的設計
流媒體服務器主程序用于開放某個視頻服務器端口,并不斷監聽端口,如有連接請求則建立連接,建立后流媒體服務進程將不斷向端口提供采集到的視頻數據流同時也接收客戶端發送過來的視頻調節命令參數。流媒體服務器主程序流程圖如圖3所示。
//打開并初始化視頻設備//
int initvideoIn(struct vdIn *vd,char *device,int width,int height,int format,int grabmethod);
opensock(serverport);//Socket連接初始化
//創建視頻采集線程
pthreadcreate (w1,NULL,(void *) grab,NULL);
//創建視頻傳輸線程//
pthreadcreate(serverth,NULL,(void *)service,newsock);
pthreadjoin(w1,NULL);//等待視頻采集結束
int closev4l(struct vdIn *vd);//關閉攝像頭
圖3 主程序流程圖
(1) 采集視頻數據
系統是在嵌入式Linux系統平臺上采用Video4Linux編程來采集視頻的。一般攝像頭是直接讀視頻設備,采集到視頻數據并存在文件中。對文件進行操作,這樣程序運行效率會很低。本系統摒棄這種方法,采用mmap(內存映射)方式截取視頻數據。mmap()系統調用使得進程之間通過映射同一個普通文件實現共享內存。普通文件被映射到進程地址空間后,進程可以向訪問普通內存一樣對文件進行訪問,不必再調用read(),write()等操作。采用共享內存通信的一個顯而易見的好處是效率高,因為進程可以直接讀寫內存,而不需要任何數據的拷貝。
//初始化videombuf,以得到所映射的buffer的信息//
ioctl(vd->fd,VIDIOCGMBUF,(vd->mbuf));
//將mmap與videombuf綁定//
void* mmap(void * addr,sizet len,int prot,int flags,int fd,offt offset );
ioctl(vd->fd,VIDIOCMCAPTURE,(vd->mmap));//截取視頻數據
ioctl(vd->fd,VIDIOCSYNC,frame);//等待一幀截取結束
(2) 傳輸視頻數據
本系統通過網絡傳輸視頻數據,用套接字(Socket)編程實現。
//接收客戶端發送的調節參數,并保存在message中//
read(sock,(unsigned char*)message,sizeof(struct clientt));
//給客戶端套接字寫視頻數據//
writesock(sock,(unsigned char *)headerframe,sizeof(struct framet));
close(newsock);//關閉客戶端socket
(3) 采集線程與傳輸線程同步
流媒體服務器的設計有個關鍵點:保證連續不斷的視頻流。針對這一點,本系統采用多線程編程,采集和傳輸并行執行。用互斥量和標志位來實現采集線程和傳輸線程的同步。
采集數據時給互斥量加鎖,直到當前幀采集完并填充完當前幀頭結構體才解鎖互斥量,再開始傳輸。同理,傳輸當前幀時采集線程等待,直到當前幀傳輸完。采集完兩幀數據傳輸第二幀。傳輸完成后,采集完第三幀傳輸第三幀。依此循環,采集完第N幀傳輸第N幀。此時實際只傳輸了第2幀到第N幀,即N-1幀。
用戶的視覺反應需要時間,此丟棄第一幀的設計思想并不會使畫面失真。反而連續不斷的視頻流傳輸到客戶端為用戶能夠獲得良好的視頻質量打下了基礎。
采集線程:
while((vd->framelock[vd->framecour] != 0) vd->signalquit)
usleep(1000);//等待上一幀傳輸結束
pthreadmutexlock (vd->grabmutex);//對互斥量加鎖
//把共享緩沖區中的數據放到一個變量中,通知系統已獲得一幀//
int convertframe(unsigned char *dst,unsigned char *src,int width,int height,int formatIn,int qualite);
pthreadmutexunlock (vd->grabmutex);//解鎖互斥量
//設置標志位,表示當前幀采集完
vd->framecour=(vd->framecour +1) % OUTFRMNUMB;
傳輸線程:
while ((frameout == videoIn.framecour) videoIn.signalquit) usleep(1000);//等待下一幀采集完
videoIn.framelock[frameout]++;//設置標志位,表示正在傳輸數據
videoIn.framelock[frameout]--;//設置標志位,表示傳輸數據結束
//設置標志位,表示傳輸的幀
frameout=(frameout+1)% OUTFRMNUMB;
3.2.2 動態網頁的設計
嵌入式Web服務器是Web服務器簡化后的專用系統。本系統選用適合嵌入式系統的Boa Web服務器。Boa是一個單任務的HTTP服務器,支持能夠實現動態Web技術的Java Script技術,源代碼開放,性能高。同時服務器本身所占空間很小,因而十分適用于嵌入式系統。
鑒于Boa移植技術已經很成熟,故不詳細討論。
Applet是能夠嵌入到一個HTML頁面中,且可通過Web瀏覽器下載和執行的一種Java類。它是Java技術容器(container)的一種特定類型。Applet可以通過網絡傳輸,由瀏覽器自動裝載并執行。這恰恰非常符合本系統的要求,因此選用Applet來很好地實現動態網頁,打開網頁就可以看到視頻數據,方便快捷。
(1) 設計流程
Applet不能單獨運行,需要嵌入在網頁中借助瀏覽器的解釋。必須要創建一個HTML文件來告訴瀏覽器需裝載什么以及如何運行它。其執行順序如下[9]:
① 瀏覽器裝入URL;
② 瀏覽器裝入HTML文檔;
③ 瀏覽器裝入Applet類;
④ 瀏覽器運行Applet。
本系統Java Applet實現三個功能:視頻數據通過Socket傳送到客戶端顯示;將客戶端調節視頻帶參數發送到服務器;將客戶端點擊的運動控制參數發送到服務器。其中init和start函數在Applet開始執行時調用,通過start創建2個線程:用于Socket通信;提供用戶界面顯示視頻和相應用戶操作。用戶界面設計用到Sun的SwingWorker類庫。
(2) 雙緩沖技術
雙緩沖技術主要應用于屏幕閃爍現象的消除。在一幀圖像的繪制過程中,如果一幀圖像的繪制時間大于屏幕的刷新時間,就會造成視覺上不連貫的效果。繪制時可在內存中建立兩個圖形緩沖區,其中一個緩沖區(前臺)用于存放顯示的當前幀,并在屏幕上顯示;同時在另一個緩沖區中完成下一幀的繪制。因為畫面的繪制過程是在用戶不可見的情況下進行,自然也就消除了這種閃爍現象。
為了保證用戶的觀看質量,本系統在動態網頁的設計中引入這種雙緩沖技術。采用Java語言中Component類[10]的一個可用于創建圖形緩沖區的方法createImage(int width,int height),其參數為繪制區域的大小。該方法返回一個大小為繪制區域的Image對象。調用該對象的getGraphics()方法得到一個Graphics對象,將它視為后臺的Graphics對象。此后,可調用Graphics類的各種繪圖方法,以繪制所需的畫面。此時,所有的操作都是在后臺的Image對象中進行的,并沒有顯示到屏幕上。當繪制完成后,再調用前臺Graphics對象的drawImage(Image img,int x,int y,ImageObserver observer)方法將已準備好的Image顯示到屏幕上。其中Image參數就是createImage方法所返回后臺的Image對象,ImageObserver參數是與前臺Graphics對象相關的Component對象或其派生類對象。
4 系統測試
在PXA 270上搭建Boa,將Java Applet小程序編譯后生成的.class執行文件、HTML腳本index.html及相關文件拷貝到/var/www/下。將編譯好的流媒體服務器的二進制文件下載到PXA 270上。加載攝像頭和USB無線網卡驅動,運行boa,再運行流媒體服務器。在PC端打開瀏覽器輸入pxa270的IP地址,就可以看到網頁監控的畫面,畫面清晰且視頻流暢,如圖4所示。
圖4 網頁監控
5 結 語
本文充分利用多媒體技術和嵌入式技術各自的特點,介紹了一種用ARM實現移動視頻監控的方法,給
出了軟硬件設計結構及USB無線網卡驅動的具體實現過程。設計了流媒體服務器,搭建了Boa作為Web服務器及實現了動態網頁。利用USB無線網卡免去了布線的煩惱;利用B/S結構使得可以通過瀏覽器來監控,實現跨平臺監視;利用雙緩沖技術,實現較高的視頻質量。基于ARM的移動視頻監控系統使得操作簡單,攜帶方便,可靠性高,成本低,具有良好的開發及應用前景。
參考文獻
[1]Chen Songqing,Wang Haining,Zhang Xiaodong.Segment-based Proxy Caching for Internet Streaming Media Delivery [J].IEEE Multimedia,2005,12(3):59-67.
[2]孫江波.基于嵌入式Linux的視頻監控系統的設計與實現[J].武漢工業學院學報,2006,25(3):31-33.
[3]Intel.Intel PXA27x Processor Family Design Guide [Z].2005.
[4]Mahonen P.Wireless Video Surveillance:System Concepts[J].Image Analysis and Processing,1999(9):1 090-1 095.
[5]宋寶華.設備驅動開發詳解[M].北京:人民郵電出版社,2008.
[6]劉濱,王永才,張冰,等.基于Linux/Qtopia的車載溫度網絡采集[J].單片機與嵌入式系統應用,2008(8):46-49.
[7]Alessandro Rubini,Jonathan Corbet.Linux Device Drivers[M].2nd Edition.Oreilly,2004.
[8]張瑜,王益涵.ARM嵌入式程序設計[M].北京:北京航空航天大學出版社,2009.
[9][美]James Jaworski.Javascript與Jscript從入門到精通[M].邱仲奇,譯.北京:電子工業出版社,2003.
[10]宋維維,陳淑珍.Java語言中的多線程和雙緩沖技術[J].計算機工程,1998,24(12):30-31.