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