Friday, September 07, 2007

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

}

No comments: