一、
linux
系統中的
usb攝像頭驅動程式
usb攝像頭以其良好的效能和低廉的**得到廣泛應用。同時因其靈活、方便的
特性,易於整合到嵌入式系統中。但是如果使用現有的符合video for linux
標準的驅動程式配合通用應用程式,難以充分利用
usb頻寬,幀速不高,不易滿足實時監控等要求。本文首先介紹在
linux
系統下usb
攝像頭驅動編制的一般方法,然後說明在此基礎上如何提高幀速。
usb裝置驅動程式完全符合通用裝置驅動的準則,不同的是核心提供了一些特別的
api函式,方便驅動註冊、銷毀自己,例如
usb_resister()
和usb_deresister();2
.4版的核心還提供了對於
hotplug
的支援。
1
.1 usb
攝像頭驅動的一般編寫方法
linux
video for linux(
簡稱v4l)
。這個標準其實定義了一套介面,核心、驅動、應用程式以這個介面為標準進行交流。目前的
v4l涵蓋了視、音訊流捕捉及處理等內容,
usb攝像頭也屬於它支援的範疇。
因此,usbvideo_device
結構,並為其指定檔案操作函式指標陣列.
fops
,向系統註冊。在應用程式發出檔案操作的相關命令時,核心根據這些指標呼叫相應函式,並將該結構作為引數傳遞給它們。這樣,就完成了驅動和核心之間的通訊。例如:
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
輪流通訊
眾所周知,
usbl.1
urb中指定
usb_iso_asap
標誌。
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帶回的資料全部填充到另一幀緩衝中,這樣可以免去時間衝突上的麻煩。
值得注意的是:這種方法要求時刻持有當前幀的序號、每一幀的起始位址等資訊,不能將兩幀影象混淆。這些資訊可以儲存在保留記憶體中,當前幀的資料整理、序號改變在
urb完成例程中實現。
二、
v4l標準的改進
v4l標準目前已經發展到第二版
v4l2
,其基本思路與
v4l相同。
2.1
標準分析
根據v4l
標準,戶態程式在需要一幀影象時,
cpu的走向如圖2。
cpu按照
123456
的順序完成乙個迴圈。在這裡,有乙個細節被忽略:在完成例程中,也就是圖
2中步驟6,該
urb被立刻發出,但是由於這時使用者程式正在阻塞等待,沒辦法再次提出獲得影象的申請,因此在判斷有無新請求時,判斷的結果必然是當前無請求,導致下乙個
urb帶回的資料被驅動丟棄;由於核態、戶態的切換需要一定的時間,加上戶態多程序同步等開銷,等到應用程式能夠再次發出獲得一副影象的申請時,已經有不止乙個
urb帶回的資料被丟棄掉,這些
urb包含的資料正好是新一幀影象的開始部分。因此驅動必須等到再下一幀影象才能儲存資料、緩衝。這樣憑白損失了一幀影象,幀速最少下降一半。
2.2
改進思路:不間斷採集
為了解決這個問題,可以改進
v4l標準作,使其增加新的功能:通過新的引數,讓
ioetl()
函式通知驅動不間斷採集、緩衝影象資料,輪流儲存在兩幀緩衝區中,並在一幀影象採集好後,設定
「影象採集好
」旗語。戶態程式只需要發出一次
「獲得影象
」請求,就可以通過阻塞等待該旗語,不斷獲得影象。在採集結束後,再次通過新的引數,讓驅動停止緩衝即可。
cpu工作流程圖如圖
注意到圖2、圖
3,兩種
「判斷有無新請求
」的不同,即可發現新方法假定一直有請求,因此不丟棄每個
urb帶回的資料,輪流儲存在兩個幀緩衝內。
v4l已經作為約定俗成的標準被核心支援,因此如果使用全新的引數,工作量將相當巨大,並且不能和現有的應用程式相容。考慮到現有的影象採集應用程式使用
vidiocmcapture
作為引數,並提供幀序號,要求驅動將影象儲存到指定序號的幀緩衝內。由於驅動通常僅僅提供幾幀緩衝,因此該序號不會大於某個數字,如
10。因此可以繼續使用
vidiocmcapture
引數,搭配較大的序號來表示新增的功能,例如用
10000
和10001
來分別表示開始和停止緩衝影象資料的要求。驅動在收到
vidiocmcapture
要求後,檢查這個序號。如果小於
10000
,則按照正常的方法處理,否則按照改進方法。這種思路可以有效解決相容性問題。
2.3
實驗結果
在賽揚366、
usbl.1
介面的計算機平台上,採用上述不間斷採集改進
v4l標準,配合雙
urb、雙幀緩衝等方法後,幀速提高兩倍有餘,有效資料傳輸速度達
960kb/s
,接近等時傳輸方式下
usb
Linux系統下USB攝像頭驅動開發
摘要 介紹了在iinux系統下開發符合video for linux標準的usb攝像頭驅動的方法,並對該標準提出 不間斷採集 的改進思路,配合雙urb 雙幀緩衝等方法,提高採集速度。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...