Filter 原理

2、Filter 原理

2.1 Filter 概述

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

  • 只有輸出 Pin,沒有輸入 pin,爲 Source Filter。
  • 既有輸出 Pin,又有輸入 pin,爲 Transform Filter。
  • 沒有輸出 Pin,只有輸入 pin,爲 Rendering Filter。

<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
);
  • 參數 rclsid 指定要建立的 Filter 的 CLSID;
  • 由於絕大多數狀況下建立的 Filter 不是被 「聚合」(Aggregation)的,因此 pUnkOuter 指定爲 NULL;
  • dwClsContext 能夠指定爲 CLSCTX_INPROC_SERVER,以建立進程內組件對象;
  • riid 在建立 Filter 成功後得到的接口的 ID,通常爲 IID_IBaseFilter,也能夠是其餘特殊的接口;
  • ppv 用於得到接口對象的指針。

<span style="color:green">Filter 必須加入到 Filter Graph 且接入到工做鏈路中才能發揮做用。若是想繞過 Filter Graph 而直接使用 Filter 實現的模塊功能,微軟公司提供了另外一種解決方案,就是將 Filter 功能移植成 DirectX 媒體對象(DMO)。</span>函數

<br />學習

2.2 Filter 的註冊

若是須要編寫本身的 Filter,才須要瞭解Filter 的註冊。因此這裏因爲篇幅緣由不詳說,若是有這方面需求的話能夠去看《DirectShow開發指南》2.2 小節,以及DirectShow Filter的開發實踐ui

<br />spa

2.3 Filter 的媒體類型

媒體類型其實是 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 來標識。它們的做用分別是:

  • majortype 定性地描述媒體類型,如制定這是一個視頻(MEDIATYPE_Video)、音頻(MEDIATYPE_Audio)或者字節流(MEDIATYPE_Stream)等;
  • subtype 輔助說明 majortype,指明具體是哪一種格式,例如,若 majortype 是視頻, subtype 能夠進一步指明這是 UYVY(MEDIASUBTYPE_UYVY)、RGB24(MEDIASUBTYPE_RGB24)仍是RGB32(MEDIASUBTYPE_RGB32)等,若 majortype 是音頻,subtype 能夠進一步指明這是 PCM 格式(MEDIASUBTYPE_PCM)仍是 AC3 格式(MEDIASUBTYPE_DOLBY_AC3)等;
  • formattype 指定了一種進一步描述格式細節的數據結構類型,格式細節描述的內容主要包括視頻圖像的大小、幀率,或者音頻的採樣頻率、量化精度等參數,這個描述格式細節的數據塊指針保存在 pbFormat 成員中。

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 />

2.4 Filter的鏈接

Filter 的鏈接實際上也就是 Filter上Pin 的鏈接。鏈接的方向通常老是由上一級 Filter(Upstream Filter)的輸出 Pin 指向下一級 Filter(Downstream Filter)的輸入 Pin。

Pin 的鏈接其實是鏈接雙方使用的媒體類型的一個 「協商」 過程。這個過程很重要,也有點複雜。具體怎麼鏈接,這裏因爲篇幅緣由不詳說,感興趣能夠去看《DirectShow開發指南》2.4 小節,或者去 《DirectShow開發指南》學習筆記_4 瞭解。

<br />

2.5 智能鏈接

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 />

相關文章
相關標籤/搜索