Directshow Transform Filter development
1. Open the Empty Win32 DLL
2.Add the stdafx.h , ColorToGray.h and ColorToGray.cpp
3.stdafx.h content is as follows
#pragma once
#include
//#include
#include
#include
#include
#include
#include
3.1. ColorToGray.def content as follows :
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
4. I added the linker library files as follows
C:\DXSDK\Samples\C++\DirectShow\BaseClasses\Debug_Unicode\strmbasd.lib
winmm.lib
5. I added the following keyword in a Project->Settings->Linker ->Output->Entry Point option
DllEntryPoint@12
6. I added the
regsvr32 /s "$(TargetPath)" to the Project->Settings->Post Build link step...
7.I got this error :
LIBCMTD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
So I Modified Project->Settings->C++->General ->Preprocessor definitions as follows :
WIN32,_DEBUG,_WINDOWS,DEBUG
8. I made it as "not using precompile header files"
Project->Settings->C++ ->Not Using Precompiled Headers
Finally I got this Error :
Creating library Debug/ColorToGray.lib and object Debug/ColorToGray.exp
LIBCMTD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/ColorToGray.dll : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
4.ColorToGray.h File Contents :
class CColorToGray : public CTransformFilter
{
public:
DECLARE_IUNKNOWN; //For Query the Interface and Release
static CUnknown *WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr);
CColorToGray(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr);
~CColorToGray();
HRESULT CheckInputType(const CMediaType *mtIn );
HRESULT CheckTransform(const CMediaType *mtIn,
const CMediaType *mtOut);
HRESULT DecideBufferSize( IMemAllocator *pAlloc,
ALLOCATOR_PROPERTIES *ppropInputRequest
);
HRESULT GetMediaType ( int iPosition,
CMediaType *pMediaType
);
HRESULT Transform ( IMediaSample *pIn,
IMediaSample *pOut
);
HRESULT SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt);
private:
BOOL canPerformTransform(const CMediaType *pMediaType) const;
VIDEOINFOHEADER m_VihOut;
VIDEOINFOHEADER m_VihIn;
};
5.ColorToGray.cpp contents as follows :
#include "stdafx.h"
#include "ColorToGray.h"
// {1CCD0EC0-3E1E-43d4-B467-DDD1CBD0B9CE}
DEFINE_GUID(CLSID_ColorToGray,
0x1ccd0ec0, 0x3e1e, 0x43d4, 0xb4, 0x67, 0xdd, 0xd1, 0xcb, 0xd0, 0xb9, 0xce);
// setup data - allows the self-registration to work.
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{ &MEDIATYPE_NULL // clsMajorType
, &MEDIASUBTYPE_NULL }; // clsMinorType
const AMOVIESETUP_PIN psudPins[] =
{ { L"Input" // strName
, FALSE // bRendered
, FALSE // bOutput
, FALSE // bZero
, FALSE // bMany
, &CLSID_NULL // clsConnectsToFilter
, L"" // strConnectsToPin
, 1 // nTypes
, &sudPinTypes // lpTypes
}
, { L"Output" // strName
, FALSE // bRendered
, TRUE // bOutput
, FALSE // bZero
, FALSE // bMany
, &CLSID_NULL // clsConnectsToFilter
, L"" // strConnectsToPin
, 1 // nTypes
, &sudPinTypes // lpTypes
}
};
const AMOVIESETUP_FILTER sudColorToGray =
{ &CLSID_ColorToGray // clsID
, L"ColorToGray Filter Test" // strName
, MERIT_DO_NOT_USE // dwMerit
, 2 // nPins
, psudPins }; // lpPin
CFactoryTemplate g_Templates[] =
{
{
L"ColorToGray Filter Test", // Filter Name
&CLSID_ColorToGray, //CLASS ID
CColorToGray::CreateInstance, // it will be called whenever the COM object is created
NULL, // Init Function is not needed
&sudColorToGray //Color ToGray AM_MOVIE_SETUP filter
}
};
int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]);
CUnknown *WINAPI CColorToGray::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
{
CColorToGray *pNewObject = new CColorToGray(NAME("ColorToGray"), punk, phr );
if (pNewObject == NULL)
{
*phr = E_OUTOFMEMORY;
}
return pNewObject;
}
CColorToGray::CColorToGray(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr):CTransformFilter(tszName,punk,CLSID_ColorToGray)
{
}
CColorToGray::~CColorToGray()
{
}
HRESULT CColorToGray::CheckInputType(const CMediaType *pMediaType )
{
if(canPerformTransform(pMediaType))
{
return S_OK;
}
return VFW_E_TYPE_NOT_ACCEPTED;
}
HRESULT CColorToGray::CheckTransform(const CMediaType *mtIn,
const CMediaType *mtOut)
{
if (canPerformTransform(mtIn))
{
if (*mtIn == *mtOut)
{
return NOERROR;
}
}
return E_FAIL;
}
HRESULT CColorToGray::DecideBufferSize( IMemAllocator *pAlloc,
ALLOCATOR_PROPERTIES *pProperties
)
{
// Is the input pin connected
if (m_pInput->IsConnected() == FALSE) {
return E_UNEXPECTED;
}
ASSERT(pAlloc);
ASSERT(pProperties);
HRESULT hr = NOERROR;
pProperties->cBuffers = 1;
// Get input pin's allocator size and use that
ALLOCATOR_PROPERTIES InProps;
IMemAllocator * pInAlloc = NULL;
hr = m_pInput->GetAllocator(&pInAlloc);
if (SUCCEEDED (hr))
{
hr = pInAlloc->GetProperties (&InProps);
if (SUCCEEDED (hr))
{
pProperties->cbBuffer = InProps.cbBuffer;
}
pInAlloc->Release();
}
if (FAILED(hr))
return hr;
ASSERT(pProperties->cbBuffer);
// Ask the allocator to reserve us some sample memory, NOTE the function
// can succeed (that is return NOERROR) but still not have allocated the
// memory that we requested, so we must check we got whatever we wanted
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pProperties,&Actual);
if (FAILED(hr)) {
return hr;
}
ASSERT( Actual.cBuffers == 1 );
if ( pProperties->cBuffers > Actual.cBuffers ||
pProperties->cbBuffer > Actual.cbBuffer) {
return E_FAIL;
}
return NOERROR;
return hr;
}
HRESULT CColorToGray::GetMediaType ( int iPosition,
CMediaType *pMediaType
)
{
// Is the input pin connected
if (m_pInput->IsConnected() == FALSE) {
return E_UNEXPECTED;
}
// This should never happen
if (iPosition < 0) {
return E_INVALIDARG;
}
// Do we have more items to offer
if (iPosition > 0) {
return VFW_S_NO_MORE_ITEMS;
}
*pMediaType = m_pInput->CurrentMediaType();
return NOERROR;
}
HRESULT CColorToGray::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt)
{
if (direction == PINDIR_INPUT)
{
ASSERT(pmt->formattype == FORMAT_VideoInfo);
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmt->pbFormat;
// WARNING! In general you cannot just copy a VIDEOINFOHEADER
// struct, because the BITMAPINFOHEADER member may be followed by
// random amounts of palette entries or color masks. (See VIDEOINFO
// structure in the DShow SDK docs.) Here it's OK because we just
// want the information that's in the VIDEOINFOHEADER stuct itself.
CopyMemory(&m_VihIn, pVih, sizeof(VIDEOINFOHEADER));
}
else // output pin
{
ASSERT(direction == PINDIR_OUTPUT);
ASSERT(pmt->formattype == FORMAT_VideoInfo);
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmt->pbFormat;
CopyMemory(&m_VihOut, pVih, sizeof(VIDEOINFOHEADER));
}
return S_OK;
}
HRESULT CColorToGray::Transform ( IMediaSample *pIn,
IMediaSample *pOut
)
{
HRESULT hr = S_OK;
BYTE* pbIn = NULL;
BYTE* pbOut= NULL;
CMediaType *pmt = 0;
if (S_OK == pOut->GetMediaType((AM_MEDIA_TYPE**)&pmt) && pmt)
{
// Notify our own output pin about the new type.
m_pOutput->SetMediaType(pmt);
DeleteMediaType(pmt);
}
pIn->GetPointer(&pbIn);
pOut->GetPointer(&pbOut);
unsigned long i = 0;
for(i = 0 ; i < m_VihOut.bmiHeader.biSizeImage; i++)
{
pbOut[i] = pbIn[i] ^ 0xff;
}
return hr;
}
//Private methods
BOOL CColorToGray::canPerformTransform(const CMediaType *pMediaType) const
{
// we accept the following image type: (RGB24, ARGB32 or RGB32)
if (IsEqualGUID(*pMediaType->Type(), MEDIATYPE_Video)) {
if (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_RGB24)) {
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pMediaType->Format();
return (pvi->bmiHeader.biBitCount == 24);
}
if (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_ARGB32)) {
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pMediaType->Format();
return (pvi->bmiHeader.biBitCount == 32);
}
if (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_RGB32)) {
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pMediaType->Format();
return (pvi->bmiHeader.biBitCount == 32);
}
}
return FALSE;
}
STDAPI DllRegisterServer()
{
//Next Register and unregister the DLL without the AMovieDllRegisterServer2() fn
return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
2.Add the stdafx.h , ColorToGray.h and ColorToGray.cpp
3.stdafx.h content is as follows
#pragma once
#include
//#include
#include
#include
#include
#include
#include
3.1. ColorToGray.def content as follows :
EXPORTS
DllGetClassObject PRIVATE
DllCanUnloadNow PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
4. I added the linker library files as follows
C:\DXSDK\Samples\C++\DirectShow\BaseClasses\Debug_Unicode\strmbasd.lib
winmm.lib
5. I added the following keyword in a Project->Settings->Linker ->Output->Entry Point option
DllEntryPoint@12
6. I added the
regsvr32 /s "$(TargetPath)" to the Project->Settings->Post Build link step...
7.I got this error :
LIBCMTD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
So I Modified Project->Settings->C++->General ->Preprocessor definitions as follows :
WIN32,_DEBUG,_WINDOWS,DEBUG
8. I made it as "not using precompile header files"
Project->Settings->C++ ->Not Using Precompiled Headers
Finally I got this Error :
Creating library Debug/ColorToGray.lib and object Debug/ColorToGray.exp
LIBCMTD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/ColorToGray.dll : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
4.ColorToGray.h File Contents :
class CColorToGray : public CTransformFilter
{
public:
DECLARE_IUNKNOWN; //For Query the Interface and Release
static CUnknown *WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr);
CColorToGray(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr);
~CColorToGray();
HRESULT CheckInputType(const CMediaType *mtIn );
HRESULT CheckTransform(const CMediaType *mtIn,
const CMediaType *mtOut);
HRESULT DecideBufferSize( IMemAllocator *pAlloc,
ALLOCATOR_PROPERTIES *ppropInputRequest
);
HRESULT GetMediaType ( int iPosition,
CMediaType *pMediaType
);
HRESULT Transform ( IMediaSample *pIn,
IMediaSample *pOut
);
HRESULT SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt);
private:
BOOL canPerformTransform(const CMediaType *pMediaType) const;
VIDEOINFOHEADER m_VihOut;
VIDEOINFOHEADER m_VihIn;
};
5.ColorToGray.cpp contents as follows :
#include "stdafx.h"
#include "ColorToGray.h"
// {1CCD0EC0-3E1E-43d4-B467-DDD1CBD0B9CE}
DEFINE_GUID(CLSID_ColorToGray,
0x1ccd0ec0, 0x3e1e, 0x43d4, 0xb4, 0x67, 0xdd, 0xd1, 0xcb, 0xd0, 0xb9, 0xce);
// setup data - allows the self-registration to work.
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{ &MEDIATYPE_NULL // clsMajorType
, &MEDIASUBTYPE_NULL }; // clsMinorType
const AMOVIESETUP_PIN psudPins[] =
{ { L"Input" // strName
, FALSE // bRendered
, FALSE // bOutput
, FALSE // bZero
, FALSE // bMany
, &CLSID_NULL // clsConnectsToFilter
, L"" // strConnectsToPin
, 1 // nTypes
, &sudPinTypes // lpTypes
}
, { L"Output" // strName
, FALSE // bRendered
, TRUE // bOutput
, FALSE // bZero
, FALSE // bMany
, &CLSID_NULL // clsConnectsToFilter
, L"" // strConnectsToPin
, 1 // nTypes
, &sudPinTypes // lpTypes
}
};
const AMOVIESETUP_FILTER sudColorToGray =
{ &CLSID_ColorToGray // clsID
, L"ColorToGray Filter Test" // strName
, MERIT_DO_NOT_USE // dwMerit
, 2 // nPins
, psudPins }; // lpPin
CFactoryTemplate g_Templates[] =
{
{
L"ColorToGray Filter Test", // Filter Name
&CLSID_ColorToGray, //CLASS ID
CColorToGray::CreateInstance, // it will be called whenever the COM object is created
NULL, // Init Function is not needed
&sudColorToGray //Color ToGray AM_MOVIE_SETUP filter
}
};
int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]);
CUnknown *WINAPI CColorToGray::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
{
CColorToGray *pNewObject = new CColorToGray(NAME("ColorToGray"), punk, phr );
if (pNewObject == NULL)
{
*phr = E_OUTOFMEMORY;
}
return pNewObject;
}
CColorToGray::CColorToGray(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr):CTransformFilter(tszName,punk,CLSID_ColorToGray)
{
}
CColorToGray::~CColorToGray()
{
}
HRESULT CColorToGray::CheckInputType(const CMediaType *pMediaType )
{
if(canPerformTransform(pMediaType))
{
return S_OK;
}
return VFW_E_TYPE_NOT_ACCEPTED;
}
HRESULT CColorToGray::CheckTransform(const CMediaType *mtIn,
const CMediaType *mtOut)
{
if (canPerformTransform(mtIn))
{
if (*mtIn == *mtOut)
{
return NOERROR;
}
}
return E_FAIL;
}
HRESULT CColorToGray::DecideBufferSize( IMemAllocator *pAlloc,
ALLOCATOR_PROPERTIES *pProperties
)
{
// Is the input pin connected
if (m_pInput->IsConnected() == FALSE) {
return E_UNEXPECTED;
}
ASSERT(pAlloc);
ASSERT(pProperties);
HRESULT hr = NOERROR;
pProperties->cBuffers = 1;
// Get input pin's allocator size and use that
ALLOCATOR_PROPERTIES InProps;
IMemAllocator * pInAlloc = NULL;
hr = m_pInput->GetAllocator(&pInAlloc);
if (SUCCEEDED (hr))
{
hr = pInAlloc->GetProperties (&InProps);
if (SUCCEEDED (hr))
{
pProperties->cbBuffer = InProps.cbBuffer;
}
pInAlloc->Release();
}
if (FAILED(hr))
return hr;
ASSERT(pProperties->cbBuffer);
// Ask the allocator to reserve us some sample memory, NOTE the function
// can succeed (that is return NOERROR) but still not have allocated the
// memory that we requested, so we must check we got whatever we wanted
ALLOCATOR_PROPERTIES Actual;
hr = pAlloc->SetProperties(pProperties,&Actual);
if (FAILED(hr)) {
return hr;
}
ASSERT( Actual.cBuffers == 1 );
if ( pProperties->cBuffers > Actual.cBuffers ||
pProperties->cbBuffer > Actual.cbBuffer) {
return E_FAIL;
}
return NOERROR;
return hr;
}
HRESULT CColorToGray::GetMediaType ( int iPosition,
CMediaType *pMediaType
)
{
// Is the input pin connected
if (m_pInput->IsConnected() == FALSE) {
return E_UNEXPECTED;
}
// This should never happen
if (iPosition < 0) {
return E_INVALIDARG;
}
// Do we have more items to offer
if (iPosition > 0) {
return VFW_S_NO_MORE_ITEMS;
}
*pMediaType = m_pInput->CurrentMediaType();
return NOERROR;
}
HRESULT CColorToGray::SetMediaType(PIN_DIRECTION direction, const CMediaType *pmt)
{
if (direction == PINDIR_INPUT)
{
ASSERT(pmt->formattype == FORMAT_VideoInfo);
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmt->pbFormat;
// WARNING! In general you cannot just copy a VIDEOINFOHEADER
// struct, because the BITMAPINFOHEADER member may be followed by
// random amounts of palette entries or color masks. (See VIDEOINFO
// structure in the DShow SDK docs.) Here it's OK because we just
// want the information that's in the VIDEOINFOHEADER stuct itself.
CopyMemory(&m_VihIn, pVih, sizeof(VIDEOINFOHEADER));
}
else // output pin
{
ASSERT(direction == PINDIR_OUTPUT);
ASSERT(pmt->formattype == FORMAT_VideoInfo);
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmt->pbFormat;
CopyMemory(&m_VihOut, pVih, sizeof(VIDEOINFOHEADER));
}
return S_OK;
}
HRESULT CColorToGray::Transform ( IMediaSample *pIn,
IMediaSample *pOut
)
{
HRESULT hr = S_OK;
BYTE* pbIn = NULL;
BYTE* pbOut= NULL;
CMediaType *pmt = 0;
if (S_OK == pOut->GetMediaType((AM_MEDIA_TYPE**)&pmt) && pmt)
{
// Notify our own output pin about the new type.
m_pOutput->SetMediaType(pmt);
DeleteMediaType(pmt);
}
pIn->GetPointer(&pbIn);
pOut->GetPointer(&pbOut);
unsigned long i = 0;
for(i = 0 ; i < m_VihOut.bmiHeader.biSizeImage; i++)
{
pbOut[i] = pbIn[i] ^ 0xff;
}
return hr;
}
//Private methods
BOOL CColorToGray::canPerformTransform(const CMediaType *pMediaType) const
{
// we accept the following image type: (RGB24, ARGB32 or RGB32)
if (IsEqualGUID(*pMediaType->Type(), MEDIATYPE_Video)) {
if (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_RGB24)) {
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pMediaType->Format();
return (pvi->bmiHeader.biBitCount == 24);
}
if (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_ARGB32)) {
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pMediaType->Format();
return (pvi->bmiHeader.biBitCount == 32);
}
if (IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_RGB32)) {
VIDEOINFOHEADER *pvi = (VIDEOINFOHEADER *) pMediaType->Format();
return (pvi->bmiHeader.biBitCount == 32);
}
}
return FALSE;
}
STDAPI DllRegisterServer()
{
//Next Register and unregister the DLL without the AMovieDllRegisterServer2() fn
return AMovieDllRegisterServer2(TRUE);
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2(FALSE);
}
Labels: Directshow samples
0 Comments:
Post a Comment
<< Home