65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (16投票s)

2010年2月22日

CPOL

2分钟阅读

viewsIcon

79439

downloadIcon

5241

本文将为您介绍如何设计源滤镜。源滤镜创建样本并从其输出引脚输出。

ds2.JPG

引言

本文是关于如何设计 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日:初始发布
© . All rights reserved.