孫奕,嚴(yán)錫君,唐躍平,黃濤
近年來(lái)隨著電子和通信行業(yè)的迅速發(fā)展,以及人們意識(shí)形態(tài)的變化,社會(huì)的安全穩(wěn)定成為人們關(guān)注的焦點(diǎn)。視頻監(jiān)控系統(tǒng)作為維護(hù)人們?nèi)粘9ぷ魃钫5挠辛ぞ撸兄絹?lái)越廣泛的應(yīng)用領(lǐng)域。因而在城市中,我們可以在銀行、集體宿舍、大型超市等公共場(chǎng)合隨處可見(jiàn)攝像頭的身影[1]。
嵌入式視頻系統(tǒng)廣泛應(yīng)用于掌上終端、PDA、GPS自動(dòng)導(dǎo)航、3G手機(jī)等嵌入式領(lǐng)域,因此,視頻信息的采集和處理技術(shù)成為嵌入式系統(tǒng)的關(guān)鍵技術(shù)。由于視頻信息的數(shù)據(jù)量大,加之人們對(duì)視頻信息的實(shí)時(shí)性、圖像質(zhì)量的要求越來(lái)越高,而數(shù)字化視頻系統(tǒng)可以充分利用計(jì)算機(jī)的快速處理能力,對(duì)圖像信息進(jìn)行壓縮、分析、存儲(chǔ)和顯示,因此,基于ARM的數(shù)字化處理系統(tǒng)正逐步取代傳統(tǒng)的圖像處理系統(tǒng)。
S3C2440處理器是三星公司開(kāi)發(fā)的一款基于ARM920T內(nèi)核的16/32bit的高性能、低功耗的嵌入式處理器,主頻400MHz,具備攝像頭接口。相對(duì)于MPCore多處理器系列處理器、Intel公司的StrongARM/XScale系列處理器,S3C2440處理器更適合應(yīng)用于對(duì)功率和成本都較敏感的嵌入式系統(tǒng)場(chǎng)合。
本文采用基于SamsungS3C2440微處理器的mini2440開(kāi)發(fā)平臺(tái)設(shè)計(jì)了一個(gè)視頻圖像采集系統(tǒng),以O(shè)V9650傳感器芯片為例,介紹其驅(qū)動(dòng)程序及簡(jiǎn)單應(yīng)用程序的設(shè)計(jì)。
整個(gè)硬件基于S3C2440處理器,64M的SDRAM和64M的Nand Flash[2],構(gòu)成圖像采集系統(tǒng)。圖像采集系統(tǒng)的硬件結(jié)構(gòu)如圖1所示:
圖1 系統(tǒng)硬件結(jié)構(gòu)圖
系統(tǒng)的硬件工作流程為:S3C2440從NAND Flash芯片裝載并執(zhí)行引導(dǎo)程序,引導(dǎo)程序?qū)AND Flash中的內(nèi)容拷貝到SDRAM中,拷貝完成后在SDRAM中執(zhí)行軟件系統(tǒng)主程序。
本系統(tǒng)的攝像頭采用Omni Vision公司生產(chǎn)的COMS攝像頭OV9650,通過(guò)串行SCCB接口與S3C2440的I2C總線接口相連,對(duì)芯片內(nèi)部寄存器的讀寫設(shè)置曝光時(shí)間、增益、飽和度等參數(shù)。其具有高敏感度、低功耗,高分辨率,支持大量常用的圖像格式、支持自動(dòng)圖像控制等特點(diǎn)。OV9650所具有的以上特點(diǎn),足以滿足本系統(tǒng)對(duì)于視頻圖像采集硬件的全部要求[3]。
視頻采集過(guò)程如圖2所示:
圖2 視頻采集流程圖
圖2中ITU-R BT 601/656為視頻設(shè)備接口,視頻采集設(shè)備采集到的視頻數(shù)據(jù)從這里輸入S3C2440處理器進(jìn)行相應(yīng)處理。處理器接收的視頻數(shù)據(jù)先進(jìn)行T模式運(yùn)算,接著通過(guò)CatchCam模塊進(jìn)行格式轉(zhuǎn)換后,根據(jù)不同的格式要求,分別送給預(yù)度量器&RGB格式器和編碼度量器進(jìn)行處理后分別發(fā)給預(yù)處理DMA和編碼DMA,并通過(guò)AHB總線,存儲(chǔ)到視頻緩沖區(qū),完成視頻采集過(guò)程。
嵌入式系統(tǒng)是以應(yīng)用為中心,以計(jì)算機(jī)技術(shù)為基礎(chǔ),適用于應(yīng)用系統(tǒng)對(duì)功能、可靠性、成本、體積、功耗有嚴(yán)格要求的專用計(jì)算機(jī)系統(tǒng)[4]。嵌入式圖像處理的應(yīng)用范圍日益廣泛,作為圖像采集的基礎(chǔ),攝像頭驅(qū)動(dòng)的性能顯得尤為重要。設(shè)備驅(qū)動(dòng)程序是處理和操作硬件控制器的軟件,是內(nèi)核中具有最高優(yōu)先級(jí)且能駐留內(nèi)存的底層硬件處理程序。
驅(qū)動(dòng)程序主要涉及兩部分的內(nèi)容。首先,通過(guò)SCCB接口來(lái)配置OV9650內(nèi)部寄存器。然后,進(jìn)行攝像頭模塊主體驅(qū)動(dòng)部分的編寫,用于獲取圖像數(shù)據(jù)和將數(shù)據(jù)傳輸?shù)竭M(jìn)程空間。驅(qū)動(dòng)的總體架構(gòu)如圖3所示:
圖3 驅(qū)動(dòng)的總體架構(gòu)
OV9650有多組寄存器,這些寄存器決定了圖像的編碼方式、分辨率等參數(shù),配置這些寄存器需要另外的數(shù)據(jù)接口。OV9650的數(shù)據(jù)接口稱為SCCB(serial camera control bus),它是一種類似IIC的串行攝像控制總線。它由兩條數(shù)據(jù)線組成:傳輸時(shí)鐘信號(hào)的SIO_C和傳輸數(shù)據(jù)信號(hào)的SIO_D[5]。SCCB的傳輸協(xié)議與IIC的相似。我們用s3c2440的IIC總線接口分別與OV9650的SIO_C和SIO_D相連接來(lái)實(shí)現(xiàn)SCCB的功能。
static void_ inline_ sccb_ start(void),sccb總線開(kāi)始傳輸數(shù)據(jù),內(nèi)核在對(duì)管腳的寄存器配置中用到了一個(gè)概念:內(nèi)存屏障,即smp_mb()函數(shù)。引入內(nèi)存屏障為保證事件的執(zhí)行次序嚴(yán)格按程序順序來(lái)執(zhí)行。static void_ inline_ sccb_ write_byte(void),把一個(gè)字節(jié)寫到芯片中,讀一個(gè)字節(jié)函數(shù)與此類似,sccb總線的stop函數(shù)與start函數(shù)類似。有了上面4個(gè)基本函數(shù),我們就可以根據(jù)sccb總線協(xié)議定義讀寫函數(shù):void sccb_ write(u8 IdAddr,u8 SubAddr,u8 data),void sccb_read(u8 IdAddr,u8 SubAddr)。配置ov9650芯片寄存器的結(jié)構(gòu)體static struct ov9650_reg{ u8 subaddr;u8 value}。打開(kāi)和關(guān)閉OV9650芯片的函數(shù)為:static void_ inline_ ov9650_ poweron(void),static void_ inline_ ov9650_ poweroff(void)。
sccb總線函數(shù)static int_ inline_ ov9650_ check(void)用于檢測(cè)從ov9650芯片讀回來(lái)的制造廠商的ID與我們定義的是否一樣,以決定是否調(diào)用該驅(qū)動(dòng)。再讀取該產(chǎn)品的ID號(hào)static u32_ inline_ show_ ov9650_ product_ id(void)。
讀取一切正確后配置寄存器,將定義的結(jié)構(gòu)體里的值依據(jù)前面的地址寫進(jìn)寄存器中,這樣就完成了攝像頭內(nèi)部寄存器的設(shè)置。
攝像接口有兩個(gè)相互獨(dú)立的DMA通道--P通道(預(yù)覽通道)和C通道(編解碼通道)。P通道主要存儲(chǔ)用于視頻顯示的RGB圖像數(shù)據(jù),C通道主要存儲(chǔ)用于編解碼的YCbCr圖像數(shù)據(jù)。設(shè)置s3c2440攝像接口一個(gè)重要的步驟是設(shè)置視頻尺寸大小,通過(guò)源尺寸、目標(biāo)尺寸和偏移量的設(shè)置,可以實(shí)現(xiàn)被攝像物體的縮放效果。
攝像接口都是通過(guò)DMA實(shí)現(xiàn)數(shù)據(jù)交換的。在DMA數(shù)據(jù)傳遞中,需要設(shè)置預(yù)覽DMA控制相關(guān)寄存器CIPRCTRL的主突發(fā)長(zhǎng)度和剩余突發(fā)長(zhǎng)度,這兩個(gè)值也可以通過(guò)調(diào)用標(biāo)準(zhǔn)函數(shù)來(lái)求得。另外,在完成每一幀視頻采集后,會(huì)觸發(fā)一個(gè)視頻中斷。初始化一個(gè)緩沖結(jié)構(gòu)體,開(kāi)辟四塊內(nèi)存,給每塊內(nèi)存提供一個(gè)狀態(tài),大小初始化為0,物理和虛擬地址通過(guò)系統(tǒng)直接賦值。
首先,對(duì)驅(qū)動(dòng)模塊進(jìn)行初始化,static int_init camif_init(void)。配置GPIO口的J部分引腳為攝像頭模式。給攝像頭分配并初始化虛擬內(nèi)存,地址從0x4F000000開(kāi)始,大小為1M。映射虛擬內(nèi)存,并返回映射后的地址。初始化外設(shè)的時(shí)鐘,并將該外設(shè)的時(shí)鐘插入到外設(shè)時(shí)鐘鏈表里。接著初始化結(jié)構(gòu)體,包括初始化互斥鎖、輸入格式、狀態(tài)、命令等。然后將該設(shè)備注冊(cè)為混雜設(shè)備,初始化SCCB總線,硬件復(fù)位攝像頭,初始化ov9650芯片等。
在open()中,打開(kāi)文件操作的結(jié)構(gòu)體struct s3c2440camif_fh *fh,其中的變量master為:操作標(biāo)志,僅僅操作那些能執(zhí)行“set”控制的文件。用kzalloc申請(qǐng)內(nèi)存的時(shí)候,所有申請(qǐng)的元素都被初始化為0。配置攝像頭即填充s3c2440camif_dev結(jié)構(gòu)體,將原視頻尺寸設(shè)為1024*1280,即SXGA的標(biāo)準(zhǔn),還有編碼目標(biāo)的尺寸和預(yù)覽目標(biāo)的尺寸等。在初始化視頻緩沖區(qū)之后注冊(cè)兩個(gè)重要的中斷函數(shù),并初始化時(shí)鐘和軟復(fù)位攝像頭。
在read()函數(shù)中,start_ capture (pdev, 0)開(kāi)始采集圖像傳到用戶空間,關(guān)閉兩個(gè)中斷,將所得的數(shù)據(jù)在內(nèi)存的4個(gè)區(qū)域依次拷貝到用戶空間里,然后將內(nèi)存區(qū)域重新置為不可用狀態(tài)。接著使能中斷enable_irq(IRQ_S3C2440_CAM_P),讀取下一幀數(shù)據(jù)。
數(shù)據(jù)采集部分通過(guò)ciwdofst=ioread32(S3C244X_CIWD OFST)從輸入信號(hào)中截取中心部分的圖像輸出到大小不變的輸出圖像緩沖中,從而實(shí)現(xiàn)對(duì)圖像的放大或縮小。ciprscc trl=ioread32(S3C244X_CIPRSCCTRL)預(yù)覽模式控制寄存器中第15位置代表啟動(dòng)預(yù)覽模式。最后設(shè)置圖像采集使能寄存器iowrite32(ciimgcpt, S3C244X_CIIMGCPT),其中,29位是使能預(yù)覽模式,31位是使能全局?jǐn)z像頭接口。
“MJPG-streamer”是一個(gè)輕量級(jí)的視頻服務(wù)器軟件,一個(gè)可以從單一輸入組件獲取圖像并傳輸?shù)蕉鄠€(gè)輸出組件的命令行應(yīng)用程序。用于從攝像頭采集圖像,把它們以流的形式通過(guò)基于IP的網(wǎng)絡(luò)傳輸?shù)綖g覽器如Firehox,Cambozola,Windows的移動(dòng)設(shè)備或者其他擁有瀏覽器的移動(dòng)設(shè)備。可以利用某些硬件壓縮功能來(lái)降低服務(wù)器CPU的開(kāi)銷。為嵌入式設(shè)備和一些常規(guī)服務(wù)器提供了一個(gè)輕量且更少CPU消耗的方案,因?yàn)樗鼰o(wú)需為視頻幀壓縮浪費(fèi)大量的計(jì)算效率。
MJPG-streamer主函數(shù)的定義在mjpg-streamer.c文件。主函數(shù)的處理流程如圖4所示:
圖4 主函數(shù)處理流程圖
MJPG-streamer采用模塊化的設(shè)計(jì)方法,以功能塊(組件)為單位進(jìn)行描述。軟件中定義了各組件的輸入、輸出,以及組件之間的銜接關(guān)系??勺孕懈鶕?jù)對(duì)功能的需求,選擇需要的模塊。這種模塊化的程序設(shè)計(jì)簡(jiǎn)化了代碼的編寫、調(diào)試、維護(hù),程序員只需要遵守設(shè)計(jì)的規(guī)范,就可以輕松的改寫軟件,或者編寫新的模塊以增強(qiáng)軟件的功能[6]。
MJPG-streamer最主要并且最常用的組件是input_uvc輸入組件和output_http輸出組件。input_uvc的主要功能是獲取攝像頭拍照的圖像并將其壓縮編碼,包括5個(gè)組件接口函數(shù),這些組件接口函數(shù)是各個(gè)組件提供給外部使用的。函數(shù)input_run(void)使用pthread_create函數(shù)創(chuàng)建工作線程。并使用pthread_detach函數(shù)將該線程設(shè)置為分離狀態(tài)。在input_uvc組件中,input_run函數(shù)創(chuàng)建cam_thread線程,該線程負(fù)責(zé)抓取攝像頭采集的一幀圖像進(jìn)行格式轉(zhuǎn)換并把它復(fù)制到全局緩沖區(qū)。其工作流程如圖5所示:
圖5 輸入組件工作線程流程圖
工作流程不斷循環(huán),直至線程退出。退出前使用pthread_cleanup_pop函數(shù)調(diào)用cam_ cleanup線程釋放在工作線程中被分配的資源。
Output_ http輸出組件中的http.c文件內(nèi)定義了服務(wù)器對(duì)客戶端請(qǐng)求的響應(yīng)。send_ snapshot、send_ stream、send_error、send_ file分別定義了如何響應(yīng)客戶端發(fā)送截圖、發(fā)送視頻流、發(fā)送錯(cuò)誤信息、發(fā)送文件的請(qǐng)求信息。Command函數(shù)執(zhí)行客戶端指定控制命令,并發(fā)送反饋信息。server_thread服務(wù)線程的作用是打開(kāi)一個(gè)TCP socket并等待客戶端連接。如有客戶端鏈接,則為每一個(gè)連接到服務(wù)器的客戶端創(chuàng)建一個(gè)client_ thread專門服務(wù)于該客戶端。系統(tǒng)客戶端采用網(wǎng)頁(yè)形式,右邊為攝像頭所拍攝的畫面,界面如圖6所示:
圖6 客戶端采集界面圖
用戶通過(guò)瀏覽器與服務(wù)器通信,從而可以觀察到前端攝像頭所監(jiān)控的畫面,雖然在實(shí)時(shí)性上略有欠缺,但畫面無(wú)較大失真現(xiàn)象,圖像質(zhì)量沒(méi)有明顯下降,整體上基本滿足系統(tǒng)要求。這款工具的源代碼簡(jiǎn)潔,注釋清晰。組件功能明確,銜接清晰。使用Linux C語(yǔ)言進(jìn)行開(kāi)發(fā),可移植到不同的計(jì)算機(jī)平臺(tái),也可以在根據(jù)GPL v2的條款下進(jìn)行改進(jìn)和發(fā)行。
隨著社會(huì)信息化的進(jìn)步,視頻監(jiān)控作為一項(xiàng)重要的工具,幾乎涉及了所有行業(yè)。視頻圖像采集在視頻監(jiān)控系統(tǒng)中扮演著重要的角色。本文給出的camera圖像處理芯片的驅(qū)動(dòng)程序可以流暢地預(yù)覽和高分辨率抓取圖像。在此基礎(chǔ)上,通過(guò)開(kāi)源視頻服務(wù)器軟件MJPG-streamer進(jìn)行進(jìn)一步處理,并將這款開(kāi)源軟件進(jìn)行處理后,構(gòu)成一個(gè)實(shí)時(shí)遠(yuǎn)程監(jiān)控系統(tǒng)。
[1]屠添翼,石躍祥.視頻監(jiān)控系統(tǒng)中的圖像采集和視頻有效存儲(chǔ)[J].計(jì)算機(jī)應(yīng)用研究.2005年,08期.
[2]柳亞?wèn)|,路林吉.嵌入式視頻控制服務(wù)器的設(shè)計(jì)[J].微型電腦應(yīng)用, 2009 (7).
[3]馬明龍.基于ARM9的視頻采集和處理系統(tǒng)的設(shè)計(jì)[D].長(zhǎng)春工業(yè)大學(xué).2010.
[4]鄧俊華,杜玉曉.基于S3C2410處理器的Linux移植[J].微型電腦應(yīng)用, 2009 (8).
[5]馬超,劉政林,鄒雪城.SCCB在ARM9嵌入式平臺(tái)上的實(shí)現(xiàn)[J].計(jì)算機(jī)與數(shù)字工程,2006,34 (7):137-140.
[6]Field R T.Software architecture in an open source world[C]// 27 th International Conference on Software Engineering,ICSE,2005:43.