初学者 DirectShow 源过滤器开发简明教程






4.96/5 (16投票s)
本文将为您介绍如何设计源滤镜。源滤镜创建样本并从其输出引脚输出。

引言
本文是关于如何设计 DirectShow 源滤镜的简明教程。 其中大多数都参考了 SDK 的示例。 下载演示并使用 GraphEdit 进行测试。 它创建一个视频流,将“My Source Filter”添加到 GraphEdit,右键单击“My Source OutPin”并选择渲染引脚。 好了,现在它可以工作了! 按播放,您将在视频屏幕上看到我的照片漂浮。

代码原理
在开发之前,请确保 SDK 已安装在您的计算机上,并在您的 VC 或 VS 中配置好。 完成这些工作后,继续。
步骤 1
构建一个项目,例如,我们选择“Win32 动态链接库”。
第二步
为您的项目添加以下库:strmbasd.lib msvcrtd.lib quartz.lib vfw32.lib winmm.lib。
包含我们需要包含的头文件
#include <streams.h>
#include <olectl.h>
#include <initguid.h>
#include "MyStream.h" //This file is not system's ,its a class's header that we create.
步骤 3
在您的计算机上找到工具“GUIDGEN.EXE”。 (如果失败,请在互联网上查找。)启动该工具,单击“New GUID”按钮,将创建一个新的 GUID。 现在,选择第二个选项,换句话说,我们想要“DEFINE_GUID(...)
”格式,之后单击“copy”按钮并将其粘贴到您的项目中。
步骤 4
设置数据类型、主要类型和次要类型。
const AMOVIESETUP_MEDIATYPE sudOpPinTypes =
{
&MEDIATYPE_Video, // Major type
&MEDIASUBTYPE_NULL // Minor type
};
对于我们的过滤器,我们需要一个输出引脚。 如下操作。 设置引脚的属性。
const AMOVIESETUP_PIN sudOpPin =
{
L"Output", // Pin string name
FALSE, // Is it rendered
TRUE, // Is it an output
FALSE, // Can we have none
FALSE, // Can we have many
&CLSID_NULL, // Connects to filter
NULL, // Connects to pin
1, // Number of types
&sudOpPinTypes }; // Pin details
设置过滤器的属性
const AMOVIESETUP_FILTER sudMyax =
{
&CLSID_MySourceFilter, // Filter CLSID
L"My Source Filter", // String name
MERIT_DO_NOT_USE, // Filter merit
1, // Number pins
&sudOpPin // Pin details
};
步骤 5
创建一个继承自 CSource
的类。 为什么选择这个类? 因为我们将开发一个源滤镜。 因此,我们必须选择合理的基类。
class CMySourceFilter:public CSource
{
public:
// The only allowed way to create Bouncing balls!
static CUnknown * WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);
private:
CMySourceFilter(LPUNKNOWN lpunk, HRESULT *phr);
};
CMySourceFilter::CMySourceFilter(LPUNKNOWN lpunk, HRESULT *phr):
CSource(NAME("MySource"),lpunk,CLSID_MySourceFilter)
{
CAutoLock cAutoLock(&m_cStateLock);
m_paStreams = (CSourceStream **) new CMyStream*[1];
if (m_paStreams == NULL) {
*phr = E_OUTOFMEMORY;
return;
}
m_paStreams[0] = new CMyStream(phr, this, L"My Source OutPin");
if (m_paStreams[0] == NULL) {
*phr = E_OUTOFMEMORY;
return;
}
}
CUnknown * WINAPI CMySourceFilter::CreateInstance(LPUNKNOWN lpunk, HRESULT *phr)
{
CUnknown *punk = new CMySourceFilter(lpunk, phr);
if (punk == NULL) {
*phr = E_OUTOFMEMORY;
}
return punk;
} // CreateInstance
完成源过滤器类后,我们如何创建新实例。 也许是一个数组,请看下面的代码片段
CFactoryTemplate g_Templates[] = {
{ L"My Source Filter"
, &CLSID_MySourceFilter
, CMySourceFilter::CreateInstance
, NULL
, &sudMyax }
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
步骤 6
添加用于注册和取消注册的两个函数
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2( TRUE );
} // DllRegisterServer
//
// DllUnregisterServer
//
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2( FALSE );
} // DllUnregisterServer
步骤 7
为了在 DLL 中创建我们的过滤器,我们还需要导出一些函数。 创建一个新的 DEF 文件
LIBRARY MySourceFilter.ax
EXPORTS
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
好的,到目前为止。 我们的过滤器已经完成,但没有引脚。 当然,您可以在 GraphEdit.exe 中对其进行测试。 您只能查看其信息,现在它什么也做不了。 我们想要添加一个输出引脚,我们想要的引脚输出视频。 继续...
步骤 8
现在我们需要插入一个从 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; // The time stamp for each sample
int m_iRepeatTime; // Time in msec between frames
BITMAPFILEHEADER * pbfh;
int xPos,yPos;
BOOL xLock,yLock;
HBITMAP hBmp;
};
引脚是如何工作的? 在 MSDN 上查找更多详细信息,点击这里!
流线程运行一个具有以下结构的循环
until (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.
好吧,想要更多细节? 下载资源。 累了!
关注点
写完这篇文章后我感到非常疲倦,但是非常高兴。 希望它对您有用。
历史
- 2010年2月22日:初始发布