摘 要: 提出了一種基于S3C2440 ARM處理器,、USB攝像頭硬件平臺和嵌入式Linux操作系統(tǒng)的視頻采集系統(tǒng)方案,。研究了USB攝像頭在Linux中的驅(qū)動(dòng)開發(fā),對系統(tǒng)總體結(jié)構(gòu),、基于V4L2的視頻采集以及視頻動(dòng)態(tài)顯示應(yīng)用程序等功能模塊設(shè)計(jì)做了具體介紹,。試驗(yàn)結(jié)果表明,本系統(tǒng)實(shí)現(xiàn)了在LCD顯示器上動(dòng)態(tài)顯示USB攝像頭采集的圖像,,且視頻采集穩(wěn)定,,圖像幀過渡平穩(wěn),提供了一種成本低,、體積小,、功耗低的圖像采集方案,能夠很好地應(yīng)用在視頻監(jiān)控等系統(tǒng)中,。
關(guān)鍵詞: 視頻采集,;S3C2440;Linux,;V4L2,;Qtopia
隨著嵌入式系統(tǒng)、網(wǎng)絡(luò)和圖像信息技術(shù)的滲透,,以及對設(shè)備體積和無線的要求越來越多,,以嵌入式體系為核心的圖像采集系統(tǒng)已成為研究熱點(diǎn)。其中,,嵌入式系統(tǒng)具有功耗低,、體積小和集成接口豐富等優(yōu)點(diǎn)[1];嵌入式Linux系統(tǒng)具有源代碼開放,、內(nèi)核穩(wěn)定,、可裁減性、支持硬件廣泛及驅(qū)動(dòng)豐富等特點(diǎn),,成為嵌入式系統(tǒng)領(lǐng)域不可或缺的操作系統(tǒng)之一,;USB攝像頭具有性能好,、價(jià)格低、使用方便,、易于集成到嵌入式系統(tǒng)等特點(diǎn),,在視頻監(jiān)控和網(wǎng)絡(luò)視頻會(huì)議等領(lǐng)域有廣泛應(yīng)用[2]。
本文以開發(fā)成本低,、體積小,、功耗低的嵌入式圖像采集系統(tǒng)為目標(biāo),采用ARM9處理器S3C2440和USB接口的攝像頭組成硬件體系,,采用嵌入式Linux OS和Qtopia文件系統(tǒng)構(gòu)建應(yīng)用系統(tǒng),,通過編寫USB攝像頭驅(qū)動(dòng)和Qt視頻顯示程序?qū)崿F(xiàn)視頻采集和視頻顯示程序,很好地完成了圖像采集的功能,。由于本系統(tǒng)成本低,、擴(kuò)展簡單、體積小,,能夠很好地?cái)U(kuò)展到和視頻相關(guān)的很多領(lǐng)域[3],。
1 系統(tǒng)硬件設(shè)計(jì)
系統(tǒng)硬件總體結(jié)構(gòu)如圖1所示,嵌入式處理器采用三星公司的基于ARM920T內(nèi)核的16/32位RISC嵌入式微處理器S3C2440,,其主頻高達(dá)400 MHz,,內(nèi)置豐富的外設(shè)資源,包括存儲器,、LCD控制器,、串口、I2C,、I2S和USB等接口控制電路,,主要面向高性價(jià)比、低功耗的應(yīng)用,,適合于圖像和視頻處理,。Flash存儲器采用64 MB NAND存儲器用于存放Linux操作系統(tǒng)啟動(dòng)引導(dǎo)程序Bootloader、Linux系統(tǒng)內(nèi)核,、Qt文件系統(tǒng)及系統(tǒng)掉電后要保存的數(shù)據(jù),。SDRAM中用于存放Linux系統(tǒng)運(yùn)行時(shí)的一些臨時(shí)數(shù)據(jù)。LCD顯示器大小為4.3英寸,,480×272分辨率,并帶有觸摸屏[4],。
目前用于攝像頭的控制芯片組主要有中芯微公司的ZC0301P和美國OV公司的OV511+芯片,。國內(nèi)市場上的USB攝像頭基本上采用的是ZC0301P,并且中芯微公司的主流控制芯片都帶有硬件JPEG編碼模塊,,利用這個(gè)特性可以直接從攝像頭得到經(jīng)過壓縮的圖片格式,,可以簡化應(yīng)用軟件的設(shè)計(jì),,因此本設(shè)計(jì)采用ZC0301P芯片的130萬像素的USB攝像頭。
在硬件系統(tǒng)中,,通過USB接口將攝像頭與S3C2440相接,。利用USB接口進(jìn)行通信只需要在Linux內(nèi)核中增加USB驅(qū)動(dòng)支持和加載ZC0301P硬件驅(qū)動(dòng)模塊。這樣的驅(qū)動(dòng)設(shè)計(jì)充分地利用了Linux模塊化的設(shè)計(jì)特點(diǎn),,同時(shí)也有利于軟件的設(shè)計(jì)和調(diào)試,。
2 嵌入式Linux系統(tǒng)設(shè)計(jì)
2.1 宿主機(jī)開發(fā)環(huán)境的建立
通常嵌入式系統(tǒng)的軟件編譯和運(yùn)行是在兩個(gè)不同平臺上進(jìn)行的,編譯是在宿主機(jī)上,,通常是PC,;運(yùn)行是在目標(biāo)板上,即S3C2440平臺,。一般是在宿主機(jī)上通過跨平臺交叉編譯器把源文件編譯成可在目標(biāo)平臺上執(zhí)行的文件,,再通過串口等方式下載到目標(biāo)平臺上的NAND或NOR存儲器上,然后由目標(biāo)機(jī)來運(yùn)行此軟件,。本系統(tǒng)采用的交叉編譯器為arm-linux-gcc-4.3.3,。
在宿主機(jī)上首先要安裝Linux操作系統(tǒng),本文使用的是Fedora10,。此外,,在系統(tǒng)中建立了交叉編譯環(huán)境。這樣,,嵌入式Linux的開發(fā)環(huán)境就搭建完成了[5],。
2.2 搭建嵌入式Linux系統(tǒng)平臺
在目標(biāo)平臺上構(gòu)建一個(gè)完整的嵌入式Linux系統(tǒng)一般需要Bootloader引導(dǎo)程序、Linux內(nèi)核以及根文件系統(tǒng)3個(gè)內(nèi)容,。
2.2.1 Bootloader引導(dǎo)程序
Bootloader引導(dǎo)程序是嵌入式開發(fā)很重要的組成部分,。Boofloader引導(dǎo)程序最基本的功能是對硬件系統(tǒng)的初始化和內(nèi)核啟動(dòng)參數(shù)設(shè)置并啟動(dòng)內(nèi)核。在嵌入式系統(tǒng)開發(fā)過程中,,Bootloader還與主機(jī)通信,,不斷檢測從主機(jī)傳來的控制信息和數(shù)據(jù)信息,完成相應(yīng)的操作,。本系統(tǒng)中使用的是U-Boot引導(dǎo)程序,。下載U-Boot源碼后,在宿主機(jī)交叉編譯器中編譯出啟動(dòng)代碼的可執(zhí)行文件,,下載到開發(fā)板中即可,。
2.2.2 Linux操作系統(tǒng)的移植
下載linux-2.6.30內(nèi)核,并解壓Linux內(nèi)核到linux-2.6.30目錄,。然后修改此目錄下的Makefile文件,,需改的主要內(nèi)容是目標(biāo)代碼的類型和為編譯內(nèi)核指定一個(gè)編譯器。注釋掉以下內(nèi)容:
#ARCH,?=$(SUBARCH)
#CROSS-COMPILE,?=
增加如下內(nèi)容:
ARCH=arm
CROSS-COMPILE=arm-inux-
做完以上修改以后,,內(nèi)核編譯以后就可在硬件板上運(yùn)行了。
2.2.3 建立根文件系統(tǒng)
根文件系統(tǒng)一直以來是所有UNIX類操作系統(tǒng)的一個(gè)核心組成部分,,在內(nèi)核啟動(dòng)的最后階段,,所執(zhí)行的操作之一就是掛載根文件系統(tǒng)。Linux的根文件系統(tǒng)包含內(nèi)核所需的文件和可執(zhí)行文件,,還有用于系統(tǒng)管理的可執(zhí)行文件,。在網(wǎng)上下載YAFFS文件系統(tǒng)代碼,并修改配置文件使之適用于本目標(biāo)平臺,。配置Linux內(nèi)核,,使內(nèi)核支持MTD(Memory Technology Devices)和YAFFS。重新編譯內(nèi)核并將內(nèi)核下載到開發(fā)板的Flash中,,然后把編譯好的文件系統(tǒng)下載到開發(fā)板中,。啟動(dòng)內(nèi)核,就可以看到在LCD中顯示Qt界面,,這樣一個(gè)完整的Linux系統(tǒng)平臺就建立好了,。
3 視頻采集的實(shí)現(xiàn)
3.1 攝像頭驅(qū)動(dòng)及V4L2簡介
在Linux下,設(shè)備驅(qū)動(dòng)程序可以看成Linux內(nèi)核與外部設(shè)備之間的接口,。設(shè)備驅(qū)動(dòng)程序向應(yīng)用程序屏蔽硬件實(shí)現(xiàn)的細(xì)節(jié),,使得應(yīng)用程序可以像操作普通文件一樣來操作外部設(shè)備,可以使用和操作文件中相同的,、標(biāo)準(zhǔn)的系統(tǒng)調(diào)用接口函數(shù)來完成對硬件設(shè)備的打開,、關(guān)閉、讀寫和I/O控制操作,,而驅(qū)動(dòng)程序的主要任務(wù)也就是要實(shí)現(xiàn)這些系統(tǒng)調(diào)用函數(shù),。
對于USB口攝像頭,其驅(qū)動(dòng)程序中提供了基本的I/O操作接口函數(shù)open,、read,、write、close的實(shí)現(xiàn)以及對I/O通道的控制接口函數(shù)ioctl的實(shí)現(xiàn)等,,并定義在struct file_operations中,。
Video4Linux2(V4L2)是Linux中關(guān)于視頻設(shè)備的內(nèi)核驅(qū)動(dòng),它為針對視頻設(shè)備的應(yīng)用程序編程提供一系列接口函數(shù),,這些視頻設(shè)備包括現(xiàn)今市場上流行的TV卡,、視頻捕捉卡和USB攝像頭等。Linux內(nèi)核提供Video4Linux2應(yīng)用程序接口,,在程序開發(fā)時(shí)首先是基于Video4Linux2 API函數(shù)來設(shè)計(jì)程序[6],。
3.2 Video4Linux2下的攝像頭采集編程
在USB攝像頭被驅(qū)動(dòng)后,只需要再編寫一個(gè)對視頻采集的應(yīng)用程序就可以了,根據(jù)嵌入式系統(tǒng)開發(fā)特征,,先在宿主機(jī)上編寫應(yīng)用程序,再使用交叉編譯器進(jìn)行編譯鏈接,,生成在目標(biāo)平臺的可執(zhí)行文件,。宿主機(jī)與目標(biāo)板通常采用打印終端的方式進(jìn)行交叉調(diào)試,成功后移植到目標(biāo)平臺,。本文編寫的視頻采集程序是在安裝Linux操作系統(tǒng)的宿主機(jī)PC上進(jìn)行的,,下面是具體論述[7]。
程序中定義的重要數(shù)據(jù)結(jié)構(gòu)為:
struct v4l2_capability cap,;
struct v4l2_fmtdesc fmtdesc,;
struct v4l2_format fmt;
struct v4l2_requestbuffers req,;
struct v4l2_buffer buf,;
這些數(shù)據(jù)結(jié)構(gòu)都是Video4Linux2支持的,它們的用途如下,。
?。?)v4l2_capability包含攝像頭的基本信息,例如設(shè)備名稱,、支持的最大及最小分辨率,、信號源信息等,分別對應(yīng)著結(jié)構(gòu)體中成員變量name,、maxwidth,、maxheight、minwidth,、minheight,、channels、type等,;
?。?)struct v4l2_fmtdesc獲取設(shè)備支持的視頻格式;
?。?)v4l2_format fmt設(shè)置視頻捕獲格式,;
(4)v4l2_requestbuffers用于請求分配內(nèi)存,;
?。?)v4l2_buffer代表驅(qū)動(dòng)中的一幀。
Linux下視頻圖像采集流程如圖2所示,。
?。?)打開視頻設(shè)備,獲得文件描述符
攝像頭在系統(tǒng)中對應(yīng)的設(shè)備文件為/dev/video0,,采用系統(tǒng)調(diào)用函數(shù)video_fd=open(“/dev/video0”,, O_RDWR,,0),video_fd為設(shè)備打開后返回的文件描述符,,以后的系統(tǒng)調(diào)用函數(shù)就可以使用它來對設(shè)備文件進(jìn)行操作了,。接著用ioctl(video_fd,VIDIOC_QUERYCAP,,&cap)函數(shù)讀取v4l2_capability中的有關(guān)攝像頭的信息,。該函數(shù)成功返回后,這些信息從內(nèi)核空間拷貝到用戶程序空間capability各成員分量中,,使用printf函數(shù)就可以得到各成員分量信息,。
(2)設(shè)置圖片格式
將圖片寬設(shè)為320,,高設(shè)為240,,其他參數(shù)保持默認(rèn)。
struct v4l2_format fmt,;
CLEAR(fmt),;
fmt.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
fmt.fmt.pix.width=320,;
fmt.fmt.pix.height=240,;
fmt.fmt.pix.field=V4L2_FIELD_INTERLACED;
fmt.fmt.pix.pixelformat=VIDEO_FORMAT,;
if(ioctl(video_fd,,VIDIOC_S_FMT,&fmt)<0)
{
exit(1),;
}
?。?)分配緩沖區(qū)
struct v4l2_requestbuffers req;
CLEAR(req),;
req.count=4,;
req.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;
req.memory=V4L2_MEMORY_MMAP,;
if(ioctl(video_fd,,VIDIOC_REQBUFS,&req)<0)
{
exit(1),;
}
然后通過調(diào)用ioctl(video_fd,,VIDIOC_QUERYBUF,&buf)獲得緩沖區(qū)的長度(buf.length)和偏移地址(fd,,buf.m.offset),,將這兩個(gè)參量作為參數(shù)傳給mmap函數(shù):
buffers[num].start=mmap(NULL,buf.length,PROT_READ|PROT_WRITE,,MAP_SHARED,,fd,buf.m.offset),;
緩沖區(qū)分配好之后,,驅(qū)動(dòng)并不會(huì)向里面寫入數(shù)據(jù),還需要將每個(gè)緩沖區(qū)放入視頻采集隊(duì)列:
ioctl(video_fd,,VIDIOC_QBUF,&buf),;
?。?)啟動(dòng)采集過程,讀取數(shù)據(jù)
完成以上初始化設(shè)置工作后,,就可以對視頻進(jìn)行采集了,,有直接讀取read()和內(nèi)存映射mmap()兩種方法。read()通過內(nèi)核緩沖區(qū)來讀取數(shù)據(jù),;而mmap()通過把設(shè)備文件映射到內(nèi)存中,,繞過了內(nèi)核緩沖區(qū),最快的磁盤訪問往往還是慢于最慢的內(nèi)存訪問,,因此mmap()方式加速了I/O訪問,。另外,mmap()系統(tǒng)調(diào)用使得進(jìn)程之間通過映射同一文件實(shí)現(xiàn)共享內(nèi)存,,各進(jìn)程可以像訪問普通內(nèi)存一樣對文件進(jìn)行訪問,,訪問時(shí)只需要使用指針而不用調(diào)用文件操作函數(shù)。因?yàn)閙map()的以上優(yōu)點(diǎn),,所以在程序?qū)崿F(xiàn)中采用內(nèi)存映射方式,。
應(yīng)用程序調(diào)用VIDIOC_STREAMON來啟動(dòng)采集過程:
enum v4l2_buf_type type=
V4L2_BUF_TYPE_VIDEO_CAPTURE;
ioctl(fd,,VIDIOC_STREAMON,,&type);
采集過程開始以后,,驅(qū)動(dòng)會(huì)不停地將數(shù)據(jù)寫入分配的緩沖區(qū)內(nèi),,當(dāng)一個(gè)緩沖區(qū)的數(shù)據(jù)準(zhǔn)備就緒后,驅(qū)動(dòng)就會(huì)將其放入輸出隊(duì)列,,等待應(yīng)用程序的處理,。當(dāng)所有的緩沖區(qū)都進(jìn)入輸出隊(duì)列后,驅(qū)動(dòng)將停止采集,,并等待緩沖區(qū)重新放入采集隊(duì)列,。讀取數(shù)據(jù)時(shí),首先需要將一個(gè)緩沖區(qū)出隊(duì)列:
struct v4l2_buffer buf;
ioctl(fd,,VIDIOC_DQBUF,,&buf);
驅(qū)動(dòng)會(huì)從輸出隊(duì)列取出一個(gè)緩沖區(qū),,并將其序號賦值給buf.index,,應(yīng)用程序可以通過buffers[buf.index].start來訪問緩沖區(qū)的數(shù)據(jù)。當(dāng)處理完成后,,需要將其重新放入采集隊(duì)列:
ioctl(fd,,VIDIOC_QBUF,&buf),;
?。?)停止采集
首先停止采集過程ioctl(fd,VIDIOC_STREAMOFF,,&type),,然后使用munmap函數(shù)刪除映射,最后調(diào)用close(fd)函數(shù)關(guān)閉設(shè)備,。
視頻圖像顯示模塊使用GUI軟件提供的API函數(shù)的方法進(jìn)行視頻圖像顯示,。視頻顯示程序基于Qt庫來編寫,原理是將buf的內(nèi)容轉(zhuǎn)為image再轉(zhuǎn)為pixmap,,然后顯示出來,。按照以上編寫流程編寫視頻顯示程序后,通過交叉編譯器編譯出目標(biāo)平臺能夠執(zhí)行的代碼,,下載到開發(fā)板中,,即可實(shí)現(xiàn)視頻的實(shí)時(shí)采集。
4 測試結(jié)果與分析
在目標(biāo)平臺上運(yùn)行編寫的視頻采集程序,,攝像頭所采集到的實(shí)時(shí)動(dòng)態(tài)圖像的截圖如圖3所示,。從圖中可以看出,該系統(tǒng)所提供的視頻畫面圖像質(zhì)量較好,,完全可以滿足實(shí)際應(yīng)用中對畫面質(zhì)量的要求,。
采用內(nèi)嵌ARM9核的S3C2440嵌入式微控制器和ZC0301P視頻處理芯片,同時(shí)結(jié)合Linux的Video4Linux視頻接口技術(shù)和視頻流傳輸技術(shù),,實(shí)現(xiàn)了快速視頻采集的應(yīng)用[8],。實(shí)踐表明,采用高性能的ARM9核的微控制器和嵌入式Linux操作系統(tǒng),,使視頻采集系統(tǒng)的視頻畫面清晰流暢,,其性能優(yōu)越、穩(wěn)定而且構(gòu)建成本低,。該方案可以廣泛應(yīng)用于視頻通信和現(xiàn)場監(jiān)測等智能控制領(lǐng)域,,具有廣闊的應(yīng)用前景,。
參考文獻(xiàn)
[1] SAMSUNG ELECTRONICS. S3C2440 user′s manual(Revision 1.2)[Z], 2003.
[2] 杜春雷.ARM體系結(jié)構(gòu)與編程[M].北京:清華大學(xué)出版社,,2003.
[3] 孫天澤,,袁文菊,張海峰.嵌入式設(shè)計(jì)及Linux驅(qū)動(dòng)開發(fā)指南[M].北京:電子工業(yè)出版社,,2005.
[4] RUBINI A. L INUX設(shè)備驅(qū)動(dòng)程序[M].魏永明,,譯.北京:中國電力出版社,2002.
[5] 劉崢嶸,,張智超,,許振山.嵌入式Linux應(yīng)用開發(fā)詳解[M].北京:機(jī)械工業(yè)出版社,2004.
[6] COX A. Video 4 Linux Programming[EB/OL]. www.redhat. com.
[7] 王艷,,吳旭光,,趙勛峰.基于ARM的嵌入式手持掃描設(shè)備的系統(tǒng)設(shè)計(jì)[J].電子測量技術(shù),2007(3):47-49.
[8] 賈明,,嚴(yán)世賢.Linux下的C編程[M].北京:人民郵電出版社,2001.