Filter(過濾器)是 DirectShow 中最基本的概念。DirectShow 是經過 Filter Graph 來管理 Filter 的。Filter Graph 是 Filter 的 "容器",而 Filter 是 Filter Graph 中的最小功能模塊。html
Filter 通常由一個或多個 Pin 組成,Filter 經過 Pin 相互鏈接,構成一條順序的鏈路。Pin 是由 Filter 建立的 COM 對象。在上面曾經提到,Filter 根據實現功能的不一樣大體可分爲 3 類:Source Filters、Transform Filters 和 Rendering Filters。<span style="color:darkOrange">另外一種實用的判別方法是根據 Filter 包含的輸入 Pin 或者輸出 Pin 的數量來判斷。</span>c++
以下圖所示,能夠根據 Filter 所包含的輸入 Pin 和輸出 Pin 的熟練來判斷 Filter 的類型:windows
<br />數據結構
Filter 是一種 COM 組件。爲了實如今 Filter Graph 中的統一操做,每一個 Filter 上都至少實現了 IBaseFilter 接口。實現 Filter 的文件通常是一個 DLL,擴展名能夠是 .dll,但更可能是 .ax。<span style="color:darkOrange">跟普通的 COM 組件同樣,Filter 的建立是經過 API 函數 CoCreateInstance 來完成的,</span>代碼以下:ide
STDAPI CoCreateInstance( REFCLSID rclsid, // class identifier (CLSID) of the object LPUNKNOWN pUnkOuter, // Pointer to controlling IUnknown DWORD dwClsContext, // Context for running executable code REFIID riid, // Reference to the identifier of the interface LPVOID * ppv // the interface pointer requested in riid );
<span style="color:green">Filter 必須加入到 Filter Graph 且接入到工做鏈路中才能發揮做用。若是想繞過 Filter Graph 而直接使用 Filter 實現的模塊功能,微軟公司提供了另外一種解決方案,就是將 Filter 功能移植成 DirectX 媒體對象(DMO)。</span>函數
<br />學習
若是須要編寫本身的 Filter,才須要瞭解Filter 的註冊。因此這裏因爲篇幅緣由不詳說,若是有這方面需求的話能夠去看《DirectShow開發指南》2.2 小節,以及DirectShow Filter的開發實踐ui
<br />spa
媒體類型其實是 DirectShow 定義的一個數據結構 AM_MEDIA_TYPE,代碼以下:.net
typedef struct _AMMediaType { GUID majortype; GUID subtype; BOOL bFixedSizeSamples; BOOL bTemporalCompression; ULONG lSampleSize; GUID formattype; IUnknown *pUnk; ULONG cbFormat; BYTE *pbFormat; }AM_MEDIA_TYPE;
從代碼中能夠看出,媒體類型主要用 3 部分來描述:majortype(主類型)、subtype(輔助說明類型)和 formattype(格式細節類型)。這 3 部分各自用一個 GUID 來標識。它們的做用分別是:
AM_MEDIA_TYPE 結構中的其餘成員,如 bFixedSizeSamples、bTemporalCompression 和 lSampleSize,它們都是可選參數,也就是說,Filter 並不必定定義這些參數,在 Filter 中引用這些參數的值也並不老是 「可信」 的。這一點對於 Filter 開發人員來講尤其重要。
常見的媒體類型這裏再也不列出,有興趣瞭解能夠在 DirectShow MSDN 查看,或者搜索相關博客,例如:媒體結構(AM_MEDIA_TYPE structure)摘自MSDN
<br />
<span style="color:green">當使用一個 AM_MEDIA_TYPE 數據結構描述媒體類型時,若是 majortype、subtype 和 formattype 都指定了一個特定的 GUID 值,那麼稱這種媒體類型爲 「徹底指定的媒體類型」;這 3 個部分只要有一個指定爲 GUID_NULL,則稱之爲 「不徹底指定的媒體類型」。</span>GUID_NULL 具備 「通配符」 的做用。
爲了方便使用,DirectShow 提供了另外一個 C++ 類——CMediaType 來操做媒體類型。CMediaType 類是從 AM_MEDIA_TYPE 數據結構中 「公共」(public)派生而來的,這樣既保留了直接訪問數據成員的靈活性,又增長了一些有用的類成員接口,如媒體類型賦值、媒體類型比較、格式數據塊內存的自動管理等。
<br />
Filter 的鏈接實際上也就是 Filter上Pin 的鏈接。鏈接的方向通常老是由上一級 Filter(Upstream Filter)的輸出 Pin 指向下一級 Filter(Downstream Filter)的輸入 Pin。
Pin 的鏈接其實是鏈接雙方使用的媒體類型的一個 「協商」 過程。這個過程很重要,也有點複雜。具體怎麼鏈接,這裏因爲篇幅緣由不詳說,感興趣能夠去看《DirectShow開發指南》2.4 小節,或者去 《DirectShow開發指南》學習筆記_4 瞭解。
<br />
Filter 經過 Pin 這樣的鏈接,就能 「串聯」 起來,從而構建一個完整的 Filter Graph。Filter Graph 的構建方法大概有如下幾種:
IFilterGraph::AddFilter
:<span style="color:darkOrange">該參數提供一個 Filter 對象,將其加入到 Filter Graph 中;</span>IFilterGraph::ConnectDirect
:該參數提供輸出 Pin、輸入 Pin 以及媒體類型,進行直接的鏈接;IGraphBuilder::AddSourceFilter
:該參數提供源文件名,自動將一個 Source Filter 加入到 Filter Graph 中;IGraphBuilder::Connect
:該參數提供輸出 pin 和輸入 pin 進行鏈接,若是鏈接失敗,自動嘗試在中間插入必要的格式轉換 Filter;IGraphBuilder::Render
:該參數提供輸出 pin,自動加入必要的 Filter 完成剩下部分 Filter Graph 的構建(直到鏈接到 Rendering Filter);IGraphBuilder::RenderFile
:該參數提供源文件名,自動加入必要的 Filter 完成這個文件的回放 Filter Graph 構建。IFilterGraph::AddFilter
用到的狀況較多。<span style="color:red">後 4 種構建方法都有 「自動」 的功能。在 DirectShow 中,這種 「自動」 機制也稱爲智能鏈接(Intelligent Connect)。</span>智能鏈接的具體實現過程,這裏因爲篇幅緣由不詳說,感興趣能夠去看《DirectShow開發指南》2.5 小節,或者去 《DirectShow開發指南》學習筆記_5 瞭解。
<br />