编写DirectShow Filters—概述

seeker

(一) 介绍DirectShow Filter开发
本章提供开发一个自定义DirectShow filter的简单框架描述,也提供了链接到更详细讨论这些任务的主题。在阅读本章之前,阅读在About DirectShow主题,它描述了全面的DirectShow构架。
1. DirectShow基类库
Directshow sdk包括了编写filters的一组C++类。虽然它们不是必需的,但推荐使用这些类来编写一个新的filter。为了使用这些基类,需要把它们编译成静态库并链接.lib文件到自己的项目中,如building DirectShow Filters中的描述。
基础类库定义了filters的一个根类,CBaseFilter类。几个其它的类继承自CBaseFitler,并且指定于其它特定类型的filters。如,CTransformFilter类设计为transform类。为了建立一个新filter,实现继承自filters类中的一个的类。如,你的类声明可能如下表示:
class CMyFilter : public CTransformFilter
{
private:
 // declare variables and methods that are specific to your filter
public:
//override various methods in CTransformFilter
};
2. 建立PINs
filter必须建立一个或多个pin。pin的数目可能在设计时间固定或者根据需要创建。pin一般继承自CBasePin类或者从继承自CBasePin的类来继承,如CBaseInputPin。filter的pin应该声明为filter类的成员变量。一些filter类已经定义了pin,但如果你的filter继承自CBaseFilter,你必须在你的继承类中声明这些pin。
3. 协商pin连接
当filter graph manager试图去连接两个filters,pins必须在各种事情上达成一致。如果不能,连接试图失败。一般,PIN协商如下列:
1) transport:transport是filters用来从output pin移动media sample到input pin的机制。例如,它们可以使用IMemInputPin接口(推模型)或者IAsyncReader接口(拉模型)。
2) Media type : 大多数pins使用media type来描述它们传递的数据格式
3) Allocator : allocator是建立缓冲区来保存数据的对象。pins必须一致哪个PIN来提供allocator。必须在buffers的尺寸上,buffers建立的数目上和其它buffer属性上一致。
基类实现了这些协商的Framework,你必须通过重载在基类中的各种方法来完成细节。这些重载的方法的设置依赖于类和自定义filter的功能性。
4. 处理和传递数据
大多数filters的主要功能是处理和传递数据。如何传递根据filter的类型
1) push source有一个工作线程,它持续的用数据填充sample并传递到downstream。
2) pull source等待它临近的downstream来请求一个Sample。它通过写数据到一个Sample并传递这个sample到downstream filter来响应。这个 downstream filter建立传递数据流动的线程。
3) transform filter通过它临近upstream filter传递samples。当它接收一个sample,处理数据并传递到downstream
4) renderer filter从upstream接收sample,并依据时间戳安排它们rendering。
其它流任务包括从graph中flushing数据,处理流的结束,响应seek请求,
5. 支持COM
DirectShow filter都是COM对象,一般在DLL中打包,基类库实现了一个支持COM的框架。

(二) 生成DirectShow Filters
DirectShow基类推荐用来实现DirectShow filter。为了生成基类,执行下列步骤:
1) 生成基类库, 位于SDK根目录下的Samples/Multimedia/DirectShow/BaseClasses,有两个库版本:retail版(strmbased.lib) 和debug版(strmbasd.lib)。
2) 包括stream.h头文件
3) 使用__stdcall调用转换(c/c++->高级)
4) 使用多线程的C run-time库(debug/retail)(c/c++->代码生成)
5) 包括一个定义文件(.def)暴露DLL函数,如下列范例:假定输出文件名为MyFilter.dll
LIBRARY MYFILTER.DLL
EXPORTS
    DllMain             PRIVATE
    DllGetClassObject   PRIVATE
    DllCanUnloadNow     PRIVATE
    DllRegisterServer   PRIVATE
    DllUnregisterServer PRIVATE
6) 链接到下列库文件
Debug Build :Strmbasd.lib, Msvcrtd.lib, Winmm.lib
Retail Build :Strmbase.lib, Msvcrt.lib, Winmm.lib
7) 在linker 设置选择"ignore default libraries"。
8) 在源代码中声明DLL入口点,如下:
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
    return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章