《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 其他 > 業(yè)界動態(tài) > NT下視頻采集及解壓驅(qū)動程序的設(shè)計(jì)與實(shí)現(xiàn)

NT下視頻采集及解壓驅(qū)動程序的設(shè)計(jì)與實(shí)現(xiàn)

2009-03-26
作者:彭 勇 黃瑞光

  摘? 要: 分析了多媒體設(shè)備驅(qū)動程序的體系結(jié)構(gòu)及視頻采集與解壓卡的驅(qū)動程序設(shè)計(jì)方案。描述了核心態(tài)驅(qū)動程序的處理流程,提供了用戶態(tài)驅(qū)動程序的設(shè)計(jì)思路和具體算法。

  關(guān)鍵詞: 驅(qū)動程序? IRP(輸入輸出請求包)? 驅(qū)動程序?qū)ο? 設(shè)備對象

?

  Windows NT的結(jié)構(gòu)決定了應(yīng)用程序不能直接操作硬件設(shè)備,它只能通過一個中間層來讀寫和控制設(shè)備,這個中間層就是驅(qū)動程序。驅(qū)動程序位于計(jì)算機(jī)軟件的最低層(HAL為硬件抽象層),直接與硬件設(shè)備的特性聯(lián)系在一起。編寫驅(qū)動程序不僅要了解設(shè)備的特性,而且還要了解操作系統(tǒng)的結(jié)構(gòu),難度較大。本文比較詳細(xì)地分析了視頻采集與解壓卡的驅(qū)動程序設(shè)計(jì)思路。

1 視頻采集與解壓卡驅(qū)動程序的結(jié)構(gòu)

  多媒體設(shè)備相對普通設(shè)備來說,有兩個特點(diǎn):數(shù)據(jù)流量大;對最終期限要求高(即實(shí)時性要求比較高)。對于視頻采集與解壓卡這類多媒體設(shè)備來說,驅(qū)動程序的編寫有其特定的方式。多媒體驅(qū)動程序的結(jié)構(gòu)如圖1所示。一般說來,根據(jù)其代碼運(yùn)行的特權(quán)級可分為兩層:核心態(tài)的驅(qū)動程序和用戶態(tài)的驅(qū)動程序。核心態(tài)的驅(qū)動程序運(yùn)行于內(nèi)核模式,可以執(zhí)行特權(quán)級指令,對任何I/O設(shè)備有全部的訪問權(quán),還能夠訪問任何虛地址和控制虛擬內(nèi)存硬件。

?

  用戶模式的驅(qū)動程序?qū)嵸|(zhì)上是一個動態(tài)鏈接庫(DLL)。它運(yùn)行在用戶態(tài),應(yīng)用程序向這個接口發(fā)出消息請求一定的操作。它們調(diào)用WIN32函數(shù)與內(nèi)核模式的驅(qū)動程序通訊(WIN32函數(shù)又調(diào)用NT執(zhí)行體提供的函數(shù),這些執(zhí)行體函數(shù)提供從用戶態(tài)到核心態(tài)的上下文轉(zhuǎn)換)。用戶模式的驅(qū)動程序根據(jù)接收的消息采取適當(dāng)?shù)牟僮?完成操作后將結(jié)果返回給應(yīng)用程序。但是這種結(jié)構(gòu)只適用于解壓一幅幅的位圖,并不適合采集和解壓本設(shè)備產(chǎn)生的視頻流。

  此卡既要采集又要解壓,若用標(biāo)準(zhǔn)模式進(jìn)行設(shè)計(jì),就要同時編寫視頻采集和視頻解壓的驅(qū)動程序,其中還要對解壓程序進(jìn)行改造,編寫復(fù)雜,尤其調(diào)試會很困難。在這種情況下,使用本設(shè)計(jì)方案,既可滿足要求,又可減小設(shè)計(jì)難度。

  內(nèi)核模式的驅(qū)動程序與一般驅(qū)動程序無多大的區(qū)別,只負(fù)責(zé)讀取數(shù)據(jù)和進(jìn)行設(shè)備控制。用戶模式的驅(qū)動程序要處理大部分的事務(wù)。在解壓時,驅(qū)動程序要向設(shè)備寫入待解壓的數(shù)據(jù),從設(shè)備中取得解壓后的數(shù)據(jù),向應(yīng)用程序提供一幀圖像的RGB數(shù)據(jù)。從設(shè)備得到的數(shù)據(jù)是分場存放的4:2:2的YCrCb格式的數(shù)據(jù),驅(qū)動程序?qū)⒚繋瑪?shù)據(jù)按行進(jìn)行格式轉(zhuǎn)換,組合成完整的一幀數(shù)據(jù)(QCIF)交付給應(yīng)用程序。

2 內(nèi)核模式的驅(qū)動程序的設(shè)計(jì)

  由于多媒體的數(shù)據(jù)量很大,按照常規(guī)的方法(采用IRP包進(jìn)行數(shù)據(jù)傳輸)設(shè)計(jì)將面臨著一個無法解決的問題——中斷太快驅(qū)動程序?qū)聿患疤幚怼R虼吮仨毑捎靡环N新的方法:在驅(qū)動程序中建立兩塊緩沖區(qū)(分別用于讀寫),應(yīng)用層驅(qū)動程序與核心層驅(qū)動程序共用緩沖區(qū)。當(dāng)設(shè)備中斷發(fā)生時,根據(jù)發(fā)生的中斷進(jìn)行處理。如果是讀中斷,先把數(shù)據(jù)從設(shè)備中讀到緩沖區(qū)中,發(fā)出一個DPC(推遲過程調(diào)用),通知應(yīng)用層驅(qū)動程序該緩沖區(qū)數(shù)據(jù)可用,可以取走數(shù)據(jù)了。如果是寫中斷,先把緩沖區(qū)中的數(shù)據(jù)寫到設(shè)備的FIFO中,然后發(fā)出一個DPC,通知用戶模式驅(qū)動程序該緩沖區(qū)數(shù)據(jù)已失效,需要寫入新數(shù)據(jù)。

  驅(qū)動程序工作流程如圖2所示。內(nèi)核模式向外顯露DriverEntry(驅(qū)動程序必須要有的一個例程)接口,其它的例程沒有固定的名字,為了讓I/O管理器找到這些例程,DriverEntry例程負(fù)責(zé)建立這些函數(shù)指針。I/O管理器從非分頁系統(tǒng)內(nèi)存分配一個IRP,響應(yīng)一個I/O請求,基于由用戶指定的I/O函數(shù),把IRP傳遞給合適的驅(qū)動程序Dispatch例程,Dispatch例程檢查請求的參數(shù),如果它們是有效的,使用IRP的內(nèi)容設(shè)置設(shè)備操作。當(dāng)操作完成時,在IRP中存放最后的狀態(tài)代碼,并把它送回I/O管理器;I/O管理器使用IRP中的信息完成請求,并把最后狀態(tài)發(fā)送給請求者。

?

  當(dāng)驅(qū)動程序被加載到系統(tǒng)中時,I/O管理器將創(chuàng)建一個驅(qū)動程序?qū)ο?在系統(tǒng)中代表一個獨(dú)立的驅(qū)動程序,并且為I/O管理器記錄每個驅(qū)動程序的調(diào)度例程的地址),然后調(diào)用其初始化例程。

  在DriverEntry這個初始化例程中完成的任務(wù)是:

  ·把驅(qū)動程序的入口填入該驅(qū)動程序?qū)ο笾小?/P>

  ·用設(shè)備的VID和DID查找每條總線上的每個插槽,找到這塊圖像壓縮解壓卡,并用IoCreateDevice創(chuàng)建設(shè)備對象,用IoCreateSymbolicLink建立符號連接。

  ·初始化放在非分頁區(qū)中的Device Extension中的各個分量。包括讀寫IRP,以及保護(hù)各自隊(duì)列的自旋鎖等。

  ·設(shè)備有兩塊專有內(nèi)存,必須將其總線相關(guān)地址轉(zhuǎn)換成系統(tǒng)范圍內(nèi)的地址,并將其映射到系統(tǒng)虛空間。對于I/O端口,將其總線相關(guān)地址轉(zhuǎn)換成系統(tǒng)范圍內(nèi)的地址即可。

  ·用ExAllocatePool()分配兩塊非分頁緩存,并把它映射到用戶地址中。

  在驅(qū)動程序讀寫設(shè)備之前,必須進(jìn)一步初始化,表明設(shè)備驅(qū)動程序的用途:解碼或編碼。上層的驅(qū)動程序調(diào)用DeviceIoControl對工作模式進(jìn)行設(shè)置,驅(qū)動程序收到此IRP后設(shè)置壓縮解壓芯片的工作模式及視頻采集芯片、總線接口芯片的參數(shù)。在開始編碼或解碼之前,上層的驅(qū)動程序必須調(diào)用DeviceIoControl取回共用緩沖區(qū)的地址。

3 用戶模式的驅(qū)動程序設(shè)計(jì)

  用戶模式的驅(qū)動程序要完成以下功能:采集時,從設(shè)備中讀取一定量(一般是一幀)的數(shù)據(jù)傳遞給應(yīng)用程序。解碼相對復(fù)雜,不僅要向設(shè)備寫入待解壓的數(shù)據(jù),從設(shè)備中讀取一幀解壓后的數(shù)據(jù),由于讀取的數(shù)據(jù)是CCIR656的視頻流不適合應(yīng)用程序的顯示,還要對其進(jìn)行格式轉(zhuǎn)換,轉(zhuǎn)換成適合計(jì)算機(jī)顯示的RGB格式,向應(yīng)用程序提供QCIF(356×288)大小的圖像。因此可將其劃分為兩部分:存取數(shù)據(jù)部分和數(shù)據(jù)轉(zhuǎn)換部分。

3.1 數(shù)據(jù)存取

  鏈接庫向外輸出一套函數(shù)供應(yīng)用程序調(diào)用,包括初始化、采集、取得配置、設(shè)置配置參數(shù)、解壓函數(shù)等等。在應(yīng)用程序使用其它輸出函數(shù)之前,必須調(diào)用初始化函數(shù),指定此鏈接庫的用途:編碼(采集)還是解碼,還要注冊一個回調(diào)函數(shù)(驅(qū)動程序在采集或解壓完一幀或規(guī)定的數(shù)據(jù)后將調(diào)用此函數(shù))。用于編碼端(采集)時,鏈接庫的工作比較簡單,根據(jù)應(yīng)用程序的要求,從設(shè)備中采集一定量的數(shù)據(jù),完成請求后,調(diào)用應(yīng)用程序注冊的回調(diào)函數(shù),在此函數(shù)中應(yīng)用程序處理采集到的數(shù)據(jù)。編碼(采集)端開辟一個線程用于從設(shè)備中讀取壓縮后的數(shù)據(jù),在進(jìn)行讀寫設(shè)備時先打開在內(nèi)核態(tài)驅(qū)動程序創(chuàng)建的用于通知的事件對象,等待其變?yōu)椤耙褌餍拧?待共用緩沖區(qū)的數(shù)據(jù)可用,將共用緩沖區(qū)中的數(shù)據(jù)拷貝到另外一個中間緩存(此緩存將作為參數(shù)傳遞給回調(diào)函數(shù))。

  用于解碼時,工作則要復(fù)雜得多。首先必須向設(shè)備寫入待解壓的數(shù)據(jù),再從設(shè)備中讀取解壓后的數(shù)據(jù),并把解壓后的數(shù)據(jù)轉(zhuǎn)換成RGB格式的數(shù)據(jù),從中提取出356×288大小的圖像數(shù)據(jù)。當(dāng)完成這些工作后,調(diào)用回調(diào)函數(shù)。既要使設(shè)備充分工作,又不至于使系統(tǒng)開銷過大,所以在解碼端開辟兩個線程,分別用于向設(shè)備寫入待解壓的數(shù)據(jù)和讀取解壓后的數(shù)據(jù)。同樣,在進(jìn)行讀寫設(shè)備時先打開在內(nèi)核態(tài)驅(qū)動程序創(chuàng)建的用于通知的事件對象,等待其變?yōu)椤耙褌餍拧?待共用緩沖區(qū)的數(shù)據(jù)可用(讀數(shù)據(jù))或數(shù)據(jù)需要更新時,根據(jù)要求處理緩沖區(qū)。需要注意的是在解碼時既要從設(shè)備收集解壓數(shù)據(jù),同時又要對解壓后的數(shù)據(jù)進(jìn)行格式轉(zhuǎn)換,進(jìn)行格式轉(zhuǎn)換是一件很費(fèi)時間的工作,所以數(shù)據(jù)格式轉(zhuǎn)換例程最好能采用另外一個線程。

3.2 數(shù)據(jù)格式轉(zhuǎn)換

3.2.1 CCIR656數(shù)據(jù)流的格式

  CCIR656的數(shù)據(jù)是分場的數(shù)據(jù)流(分為奇偶場),在每行數(shù)據(jù)的開始有SAV(有效視頻數(shù)據(jù)的開始),數(shù)據(jù)的結(jié)尾有EAV(有效視頻數(shù)據(jù)的結(jié)尾)。每場(奇場和偶場)數(shù)據(jù)、場逆程數(shù)據(jù)的SAV和EAV均不相同。CCIR656數(shù)據(jù)流格式如圖3所示。

?

?

  鏈接庫只需向應(yīng)用程序提供QCIF(356×244)的圖像數(shù)據(jù),而每行數(shù)據(jù)有720個有效象素,一般每行數(shù)據(jù)的開始和最后的幾個象素點(diǎn)是無關(guān)緊要的,因此通過舍棄每行數(shù)據(jù)的開始和結(jié)束的4個象素后再進(jìn)行點(diǎn)抽樣,可得到每行356個有效象素。每場數(shù)據(jù)有244行有效數(shù)據(jù)(剛好是一場)剛好可以滿足需求,并且還可容納一定的錯誤。如果第一場數(shù)據(jù)出現(xiàn)錯誤,則丟掉此場數(shù)據(jù),接著轉(zhuǎn)換第二場數(shù)據(jù);若第二場數(shù)據(jù)未發(fā)生錯誤,則將此場數(shù)據(jù)送給應(yīng)用程序;若這一幀的兩場數(shù)據(jù)均有問題,則只有丟掉此幀數(shù)據(jù);若第一場數(shù)據(jù)正確,則不用轉(zhuǎn)換第二場數(shù)據(jù)。

3.2.2 設(shè)計(jì)方案

  在第一次調(diào)用此函數(shù)時,由于不知道有效數(shù)據(jù)從何處開始,所以需要在遍歷緩沖區(qū)查找SAV,找到后再開始處理。在后面的運(yùn)行中,起始位置可由前一個緩沖區(qū)的偏移位置提供定位參考。在抽樣轉(zhuǎn)換過程中,有可能遇到下一個有效象素點(diǎn)(全部或部分分量)或者要處理的定位碼(SAV和EAV)不在此緩沖區(qū)內(nèi)(在下一個緩沖區(qū)),這時應(yīng)記錄這個象素或者定位碼所缺分量的偏移和已得到的部分分量。對于驗(yàn)證部分SAV,須決定從哪個字節(jié)開始驗(yàn)證。

  如果緩沖區(qū)開始的數(shù)據(jù)就是有效數(shù)據(jù)的分量,首先查看上一個象素是否已得到完整的處理,否則找到所缺的分量,轉(zhuǎn)換此象素,再對其余象素進(jìn)行抽樣轉(zhuǎn)換處理。對于驗(yàn)證EAV,驗(yàn)證完畢后,跳過行逆程數(shù)據(jù),設(shè)置合適的偏移量(下一個有效數(shù)據(jù)行的開始在緩沖區(qū)中的位置),進(jìn)入下一次循環(huán)。對于出錯的處理,如果已發(fā)現(xiàn)正在處理的那一場數(shù)據(jù)有錯誤(每個象素的分量不可能是255和0,若是說明出錯),開始再次搜索SAV。此場余下的點(diǎn)不再轉(zhuǎn)換,處理點(diǎn)位置只簡單地向后移動,以便得到下一步處理所需的偏移。如果奇場數(shù)據(jù)出錯,便處理偶場數(shù)據(jù),否則偶場數(shù)據(jù)不用處理。格式轉(zhuǎn)換流程如圖4所示。

?

?

  由于壓縮后的數(shù)據(jù)較少,PIO(程序控制的I/O)所需的時間較短,并且不需進(jìn)行后續(xù)處理;而解壓后的數(shù)據(jù)量大,有27Mb/s,PIO所需的時間長,還要進(jìn)行格式轉(zhuǎn)換。所以本驅(qū)動程序每秒可壓縮25~30幀圖像,可解壓10~15幀圖像。若考慮在壓縮時只傳出一場壓縮后的數(shù)據(jù),可解壓的幀數(shù)會更多,圖像質(zhì)量不會下降,但只能提供356×288格式的圖像,不能提供更高分辨率的圖像數(shù)據(jù)。

?

參考文獻(xiàn)

1 Art Baker.Windows NT 設(shè)備驅(qū)動程序設(shè)計(jì)指南.北京:機(jī)械工業(yè)出版社,1997

2 Jeffrey Richer.Windows 高級編程(第三版).北京:清華大學(xué)出版社,1999

3 Walter Oney.Programing? the? windows driver model. Microsoft? Press,1999

4 Peter G. Viscarola? NT Device Driver Development.北京:電子工業(yè)出版社,2000

5 Windows NT技術(shù)內(nèi)幕(第二版).Microsoft Press,1999

6 NT DDK document.Microsoft,1996

7 VC技術(shù)內(nèi)幕(第四版).北京:清華大學(xué)出版社,1998

8 錢能.C++ 程序設(shè)計(jì)教程.北京:清華大學(xué)出版社,1999

本站內(nèi)容除特別聲明的原創(chuàng)文章之外,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點(diǎn)。轉(zhuǎn)載的所有的文章、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認(rèn)版權(quán)者。如涉及作品內(nèi)容、版權(quán)和其它問題,請及時通過電子郵件或電話通知我們,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟(jì)損失。聯(lián)系電話:010-82306118;郵箱:aet@chinaaet.com。