這里首先涉及到USB的傳輸速度的問題。一個USB2.0的理論傳輸速度為480Mbps,也就是60MBps。當然,實際上不可能達到這個理論的最大值。一般只能達到這個值的70%左右,讀入速度為30-42MBps,寫入速度為25-30MBps。當我們用一個攝像頭采集時,假設采集一幀的分辨率為 640*480(這個分辨率是大多數攝像頭都支持的分辨率),圖像是24位(3個字節表示一個像素點)的位圖,采集幀率為30Fps,那么所需的帶寬為 640*480*24*30bps,即640*480*24*30/8/1024/1024=26.37MBps。可見,當插上一個USB攝像頭的時候,按照這種方式進行采集時,就已經占了讀入的大半帶寬,當插上兩時,結果可想而知,要么很卡,要么程序就無法運行。
那這樣的話,豈不是不能進行多個攝像頭的同時采集?實際上,剛才說的傳輸速度,是針對一個USB Controller而言。在PC機上一般不可能只有一個USB Controller。所以,當多個攝像頭插在不同的USB Controller上面時,就能進行流暢的視頻采集了。在這里還有必要說下USB Controller的問題。一台電腦上面可能有多個USB插口,但是並不等同與有相同數目的USB Controller。以我的筆記本為例,上面有4個USB插口,而只有兩個USB Controller。稍微查一下就能得知,一個USB Controller上面連了一個USB插口,另外一個USB Controller上面連了3個USB插口。為什么會這樣呢,詳細講解下USB的結構。
因此,不管有多少個USB插口在電腦上,只有連在了不同的USB Controller上面,才能保證視頻的流暢性。這點可以借助驅動精靈來查看是否不同的攝像頭接在了不同的USB Controller上面。驅動精靈的硬件檢測選項單里面,點擊詳細信息,然后端口->USB,里面就有各種詳細的連接情況。一般一個攝像頭,名稱為Composite Device,可是查看一個USB Controller上面是不是連接了多個Composite Device,以確保一對一的連接。這樣才能保證連接端口沒有出現問題。
回到zedboard,它只提供了一個USB Controller,因此使用兩個攝像頭時必須HUB分接。前面已經講到一個USB攝像頭如果采集的視頻幀大小640*480,那么一個攝像頭已經占據了USB Controller接口的大部分傳輸帶寬,如果再開啟一個攝像頭,另一個攝像頭肯定就不能正常打開了,程序當然就不能正常運行了。
在內核編譯過程中,如果將UVC驅動編譯進入內核,攝像頭采集視頻時會默認申請USB接口的全部帶寬。所以要將UVC驅動編譯為模塊,手動設置驅動的工作模式。關於內核的配置編譯,參考上一篇參賽手記,這里不再詳述。
將UVC驅動編譯為模塊后,生成uvcvideo.ko和videobuf2-vmalloc.ko,然后在zedboard控制台中輸入
insmod videobuf2-vmalloc.ko
insmod uvcvideo.ko quirks=128
其中insmod uvcvideo.ko quirks=128將uvc視頻驅動加載到內核中,並強制要求攝像頭計算所需帶寬,而不是申請USB接口的全部帶寬。
通過以上限制,就解決zedboard的HUB分接兩個攝像頭的帶寬矛盾。