摘 要: 提出了一種基于S3C2440 ARM處理器,、USB攝像頭硬件平臺(tái)和嵌入式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è)資源,,包括存儲(chǔ)器,、LCD控制器、串口,、I2C,、I2S和USB等接口控制電路,主要面向高性價(jià)比,、低功耗的應(yīng)用,,適合于圖像和視頻處理。Flash存儲(chǔ)器采用64 MB NAND存儲(chǔ)器用于存放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è)不同平臺(tái)上進(jìn)行的,,編譯是在宿主機(jī)上,,通常是PC;運(yùn)行是在目標(biāo)板上,,即S3C2440平臺(tái),。一般是在宿主機(jī)上通過跨平臺(tái)交叉編譯器把源文件編譯成可在目標(biāo)平臺(tái)上執(zhí)行的文件,,再通過串口等方式下載到目標(biāo)平臺(tái)上的NAND或NOR存儲(chǔ)器上,然后由目標(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)平臺(tái)
在目標(biāo)平臺(tái)上構(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)平臺(tái),。配置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)平臺(tái)就建立好了,。
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)平臺(tái)的可執(zhí)行文件。宿主機(jī)與目標(biāo)板通常采用打印終端的方式進(jìn)行交叉調(diào)試,,成功后移植到目標(biāo)平臺(tái),。本文編寫的視頻采集程序是在安裝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è)備名稱,、支持的最大及最小分辨率、信號(hào)源信息等,,分別對應(yīng)著結(jié)構(gòu)體中成員變量name,、maxwidth、maxheight,、minwidth,、minheight,、channels、type等,;
(2)struct v4l2_fmtdesc獲取設(shè)備支持的視頻格式,;
?。?)v4l2_format fmt設(shè)置視頻捕獲格式;
?。?)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ū),,并將其序號(hào)賦值給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)平臺(tái)能夠執(zhí)行的代碼,,下載到開發(fā)板中,即可實(shí)現(xiàn)視頻的實(shí)時(shí)采集,。
4 測試結(jié)果與分析
在目標(biāo)平臺(tái)上運(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.