新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 基于嵌入式Linux與S3C2410平臺的視頻采集

基于嵌入式Linux與S3C2410平臺的視頻采集

作者: 時間:2005-04-12 來源:網(wǎng)絡 收藏

摘要:首先簡介系統(tǒng)的和在上進行開發(fā)所需的軟件環(huán)境,接著詳細論述在該上如何實現(xiàn)這一應用,并對程序的實現(xiàn)進行具體的介紹,最后完成應用程序向目標平臺的移植。

關鍵詞: Video4 內(nèi)存映射

隨著多媒體技術、網(wǎng)絡技術的迅猛發(fā)展和后PC機時代的到來,利用系統(tǒng)實現(xiàn)遠程監(jiān)控、可視電話和視頻會議等應用已成為可能。為了實現(xiàn)這些應用,實時獲得視頻數(shù)據(jù)是一個重要環(huán)節(jié)。針對這一點,本文在嵌入式Linux系統(tǒng)平臺上,利用Video4Linux內(nèi)核應用編程接口函數(shù),實現(xiàn)了單幀圖像和視頻連續(xù)幀的,并保存成文件的形式供進一步視頻處理和網(wǎng)絡傳輸用。

1 系統(tǒng)平臺上的硬件系統(tǒng)

本文使用的系統(tǒng)平臺硬件功能框圖如圖1所示。該平臺采用Samsung公司的處理器。該處理器內(nèi)部集成了ARM公司ARM920T處理器核的32位微控制器,資源豐富,帶獨立的16KB的指令Cache和16KB數(shù)據(jù)Cache、LCD控制器、RAM控制器、NAND閃存控制器、3路UART、4路DMA、4路帶PWM的Timer、并行I/O口、8路10位ADC、Touch Screen接口、I2C接口、I2S接口、2個USB接口控制器、2路SPI,主頻最高可達203MHz。在處理器豐富資源的基礎上,還進行了相關的配置和擴展,平臺配置了16MB 16位的Flash和64MB 32位的SDRAM。通過以太網(wǎng)控制器芯片DM9000E擴展了一個網(wǎng)口,另外引出了一個HOST USB接口。通過在USB接口上外接一個帶USB口的攝像頭,將采集到的視頻圖像數(shù)據(jù)放入輸入緩沖區(qū)中。然后,或者保存成文件的形式,或者運行移植到平臺上的圖像處理程序,對緩沖的圖像數(shù)據(jù)直接進行相關處理,再保存并打成UDP包。最后,通過網(wǎng)絡接口將圖像發(fā)送到Internet上。本文只討論其中視頻采集部分的具體實現(xiàn)。

2 系統(tǒng)平臺中的軟件系統(tǒng)

2.1 Linux與嵌入式系統(tǒng)

Linux具有內(nèi)核小,效率高,源代碼開放,內(nèi)核直接提供網(wǎng)絡支持等優(yōu)點。但嵌入式系統(tǒng)的硬件資源畢竟有限,因此不能直接把Linux作為操作系統(tǒng),需要針對具體的應用通過配置內(nèi)核、裁減shell和嵌入式C庫對系統(tǒng)定制,使整個系統(tǒng)能夠存放到容量較小的Flash中。Linux的動態(tài)模塊加載,使Linux的裁減極為方便 ,高度模塊化的部件使添加非常容易。正因為Linux的上述優(yōu)點,在本文實現(xiàn)的平臺上,使用的操作系統(tǒng)是對Linux進行了定制的armlinux。它啟用了MMU(內(nèi)存管理單元),是針對支持MMU的處理器設計的。

2.2 開發(fā)環(huán)境的建立

絕大多數(shù)Linux的軟件開發(fā)都以native方式進行,即本機開發(fā)、調(diào)試,本機運行的方式。這種方式通常不適于嵌入式系統(tǒng)的軟件開發(fā),因為對于嵌入式系統(tǒng)的開發(fā),它沒有足夠的資源在本機(即嵌入式系統(tǒng)平臺)運行開發(fā)工具和調(diào)試工具。通常的嵌入式系統(tǒng)軟件開發(fā)采用交叉編譯調(diào)試的方式。交叉編譯調(diào)試環(huán)境建立在宿主機(即圖1所示通過串口連接的宿主機PC)上,對應的開發(fā)板叫做目標板(即嵌入式ARM2410系統(tǒng))。

通常宿主機和目標板上的處理器不同,宿主機通常為Intel處理器,而目標板如圖1所示為SAMSUNG S3C2410,所以程序需要使用針對處理器特點的編譯器才能生成在相應平臺上可運行的代碼。GNU編譯器提供這樣的功能,在編譯時,可以選擇開發(fā)所需的宿主機和目標機,從而建立開發(fā)環(huán)境。在進行嵌入式開發(fā)前的第一步工作就是把一臺PC機作為宿主機開發(fā)機,并在其上安裝指定的操作系統(tǒng)。對于嵌入式Linux,宿主機PC上應安裝Linux系統(tǒng)。之后,在宿主機上建立交叉編譯調(diào)試的開發(fā)環(huán)境,開發(fā)環(huán)境的具體建立這里不細談。本文采用移植性很強的C語言在宿主機上編寫視頻采集程序,再利用交叉編譯調(diào)試工具編譯鏈接生成可執(zhí)行代碼,最后向目標平臺移植。

3 視頻采集的具體實現(xiàn)

上面提到系統(tǒng)平臺上運行的是armlinux。在啟動后,啟用了MMU,系統(tǒng)進入保護模式,所以應用程序就不能直接讀寫外設的I/O區(qū)域(包括I/O端口和I/O內(nèi)存),這時一般就要借助于該外設的驅(qū)動來進入內(nèi)核完成這個工作。本系統(tǒng)中的視頻采集分兩步實現(xiàn):一是為USB口數(shù)碼攝像頭在內(nèi)核中寫入驅(qū)動,二是要再寫入上層應用程序獲取視頻數(shù)據(jù)。本文著重討論后一步。

3.1 USB口數(shù)碼攝像頭的驅(qū)動實現(xiàn)

在Linux下,設備驅(qū)動程序可以看成Linux內(nèi)核與外部設備之間的接口。設備驅(qū)動程序向應用程序屏蔽了硬件實現(xiàn)了的細節(jié),使得應用程序可以像操作普通文件一樣來操作外部設備,可以使用和操作文件中相同的、標準的系統(tǒng)調(diào)用接口函數(shù)來完成對硬件設備的打開、關閉、讀寫和I/O控制操作,而驅(qū)動程序的主要任務也就是要實現(xiàn)這些系統(tǒng)調(diào)用函數(shù)。本系統(tǒng)平臺使用的嵌入式armLinux系統(tǒng)在內(nèi)核主要功能上與Linux操作系統(tǒng)沒本質(zhì)區(qū)別,所以驅(qū)動程序要實現(xiàn)的任務也一樣,只要編譯時使用的編譯器、部分頭文件和庫文件等要涉及到具體處理器體系結構,這些都可以在Makefile文件中具體指定。

Video4Linux(簡V4L)是Linux中關于視頻設備的內(nèi)核驅(qū)動,它為針對視頻設備的應用程序編程提供一系列接口函數(shù),這些視頻設備包括現(xiàn)今市場上流行的TV卡、視頻捕捉卡和USB攝像頭等。對于USB口攝像頭,其驅(qū)動程序中需要提供基本的I/O操作接口函數(shù)open、read、write、close的實現(xiàn)。對中斷的處理實現(xiàn),內(nèi)存映射功能以及對I/O通道的控制接口函數(shù)ioct1的實現(xiàn)等,并把它們定義在struct file_operations中。這樣當應用程序?qū)υO備文件進行諸如open、close、read、write等系統(tǒng)調(diào)用操作時,Linux內(nèi)核將通過file_operations結構訪問驅(qū)動程序提供的函數(shù)。例如,當應用程序?qū)υO備文件執(zhí)行讀操作時,內(nèi)核將調(diào)用file_operations結構中的read函數(shù)。在系統(tǒng)平臺上對USB口數(shù)碼攝像頭驅(qū)動,首先把USB控制器驅(qū)動模塊靜態(tài)編譯進內(nèi)核,使平臺中支持USB接口,再在需要使用攝像頭采集時,使用insmode動態(tài)加載其驅(qū)動模塊,這樣攝像頭就可正常工作了,接著進行了下一步對視頻流的采集編程。

3.2 Video4Linux下的攝像頭采集編程

在USB攝像頭被驅(qū)動后,只需要再編寫一個對視頻流采集的應用程序就可以了。根據(jù)嵌入式系統(tǒng)開發(fā)特征,先在宿主機上編寫應用程序,再使用交叉編譯器進行編譯鏈接,生成在目標平臺的可執(zhí)行文件。宿主機與目標板通信采用打印終端的方式進行交叉調(diào)試,成功后移植到目標平臺。本文編寫采集程序是在安裝Linux操作系統(tǒng)的宿主機PC機上進行的,下面是具體論述。

(1)程序中定義的數(shù)據(jù)結構

struct voide_capability grab_cap;

struct voide_picture grab_pic;

struct voide_mmap grab_buf;

struct voide_mbuf grab_vm;

這些數(shù)據(jù)結構都是由Video4Linux支持的,它們的用途如下:

*video_capability包含攝像頭的基本信息,例如設備名稱、支持的最大最小分辨率、信號源信息等,分別對應著結構體中成員變量name[32]、maxwidth、maxheight、minwidth、minheight、channels(信號源個數(shù))、type等;

*voide_picture包含設備采集圖像的各種屬性,如brightness(亮度)、hue(色調(diào))、contrast(對比度)、whiteness(色度)、depth(深度)等;

*video_mmap用于內(nèi)存映射;

*voido_mbuf利用mmap進行映射的幀信息,實際上是輸入到攝像頭存儲器緩沖中的幀信息,包括size(幀的大?。?、frames(最多支持的幀數(shù))、offsets(每幀相對基址的偏移)。

程序中用到的主要系統(tǒng)調(diào)用函數(shù)有:open("/dev/voideo0",int flags)、close(fd)、mmap(void *start,size_t length,int prot,int flags,int fd,off_t offset)、munmap(void *start,size_tlength)和ioctl(int fd,int cmd,…)。

前面提到Linux系統(tǒng)中把設備看成設備文件,在用戶空間可以通過標準的I/O系統(tǒng)調(diào)用函數(shù)操作設備文件,從而達到與設備通信交互的目的。當然,在設備驅(qū)動中要提供對這些函數(shù)的相應支持。這里說明一下ioctl(int fd,int cmd,…)函數(shù),它在用戶程序中用來控制I/O通道,其中,fd代表設備文件描述符,cmd代表用戶程序?qū)υO備的控制命令,省略號一般是一個表示類型長度的參數(shù),也可沒有。

(2)采集程序?qū)崿F(xiàn)過程

首先打開視頻設備,攝像頭在系統(tǒng)中對應的設備文件為/dev/video0,采用系統(tǒng)調(diào)用函數(shù)grab_fd=open("/dev/video0",O_RDWR),grab_fd是設備打開后返回的文件描述符(打開錯誤返回-1),以后的系統(tǒng)調(diào)用函數(shù)就可使用它來對設備文件進行操作了。接著,利用ioct1(grab_fd,VIDIOCGCAP,grab_cap)函數(shù)讀取struct video_capability中有關攝像頭的信息。該函數(shù)成功返回后,這些信息從內(nèi)核空間拷貝到用戶程序空間grab_cap各成員分量中,使用printf函數(shù)就可得到各成員分量信息,例如printf("maxheight=%d",grab_fd.maxheight)獲得最大垂直分辨率的大小。不規(guī)則用ioct1(grab_fd,VIDIOCGPICT,grab_pic)函數(shù)讀取攝像頭緩沖中voideo_picture信息。在用戶空間程序中可以改變這些信息,具體方法為先給分量賦新值,再調(diào)用VIDIOCSPICT ioct1函數(shù),例如:

grab_fd.depth=3;

if(ioct1(grab_fd,VIDIOCSPICT,grab_pic)0)

{perror("VIDIOCSPICT");return -1;};

完成以上初始化設備工作后,就可以對視頻圖像截取了,有兩種方法:一種是read()直接讀取;另外一種mmap()內(nèi)存映射。Read()通過內(nèi)核緩沖區(qū)來讀取數(shù)據(jù);而mmap()通過把設備文件映射到內(nèi)存中,繞過了內(nèi)核緩沖區(qū),最快的磁盤訪問往往還是慢于最慢的內(nèi)存訪問,所以mmap()方式加速了I/O訪問。另外,mmap()系統(tǒng)調(diào)用使得進程之間通過映射同一文件實現(xiàn)共享內(nèi)存,各進程可以像訪問普通內(nèi)存一樣對文件進行訪問,訪問時只需要使用指針而不用調(diào)用文件操作函數(shù)。因為mmap()的以上優(yōu)點,所以在程序?qū)崿F(xiàn)中采用了內(nèi)存映射方式,即mmap()方式。

利用mmap()方式視頻裁取具體進行操作如下。

①先使用ioct1(grab_fd,VIDIOCGMBUF,grab_vm)函數(shù)獲得攝像頭存儲緩沖區(qū)的幀信息,之后修改voideo_mmap中的設置,例如重新設置圖像幀的垂直及水平分辨率、彩色顯示格式??衫萌缦抡Z句

grab_buf.height=240;

grab_buf.width=320;

grab_buf.format=VIDEO_PALETTE_RGB24;

②接著把攝像頭對應的設備文件映射到內(nèi)存區(qū),具體使用grab_data=(unsigned char*)mmap(0,grab_vm.size,PROT_READ|PROT_WRITE,MAP_SHARED,grad_fd,0)操作。這樣設備文件的內(nèi)容就映射到內(nèi)存區(qū),該映射內(nèi)容區(qū)可讀可寫并且不同進程間可共享。該函數(shù)成功時返回映像內(nèi)存區(qū)的指針,挫敗時返回值為-1。

下面對單幀采集和連續(xù)幀采集進行說明:

*單幀采集。在上面獲取的攝像頭存儲緩沖區(qū)幀信息中,最多可支持的幀數(shù)(frames的值)一般為兩幀。對于單幀采集只需設置grab_buf.frame=0,即采集其中的第一幀,使用ioctl(grab_fd,VIDIOCMCAPTURE,grab_buf)函數(shù),若調(diào)用成功,則激活設備真正開始一幀圖像的截取,是非阻塞的。接著使用ioct1(grab_fd,VIDIOCSYNC,frame)函數(shù)判斷該幀圖像是否截取完畢,成功返回表示截取完畢,之后就可把圖像數(shù)據(jù)保存成文件的形式。

*連續(xù)幀采集。在單幀的基礎上,利用grab_fd.frames值確定采集完畢攝像頭幀緩沖區(qū)幀數(shù)據(jù)進行循環(huán)的次數(shù)。在循環(huán)語句中,也是使用VIDIOCMCCAPTURE ioct1和VIDIOCSYNC ioctl函數(shù)完成每幀截取,但要給采集到的每幀圖像賦地址,利用語句buf=grab_data+grab_vm.offsets[frame],然后保存文件的形式。若要繼續(xù)采集可再加一個外循環(huán),在外循環(huán)語句只要給原來的內(nèi)循環(huán)再賦frame=0即可。

4 小結

筆者最后在宿主機PC上使用交叉編譯器編譯鏈接連續(xù)幀采集程序(以雙幀采集為例并保存成bmp文件文件形式)使之生成可執(zhí)行代碼,并完成了向目標平臺的移植。為了進一步觀察采集的圖像效果,筆者在目標平臺帶網(wǎng)絡支持的基礎上,編寫了一個簡單的網(wǎng)絡通信程序,把采集到并保存為bmp的圖像文件通過網(wǎng)絡傳輸?shù)絇C機上進行顯示,把采集到并保存為bmp的圖像文件通過網(wǎng)絡傳輸?shù)絇C機上進行顯示,通過對效果的分析,再回到采集程序中重新設置video_picture中的信息,如亮度、對比度等和voide_mmap中的分辨率,重新移植以達到最好效果為準。

在圖1中的嵌入式系統(tǒng)平臺上,應用本文所述方法完成視頻采集工作,再加上相關的視頻處理并接入網(wǎng)絡,就構成了一個智能終端設備,可用于工廠、銀行及小區(qū)等場合全天候的智能監(jiān)控,具有廣闊的市場和應用前景。

linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)


評論


相關推薦

技術專區(qū)

關閉