Directshow - Create DirectShow Filter DLL

翻译 2011年10月14日 21:10:19

1        题外话

这几天没有什么太多的任务,回顾一下DirectShow的东西,发现MSDN上有一篇文章不错,翻译一下,顺便提高一下英文。

题目:How to Create aDirectShow Filter DLL

出处:http://msdn.microsoft.com/en-us/library/dd389096(v=VS.85).aspx

2        翻译内容

本文描述如何在微软的DirectShow中实现一个动态链接库(DLL)的组件。本文是How to ImplementIUnknown的继续,其描述了如何让你的组件通过继承CUnknown基类来实现一个IUnknown接口。

本文包括以下几个章节。

·        类工厂和工厂模板(ClassFactories and Factory Templates)

·        工厂模板数组(FactoryTemplate Array)

·        动态链接库函数(DLLFunctions)

注册一个DirectShow filter需要以下附件的步骤,这些步骤并没有在本文中描述。关于注册filter可以参考How to RegisterDirectShow Filters。

2.1  类工厂和工厂模板

在客户端创建一个COM对象实例之前,它会调用CoGetClassObject函数创建一个对象的类工厂。然后客户端再调用类工厂的IClassFactory::CreateInstance方法。实际上是这个类工厂创建了这个组件并返回客户端请求的接口的指针。(CoCreateInsatance函数合并了这些步骤,在它的内部调用了上面的那些过程。)

下面的图示说明了方法调用的过程。


CoGetClassObject调用定义在DLL中的DllGetClassObject函数。DllGetClassObject创建一个类工厂并且返回一个类工厂接口的指针。DirectShow已经为你实现了DllGetClassObject,但是这个方法以一种指定的方式依赖于你的代码。为了理解它是如何工作的,你必须理解DirectShow如何实现类工厂的。

一个类工厂就是用来创建其他COM对象的COM对象。一个类工厂创建一种类型的对象。在DirectShow中,每个类工厂就是一个类似于CClassFactory的类。类工厂通过其他的一个类来实现,CFactoryTemplate,也叫工厂模板。每一个类工厂持有一个工厂模板的指针。工厂模板包含一个特定组件的一下信息,例如组件标识符(CLSID),一个创建组件的函数指针。

DLL中声明一个全局的工厂模板数组,一个数组对应一个组件。当DllGetClassObject创建一个新的类工厂时,它依据CLSID查找模板数组。假设找到匹配的一个元素,它创建一个持有对应模板指针的类工厂。当客户端调用IClassFactory::CreateInstance,类工厂调用定义在模板中的实例化函数创建出相应的组件。

下面的示意图说明了方法的调用过程。


你从这种架构中得到的好处是,针对于你的组件你只需要做很少的事情,例如实现实例化函数,而不必实现整个的类工厂。

2.2  工厂模板数组

工厂模板包含下面这些公有成员变量:

const WCHAR *              m_Name;              // Name

const CLSID *              m_ClsID;             // CLSID

LPFNNewCOMObject          m_lpfnNew;           // Function to create an instance

                                                //   of the component

LPFNInitRoutine            m_lpfnInit;          // Initialization function (optional)

const AMOVIESETUP_FILTER * m_pAMovieSetup_Filter; // Set-upinformation (for filters)

 

 

其中两个函数指针,m_lpfunNew和m_lpfnInit定义为下面的形式:

typedef CUnknown *(CALLBACK *LPFNNewCOMObject)(LPUNKNOWNpUnkOuter, HRESULT *phr);

typedef void (CALLBACK *LPFNInitRoutine)(BOOL bLoading, constCLSID *rclsid);

 

第一个是组件实例化的函数。第二个是可选的初始化函数。如果你提供一个初始化的函数,它将从内部在DLL的入口点(entry-point)被调用。(关于DLL的入口函数将在本文的后面进行讨论。)

假设你已经创建了一个包含继承至CUnknown的CMyCompone的DLL。在你的DLL中你必须提供下面的一些元素:

·        初始化函数,返回一个新的CMyComponet实例的公有方法。

·        一个命名为g_Templates的全局的工厂模板数组。这个数组包含CMyComponet的工厂模板。

·        一个指定数组大小的全局变量g_cTemplates。

下面的例子说明如何声明这些元素:

// Public method that returns a new instance.

CUnknown * WINAPI CMyComponent::CreateInstance(LPUNKNOWN pUnk,HRESULT *pHr)

{

    CMyComponent *pNewObject= new CMyComponent(NAME("My Component"), pUnk, pHr );

    if (pNewObject == NULL){

        *pHr =E_OUTOFMEMORY;

    }

    return pNewObject;

}

 

CFactoryTemplate g_Templates[1] =

{

    {

      L"My Component",                // Name

     &CLSID_MyComponent,            // CLSID

     CMyComponent::CreateInstance,   //Method to create an instance of MyComponent

      NULL,                           // Initializationfunction

      NULL                            // Set-up information (forfilters)

    }

};

int g_cTemplates = sizeof(g_Templates) /sizeof(g_Templates[0]);   

 

CreateInstance方法调用类的构造函数返回一个新实例的指针。参数pUnk是IUnknown接口的指针,你可以把这个参数传递给类的构造函数。参数pHr指向一个HRESULT。构造函数给pHr赋一个适当值,但是如果构造失败,需要把这个值赋为E_OUTOFMEMORY。

NAME宏在Debug版本将生成一个字符串,但是在最终的Release版本被设置为NULL。在这个例子中被用来在Debug log给组件一个名字,但是在Release版中不占用内存。

CreateInstance方法可以是任何名字,因为在类工厂中引用的是工厂模板中的函数指针。然而,g_Templates和g_cTemplates是全局的变量,为了使其在类工厂中被找到必须使用这个名字。

2.3  动态链接库函数

为了使其被注册,卸载和被载入内存一个DLL必须实现下面的函数:

·        DllMain: DLL的入口点。DllMain是一个系统保留的函数名。DirectShow的实现使用DllEntryPoint。可以参考PlatformSDK获取更多的信息。

·        DllGetClassObject: 创建一个类工厂实例。在前面的段落介绍过。

·        DllCanUnloadNow: 询问这个DLL是否可以被安全卸载。

·        DllRegisterServer: 为DLL创建注册表。

·        DllUnRegisterServer: 移除DLL的注册表项。

在这些当中,前三个已经被DirectShow实现了。如果你的工厂模板通过m_lpfnInit成员变量提供一个初始化函数,这个初始化化函数将在DLL的如果点从内部调用。了解更多的系统什么使用调用DLL入口点函数,参考DllMain。

你必须实现DllRegisterServer和DllUnregisterServer,但是DirectShow提供了一个已经做了一些必要工作的函数AMovieDllRegisterServer2。你的组件可以简单的调用这个函数,如下面的例子所示:

STDAPI DllRegisterServer()

{

    return AMovieDllRegisterServer2(TRUE );

}

 

STDAPI DllUnregisterServer()

{

    returnAMovieDllRegisterServer2( FALSE );

}

 

然而,在DllRegisterServer和DllUnregisterServer的内部,你可以定制一下所需的注册过程。如果你的DLL包含一个filter,你也许需要一些附件的工作。更多的信息可以参考How to Register DirectShow Filters。

在你的模块定义文件(.def)中,要暴露出所有接入点所需的函数,下面是一个.def文件的例子:

EXPORTS

    DllGetClassObjectPRIVATE

    DllCanUnloadNow PRIVATE

    DllRegisterServerPRIVATE

    DllUnregisterServerPRIVATE

 

你可以使用Regsvr32.exe工具注册DLL。

 


C++模板进阶

模版元编程(template metaprogram)是C++中最复杂也是威力最强大的编程范式,它是一种可以创建和操纵程序的程序。模版元编程完全不同于普通的运行期程序,它很独特,因为模版元程序的执行完全是在编译期,并且模版元程序操纵的数据不能是运行时变量,只能是编译期常量,不可修改,另外它用到的语法元素也是相当有限,不能使用运行期的一些语法,比如if-else,for等语句都不能用。
  • 2017年09月06日 19:28

DirectShow Filter 基础与简单的示例程序

DirectShow 是一个 Windows 平台上的流媒体框架,提供了高质量的多媒体流采集和回放功能。 Filter 实质是一个 COM 组件,所以学习开发 Filter 前你应该对 COM 相关...
  • 91program
  • 91program
  • 2014-06-05 07:32:48
  • 2515

DirectShow基础编程 最简单transform filter 编写步骤

目标编写一个transform filter,功能是对图像进行翻转。一、选择基类从CBaseFilter派生出三个用于编写transform filter的类,分别是:CTransformFilter...
  • mao0514
  • mao0514
  • 2014-10-25 15:03:43
  • 1553

DirectShow 注册 filter

用如下的命令注册:regsvr32  wavdest.ax 附:注册与反注册ActiveX控件 regsvr32.exe使用详解:   regsvr3...
  • luckyboy101
  • luckyboy101
  • 2012-07-31 13:52:31
  • 1490

DirectShow中注册过滤器的方法

转自 http://blog.csdn.net/lukeliuli/archive/2007/10/23/1840354.aspx二种方法1 直接写*.reg 文件2 通过IFilterMapper2...
  • tingya
  • tingya
  • 2008-02-02 16:35:00
  • 2475

RTSP/RTMP/HTTP DirectShow Source Filter

供directshow 开发使用的filter,支持 rtmp ,http,rtsp http://www.datastead.com/products/rtsprtmpsrc.html ...
  • xiaojun111111
  • xiaojun111111
  • 2016-08-09 16:57:14
  • 590

DirectShow Filter 开发典型例子分析 ——字幕叠加 (FilterTitleOverlay)1

本文分析一下《DirectShow开发指南》中的一个典型的Transform Filter的例子:字幕叠加(FilterTitleOverlay)。通过分析该例子,我们可以学习到DirectShow ...
  • leixiaohua1020
  • leixiaohua1020
  • 2013-10-09 12:47:36
  • 10842

DirectShow Filter的开发(概述)

学习DirectShow Filter的开发,不外乎以下几种方法:看帮助文档、看示例代码和看SDK基类源代码。看帮助文档,应着重于总体概念上的理解;看示例代码应与基类源代码的研究同步进行,因为自己写F...
  • zhoujiaxq
  • zhoujiaxq
  • 2014-02-12 10:20:23
  • 2635

利用Directshow开发源Filter

摘要:我们一般不推荐自己开发音频或者视频捕捉过滤器,因为diectshow对于音视频的捕捉设备以经提供了支持。所以,这篇文档,对于某些用户需要从特定设备捕捉一些数据提供一些帮助。这篇文档主要包括以下内...
  • aoosang
  • aoosang
  • 2005-05-26 10:45:00
  • 4974

深入浅出DirectShow Filter(一)

深入浅出DirectShow Filter  (2005-11-08 17:46:22) 转载▼   分类: 多媒体/流媒体 By 陆其明 ...
  • l5201314131413141314
  • l5201314131413141314
  • 2011-12-12 14:56:09
  • 2252
收藏助手
不良信息举报
您举报文章:Directshow - Create DirectShow Filter DLL
举报原因:
原因补充:

(最多只允许输入30个字)