DirectShow基础编程 最简单transform filter 编写步骤
2016-01-07 16:45
441 查看
目标编写一个transform filter,功能是对图像进行翻转。
一、选择基类
从CBaseFilter派生出三个用于编写transform filter的类,各自是:CTransformFilter 、CTransInPlaceFilter 和CVideoTransformFilter ,三个基类的差别能够看MSDN的说明,我们选择CTransformFilter类。
选择好基类,我们就创建一个空的DLLproject,加入三个文件,各自是:FlipFilter.h、FlipFilter.cpp和FlipFilter.def。
二、声明Filter类
在FlipFilter.h中加入下列代码声明
[cpp] view plaincopyprint?#include <streams.h>
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);
[cpp] view plaincopyprint?
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);
[cpp] view plaincopyprint?
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);
[cpp] view plaincopyprint?
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。
四、协商分配器的属性。决定数据的属性
[cpp] view plaincopyprint?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调用。
五、实现数据转换
[cpp] view plaincopyprint" style="color: rgb(204, 204, 204); text-decoration: none; background-image: none; border: none; padding: 0px; margin: 0px 10px 0px 0px; font-size: 9px; background-position: initial initial; background-repeat: initial initial;">?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实例。这是标准格式
[cpp] view plaincopyprint?
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、声明工厂类模版
[cpp] view plaincopyprint?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的全局入口
[cpp] view plaincopyprint" style="color: rgb(204, 204, 204); text-decoration: none; background-image: none; border: none; padding: 0px; margin: 0px 10px 0px 0px; font-size: 9px; background-position: initial initial; background-repeat: initial initial;">?
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编写完毕。
一、选择基类
从CBaseFilter派生出三个用于编写transform filter的类,各自是:CTransformFilter 、CTransInPlaceFilter 和CVideoTransformFilter ,三个基类的差别能够看MSDN的说明,我们选择CTransformFilter类。
选择好基类,我们就创建一个空的DLLproject,加入三个文件,各自是:FlipFilter.h、FlipFilter.cpp和FlipFilter.def。
二、声明Filter类
在FlipFilter.h中加入下列代码声明
[cpp] view plaincopyprint?#include <streams.h>
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);
[cpp] view plaincopyprint?
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);
[cpp] view plaincopyprint?
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);
[cpp] view plaincopyprint?
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。
四、协商分配器的属性。决定数据的属性
[cpp] view plaincopyprint?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调用。
五、实现数据转换
[cpp] view plaincopyprint" style="color: rgb(204, 204, 204); text-decoration: none; background-image: none; border: none; padding: 0px; margin: 0px 10px 0px 0px; font-size: 9px; background-position: initial initial; background-repeat: initial initial;">?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实例。这是标准格式
[cpp] view plaincopyprint?
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、声明工厂类模版
[cpp] view plaincopyprint?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的全局入口
[cpp] view plaincopyprint" style="color: rgb(204, 204, 204); text-decoration: none; background-image: none; border: none; padding: 0px; margin: 0px 10px 0px 0px; font-size: 9px; background-position: initial initial; background-repeat: initial initial;">?
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编写完毕。
相关文章推荐
- 2016-1-7-Thingking in Java 读书笔记(三)--操作符
- qt tableview代理1
- Java高级工程师面试题目汇集(关于Struts,Spring,Hibernate三大框架的面试)
- C#实现每隔一段时间执行代码(多线程)
- C# 生成月份及天选择列表,方便做下拉框联动
- 排序算法(一)
- python入门神图
- ftp 操作,支持断点续传或者继续下载。
- Python之绘图和可视化
- Python之绘图和可视化
- C# 委托事件的应用
- php
- 常见汇编代码
- qt tableview代理实现
- Java数据类型和MySql数据类型对应表
- c#自动关闭 MessageBox 弹出的窗口
- JAVA线程锁-读写锁应用,简单的缓存系统
- “鸡翁一值钱5,鸡母一值钱3,鸡雏三值钱1。百钱买百鸡,问鸡翁、母、雏各几何?”java穷举法解题
- 你真的搞明白Java中基本数据类型的转换了吗?
- Python Web-第二周-正则表达式(Using Python to Access Web Data)