作者: 沈浩 譚駿珊
時間: 2004-09-15
出處: ahcit
概述
流媒體的處理,以其複雜性和技術性,一向廣受工業界的關注。特別伴隨着因特網的普及,流媒體在網絡上已廣泛應用﹐怎樣使流媒體的處理變得簡單而富有成效逐漸成爲了焦點問題。選擇一種合適的應用方案,將事半功倍。此時,微軟的DirectShow給了我們一個不錯的選擇。
DirectShow是微軟公司在ActiveMovie和Video for Windows的基礎上推出的新一代基於COM的流媒體處理的開發包,與DirectX開發包一起發佈。目前,DirectX最新版本爲9.0。DirectShow爲多媒體流的捕捉和回放提供了強有力的支持。運用DirectShow,我們可以很方便地從支持WDM驅動模型的採集卡上捕獲數據,並且進行相應的後期處理乃至存儲到文件中。這樣使在多媒體數據庫管理系統(MDBMS)中多媒體數據的存取變得更加方便。
DirectShow 原理及重要的接口
1、DirectShow工作原理
1) DirectShow的系統結構
DirectShow的體系結構如圖1所示。
圖1 DirectShow系統 |
DirectShow位於應用層中。它使用一種叫Filter Graph的模型來管理整個數據流的處理過程;參與數據處理的各個功能模塊叫Filter;各個Filter 在Filter Graph中按一定的順序連接成一條“流水線”協同工作。按照功能來分,Filter大致分爲三類:Source Filters、Transform Filters和Rendering Filters。Source Filters主要負責取得數據,數據源可以是文件、因特網、或者計算機裏的採集卡、數字攝像機等,然後將數據往下傳輸;Transform Fitlers主要負責數據的格式轉換、傳輸;Rendering Filtes主要負責數據的最終去向,我們可以將數據送給聲卡、顯卡進行多媒體的演示,也可以輸出到文件進行存儲。
在DirectShow系統之上,我們看到的,即是我們的應用程序(Application)。應用程序要按照一定的意圖建立起相應的Filter Graph,然後通過Filter Graph Manager來控制整個的數據處理過程。DirectShow能在Filter Graph運行的時候接收到各種事件,並通過消息的方式發送到我們的應用程序。這樣,就實現了應用程序與DirectShow系統之間的交互。
2) Filter概述以及連接
過濾器(Filter)是DirectShow中最基本的概念。DirectShow是通過Filter Graph來管理Filter的。Filter Graph是Filter的“容器”,而Filter是Filter Graph中的最小功能模塊。Filter是一種COM組件,對於每個Filter,都有其自己的Pin,它是由Filter創建的COM對象。Filter通過Pin來進行他們之間的連接。Pin分爲兩種:輸出Pin和輸入Pin。輸出的Pin把Filter處理後的數據傳送到Filter的外部,而輸入Pin則是把Filter外部的數據接收到Filter中,以便Filter對這些數據進行處理。對於三種類型的Filter(Source Filter,Transform Filter,Rendering Filter)的連接圖如下:
圖2 Filter的連接 |
2、DirectShow對硬件的支持原理
大家知道,爲了提高系統的穩定性,Windows操作系統對硬件操作進行了隔離;應用程序一般不能直接訪問硬件。DirectShow Filter工作在用戶模式(User mode,操作系統特權級別爲Ring 3),而硬件工作在內核模式(Kernel mode,操作系統特權級別爲Ring 0),DirectShow解決的方法是,爲這些硬件設計包裝Filter;這種Filter能夠工作在用戶模式下,外觀、控制方法跟普通Filter一樣,而包裝Filter內部完成與硬件驅動程序的交互。這樣的設計,使得編寫DirectShow應用程序的開發人員,從爲支持硬件而需做出的特殊處理中解脫出來。DirectShow已經集成的包裝Filter,包括Audio Capture Filte(qcap.dll)、VfW Capture Filter(qcap.dll,Filter的Class Id爲CLSID_VfwCapture)、TV Tuner Filter(KSTVTune.ax,Filter的Class Id爲CLSID_CTVTunerFilter)、Analog Video Crossbar Filter(ksxbar.ax)、TV Audio Filter(Filter的Class Id爲CLSID_TVAudioFilter)等;另外,DirectShow爲採用WDM驅動程序的硬件設計了KsProxy Filter(Ksproxy.ax,)。下圖就是各個包裝Filter與硬件交互的結構圖:
應用程序 | |||
DirectShow Filter Graph | |||
KsTune.ax | KsXbar.ax | KsCap.ax | 其他普通的Filter |
Stream Class | |||
Tuner minidriver | Crossbar mindriver | Capture minidriver | Tuner,Crossbar,Capture minidriver |
3、DirectShow 的重要接口
DirectShow採用了COM標準,所以很多重要的功能都是通過COM接口來完成。下面就列舉一些重要的DirectShow的接口。
(1) IGraphBuilder接口
用於構造Filter Graph的接口,建立和管理一系列的Filter,過濾和處理源媒體流。
(2) IMediaControl接口
用於控制多媒體流在過濾器圖表中的流動,如流的啓動和停止。
(3) IMediaEvent接口
用於捕獲播放過程中發生的事件,並通知應用程序,如EC_COMPLETE等。
(4) IVideoWindow接口
用於控制視頻窗口的屬性。
(5) IMeadiaSeeking接口
用於查找媒體的接口,定位流媒體,控制多媒體數據播放提供精確控制。
(6) IBaseFilter接口
從ImediaFilter接口繼承,用來定義一個具體的過濾器指針,並對多媒體數據進行處理。
(7) IPin接口
用於管理兩個過濾器之間的Pin,從而連接過濾器。
(8) IsampleGrabberCB接口
是Sample Grabber過濾器的一個接口,用於當流媒體數據通過過濾器時進行採樣以獲得幀圖象。
用DirectShow來使用攝像頭,一般要求攝像頭的驅動是WDM格式的,當然,一些比較老的驅動格式DirectShow也可支持。在DirectShow中,有一個Sample Grabber過濾器,它是一個可以被插入流的過濾器,它有自己的緩衝,存放採樣。我們就可以用它來從一個視頻文件中簡單的撲獲一楨。DirectShow通過圖形過濾管理器(Filter Graph Manager)來與上層應用程序和下層的驅動進行聯繫。DirectShow通過捕獲過濾器(Capture Filter)來支持對攝像頭的捕獲,一個捕獲過濾器有多個插口(pin),其中的預覽(preview)插口可用來進行顯示禎圖象。
1、創建圖形過濾管理器Filter Graph
如上面原理所述,首先要創建Filter Graph:
CComPtr< IGraphBuilder > m_pGraph;
hr=m_pGraph.CoCreateInstance( CLSID_FilterGraph );
2、連接設備
還要創建系統枚舉器組件對象:
CComPtr<ICreateDevEnum>pCreateDevEnum;pCreateDevEnum.CoCreateInstance( CLSID_SystemDeviceEnum );
然後使用接口方法CreateClassEnumerator ()爲指定的Filter註冊類型目錄創建一個枚舉器,並獲得IenumMoniker接口:
CComPtr< IEnumMoniker > pEm;
pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0 );
接着在調用BindToObject()以後,可以將設備標識生成一個DirectShow Filter,將其加到Filter Graph中就可以參與工作了。
CComPtr< IMoniker > pM;
CComPtr< IPropertyBag > pBag;
hr=pM->BindToStorage(0,0,ID_IPropertyBag, (void**) &pBag );
3、創建Sample Grabber過濾器
CComPtr< ISampleGrabber > m_pGrabber
hr=m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
當創建好SampleGrabber以後,在Sample Grabber 過濾器連接到別的過濾器之前你必須配置它。然後查詢IsampleGrabber接口,還要設置流媒體類型:
m_pGrabber->SetMediaType();
可以僅僅指定主媒體類型;或者主類型加子類型;或者主類型,子類型和類型格式。然後就把它加載到FilterGraph中去:
m_pGraph->AddFilter(pGrabBase,"Grabber" );
4、查找Filter Graph 的Pin並完成後續連接。
接下來就可以通過調用IGraphBuilder 的FindPin()接口來查找過濾管理器中的Pin接口,並通過ICaptureGraphBuilder2 中的接口RenderStream()來完成後續的連接。
hr=pCGB2->FindPin(pCap,PINDIR_OUTPUT,&PIN_CATEGORY_VIDEOPORT, NULL,FALSE,0,&pVPPin);
hr=pCGB2->RenderStream(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video, pCap,pGrabBase,pRenderer);
5、獲取流媒體類型並運行
通過GetConnectedMediaType()獲取連接流媒體的類型以後,我們可以通過IsampleGrabberCB類的接口BufferCB()來把視頻的數據拷貝到自定義的緩衝區中,然後通過在緩衝區的拷貝進行視頻到圖象數據的拷貝。最後運行﹕
CComQIPtr<IMediaControl,&IID_IMediaControl > pControl = m_pGraph;
hr = pControl->Run( );
結論
本文討論了DirectShow的基本原理,創建Filter Graph的基本方法,以及通過DirectShow來捕獲視頻數據,然後將其保存爲自己想要的圖象,對於多媒體數據庫管理系統是一個非常有利的補充,如對考試報名的軟件系統有很強的適應性,可以降低開發成本。提高用戶的實用性。
DirectShow技術是一個開發多媒體的行之有效的方法。在未來幾年中,DirectShow技術的發展前景相當廣闊,掌握DirectShow的技術將有重要的實用意義。