DirectShow是一个强大的多媒体框架,用于在Windows平台上处理视频和音频数据。本文将指导如何设计一个DirectShow的源过滤器。源过滤器是DirectShow架构中的基本组件之一,它负责生成数据流。
在开始开发之前,请确保计算机上安装了DirectShowSDK,并且在Visual C++或Visual Studio环境中正确配置了它。
首先,创建一个项目。例如,可以选择“Win32 Dynamic-Link Library”。
接下来,为项目添加以下库:
strmbasd.lib msvcrtd.lib quartz.lib vfw32.lib winmm.lib
然后,包含需要的头文件:
#include <streams.h>
#include <olectl.h>
#include <initguid.h>
#include "MyStream.h"
注意,"MyStream.h"不是系统的头文件,而是创建的类的头文件。
使用工具"GUIDGEN.EXE"生成一个新的GUID。如果找不到这个工具,可以在网上搜索。启动工具,点击"New GUID"按钮,然后选择"DEFINE_GUID(...)"格式,复制并粘贴到项目中。
定义主要类型和次要类型:
const AMOVIESETUP_MEDIATYPE sudOpPinTypes = {
&MEDIATYPE_Video,
&MEDIASUBTYPE_NULL
};
对于过滤器,需要一个输出引脚。按照以下步骤设置引脚的属性:
const AMOVIESETUP_PIN sudOpPin = {
L"Output",
FALSE,
TRUE,
FALSE,
FALSE,
&CLSID_NULL,
NULL,
1,
&sudOpPinTypes
};
设置过滤器的属性:
const AMOVIESETUP_FILTER sudMyax = {
&CLSID_MySourceFilter,
L"My Source Filter",
MERIT_DO_NOT_USE,
1,
&sudOpPin
};
创建一个继承自CSource的类。为什么选择这个类?因为将要开发一个源过滤器,所以必须选择合理的基类。
class CMySourceFilter:public CSource {
public:
static CUnknown * WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);
private:
CMySourceFilter(LPUNKNOWN lpunk, HRESULT *phr);
};
完成源过滤器类后,如何创建新实例?也许可以使用数组,请看以下代码片段:
CFactoryTemplate g_Templates[] = {
{ L"My Source Filter", &CLSID_MySourceFilter, CMySourceFilter::CreateInstance, NULL, &sudMyax }
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
添加注册和注销函数:
STDAPI DllRegisterServer() {
return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer() {
return AMovieDllRegisterServer2(FALSE);
}
为了在DLL中创建过滤器,还需要导出一些函数。创建一个新的DEF文件:
LIBRARY MySourceFilter.ax
EXPORTS
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
现在需要插入一个新类,继承自CSourceStream。它可以生成样本并将其推送到下一个过滤器。
class CMyStream : public CSourceStream {
public:
STDMETHOD(Notify)(IBaseFilter * pSender, Quality q);
HRESULT CheckMediaType(const CMediaType *pMediaType);
HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);
HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProperties);
HRESULT FillBuffer(IMediaSample *pms);
CMyStream(HRESULT *phr, CSource *pms, LPCWSTR pName);
virtual ~CMyStream();
private:
CRefTime m_rtSampleTime;
int m_iRepeatTime;
BITMAPFILEHEADER * pbfh;
int xPos, yPos;
BOOL xLock, yLock;
HBITMAP hBmp;
};
关于引脚的更多详细信息,请参考MSDN文档。
流线程运行一个循环,结构如下:
while (!stopped) {
1. Get a media sample from the allocator.
2. Fill the sample with data.
3. Time stamp the sample.
4. Deliver the sample downstream.
}