DirectShow基础编程 最简单transform filter 编写步骤

目标编写一个transform filter,功能是对图像进行翻转。

MSDN中有一章 "Writing Transform Filters" 列出了编写transform filter的六个基本步骤,我们按照这六个步骤一步一步来。

 

一、选择基类

从CBaseFilter派生出三个用于编写transform filter的类,分别是:CTransformFilter 、CTransInPlaceFilter 和CVideoTransformFilter ,三个基类的区别可以看MSDN的说明,我们选择CTransformFilter类。

选择好基类,我们就创建一个空的DLL工程,添加三个文件,分别是:FlipFilter.h、FlipFilter.cpp和FlipFilter.def。

 

二、声明Filter类

在FlipFilter.h中添加下列代码声明

#include extern "C" const GUID CLSID_FlipFilter; class CFlipFilter : public CTransformFilter { private: CFlipFilter(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr); public: static CUnknown * WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr); HRESULT CheckInputType(const CMediaType *mtIn); HRESULT GetMediaType(int iPosition, CMediaType *pMediaType); HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut); HRESULT DecideBufferSize(IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop); HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut); };

 

三、媒体类型协商

这一步是Filter的pin在连接的时候必须进行的步骤,主要重载三个函数:

1、HRESULT CheckInputType(const CMediaType *mtIn);

HRESULT CFlipFilter::CheckInputType(const CMediaType *mtIn) { if (mtIn->majortype != MEDIATYPE_Video || mtIn->subtype != MEDIASUBTYPE_RGB24 || mtIn->formattype != FORMAT_VideoInfo ) { return VFW_E_TYPE_NOT_ACCEPTED; } VIDEOINFO* pvi = (VIDEOINFO*)mtIn->Format(); if (pvi->bmiHeader.biBitCount != 24) { return VFW_E_TYPE_NOT_ACCEPTED; } return S_OK; }

CTransformFilter使用CTransformInputPin类作为输入pin,CTransformInputPin::CheckMediaType(const CMediaType* pmt)中调用m_pTransformFilter->CheckInputType(pmt);因此我们可以简单的认为CheckInputType就是输入pin的CheckMediaType。这样设计的是为了不需要重新定义输入pin类,只需要定义Filter类,简化编写Transform filter的步骤,另外的几个接口也是这样的一个设计原理。

2、HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);

HRESULT CFlipFilter::GetMediaType(int iPosition, CMediaType *pMediaType) { if (m_pInput->IsConnected() == FALSE) { return E_UNEXPECTED; } if (iPosition < 0) { return E_INVALIDARG; } if (iPosition > 0) { return VFW_S_NO_MORE_ITEMS; } CheckPointer(pMediaType,E_POINTER); *pMediaType = m_pInput->CurrentMediaType(); return NOERROR; }

同样的,这个函数也是为输入pin所写。

3、HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut);

HRESULT CFlipFilter::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut) { if (*mtIn == *mtOut) { return NOERROR; } return E_FAIL; }

这个函数是输出pin调用。CTransformOutputPin::CheckMediaType(const CMediaType* pmtOut)中调用m_pTransformFilter->CheckTransform。

 

四、协商分配器的属性,决定数据的属性

HRESULT CFlipFilter::DecideBufferSize(IMemAllocator * pAllocator, ALLOCATOR_PROPERTIES *pprop) { if (m_pInput->IsConnected() == FALSE) { return E_UNEXPECTED; } CheckPointer(pAllocator,E_POINTER); CheckPointer(pprop,E_POINTER); HRESULT hr = NOERROR; pprop->cBuffers = 1; pprop->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize(); ASSERT(pprop->cbBuffer); ALLOCATOR_PROPERTIES Actual; hr = pAllocator->SetProperties(pprop,&Actual); if (FAILED(hr)) { return hr; } ASSERT( Actual.cBuffers == 1 ); if (pprop->cBuffers > Actual.cBuffers || pprop->cbBuffer > Actual.cbBuffer) { return E_FAIL; } return NOERROR; }

这个函数由CTransformOutputPin::DecideBufferSize调用。

 

五、实现数据转换

HRESULT CFlipFilter::Transform(IMediaSample *pIn, IMediaSample *pOut) { CheckPointer(pIn,E_POINTER); CheckPointer(pOut,E_POINTER); BYTE *pSourceBuffer, *pDestBuffer; long lSourceSize = pIn->GetActualDataLength(); pIn->GetPointer(&pSourceBuffer); pOut->GetPointer(&pDestBuffer); //翻转图像 CMediaType pMediaType1 = m_pInput->CurrentMediaType(); VIDEOINFOHEADER* pvi = (VIDEOINFOHEADER*)pMediaType1.pbFormat; int nWidth = WIDTHBYTES(pvi->bmiHeader.biWidth * pvi->bmiHeader.biBitCount); for (int i = 0; i < pvi->bmiHeader.biHeight; i ++) { CopyMemory((PVOID) (pDestBuffer + nWidth * i), (PVOID) (pSourceBuffer + nWidth * (pvi->bmiHeader.biHeight - i - 1)), nWidth); } REFERENCE_TIME TimeStart, TimeEnd; if(NOERROR == pIn->GetTime(&TimeStart, &TimeEnd)) { pOut->SetTime(&TimeStart, &TimeEnd); } LONGLONG MediaStart, MediaEnd; if(pIn->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR) { pOut->SetMediaTime(&MediaStart,&MediaEnd); } HRESULT hr = pIn->IsSyncPoint(); if(hr == S_OK) { pOut->SetSyncPoint(TRUE); } else if(hr == S_FALSE) { pOut->SetSyncPoint(FALSE); } else { return E_UNEXPECTED; } hr = pIn->IsPreroll(); if(hr == S_OK) { pOut->SetPreroll(TRUE); } else if(hr == S_FALSE) { pOut->SetPreroll(FALSE); } else { return E_UNEXPECTED; } hr = pIn->IsDiscontinuity(); if(hr == S_OK) { pOut->SetDiscontinuity(TRUE); } else if(hr == S_FALSE) { pOut->SetDiscontinuity(FALSE); } else { return E_UNEXPECTED; } long lDataLength = pIn->GetActualDataLength(); pOut->SetActualDataLength(lDataLength); return NOERROR; }

 

六、添加COM信息,使DLL成为filter

1、创建filter实例,这是标准格式

CUnknown* CFlipFilter::CreateInstance(LPUNKNOWN punk, HRESULT *phr) { ASSERT(phr); CFlipFilter *pNewObject = new CFlipFilter(NAME("FlipFilter"), punk, phr); if (pNewObject == NULL) { if (phr) *phr = E_OUTOFMEMORY; } return pNewObject; }

2、声明工厂类模版

const AMOVIESETUP_MEDIATYPE sudInputPinTypes = { &MEDIATYPE_Video, &MEDIASUBTYPE_NULL }; const AMOVIESETUP_MEDIATYPE sudOutputPinTypes = { &MEDIATYPE_Video, &MEDIASUBTYPE_NULL }; const AMOVIESETUP_PIN sudpPins[] = { { L"Input", FALSE, FALSE, FALSE, FALSE, &CLSID_NULL, NULL, 1, &sudInputPinTypes }, { L"Output", FALSE, TRUE, FALSE, FALSE, &CLSID_NULL, NULL, 1, &sudOutputPinTypes } }; const AMOVIESETUP_FILTER sudFlipFilter = { &CLSID_FlipFilter, L"FlipFilter", MERIT_DO_NOT_USE, 2, sudpPins }; CFactoryTemplate g_Templates[] = { { L"FlipFilter" , &CLSID_FlipFilter , CFlipFilter::CreateInstance , NULL , &sudFlipFilter } }; int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]); REGFILTER2 rf2FilterReg = { 1, MERIT_DO_NOT_USE, 2, sudpPins };

3、注册和注销filter,DLL的全局入口

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 ); }

 

Filter编写完成。

 

注:完整代码下载:http://d.download.csdn.net/down/2435821/bwmwm

 

 

 

你可能感兴趣的:(DirectX,filter,编程,templates,properties,null,winapi)