初学者 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日:初始发布


