摘要:介紹了在iinux系統下開發符合video for linux標準的usb攝像頭驅動的方法,並對該標準提出「不間斷採集」的改進思路,配合雙urb、雙幀緩衝等方法,提高採集速度。
usb攝像頭以其良好的效能和低廉的**得到廣泛應用。同時因其靈活、方便的特性,易於整合到嵌入式系統中。但是如果使用現有的符合video for linux標準的驅動程式配合通用應用程式,難以充分利用usb頻寬,幀速不高,不易滿足實時監控等要求。本文首先介紹在linux系統下usb攝像頭驅動編制的一般方法,然後說明在此基礎上如何提高幀速。
1 linux系統中的usb攝像頭驅動程式
usb裝置驅動程式完全符合通用裝置驅動的準則,不同的是核心提供了一些特別的api函式,方便驅動註冊、銷毀自己,例如usb_resister()和usb_deresister();2.4版的核心還提供了對於hotplug的支援。
1.1 usb攝像頭驅動的一般編寫方法
static struct video_device vdev_template=;
//宣告video_device,指出掛接驅動
static struct file_operations ov511_fops=;
//宣告本驅動的檔案操作函式指標
struct video_device*vdev=video_devdata(file);
//從檔案指標中提取出video_device結構
在video_device結構中,有乙個私有指標priv,可以將它指向一塊保留記憶體。在這塊記憶體中,儲存著本驅動、本裝置的相關初始化資訊。這塊記憶體的申請、初始化、指標指向等工作都是在usb驅動的列舉函式.probe中完成。這樣,在列舉函式將控制權返還給系統後,因為核心不銷毀保留記憶體,所以驅動仍然保留著自己的資訊。這點與windows系統中wdm驅動有異曲同工之處。當然,在驅動解除安裝函式中,應當將申請的各塊記憶體全部釋放。
1.2 使用雙urb輪流通訊
urb->transfer_flags=usb_iso_asap;//盡可能快地發出本urb
linux系統中任何usb傳輸都通過urb實現。為提高速度,可以考慮擴大urb的緩衝,這樣可以降低每個usb事務中握手資訊所佔比例,提高有效資料的傳輸速度。但是受限於匯流排頻寬和具體的usb裝置晶元,單純擴大urb的緩衝不能無限制地解決問題。具體分析一下usb傳輸在作業系統中的實現:每次傳輸都要包括urb的建立、發出、**、資料整理等階段,這些時間不產生有效資料。因此可以建立兩個urb,在等待乙個urb被**時,也就是影象正在被感測器採集時,處理、初始化另乙個urb,並在**後立刻將其發出。兩個urb交替使用,大大減少了額外時間。工作流程如圖1所示。
這個過程是在urb的完成例程中實現的,有兩點需要注意:首先處理再次初始化的**時間不能長,否則會造成完成例程的重人,如果確實來不及,可以在完成例程中設定標誌,例如「資料採集好」旗語,由應用程式使用阻塞ioctl()來查詢該旗語並做處理;其次由於cpu可能會在完成例程中停留較長時間,系統負擔較大,可以在.open函式中初始化兩個urb並將其發出,有限度地減輕系統負擔。
1.3 使用雙幀緩衝提高效率
linux系統中,檔案操作通常是由read、write等系統呼叫來完成。這些系統呼叫在驅動中的解決方法就是用copy_to_user()、copy_from_user()等函式在核態、戶態記憶體空間中互相拷貝。但是對於大批量的影象資料,採用拷貝的方法顯然會增加時間開銷,因此用記憶體對映的方法解決。首先使用vmalloc()申請足夠大的核態記憶體,將其作為影象資料緩衝空間,兩個urb帶回的影象資料在這裡暫存;然後使用remap_page_range()函式將其逐頁對映到使用者空間中。戶態的影象處理程式使用mmap()函式,直接讀寫核態影象緩衝記憶體,大大減少額外開銷。
影象資料的處理可能要花費比較長的時間,不同的演算法對於資料保留時間的要求也不一樣。因此可以申請兩幀影象緩衝,在處理一幀影象的同時,將兩個urb帶回的資料全部填充到另一幀緩衝中,這樣可以免去時間衝突上的麻煩。
2 v4l標準的改進
v4l標準目前已經發展到第二版v4l2,其基本思路與v4l相同。
2.1 標準分析
根據v4l標準,戶態程式在需要一幀影象時,cpu的走向如圖2。cpu按照123456的順序完成乙個迴圈。在這裡,有乙個細節被忽略:在完成例程中,也就是圖2中步驟6,該urb被立刻發出,但是由於這時使用者程式正在阻塞等待,沒辦法再次提出獲得影象的申請,因此在判斷有無新請求時,判斷的結果必然是當前無請求,導致下乙個urb帶回的資料被驅動丟棄;由於核態、戶態的切換需要一定的時間,加上戶態多程序同步等開銷,等到應用程式能夠再次發出獲得一副影象的申請時,已經有不止乙個urb帶回的資料被丟棄掉,這些urb包含的資料正好是新一幀影象的開始部分。因此驅動必須等到再下一幀影象才能儲存資料、緩衝。這樣憑白損失了一幀影象,幀速最少下降一半。
2.2 改進思路:不間斷採集
為了解決這個問題,可以改進v4l標準作,使其增加新的功能:通過新的引數,讓ioetl()函式通知驅動不間斷採集、緩衝影象資料,輪流儲存在兩幀緩衝區中,並在一幀影象採集好後,設定「影象採集好」旗語。戶態程式只需要發出一次「獲得影象」請求,就可以通過阻塞等待該旗語,不斷獲得影象。在採集結束後,再次通過新的引數,讓驅動停止緩衝即可。cpu工作流程圖如圖3。
注意到圖2、圖3,兩種「判斷有無新請求」的不同,即可發現新方法假定一直有請求,因此不丟棄每個urb帶回的資料,輪流儲存在兩個幀緩衝內。
v4l已經作為約定俗成的標準被核心支援,因此如果使用全新的引數,工作量將相當巨大,並且不能和現有的應用程式相容。考慮到現有的影象採集應用程式使用vidiocmcapture作為引數,並提供幀序號,要求驅動將影象儲存到指定序號的幀緩衝內。由於驅動通常僅僅提供幾幀緩衝,因此該序號不會大於某個數字,如10。因此可以繼續使用vidiocmcapture引數,搭配較大的序號來表示新增的功能,例如用10000和10001來分別表示開始和停止緩衝影象資料的要求。驅動在收到vidiocmcapture要求後,檢查這個序號。如果小於10000,則按照正常的方法處理,否則按照改進方法。這種思路可以有效解決相容性問題。
2.3 實驗結果
在賽揚366、usbl.1介面的計算機平台上,採用上述不間斷採集改進v4l標準,配合雙urb、雙幀緩衝等方法後,幀速提高兩倍有餘,有效資料傳輸速度達960kb/s,接近等時傳輸方式下usb匯流排的頻寬極限。
Linux系統下USB攝像頭驅動開發
一 linux 系統中的 usb攝像頭驅動程式 usb攝像頭以其良好的效能和低廉的 得到廣泛應用。同時因其靈活 方便的 特性,易於整合到嵌入式系統中。但是如果使用現有的符合video for linux 標準的驅動程式配合通用應用程式,難以充分利用 usb頻寬,幀速不高,不易滿足實時監控等要求。本文...
樹莓派使用免驅USB攝像頭
樹莓派使用免驅usb攝像頭 使用命令lsusb,查詢usb,插拔前後各用一次,找到usb口。使用命令ls dev video 插拔前後各查詢一次,得到裝置檔案。安裝fswebcamsudo apt get install fswebcam拍照fswebcam dev video0 home pi n...
USB攝像頭 介紹
從攝像頭的工作原理就可以列出攝像頭的主要結構和元件 1 鏡頭 lens 透鏡結構,由幾片透鏡組成,有塑膠透鏡 plastic 或玻璃透鏡 glass 2 影象感測器 sensor 可以分為兩類 ccd charge couple device 電荷耦合器件 cmos complementary me...