摘? 要: 分析了多媒體設備驅動程序的體系結構及視頻采集與解壓卡的驅動程序設計方案。描述了核心態驅動程序的處理流程,提供了用戶態驅動程序的設計思路和具體算法。
關鍵詞: 驅動程序? IRP(輸入輸出請求包)? 驅動程序對象? 設備對象
?
Windows NT的結構決定了應用程序不能直接操作硬件設備,它只能通過一個中間層來讀寫和控制設備,這個中間層就是驅動程序。驅動程序位于計算機軟件的最低層(HAL為硬件抽象層),直接與硬件設備的特性聯系在一起。編寫驅動程序不僅要了解設備的特性,而且還要了解操作系統的結構,難度較大。本文比較詳細地分析了視頻采集與解壓卡的驅動程序設計思路。
1 視頻采集與解壓卡驅動程序的結構
多媒體設備相對普通設備來說,有兩個特點:數據流量大;對最終期限要求高(即實時性要求比較高)。對于視頻采集與解壓卡這類多媒體設備來說,驅動程序的編寫有其特定的方式。多媒體驅動程序的結構如圖1所示。一般說來,根據其代碼運行的特權級可分為兩層:核心態的驅動程序和用戶態的驅動程序。核心態的驅動程序運行于內核模式,可以執行特權級指令,對任何I/O設備有全部的訪問權,還能夠訪問任何虛地址和控制虛擬內存硬件。
?
用戶模式的驅動程序實質上是一個動態鏈接庫(DLL)。它運行在用戶態,應用程序向這個接口發出消息請求一定的操作。它們調用WIN32函數與內核模式的驅動程序通訊(WIN32函數又調用NT執行體提供的函數,這些執行體函數提供從用戶態到核心態的上下文轉換)。用戶模式的驅動程序根據接收的消息采取適當的操作,完成操作后將結果返回給應用程序。但是這種結構只適用于解壓一幅幅的位圖,并不適合采集和解壓本設備產生的視頻流。
此卡既要采集又要解壓,若用標準模式進行設計,就要同時編寫視頻采集和視頻解壓的驅動程序,其中還要對解壓程序進行改造,編寫復雜,尤其調試會很困難。在這種情況下,使用本設計方案,既可滿足要求,又可減小設計難度。
內核模式的驅動程序與一般驅動程序無多大的區別,只負責讀取數據和進行設備控制。用戶模式的驅動程序要處理大部分的事務。在解壓時,驅動程序要向設備寫入待解壓的數據,從設備中取得解壓后的數據,向應用程序提供一幀圖像的RGB數據。從設備得到的數據是分場存放的4:2:2的YCrCb格式的數據,驅動程序將每幀數據按行進行格式轉換,組合成完整的一幀數據(QCIF)交付給應用程序。
2 內核模式的驅動程序的設計
由于多媒體的數據量很大,按照常規的方法(采用IRP包進行數據傳輸)設計將面臨著一個無法解決的問題——中斷太快驅動程序將來不及處理。因此必須采用一種新的方法:在驅動程序中建立兩塊緩沖區(分別用于讀寫),應用層驅動程序與核心層驅動程序共用緩沖區。當設備中斷發生時,根據發生的中斷進行處理。如果是讀中斷,先把數據從設備中讀到緩沖區中,發出一個DPC(推遲過程調用),通知應用層驅動程序該緩沖區數據可用,可以取走數據了。如果是寫中斷,先把緩沖區中的數據寫到設備的FIFO中,然后發出一個DPC,通知用戶模式驅動程序該緩沖區數據已失效,需要寫入新數據。
驅動程序工作流程如圖2所示。內核模式向外顯露DriverEntry(驅動程序必須要有的一個例程)接口,其它的例程沒有固定的名字,為了讓I/O管理器找到這些例程,DriverEntry例程負責建立這些函數指針。I/O管理器從非分頁系統內存分配一個IRP,響應一個I/O請求,基于由用戶指定的I/O函數,把IRP傳遞給合適的驅動程序Dispatch例程,Dispatch例程檢查請求的參數,如果它們是有效的,使用IRP的內容設置設備操作。當操作完成時,在IRP中存放最后的狀態代碼,并把它送回I/O管理器;I/O管理器使用IRP中的信息完成請求,并把最后狀態發送給請求者。
?
當驅動程序被加載到系統中時,I/O管理器將創建一個驅動程序對象(在系統中代表一個獨立的驅動程序,并且為I/O管理器記錄每個驅動程序的調度例程的地址),然后調用其初始化例程。
在DriverEntry這個初始化例程中完成的任務是:
·把驅動程序的入口填入該驅動程序對象中。
·用設備的VID和DID查找每條總線上的每個插槽,找到這塊圖像壓縮解壓卡,并用IoCreateDevice創建設備對象,用IoCreateSymbolicLink建立符號連接。
·初始化放在非分頁區中的Device Extension中的各個分量。包括讀寫IRP,以及保護各自隊列的自旋鎖等。
·設備有兩塊專有內存,必須將其總線相關地址轉換成系統范圍內的地址,并將其映射到系統虛空間。對于I/O端口,將其總線相關地址轉換成系統范圍內的地址即可。
·用ExAllocatePool()分配兩塊非分頁緩存,并把它映射到用戶地址中。
在驅動程序讀寫設備之前,必須進一步初始化,表明設備驅動程序的用途:解碼或編碼。上層的驅動程序調用DeviceIoControl對工作模式進行設置,驅動程序收到此IRP后設置壓縮解壓芯片的工作模式及視頻采集芯片、總線接口芯片的參數。在開始編碼或解碼之前,上層的驅動程序必須調用DeviceIoControl取回共用緩沖區的地址。
3 用戶模式的驅動程序設計
用戶模式的驅動程序要完成以下功能:采集時,從設備中讀取一定量(一般是一幀)的數據傳遞給應用程序。解碼相對復雜,不僅要向設備寫入待解壓的數據,從設備中讀取一幀解壓后的數據,由于讀取的數據是CCIR656的視頻流不適合應用程序的顯示,還要對其進行格式轉換,轉換成適合計算機顯示的RGB格式,向應用程序提供QCIF(356×288)大小的圖像。因此可將其劃分為兩部分:存取數據部分和數據轉換部分。
3.1 數據存取
鏈接庫向外輸出一套函數供應用程序調用,包括初始化、采集、取得配置、設置配置參數、解壓函數等等。在應用程序使用其它輸出函數之前,必須調用初始化函數,指定此鏈接庫的用途:編碼(采集)還是解碼,還要注冊一個回調函數(驅動程序在采集或解壓完一幀或規定的數據后將調用此函數)。用于編碼端(采集)時,鏈接庫的工作比較簡單,根據應用程序的要求,從設備中采集一定量的數據,完成請求后,調用應用程序注冊的回調函數,在此函數中應用程序處理采集到的數據。編碼(采集)端開辟一個線程用于從設備中讀取壓縮后的數據,在進行讀寫設備時先打開在內核態驅動程序創建的用于通知的事件對象,等待其變為“已傳信”,待共用緩沖區的數據可用,將共用緩沖區中的數據拷貝到另外一個中間緩存(此緩存將作為參數傳遞給回調函數)。
用于解碼時,工作則要復雜得多。首先必須向設備寫入待解壓的數據,再從設備中讀取解壓后的數據,并把解壓后的數據轉換成RGB格式的數據,從中提取出356×288大小的圖像數據。當完成這些工作后,調用回調函數。既要使設備充分工作,又不至于使系統開銷過大,所以在解碼端開辟兩個線程,分別用于向設備寫入待解壓的數據和讀取解壓后的數據。同樣,在進行讀寫設備時先打開在內核態驅動程序創建的用于通知的事件對象,等待其變為“已傳信”,待共用緩沖區的數據可用(讀數據)或數據需要更新時,根據要求處理緩沖區。需要注意的是在解碼時既要從設備收集解壓數據,同時又要對解壓后的數據進行格式轉換,進行格式轉換是一件很費時間的工作,所以數據格式轉換例程最好能采用另外一個線程。
3.2 數據格式轉換
3.2.1 CCIR656數據流的格式
CCIR656的數據是分場的數據流(分為奇偶場),在每行數據的開始有SAV(有效視頻數據的開始),數據的結尾有EAV(有效視頻數據的結尾)。每場(奇場和偶場)數據、場逆程數據的SAV和EAV均不相同。CCIR656數據流格式如圖3所示。
?
?
鏈接庫只需向應用程序提供QCIF(356×244)的圖像數據,而每行數據有720個有效象素,一般每行數據的開始和最后的幾個象素點是無關緊要的,因此通過舍棄每行數據的開始和結束的4個象素后再進行點抽樣,可得到每行356個有效象素。每場數據有244行有效數據(剛好是一場)剛好可以滿足需求,并且還可容納一定的錯誤。如果第一場數據出現錯誤,則丟掉此場數據,接著轉換第二場數據;若第二場數據未發生錯誤,則將此場數據送給應用程序;若這一幀的兩場數據均有問題,則只有丟掉此幀數據;若第一場數據正確,則不用轉換第二場數據。
3.2.2 設計方案
在第一次調用此函數時,由于不知道有效數據從何處開始,所以需要在遍歷緩沖區查找SAV,找到后再開始處理。在后面的運行中,起始位置可由前一個緩沖區的偏移位置提供定位參考。在抽樣轉換過程中,有可能遇到下一個有效象素點(全部或部分分量)或者要處理的定位碼(SAV和EAV)不在此緩沖區內(在下一個緩沖區),這時應記錄這個象素或者定位碼所缺分量的偏移和已得到的部分分量。對于驗證部分SAV,須決定從哪個字節開始驗證。
如果緩沖區開始的數據就是有效數據的分量,首先查看上一個象素是否已得到完整的處理,否則找到所缺的分量,轉換此象素,再對其余象素進行抽樣轉換處理。對于驗證EAV,驗證完畢后,跳過行逆程數據,設置合適的偏移量(下一個有效數據行的開始在緩沖區中的位置),進入下一次循環。對于出錯的處理,如果已發現正在處理的那一場數據有錯誤(每個象素的分量不可能是255和0,若是說明出錯),開始再次搜索SAV。此場余下的點不再轉換,處理點位置只簡單地向后移動,以便得到下一步處理所需的偏移。如果奇場數據出錯,便處理偶場數據,否則偶場數據不用處理。格式轉換流程如圖4所示。
?
?
由于壓縮后的數據較少,PIO(程序控制的I/O)所需的時間較短,并且不需進行后續處理;而解壓后的數據量大,有27Mb/s,PIO所需的時間長,還要進行格式轉換。所以本驅動程序每秒可壓縮25~30幀圖像,可解壓10~15幀圖像。若考慮在壓縮時只傳出一場壓縮后的數據,可解壓的幀數會更多,圖像質量不會下降,但只能提供356×288格式的圖像,不能提供更高分辨率的圖像數據。
?
參考文獻
1 Art Baker.Windows NT 設備驅動程序設計指南.北京:機械工業出版社,1997
2 Jeffrey Richer.Windows 高級編程(第三版).北京:清華大學出版社,1999
3 Walter Oney.Programing? the? windows driver model. Microsoft? Press,1999
4 Peter G. Viscarola? NT Device Driver Development.北京:電子工業出版社,2000
5 Windows NT技術內幕(第二版).Microsoft Press,1999
6 NT DDK document.Microsoft,1996
7 VC技術內幕(第四版).北京:清華大學出版社,1998
8 錢能.C++ 程序設計教程.北京:清華大學出版社,1999