您的位置:首页 > 其它

一个最简单的源Filter的编写步骤 转贴

2010-05-24 11:26 288 查看

一个最简单的源Filter的编写步骤
收藏

1.创建一个空的Dll工程,添加5个空文件分别名为:MyOutputPin.h、
MySourceFilter.h、MyOutputPin.cpp、MySourceFilter.cpp和MySourceFilter.def。

2.声明两个类,一个是Filter的实现类,一个是输出Pin的实现类,由于是最简单的源Filter,因此Filter只有一个输出Pin。实
现的功能是从本地磁盘读取三个图片文件,轮流显示这三张图片,效果是模拟一个视频流。这两个类的声明代码:

view
plain
copy
to clipboard
print
?

//MySourceFilter.h

class
CMySourceFilter

//从SDK库中的CSource类派生

: public
CSource

{

public
:

//实例化接口

static
CUnknown * WINAPI CreateInstance(LPUNKNOWN lpunk,
HRESULT
*phr);

private
:

//构造函数

CMySourceFilter(LPUNKNOWN lpunk, HRESULT
*phr);

};

//MySourceFilter.h
class CMySourceFilter
//从SDK库中的CSource类派生
:	public CSource
{
public:
//实例化接口
static CUnknown * WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr);
private:
//构造函数
CMySourceFilter(LPUNKNOWN lpunk, HRESULT *phr);
};


view
plain
copy
to clipboard
print
?

//MyOutputPin.h

class
CMyOutputPin

//CSource的派生类都使用
CSourceStream的派生类做为pin

:public
CSourceStream

{

public
:

CMyOutputPin(HRESULT
*phr, CSource *pFilter);

~CMyOutputPin(void
);

//填充样本函数

//参数pMediaSample就是要传递到下一个
Filter输入pin的样本

//把数据填充到pMediaSample中就是这个函数的功能

HRESULT
FillBuffer(IMediaSample *pMediaSample);

//协商每个CMediaSample数据块的大小

HRESULT
DecideBufferSize(IMemAllocator *pIMemAlloc,

ALLOCATOR_PROPERTIES *pProperties);

//获得媒体类型

//在枚举器中枚举支持的媒体类型时调用此函数得到PIN支持的媒体类型

//此函数设置pmt的各个成员,因此,由此函数的内容觉
得PIN支持什么媒体类型

HRESULT
GetMediaType(
int
iPosition, CMediaType *pmt);

//检测是否支持参数传入的媒体类型

HRESULT
CheckMediaType(
const
CMediaType *pMediaType);

//这是质量控制接口,最简单的源Filter不需要质量控制

STDMETHODIMP Notify(IBaseFilter *pSelf, Quality q)

{

return
E_FAIL;

}

private
:

BYTE
* m_pData[3];
//存储图片数据

int
m_nWidth;
//图片的宽

int
m_nHeight;
//图片的高

int
m_nImageSize;
//图片数据的大小

int
m_nCount;
//计数器,用来切换图片数据的缓冲区

};

//MyOutputPin.h
class CMyOutputPin
//CSource的派生类都使用CSourceStream的派生类做为pin
:public CSourceStream
{
public:
CMyOutputPin(HRESULT *phr, CSource *pFilter);
~CMyOutputPin(void);
//填充样本函数
//参数pMediaSample就是要传递到下一个Filter输入pin的样本
//把数据填充到pMediaSample中就是这个函数的功能
HRESULT FillBuffer(IMediaSample *pMediaSample);
//协商每个CMediaSample数据块的大小
HRESULT DecideBufferSize(IMemAllocator *pIMemAlloc,
ALLOCATOR_PROPERTIES *pProperties);
//获得媒体类型
//在枚举器中枚举支持的媒体类型时调用此函数得到PIN支持的媒体类型
//此函数设置pmt的各个成员,因此,由此函数的内容觉得PIN支持什么媒体类型
HRESULT GetMediaType(int iPosition, CMediaType *pmt);
//检测是否支持参数传入的媒体类型
HRESULT CheckMediaType(const CMediaType *pMediaType);
//这是质量控制接口,最简单的源Filter不需要质量控制
STDMETHODIMP Notify(IBaseFilter *pSelf, Quality q)
{
return E_FAIL;
}
private:
BYTE* m_pData[3];//存储图片数据
int m_nWidth;//图片的宽
int m_nHeight;//图片的高
int m_nImageSize;//图片数据的大小
int m_nCount;//计数器,用来切换图片数据的缓冲区
};

3.实现CMySourceFilter类。这个类只有两个函数需要编写,很简单。

view
plain
copy
to clipboard
print
?

//CMySourceFilter.cpp

CUnknown* CMySourceFilter::CreateInstance(LPUNKNOWN lpunk, HRESULT
*phr)

{

//实例化函数的工作就是实例化一个源Filter的对象

CUnknown *punk = new
CMySourceFilter(lpunk,phr);

if
(punk == NULL)

{

*phr = E_OUTOFMEMORY;

}

return
punk;

}

CMySourceFilter::CMySourceFilter(LPUNKNOWN lpunk, HRESULT
*phr)

: CSource(L"MyFilter"
,lpunk,CLSID_MyFilter,phr)

{

//创建一个pin的对象实例

//在CSourceStream的构造函数中,会把pin
添加到Filter中

CMyOutputPin* pOutPin = new
CMyOutputPin(phr,
this
);

if
(FAILED(*phr))

{

//因此,在创建失败的时候,要将这个pin从Filter中移除

RemovePin(pOutPin);

pOutPin->Release();

}

}

//CMySourceFilter.cpp
CUnknown*
CMySourceFilter::CreateInstance(LPUNKNOWN lpunk, HRESULT *phr)
{
//实例化函数的工作就是实例化一个源Filter的对象
CUnknown *punk = new CMySourceFilter(lpunk,phr);
if (punk == NULL)
{
*phr = E_OUTOFMEMORY;
}
return punk;
}
CMySourceFilter::CMySourceFilter(LPUNKNOWN lpunk, HRESULT *phr)
: CSource(L"MyFilter",lpunk,CLSID_MyFilter,phr)
{
//创建一个pin的对象实例
//在CSourceStream的构造函数中,会把pin添加到Filter中
CMyOutputPin* pOutPin = new CMyOutputPin(phr,this);
if (FAILED(*phr))
{
//因此,在创建失败的时候,要将这个pin从Filter中移除
RemovePin(pOutPin);
pOutPin->Release();
}
}

4.实现CMyOutputPin类,编写Filter主要就是写pin。

view
plain
copy
to clipboard
print
?

//MyOutputPin.cpp

//构造函数

CMyOutputPin::CMyOutputPin(HRESULT
*phr, CSource *pFilter)

: CSourceStream(L"MyFilter"
,phr,pFilter,L
"Out"
)

, m_nWidth(0)

, m_nHeight(0)

, m_nImageSize(0)

, m_nCount(0)

{

//把图片读到内存中,准备好数据

m_pData[0] = LoadBitmapFileToMemory(L"E://DirectShow//MySourceFilter//1.bmp"
,

m_nWidth,m_nHeight,m_nImageSize);

m_pData[1] = LoadBitmapFileToMemory(L"E://DirectShow//MySourceFilter//2.bmp"
,

m_nWidth,m_nHeight,m_nImageSize);

m_pData[2] = LoadBitmapFileToMemory(L"E://DirectShow//MySourceFilter//3.bmp"
,

m_nWidth,m_nHeight,m_nImageSize);

}

//析构函数

CMyOutputPin::~CMyOutputPin(void
)

{

//释放内存

delete
[]m_pData[0];

delete
[]m_pData[1];

delete
[]m_pData[2];

}

//获取媒体类型

//填充pmt

//最简单的源Filter,因此只支持一种类型,所以
iPosition为0

HRESULT
CMyOutputPin::GetMediaType(
int
iPosition, CMediaType *pmt)

{

CheckPointer(pmt,E_POINTER);

CAutoLock cAutoLock(m_pFilter->pStateLock());

if
(iPosition < 0)

{

return
E_INVALIDARG;

}

// Have we run off the end of types?

if
(iPosition > 0)

{

return
VFW_S_NO_MORE_ITEMS;

}

//给媒体类型申请Format的空间

//填充每一个对象,主要是BITMAPINFOHEADER结


VIDEOINFO *pvi = (VIDEOINFO *) pmt->AllocFormatBuffer(sizeof
(VIDEOINFO));

if
(NULL == pvi)

return
(E_OUTOFMEMORY);

ZeroMemory(pvi, sizeof
(VIDEOINFO));

pvi->bmiHeader.biBitCount = 24;

pvi->bmiHeader.biHeight = m_nHeight;

pvi->bmiHeader.biWidth = m_nWidth;

pvi->bmiHeader.biSizeImage = m_nImageSize;

pvi->bmiHeader.biPlanes = 1;

pvi->bmiHeader.biSize = sizeof
(BITMAPINFOHEADER);

pvi->bmiHeader.biCompression = BI_RGB;

pvi->bmiHeader.biClrImportant = 0;

SetRectEmpty(&pvi->rcSource);

SetRectEmpty(&pvi->rcTarget);

pmt->SetType(&MEDIATYPE_Video);//设置主媒体类型

pmt->SetSubtype(&MEDIASUBTYPE_RGB24);//设置子媒体类型

pmt->SetFormatType(&FORMAT_VideoInfo);//设置详细格式类型

pmt->SetSampleSize(m_nImageSize);//设置Sample的大小

pmt->SetTemporalCompression(FALSE);

return
NOERROR;

}

//检查媒体类型

//主要是对GetMediaType中设置的各个参数进行比较

HRESULT
CMyOutputPin::CheckMediaType(
const
CMediaType *pMediaType)

{

CheckPointer(pMediaType,E_POINTER);

if
(*(pMediaType->Type()) != MEDIATYPE_Video

|| !(pMediaType->IsFixedSize()))

{

return
E_INVALIDARG;

}

const
GUID *SubType = pMediaType->Subtype();

if
(SubType == NULL)

{

return
E_INVALIDARG;

}

if
(*SubType != MEDIASUBTYPE_RGB24)

{

return
E_INVALIDARG;

}

const
GUID* FormatType = pMediaType->FormatType();

if
(FormatType == NULL)

{

return
E_INVALIDARG;

}

if
(*FormatType != FORMAT_VideoInfo)

{

return
E_INVALIDARG;

}

VIDEOINFO* pvi = (VIDEOINFO*)pMediaType->Format();

if
(pvi == NULL)

{

return
E_INVALIDARG;

}

if
(pvi->bmiHeader.biBitCount != 24 ||

pvi->bmiHeader.biWidth != m_nWidth ||

pvi->bmiHeader.biHeight != m_nHeight)

{

return
E_INVALIDARG;

}

return
S_OK;

}

//协商Sample的大小

HRESULT
CMyOutputPin::DecideBufferSize(IMemAllocator *pIMemAlloc, ALLOCATOR_PROPERTIES *pProperties)

{

CheckPointer(pIMemAlloc,E_POINTER);

CheckPointer(pProperties,E_POINTER);

CAutoLock cAutoLock(m_pFilter->pStateLock());

HRESULT
hr = NOERROR;

VIDEOINFO *pvi = (VIDEOINFO *) m_mt.Format();

//确定只有一个buffer

pProperties->cBuffers = 1;

//设置buffer的大小

pProperties->cbBuffer = m_nImageSize;

ASSERT(pProperties->cbBuffer);

//设置属性页

ALLOCATOR_PROPERTIES Actual;

hr = pIMemAlloc->SetProperties(pProperties,&Actual);

if
(FAILED(hr))

{

return
hr;

}

if
(Actual.cbBuffer < pProperties->cbBuffer)

{

return
E_FAIL;

}

ASSERT(Actual.cBuffers == 1);

return
NOERROR;

}

//填充Sample

HRESULT
CMyOutputPin::FillBuffer(IMediaSample *pMediaSample)

{

CheckPointer(pMediaSample,E_POINTER);

BYTE
* pData = NULL;

long
lDataSize = 0;

//获得Sample中存放数据的地址

pMediaSample->GetPointer(&pData);

//取得Sample分配的内存大小

lDataSize = pMediaSample->GetSize();

ZeroMemory(pData,lDataSize);

//把当前需要显示的数据拷贝到内存中

CopyMemory(pData,m_pData[m_nCount%3],m_nImageSize);

//设置时间戳

REFERENCE_TIME start = TS_ONE * m_nCount;

REFERENCE_TIME stop = TS_ONE + start;

pMediaSample->SetTime(&start,&stop);

//准备下一帧数据

m_nCount++;

pMediaSample->SetSyncPoint(TRUE);

return
NOERROR;

}

//MyOutputPin.cpp
//构造函数
CMyOutputPin::CMyOutputPin(HRESULT *phr, CSource *pFilter)
: CSourceStream(L"MyFilter",phr,pFilter,L"Out")
, m_nWidth(0)
, m_nHeight(0)
, m_nImageSize(0)
, m_nCount(0)
{
//把图片读到内存中,准备好数据
m_pData[0] =
LoadBitmapFileToMemory(L"E://DirectShow//MySourceFilter//1.bmp",
m_nWidth,m_nHeight,m_nImageSize);
m_pData[1] =
LoadBitmapFileToMemory(L"E://DirectShow//MySourceFilter//2.bmp",
m_nWidth,m_nHeight,m_nImageSize);
m_pData[2] =
LoadBitmapFileToMemory(L"E://DirectShow//MySourceFilter//3.bmp",
m_nWidth,m_nHeight,m_nImageSize);
}
//析构函数
CMyOutputPin::~CMyOutputPin(void)
{
//释放内存
delete []m_pData[0];
delete []m_pData[1];
delete []m_pData[2];
}
//获取媒体类型
//填充pmt
//最简单的源Filter,因此只支持一种类型,所以iPosition为0
HRESULT CMyOutputPin::GetMediaType(int iPosition, CMediaType *pmt)
{
CheckPointer(pmt,E_POINTER);
CAutoLock cAutoLock(m_pFilter->pStateLock());
if(iPosition < 0)
{
return E_INVALIDARG;
}
// Have we run off the end of types?
if(iPosition > 0)
{
return VFW_S_NO_MORE_ITEMS;
}
//给媒体类型申请Format的空间
//填充每一个对象,主要是BITMAPINFOHEADER结构
VIDEOINFO *pvi = (VIDEOINFO *)
pmt->AllocFormatBuffer(sizeof(VIDEOINFO));
if(NULL == pvi)
return(E_OUTOFMEMORY);
ZeroMemory(pvi, sizeof(VIDEOINFO));
pvi->bmiHeader.biBitCount = 24;
pvi->bmiHeader.biHeight = m_nHeight;
pvi->bmiHeader.biWidth = m_nWidth;
pvi->bmiHeader.biSizeImage = m_nImageSize;
pvi->bmiHeader.biPlanes = 1;
pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biCompression = BI_RGB;
pvi->bmiHeader.biClrImportant = 0;
SetRectEmpty(&pvi->rcSource);
SetRectEmpty(&pvi->rcTarget);
pmt->SetType(&MEDIATYPE_Video);//设置主媒体类型
pmt->SetSubtype(&MEDIASUBTYPE_RGB24);//设置子媒体类型
pmt->SetFormatType(&FORMAT_VideoInfo);//设置详细格式类型
pmt->SetSampleSize(m_nImageSize);//设置Sample的大小
pmt->SetTemporalCompression(FALSE);
return NOERROR;
}
//检查媒体类型
//主要是对GetMediaType中设置的各个参数进行比较
HRESULT CMyOutputPin::CheckMediaType(const CMediaType *pMediaType)
{
CheckPointer(pMediaType,E_POINTER);
if (*(pMediaType->Type()) != MEDIATYPE_Video
|| !(pMediaType->IsFixedSize()))
{
return E_INVALIDARG;
}
const GUID *SubType = pMediaType->Subtype();
if (SubType == NULL)
{
return E_INVALIDARG;
}
if (*SubType != MEDIASUBTYPE_RGB24)
{
return E_INVALIDARG;
}
const GUID* FormatType = pMediaType->FormatType();
if (FormatType == NULL)
{
return E_INVALIDARG;
}
if (*FormatType != FORMAT_VideoInfo)
{
return E_INVALIDARG;
}
VIDEOINFO* pvi = (VIDEOINFO*)pMediaType->Format();
if (pvi == NULL)
{
return E_INVALIDARG;
}
if (pvi->bmiHeader.biBitCount != 24 ||
pvi->bmiHeader.biWidth != m_nWidth ||
pvi->bmiHeader.biHeight != m_nHeight)
{
return E_INVALIDARG;
}
return S_OK;
}
//协商Sample的大小
HRESULT CMyOutputPin::DecideBufferSize(IMemAllocator *pIMemAlloc,
ALLOCATOR_PROPERTIES *pProperties)
{
CheckPointer(pIMemAlloc,E_POINTER);
CheckPointer(pProperties,E_POINTER);
CAutoLock cAutoLock(m_pFilter->pStateLock());
HRESULT hr = NOERROR;
VIDEOINFO *pvi = (VIDEOINFO *) m_mt.Format();
//确定只有一个buffer
pProperties->cBuffers = 1;
//设置buffer的大小
pProperties->cbBuffer = m_nImageSize;
ASSERT(pProperties->cbBuffer);
//设置属性页
ALLOCATOR_PROPERTIES Actual;
hr = pIMemAlloc->SetProperties(pProperties,&Actual);
if(FAILED(hr))
{
return hr;
}
if(Actual.cbBuffer < pProperties->cbBuffer)
{
return E_FAIL;
}
ASSERT(Actual.cBuffers == 1);
return NOERROR;
}
//填充Sample
HRESULT CMyOutputPin::FillBuffer(IMediaSample *pMediaSample)
{
CheckPointer(pMediaSample,E_POINTER);
BYTE* pData = NULL;
long lDataSize = 0;
//获得Sample中存放数据的地址
pMediaSample->GetPointer(&pData);
//取得Sample分配的内存大小
lDataSize = pMediaSample->GetSize();
ZeroMemory(pData,lDataSize);
//把当前需要显示的数据拷贝到内存中
CopyMemory(pData,m_pData[m_nCount%3],m_nImageSize);
//设置时间戳
REFERENCE_TIME start = TS_ONE * m_nCount;
REFERENCE_TIME stop = TS_ONE + start;
pMediaSample->SetTime(&start,&stop);
//准备下一帧数据
m_nCount++;
pMediaSample->SetSyncPoint(TRUE);
return NOERROR;
}

LoadBitmapFileToMemory函数的实现

view
plain
copy
to clipboard
print
?

BYTE
* LoadBitmapFileToMemory(
TCHAR
* pFileName,
int
& nWidth,
int
& nHeight,
int
& nImageDataSize)

{

HBITMAP
hBitmap = (
HBITMAP
)LoadImage( NULL, pFileName, IMAGE_BITMAP, 0, 0,

LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE );

if
(hBitmap == NULL)

return
NULL;

HDC
hDC = CreateCompatibleDC(NULL);

HBITMAP
hOldBitmap = (
HBITMAP
)SelectObject(hDC, hBitmap);

BITMAP bmp;

GetObject(hBitmap, sizeof
(bmp), &bmp);

BITMAPINFOHEADER bih = {0};//位图信息头

bih.biBitCount = bmp.bmBitsPixel;//每个像素字节大小

bih.biCompression = BI_RGB;

bih.biHeight = bmp.bmHeight;//高


bih.biPlanes = 1;

bih.biSize = sizeof
(BITMAPINFOHEADER);

bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//图像数据大小

bih.biWidth = bmp.bmWidth;//宽度

nImageDataSize = bmp.bmWidthBytes * bmp.bmHeight;

byte * p = new
byte[nImageDataSize];
//申请内存保存位图数据

GetDIBits(hDC, hBitmap, 0, bmp.bmHeight, p,

(LPBITMAPINFO) &bih, DIB_RGB_COLORS);//获取位图数据

SelectObject(hDC, hOldBitmap);

DeleteObject(hBitmap);

DeleteDC(hDC);

nWidth = bmp.bmWidth;

nHeight = bmp.bmHeight;

return
p;

}

BYTE*
LoadBitmapFileToMemory(TCHAR* pFileName, int& nWidth, int&
nHeight, int& nImageDataSize)
{
HBITMAP hBitmap = (HBITMAP)LoadImage( NULL, pFileName, IMAGE_BITMAP, 0,
0,
LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE );
if(hBitmap == NULL)
return NULL;
HDC hDC = CreateCompatibleDC(NULL);
HBITMAP hOldBitmap = (HBITMAP)SelectObject(hDC, hBitmap);
BITMAP bmp;
GetObject(hBitmap, sizeof(bmp), &bmp);
BITMAPINFOHEADER bih = {0};//位图信息头
bih.biBitCount = bmp.bmBitsPixel;//每个像素字节大小
bih.biCompression = BI_RGB;
bih.biHeight = bmp.bmHeight;//高度
bih.biPlanes = 1;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;//图像数据大小
bih.biWidth = bmp.bmWidth;//宽度
nImageDataSize = bmp.bmWidthBytes * bmp.bmHeight;
byte * p = new byte[nImageDataSize];//申请内存保存位图数据
GetDIBits(hDC, hBitmap, 0, bmp.bmHeight, p,
(LPBITMAPINFO) &bih, DIB_RGB_COLORS);//获取位图数据
SelectObject(hDC, hOldBitmap);
DeleteObject(hBitmap);
DeleteDC(hDC);
nWidth = bmp.bmWidth;
nHeight = bmp.bmHeight;
return p;
}

5.主要的工作已经做完了,功能已经实现,接下来就是生成Filter。

view
plain
copy
to clipboard
print
?

//MySourceFilter.h

//动态库工程自然也要有入口函数(固定格式)

extern

"C"

BOOL
WINAPI DllEntryPoint(
HINSTANCE
,
ULONG
,
LPVOID
);

BOOL
APIENTRY DllMain(
HANDLE
hModule,

DWORD
dwReason,

LPVOID
lpReserved)

{

return
DllEntryPoint((
HINSTANCE
)(hModule), dwReason, lpReserved);

}

//组件就少不了注册与注销函数(固定格式)

STDAPI DllRegisterServer()

{

return
AMovieDllRegisterServer2(TRUE);

}

STDAPI DllUnregisterServer()

{

return
AMovieDllRegisterServer2(FALSE);

}

//组件,就要有GUID(通过工具创建)

DEFINE_GUID(CLSID_MyFilter,

0x159386e0, 0x5193, 0x48ac, 0x8a, 0x57, 0x17, 0x88, 0xc7, 0x33, 0x40, 0xc1);

//以下是注册信息的模版,写了注释的地方是我们需要填写的,其他的采用默认

const
AMOVIESETUP_MEDIATYPE sudOpPinTypes =

{

&MEDIATYPE_Video, // Major type

&MEDIASUBTYPE_NULL // Minor type

};

const
AMOVIESETUP_PIN sudOpPin =

{

L"Output"
,

FALSE,

TRUE,

FALSE,

FALSE,

&CLSID_NULL,

NULL,

1,

&sudOpPinTypes };

const
AMOVIESETUP_FILTER sudBallax =

{

&CLSID_MyFilter, // 自定义的GUID

L"MyFilter"
,
// Filter的名字

MERIT_DO_NOT_USE,

1,

&sudOpPin

};

// COM global table of objects in this dll

CFactoryTemplate g_Templates[] = {

{ L"MyFilter"
//Filter的名字

, &CLSID_MyFilter//自定义的
GUID

, CMySourceFilter::CreateInstance//Filter的实例化接口

, NULL

, &sudBallax }

};

int
g_cTemplates =
sizeof
(g_Templates) /
sizeof
(g_Templates[0]);

//MySourceFilter.h
//动态库工程自然也要有入口函数(固定格式)
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD  dwReason,
LPVOID lpReserved)
{
return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}
//组件就少不了注册与注销函数(固定格式)
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
//组件,就要有GUID(通过工具创建)
DEFINE_GUID(CLSID_MyFilter,
0x159386e0, 0x5193, 0x48ac, 0x8a, 0x57, 0x17, 0x88, 0xc7, 0x33, 0x40,
0xc1);
//以下是注册信息的模版,写了注释的地方是我们需要填写的,其他的采用默认
const AMOVIESETUP_MEDIATYPE sudOpPinTypes =
{
&MEDIATYPE_Video,       // Major type
&MEDIASUBTYPE_NULL      // Minor type
};
const AMOVIESETUP_PIN sudOpPin =
{
L"Output",
FALSE,
TRUE,
FALSE,
FALSE,
&CLSID_NULL,
NULL,
1,
&sudOpPinTypes };
const AMOVIESETUP_FILTER sudBallax =
{
&CLSID_MyFilter,    // 自定义的GUID
L"MyFilter",       // Filter的名字
MERIT_DO_NOT_USE,
1,
&sudOpPin
};

// COM global table of objects in this dll
CFactoryTemplate g_Templates[] = {
{ L"MyFilter"//Filter的名字
, &CLSID_MyFilter//自定义的GUID
, CMySourceFilter::CreateInstance//Filter的实例化接口
, NULL
, &sudBallax }
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);

6.MySourceFilter.def文件的内容

view
plain
copy
to clipboard
print
?

LIBRARY
"MySourceFilter.ax"

EXPORTS

DllMain PRIVATE

DllGetClassObject PRIVATE

DllCanUnloadNow PRIVATE

DllRegisterServer PRIVATE

DllUnregisterServer PRIVATE

LIBRARY
"MySourceFilter.ax"
EXPORTS
DllMain                 PRIVATE
DllGetClassObject       PRIVATE
DllCanUnloadNow         PRIVATE
DllRegisterServer       PRIVATE
DllUnregisterServer     PRIVATE

7.注意

1)包含头文件 #include <initguid.h>,否则有可能提示 error LNK2001: 无法解析的外部符号
_CLSID_MyFilter

2)包含导出库#pragma comment(lib, "winmm")

3)包含导入库#pragma comment(lib, "strmbase.lib"),Debug下包含#pragma
comment(lib, "strmbasd.lib")

8.大功告成。调用regsvr32注册Filter。使用GraphEdit调试Filter。(VS2005)

在工程的属性中选择调试,在命令中填入GraphEdit的完整路径,把Filter的工程作为启动项。按下F5,在运行的GraphEdit中选
择我们的Filter,Render pin,就可以看到一条完整的链路,然后run,效果出来了,三幅图片轮流显示在窗口中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐