⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 directshow 学习笔记(二)filter - hanyufeng的专栏 - csdnblog.htm

📁 directshow的开发过程的详细介绍
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<DIV id=main>
<DIV class=Tag>
<SCRIPT language=javascript 
src="DirectShow 学习笔记(二)Filter - hanyufeng的专栏 - CSDNBlog.files/urltag.aspx"></SCRIPT>

<DIV style="CLEAR: both"></DIV></DIV><SPAN class=PreAndNext 
id=viewpost.ascx_PreviousAndNextEntriesUp>
<DIV align=center><A 
href="http://blog.csdn.net/hanyufeng/archive/2006/10/16/1336648.aspx">上一篇:&nbsp;DirectShow 
媒体文件回放总结</A>&nbsp;|&nbsp;<A 
href="http://blog.csdn.net/hanyufeng/archive/2006/10/16/1336638.aspx">下一篇:&nbsp;DirectShow 
学习笔记(1)</A></DIV></SPAN><BR>
<SCRIPT>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</SCRIPT>

<DIV class=post>
<DIV class=postTitle><A 
href="http://blog.csdn.net/hanyufeng/archive/2006/10/16/1336645.aspx"><IMG 
height=13 
src="DirectShow 学习笔记(二)Filter - hanyufeng的专栏 - CSDNBlog.files/zhuan.gif" 
width=15 border=0>&nbsp;DirectShow 学习笔记(二)Filter</A> </DIV>
<DIV class=postText>
<DIV><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">11</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">、</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">Filter</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">原理——概述</SPAN></STRONG></DIV>
<DIV><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Filter 
</SPAN>是DirectShow中最基本的概念。DirectShow使用Filter Graph来管理Filter(管理者叫做Filter Graph 
Manager)。Filter Graph是Filter的“容器“,而Filter是Filter 
Graph中的最小功能模块。<SPAN>&nbsp;&nbsp;&nbsp; </SPAN></DIV>
<DIV style="TEXT-INDENT: 21pt">Filter是一种COM组件。为了实现在Filter 
Graph中的统一操作,每个Filter上都至少实现了IBaseFilter接口。IBaseFilter继承自IMediaFilter。Filter Graph 
Manager正是通过IMediaFilter的接口方法来控制Filter Graph的状态(运行、暂停、停止)转换。</DIV>
<DIV style="TEXT-INDENT: 21pt">Filter的类别:</DIV>
<DIV style="TEXT-INDENT: 21pt"><STRONG>Source 
Filters</STRONG>主要负责获取数据,数据源可以是文件也可以是设备。只有输出Pin。</DIV>
<DIV style="TEXT-INDENT: 21pt"><STRONG>Transform 
Filters</STRONG>主要负责数据的格式转换,例如数据流分离/合成、编码/解码等,然后将数据继续往下传输。既有输入Pin又有输出Pin。</DIV>
<DIV style="TEXT-INDENT: 21pt"><STRONG>Rendering 
Filters</STRONG>主要负责数据的最终去向,送达设备或文件。只有输出Pin。</DIV>
<DIV>&nbsp;</DIV>
<DIV><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">12</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">、</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">Filter</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">原理——注册</SPAN></STRONG></DIV>
<DIV 
style="TEXT-INDENT: 21pt">实现Filter的文件一般是一个DLL,扩展名可以是.dll,但更多的时候是.ax。一般一个Filter项目都会包含一个.def文件,用于定义4个导出函数。</DIV>
<DIV 
style="TEXT-INDENT: 21pt">既然Filter是一种COM组件,使用前就必须先注册。Filter的注册信息一般包括两部分:基本的COM信息和Filter特有信息。在.def文件定义的4个导出函数:DllGetClassObject在创建Filter对象的时候被调用,根据CLSID返回对应的类工厂对象;DllCanUnloadNow用于判断是否可以从内存中卸载Filter 
DLL,即DLL中实现的所有COM对象是否都已经释放;DllRegisterServer和DllUnregisterServer调用AMovieDllRegisterServer2函数完成COM组件的自注册功能。</DIV>
<DIV>&nbsp;</DIV>
<DIV><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">13</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">、</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">Filter</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">原理——连接</SPAN></STRONG></DIV>
<DIV 
style="TEXT-INDENT: 21pt">Filter一般由一个或多个Pin组成,Filter之间通过Pin相互连接,构成一条顺序的链路。</DIV>
<DIV 
style="TEXT-INDENT: 21pt">Filter的连接实际上也是Filter上Pin的连接,Pin的连接实际上是连接双方使用的媒体类型的一个“协商”过程。试图连接的两个Filter必须处在同一个Filter 
Graph中,可以调用接口方法IFilterGraph::AddFilter将指定的Filter加入到Filter Graph。</DIV>
<DIV style="TEXT-INDENT: 21pt">整个连接过程的步骤大致如下:</DIV>
<DIV style="TEXT-INDENT: 21pt">A、Filter Graph 
Manager在输出Pin上调用IPin::Connect;</DIV>
<DIV 
style="TEXT-INDENT: 21pt">B、如果输出Pin接受连接,则调用输入Pin上的IPin::ReceiveConnection;</DIV>
<DIV style="TEXT-INDENT: 21pt">C、如果输入Pin也接受这次连接,则双方连接成功。</DIV>
<DIV>&nbsp;</DIV>
<DIV><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">14</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">、</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">Filter</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">原理——</SPAN></STRONG>动态重建技术</DIV>
<DIV><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN>由于一些原因,我们需要对已有的Filter 
Graph进行修改。通常的做法是,先将Filter Graph停止,进行修改之后,在重新启动。另外还能够在保持Filter 
Graph运行状态的同时实现动态重建。Filter Graph的重建包括如下几种情形:</DIV>
<DIV><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
A</SPAN>、仅仅改变Filter之间连接的媒体类型;</DIV>
<DIV><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
B</SPAN>、增加或删除Filter,重新进行相关Filter之间的连接;</DIV>
<DIV><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; C</SPAN>、对一条Filter链路(Filter 
Chain)进行操作。</DIV>
<DIV>&nbsp;</DIV>
<DIV><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">15</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">、</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">Filter</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">原理——数据传送</SPAN></STRONG></DIV>
<DIV style="TEXT-INDENT: 21pt"><SPAN style="COLOR: blue">每个</SPAN><SPAN 
style="COLOR: blue">Pin</SPAN><SPAN style="COLOR: blue">上都实现了</SPAN><SPAN 
style="COLOR: blue">IPin</SPAN><SPAN style="COLOR: blue">接口,这个接口主要用于</SPAN><SPAN 
style="COLOR: blue">Pin</SPAN><SPAN 
style="COLOR: blue">的连接,而不是数据传送。真正用于数据传送的一般是输入</SPAN><SPAN 
style="COLOR: blue">Pin</SPAN><SPAN style="COLOR: blue">上实现的</SPAN><SPAN 
style="COLOR: blue">IMemInputPin</SPAN><SPAN 
style="COLOR: blue">接口和输出</SPAN><SPAN style="COLOR: blue">Pin</SPAN><SPAN 
style="COLOR: blue">上实现的</SPAN><SPAN 
style="COLOR: blue">IAsyncReader</SPAN><SPAN 
style="COLOR: blue">接口。</SPAN>Filter之间的成功连接为数据传送做好了准备。<SPAN 
style="COLOR: blue">Filter</SPAN><SPAN style="COLOR: blue">之间是以</SPAN><SPAN 
style="COLOR: blue">Sample</SPAN><SPAN style="COLOR: blue">的形式传送数据的,</SPAN><SPAN 
style="COLOR: blue">Sample</SPAN><SPAN 
style="COLOR: blue">是一个封装了一定大小数据内存的</SPAN><SPAN style="COLOR: blue"><A title="" 
href="http://blog.csdn.net/ZhangXinbin/archive/2006/09/14/COM">COM</A></SPAN><SPAN 
style="COLOR: blue">组件。</SPAN><SPAN style="COLOR: blue">Samplle</SPAN><SPAN 
style="COLOR: blue">是由分配器(</SPAN><SPAN style="COLOR: blue">Allicator</SPAN><SPAN 
style="COLOR: blue">,也是一个</SPAN><SPAN style="COLOR: blue"><A title="" 
href="http://blog.csdn.net/ZhangXinbin/archive/2006/09/14/COM">COM</A></SPAN><SPAN 
style="COLOR: blue">组件)来管理的。连接双方的</SPAN><SPAN 
style="COLOR: blue">Pin</SPAN><SPAN 
style="COLOR: blue">必须使用同一个分配器,但是这个分配器到底由哪个</SPAN><SPAN 
style="COLOR: blue">Pin</SPAN><SPAN style="COLOR: blue">来创建也需要协商。</SPAN></DIV>
<DIV style="TEXT-INDENT: 21pt"><SPAN 
style="COLOR: blue">数据传送主要有两种模式:推模式(</SPAN><SPAN style="COLOR: blue">Push 
Model</SPAN><SPAN style="COLOR: blue">)和拉模式(</SPAN><SPAN 
style="COLOR: blue">Pull Model</SPAN><SPAN style="COLOR: blue">)。</SPAN></DIV>
<DIV style="TEXT-INDENT: 21pt"><SPAN style="COLOR: blue">DirectShow</SPAN><SPAN 
style="COLOR: blue">总是使用专门的线程来传送数据。</SPAN>所以,DirectShow应用程序至少包含两条线程,一条应用程序主线程以及至少一条数据传送子线程。</DIV>
<DIV style="TEXT-INDENT: 21pt">&nbsp;</DIV>
<DIV><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">16</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">、</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">Filter</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">原理——状态转换</SPAN></STRONG></DIV>
<DIV><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
Filter</SPAN>有3种状态:停止(Stopped)、暂停(Paused)和运行(Running)。其中,暂停可以理解为数据就绪状态,是为了快速切换到运行状态而设计的。作为一种中间状态,暂停也是停止与运行之间切换所必经的一种状态。</DIV>
<DIV style="TEXT-INDENT: 21pt">&nbsp;</DIV>
<DIV><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">17</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">、</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">Filter</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">原理——媒体定位的实现</SPAN></STRONG></DIV>
<DIV style="TEXT-INDENT: 21pt">应用程序可以通过Filter Graph 
Manager上获得的IMediaSeeking接口,实现对流媒体的随机定位(Seeking)和调整媒体文件的回放速率。实际上,IMediaSeeking接口的真正实现在Filter上。</DIV>
<DIV 
style="TEXT-INDENT: 21pt">用于媒体定位的还有另外一个接口IMediaPosition,这是一个支持自动化(Automation)的接口,是为那些弱类型编程语言(如VB)开发DirectShow应用程序而设计的。对于Filter开发人员来说,并不要求实现IMediaPosition。Filter 
Graph Manager会自动将IMediaPosition的接口方法调用转换为IMediaSeeking的接口方法调用。</DIV>
<DIV>&nbsp;</DIV>
<DIV><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">18</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">、</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">Filter</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">原理——质量控制的实现</SPAN></STRONG></DIV>
<DIV style="TEXT-INDENT: 21pt">数据线程是通过一种“压迫式”方式往下传送数据的。虽然Video 
Renderer接收到Sample后,会根据Sample上的时间戳来正确安排显示时机,但仅仅这样是不够的,它并不能改善Filter 
Graph运行时的性能。因此,DirectShow另外设计了一种“自适应”的反馈机制:质量控制(Quality 
Control)。质量控制通过IQualityControl接口来实现。具体质量控制策略的实现取决于具体的Filter实现,可能调整发送速度,也可能是丢失部分数据。</DIV>
<DIV>&nbsp;</DIV>
<DIV><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">19</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">、</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">Filter</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">原理——音视频同步解决方案</SPAN></STRONG></DIV>
<DIV><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
</SPAN>在任何系统设计中,最关键的都是系统框架以及控制部分。DirectShow也不例外,这个重要的部分就是Filter Graph 
Manager,它向下直接控制Filter 
Graph中的所有Filter,向上对应用程序提供编程接口。可惜的是,微软公司并没有提供这些功能控制的源代码。</DIV>
<DIV style="TEXT-INDENT: 21pt">DirectShow的音视频同步解决方案就是为Filter 
Graph选择一个公共的参考时钟(Reference Clock),并且要求传送到Renderer Filter的每个Sample都打上时间戳(Time 
Stamp);Video Renderer或Audio 
Renderer根据Sample的时间戳以及参考时钟当前的参考时间,来正确安排Sample的播放时机。</DIV>
<DIV>&nbsp;</DIV>
<DIV><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">20</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">、</SPAN></STRONG><STRONG><SPAN 
style="FONT-SIZE: 12pt; COLOR: blue">Filter</SPAN></STRONG><STRONG><SPAN 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -