二、Filter 原理

2.1 Filter 概述

Filter(过滤器)是 DirectShow 中最基本的概念。DirectShow 是通过 Filter Graph 来管理 Filter 的。Filter Graph 是 Filter 的 "容器",而 Filter 是 Filter Graph 中的最小功能模块

Filter 一般由一个或多个 Pin 组成,Filter 通过 Pin 相互连接,构成一条顺序的链路。Pin 是由 Filter 创建的 COM 对象。在上面曾经提到,Filter 根据实现功能的不同大致可分为 3 类:Source Filters、Transform Filters 和 Rendering Filters。另一种实用的判别方法是根据 Filter 包含的输入 Pin 或者输出 Pin 的数量来判断。

如下图所示,可以根据 Filter 所包含的输入 Pin 和输出 Pin 的熟练来判断 Filter 的类型:

  • 只有输出 Pin,没有输入 pin,为 Source Filter。
  • 既有输出 Pin,又有输入 pin,为 Transform Filter。
  • 没有输出 Pin,只有输入 pin,为 Rendering Filter。

Filter 是一种 COM 组件。为了实现在 Filter Graph 中的统一操作,每个 Filter 上都至少实现了 IBaseFilter 接口。实现 Filter 的文件一般是一个 DLL,扩展名可以是 .dll,但更多是 .ax。跟普通的 COM 组件一样,Filter 的创建是通过 API 函数 CoCreateInstance 来完成的,代码如下:

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 用于获得接口对象的指针。

Filter 必须加入到 Filter Graph 且接入到工作链路中才能发挥作用。如果想绕过 Filter Graph 而直接使用 Filter 实现的模块功能,微软公司提供了另一种解决方案,就是将 Filter 功能移植成 DirectX 媒体对象(DMO)。

2.2 Filter 的注册

如果需要编写自己的 Filter,才需要了解Filter 的注册。所以这里由于篇幅原因不详说,如果有这方面需求的话可以去看《DirectShow开发指南》2.2 小节,以及DirectShow Filter的开发实践

2.3 Filter 的媒体类型

媒体类型实际上是 DirectShow 定义的一个数据结构 AM_MEDIA_TYPE,代码如下:

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

当使用一个 AM_MEDIA_TYPE 数据结构描述媒体类型时,如果 majortype、subtype 和 formattype 都指定了一个特定的 GUID 值,那么称这种媒体类型为 “完全指定的媒体类型”;这 3 个部分只要有一个指定为 GUID_NULL,则称之为 “不完全指定的媒体类型”。GUID_NULL 具有 “通配符” 的作用。

为了方便使用,DirectShow 提供了另一个 C++ 类——CMediaType 来操作媒体类型。CMediaType 类是从 AM_MEDIA_TYPE 数据结构中 “公共”(public)派生而来的,这样既保留了直接访问数据成员的灵活性,又增加了一些有用的类成员接口,如媒体类型赋值、媒体类型比较、格式数据块内存的自动管理等。

2.4 Filter的连接

Filter 的连接实际上也就是 Filter上Pin 的连接。连接的方向一般总是由上一级 Filter(Upstream Filter)的输出 Pin 指向下一级 Filter(Downstream Filter)的输入 Pin。

Pin 的连接实际上是连接双方使用的媒体类型的一个 “协商” 过程。这个过程很重要,也有点复杂。具体怎么连接,这里由于篇幅原因不详说,感兴趣可以去看《DirectShow开发指南》2.4 小节,或者去 《DirectShow开发指南》学习笔记_4 了解。

2.5 智能连接

Filter 通过 Pin 这样的连接,就能 “串联” 起来,从而构建一个完整的 Filter Graph。Filter Graph 的构建方法大概有以下几种:

  • IFilterGraph::AddFilter:该参数提供一个 Filter 对象,将其加入到 Filter Graph 中;
  • 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用到的情况较多。后 4 种构建方法都有 “自动” 的功能。在 DirectShow 中,这种 “自动” 机制也称为智能连接(Intelligent Connect)。智能连接的具体实现过程,这里由于篇幅原因不详说,感兴趣可以去看《DirectShow开发指南》2.5 小节,或者去 《DirectShow开发指南》学习笔记_5 了解。

Filter 原理的更多相关文章

  1. Bloom Filter 原理与应用

    介绍 Bloom Filter是一种简单的节省空间的随机化的数据结构,支持用户查询的集合.一般我们使用STL的std::set, stdext::hash_set,std::set是用红黑树实现的,s ...

  2. url去重 --布隆过滤器 bloom filter原理及python实现

    https://blog.csdn.net/a1368783069/article/details/52137417 # -*- encoding: utf-8 -*- ""&qu ...

  3. 无人驾驶技术之Kalman Filter原理介绍

    基本思想 以K-1时刻的最优估计Xk-1为准,预测K时刻的状态变量Xk/k-1,同时又对该状态进行观测,得到观测变量Zk,再在预测与观之间进行分析,或者说是以观测量对预测量进行修正,从而得到K时刻的最 ...

  4. filter原理

    index.jsp: <a href="product-input.action">input</a> <form action="prod ...

  5. 3.filter原理(bitset机制与caching机制)

    主要知识点: 一次filter执行顺序 filter和query的特点     一.一次filter执行顺序     1.在倒排索引中查找搜索串,获取document list 以一下date数据来举 ...

  6. 通俗理解kalman filter原理

    [哲学思想]即使我们对真相(真值)一无所知,我们任然可以通过研究事物规律,历史信息,当前观测而能尽可能靠近真相(真值). [线性预测模型]温度的变化是线性规律的,已知房间温度真值每小时上升1度左右(用 ...

  7. BloomFilter 与 Cuckoo Filter

    BloomFilter 与 CuckooFilter Bloom Filter 原理 Bloom Filter是一种空间效率很高的随机数据结构,它的原理是,当一个元素被加入集合时,通过K个相互独立的H ...

  8. 大数据量下的集合过滤—Bloom Filter

    算法背景 如果想判断一个元素是不是在一个集合里,一般想到的是将集合中所有元素保存起来,然后通过比较确定.链表.树.散列表(又叫哈希表,Hash table)等等数据结构都是这种思路,存储位置要么是磁盘 ...

  9. 为什么 “return s and s.strip()” 在用 filter 去掉空白字符时好使?

    如题: 给定一个数组,其中该数组中的每个元素都为字符串,删除该数组中的空白字符串. _list = ["A", "", "", " ...

随机推荐

  1. java使用htmlunit工具抓取js中加载的数据

    htmlunit 是一款开源的java 页面分析工具,读取页面后,可以有效的使用htmlunit分析页面上的内容.项目可以模拟浏览器运行,被誉为java浏览器的开源实现.这个没有界面的浏览器,运行速度 ...

  2. uiautomatorviewer 报错 Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncException: Remote object doesn't exist!

    在进行自动化时经常需要使用到 uiautomatorviewer获取控件的各个属性,然后在脚本中通过各个控件的属性来操作. 如果使用的是uiautomator2的话,一般都是使用weditor这个来查 ...

  3. TopCoder12808 「SRM594Medium」FoxAndGo3 二分图最大独立集

    问题描述 一个 \(N \times N\) 围棋棋盘,任意两个白子不相邻,你要加入若干个黑子并提出白子,最大化空格数目. submit 题解 显然最终棋盘的局面不能够一个白子和它周围的空格都是空的, ...

  4. 一些你不知道的js特性【一】

    关于js 我们知道完整的js包括三个方面ECMAScript.DOM(文档对象模型).BOM(浏览器对象模型). ECMAScript定义了与宿主无关的预言基础,比如:语法(包含正则语法).类型.语句 ...

  5. Python函数(函数定义、函数调用)用法详解

    Python 中,函数的应用非常广泛,前面章节中我们已经接触过多个函数,比如 input() .print().range().len() 函数等等,这些都是 Python 的内置函数,可以直接使用. ...

  6. 【OCR技术系列之四】基于深度学习的文字识别

    上一篇提到文字数据集的合成,现在我们手头上已经得到了3755个汉字(一级字库)的印刷体图像数据集,我们可以利用它们进行接下来的3755个汉字的识别系统的搭建.用深度学习做文字识别,用的网络当然是CNN ...

  7. Gluserfs 架构详解【译】官网

    Gluserfs详解 排版看着不舒服的,可以查看[我的简书](https://www.jianshu.com/p/0340e429431b) doc home:https://docs.gluster ...

  8. 一起学Android之AsyncTask

    概述 在Android开发中,为了方便我们在后台线程中执行操作,然后将结果发送给主线程,从而在主线程中进行UI更新等操作,Anddroid开发框架提供了一个助手类AsyncTask,它对Thread和 ...

  9. Git - Git推送本地分支到远程分支报错(! [rejected] non-fast-forward)的解决办法

    一般都是冲突造成的,解决方案执行如下命令(dev为分支名称): git fetch origin dev  #获取远程 dev 分支的修改 git merge origin dev       #合并 ...

  10. Access Editor Settings 访问编辑器设置

    This topic demonstrates how to access editors in a Detail View using a View Controller. This Control ...