王建新,張 凱,王 秀
(西安科技大學雁塔校區通信與信息工程學院,西安710054)
目前,各種視頻采集以及傳輸的系統都是由DSP(圖像處理),ARM(圖像顯示)以及利用FPGA搭建整個框架[1],這樣會造成資源嚴重浪費,并且成本較大。隨著嵌入式技術的迅猛發展,利用嵌入式實現遠程視頻采集、可視電話會議等應用已經成為可能。
本文基于 S3C2440和 Linux系統平臺,采用USB攝像頭捕捉視頻信號,利用V4L2應用編程接口函數,實現了視頻連續幀圖像的采集,并利用TCP傳輸方式傳輸給服務器端,實現對嵌入式視頻遠程傳輸。開發的終端具有體積小,功耗低,適用于便攜式視頻采集需要。
本文以三星公司S3C2440為硬件平臺,其片上64 M SDRAM可以滿足視頻采集軟件的內存需要,256 M NAND FlLASH用于存放文件和系統,3個通道的UART等控制器和豐富的接口,使其擴展功能強大,功耗低,簡單穩定符合要求。整個硬件框架如圖1所示。

圖1 系統硬件架構
視頻采集傳輸系統軟件架構由以下部分組成:USB(ZC301)攝像頭,攝像頭驅動,視頻采集應用程序,視頻傳輸,視頻顯示組成。如圖2所示。

圖2 視頻采集傳輸系統軟件構架
USB攝像頭進行采集圖像數據,采集圖像格式為MJPE,采集應用程序通過攝像頭驅動從攝像頭獲得采集的圖像數據。利用V4L2接口函數對設備采集的數據進行操作,最后通過網絡傳輸(TCP)將數據傳輸給PC機進行顯示[2]。
Linu系統具有開源性,高可靠性和強大的網絡功能等特點。在此基于linux2.6內核,對其進行裁剪和配置,使內核支持USB驅動和V4L2標準,建立交叉編譯環境,移植編譯好的內核到目標板,以構建linux文件系統,進行視頻采集傳輸應用程序的開發。
在linux系統下,圖像采集設備依賴于V4L2(Video 4 linux 2)標準支持,它針對linux內核視頻設備提供了一系列API接口函數[3],視頻采集流程如圖3所示。
①打開視頻設備
在V4L2中,視頻設備被看作一個文件。使用open()函數以阻塞模式打開攝像頭設備,函數格式為:

open()函數中包含兩個參數,第1個參數代表打開的設備文件名,第2個參數代表設備的打開類型(讀/寫,阻塞或非阻塞),返回值為文件描述符fd,若返回值為大于0,則打開設備正確;若返回值為-1,則打開設備錯誤。
②初始化設備,包括獲取設備信息,設置設備格式,函數格式為:

圖3 視頻采集流程

③設置視頻捕獲格式
當檢測完視頻設備支持的標準后,還需要設定視頻捕獲格式,函數格式如下:

④分配內存
向驅動申請幀緩沖,一般不超過5個。使用ioctl命令字VIDIOC_REQBUFS來調用struct v4l2_requestbuffers,v4l2_requestbuffers結構中定義了緩存的數量,驅動會據此申請對應數量的視頻緩存。

⑤獲取并記錄緩存的物理空間
使用VIDIOC_REQBUFS,獲取兩個緩存,并通過調用VIDIOC_QUERYBUF命令來獲取這些緩存的地址,再使用mmap()函數轉換成應用程序中的絕對地址,最后把這段緩存放入緩存隊列。使用V4L2進行圖像采集時候,在一幀緩沖完成之后,都會將第二幀覆蓋到另一個緩存中,req.count個緩存輪流使用,不丟數據。函數格式如下:
ioctl(fd,VIDIOC_QUERYBUF,&buf);//獲取到對應index的緩存信息,此處主要利用length信息及offset信息來完成后面的mmap操作。與用戶空間傳遞數據的一個中介,會被循環利用。

⑥圖像數據采集
V4L2有三種視頻圖像采集方式:read()、write()方式,內存映射方式和用戶指針方式。
本文采用的內存映射方式是在內核空間開辟一段地址空間,通過mmap()系統調用將其映謝到地址空間。
圖像采集過程中需要使用兩個ioctl的命令:即VIDIOC_DQBUF和VIDIOC_QBUF命令。函數格式為:

在配置內核時候,對USB驅動初始化,我們加上V4L2,并修改.config文件,支持ZC301攝像頭,然后進行編譯成內核鏡像。
常用的圖像傳輸協議有TCP協議和UDP協議。
TCP是傳輸控制協議,是一種面向連接(連接導向)的、可靠的、基于字節流的運輸層通信協議。UDP即用戶數據報協議,是一種無連接協議,傳輸數據之前客戶端和服務器端不建立連接[4]。
在傳輸過程中,TCP在丟包方面比UDP嚴密,不容易丟包。因此本文為利用TCP協議來傳輸數據,首先初始化攝像頭利用V4L2接口,連接到linux系統的公用協議標準,然后將數據存放至緩沖區,產生數據包,并且將數據包利用TCP傳輸,最后傳輸到 PC 機并顯示出來[5]。
在linux中網絡編程是通過socket接口來進行的。Socket是一種常用的進程之間的通信機制。TCP協議下的socket編程流程圖,如圖4所示。
Socket編程基本函數有 socket()、bind()、listen()、accept()、Send()以及 Recv()等,其中根據客戶端還是服務器,這些函數的調用流程有所區別,這里對每個函數進行簡明:

圖4 TCP協議socket編程流程圖
Socket():該函數用于建立一個socket連接,可以指定socket類型信息,對結構體sockaddr_in初始化:包含地址族,端口號,IP地址等;
Bind()該函數用于將本地IP地址綁定到端口號,若綁定其他IP地址則不成功。另外還用于TP連接;
Listen():服務端程序成功建立套接字和地址進行綁定之后,還需要準備在該套接字上接受新的連接請求;
Accept():調用accept()函數等待并且接收客戶端的連接請求;
Connect():用于與服務器建立連接;
Send()與Recv():分別用于發送和接收數據。
搭建目標機linux2.6.32運行環境,并且通過宿主機使用交叉編譯器連接生成可執行文件,向目標機移植后運行。
將USB攝像頭同目標機連接好了之后,若成功掛載USB攝像頭,則終端下會顯示識別USB設備,如圖5所示。

圖5 USB攝像頭驅動測試結果
對整個系統進行測試,該系統在傳輸320×240大小并以MJPEG編碼的視頻時,視頻監控服務器端觀察圖像流暢并且清晰,足夠滿足視頻監控需求,如圖6所示。

圖6 系統測試結果
本文提出一種基于S3C2440平臺和嵌入式linux系統的C/S模型視頻采集和傳輸方案,采用普通市面上的USB攝像頭,極大的降低了成本,利用socket編程實現TCP網絡傳輸過程,經測試,服務器端可以實時的接受到采集傳輸的視頻,圖像清晰,滿足視頻監控要求。
[1]周立功.ARM&WinCE實驗與實踐—基于S3C2410[M].北京:北京航空航天大學出版社,2007.
[2]王培珍,徐俊生.基于ARM9的嵌入式linux圖像采集設計系統[J].中國制造業信息化,2007,10:85-88
[3]李新峰,何廣生,趙秀文.基于ARM9的嵌入式Linux開發技術[M].北京:電子工業出版社,2008,10:118-127
[4]陳文智.嵌入式系統開發原理與實踐[M].北京:清華大學出版社,2005.
[5]怯肇乾.嵌入式網絡通信開發應用[M].北京:北京航空航天大學出版社,2010.
[6]吳明暉.基于ARM的嵌入式系統開發和應用[M].北京:人民郵電出版社,2005.
[7]江湖,蘇詳芳,劉立海,等.基于網絡的數字視頻監控系統[J].武漢大學學報(自然科學版),2000,46(5):608-612.
[8]Lu Yinli,Yu Hongli,Zhang Pengpeng.The Implementation of Embedded Image Acquisition Based on V4L2[C]//Electronics,Communications and Control(ICECC),2011 International Conference.Heng yang,China.2011:549-552