要建立一個篩選器表,您要從建立一個篩選器表管理器的執行個體開始,如下所示:
IGraphBuilder* pIGB;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph,
NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder,
(void **)&pIGB);
篩選器表管理器支援下列表產生方法:
- IFilterGraph::ConnectDirect方法,嘗試在兩個插頭之間建立直接的串連。如果插頭無法串連,方法失敗。
- IGraphaBuilder::Connet方法,也可以串連兩個插頭。它儘可能進行直接連接。如果無法直接連接,它使用中介篩選器來完成串連。
- IGraphBuilder::Render方法,由一個輸出插頭啟動,產生整個表。此方法添加需要的篩選器,直到到達一個還原篩選器。
- IGraphBuilder::RenderFile方法,產生一個完整的檔案播放器表。它使用IGraphBuilder::AddSourceFilter方法來根據檔案的類型添加一個源篩選器,然後使用IGraphBuilder::Render來產生表中的其它部分。
- IFilterGraph::AddFilter方法,向表添加一個篩選器。它不會將此篩選器串連到其它的篩選器上。應用程式必須首先建立一個篩選器執行個體,可以使用CoCreateInstance,或者使用篩選器映像和系統裝置列舉器對象。
這些方法為產生表提供了三個基本途徑:
1、應用程式指示篩選器表管理器自動產生全部表。
2、應用程式和表管理器共同完成表產生的工作。
3、應用程式通過獨立的添加和串連每個篩選器,產生整個表。
途徑1:篩選器表管理器產生全部表
當你只是想簡單的播放一個檔案或某些可識別的格式時(如AVI、MPEG、WAV或MP3),可使用此途徑。這個技術在文章<如何播放一個檔案>中有樣本。在DirectShow中,術語“還原”經常用來代替“播放”,其過程就是在監視器上顯示視頻資料,或通過系統的喇叭播放音頻資料。為了指示篩選器表管理器自動建立一個能還原指定檔案的篩選器表,應用程式使用IGraphBuilder::RenderFile方法。(注意,此方法實際上並不會播放檔案;它只是產生表。)下面的部分介紹了表管理器建立表的基本步驟:
發現篩選器
篩選器表管理器的第一步是發現和建立需要的篩選器。它首先根據資料的媒體類型選擇篩選器。這是因為兩個篩選器,只有它們的插頭所處理的媒體類型一致時,這兩個插頭才能進行串連。篩選器表管理器通過搜尋註冊表中媒體類型和副檔名的組合來確定媒體類型。如.wma、.avi和.wav。如果沒有此副檔名的組合,篩選器表管理器搜尋檔案中特有的“檢驗位元組”。從這些檢驗位元組,能夠確定DirectShow媒體類型和相應的源篩選器。在內部,RenderFile方法調用IGraphBuilder::AddSourceFilter來完成這個任務。
如果發現某個Moniker的源篩選器,可以讀取指定類型的檔案,篩選器表管理器將使用CoCreateInstance,利用返回的GUID,建立一個篩選器的執行個體。對於大部分檔案類型,源篩選器將作為檔案源(同步)篩選器。然後,篩選器表管理器調用IFilterGraph::AddFilter方法將篩選器添加到篩選器表。當篩選器得到添加入表的通知,它會建立一個或多個與將要讀取的檔案類型相匹配的輸出插頭。
在插頭建立完成後,表管理器檢查每個插頭支援的媒體類型,然後再次查看註冊表,尋找篩選器,這個篩選器要能夠訪問輸入插頭的媒體類型。當它發現一個合適的篩選器,就將它添加到表中。所有的DirectShow篩選器在Windows註冊表中都具有唯一的標識GUID,與GUID同時儲存著其它資訊,包括篩選器的種類、把持的媒體類型和merit。篩選器表管理器使用這些資訊來確定要建立哪一個篩選器。
種類標識了篩選器的一般功能,用於限制搜尋範圍。
媒體類型描述了哪種類型的資料可以被篩選器訪問,做為輸入,哪種類型的資料可以發送,做為輸出。
merit值表示在自動表產生過程中,是否應該考慮此篩選器。如果系統中有兩個篩選器具有相似的媒體類型資訊,篩選器表管理器就會選擇merit值較高的那個。某些篩選器特意給出一個較低的merit值,因為它們是為專用的篩選器表設計的。這種篩選器必須由應用程式單獨的添加到表中。
為了搜尋註冊表,篩選器表管理器會建立一個DirectShow Filter Mapper對象的執行個體,並調用IFilterMapper2::EnumMatchingFilters方法來執行搜尋。這個方法從媒體類型、插頭數目、merit和其它條件與DirectShow篩選器進行匹配。它返回一個標準的COM IEnumMoniker對象,其中包含了符合搜尋條件的所有篩選器的Moniker。(Moniker的使用使這個方法能在不建立執行個體的情況下就能查詢對象,並且列舉出來的並不一定是真正的COM對象,如硬體裝置。)
串連篩選器
當每個篩選器進行添加時,它會配置自己的插頭,並做好串連上一個篩選器(上遊篩選器)的準備。篩選器表管理器調用IGraphBuilder::Connect方法,串連上遊篩選器的輸出插頭和下遊篩選器的輸入插頭。兩個插頭互相溝通以確認串連的媒體類型,並確定由哪個插頭提供記憶體配置對象。
完成表
兩個插頭串連完成後,篩選器表管理器檢查新的篩選器輸出插頭支援的媒體類型,並搜尋能夠處理此媒體類型的篩選器。這個過程重複進行,直到所有需要的篩選器都被加入到表中。在一個檔案播放表中,第二個篩選器一般是分解篩選器,它讀取未加工的資料流,如AVI或MPEG,然後分解為音頻流和視頻流,並為每個流建立輸出插頭。如果流中的資料是壓縮的,流的下一個篩選器就是解壓縮器,再後面是一個還原器。
表產生以後,應用程式只需要從篩選器表管理器獲得IMediaControl介面,然後調用IMediaControl::Run方法,就可以開始播放檔案了。
途徑2:應用程式和篩選器表管理器共同完成表產生工作
除了簡單的還原檔案外,如果還要做其它的事情,就需要您的應用程式至少做一些表產生的工作了。例如,如果你想產生一個將AVI檔案轉換為ASF檔案的篩選器表,您仍然可以調用IGraphBuilder::RenderFile來讓篩選器表管理器建立一個AVI播放表,但是後面您必須修改這個表,以輸出一個ASF檔案。這個需要中斷連線,移除視頻音頻還原器(通過調用IFilterGraph::RemoveFilter),並用ASF寫篩選器來替代它們。
還有一件必須要做的事是添加一個中介篩選器,用以將流從一種媒體類型轉換為另一種類型。應用程式可以直接添加中介篩選器,或者使用IGraphBuilder::Connet方法。當調用此方法時,篩選器表管理器首先嘗試直接連接篩選器,如果不能統一媒體類型,管理器將搜尋中介篩選器。只要表管理器找到一能夠處理給定媒體類型的篩選器,它先嘗試與已經被添加到表中的篩選器進行串連。要禁止表管理器插入中介篩選器,請使用IFilterGraph::ConnetDirect方法。
在上例中,應用程式產生表的下遊一部分。在其它情況下,應用程式可能需要產生表的上遊部分。此時,一旦您已經添加並串連好必須手工添加的部分,就可以使用IGraphBuilder::Render方法來指示表管理器從指定輸出插頭完成表的其它部分。如果一個篩選器有多於一個的輸出插頭,應用程式必須為每個插頭調用Render。
途徑3:應用程式自己產生整個表
在有些情況下,您的應用程式也許需要獨立添加和串連每個篩選器,產生整個表。此時,您可能特別瞭解哪些篩選器應當被加入表中,因此不需要使用篩選器映像對象來探索篩選器。可使用AddFilter方法向表中添加篩選器,然後使用Connect或ConnectDirect將它們進行串連。