I've written a small transform filter (derived from TransInPlaceFilter baseclass), and managed to make it work properly in a Directshow graph, entirely coded in C++. I basically followed the 5 first steps described on MSDN, and the last part of the 6th step (in order to use the filter directly within an application).
For a lot of reasons (including being able to use the filter in GraphEdit), I need to export that filter in a DLL and register it.
I've been trying to follow these steps : setting up the "CreateInstance" method, the CFactoryTemplate class, filter/pins description (AMOVIESETUP_FILTER, AMOVIESETUP_PIN, AMOVIESETUP_MEDIA), Registering/Unregistering functions, and finally DLLmain/entrypoint.
The code successfully compiles and provides a DLL, which seems to register without any problem using Regsvr32.
But then I'm unable to use the filter :
- It appears in the list in GraphEdit, but fails when I try to insert it : 0x800401f9 ("Error in DLL").
- When I try to create it in C++ (using
pCustomFilter.CoCreateInstance(CLSID_Custom), after defining the correct GUID), I get error 0x80040154 (REGDB_E_CLASSNOTREG)
I'm quite confused here. Have I missed something in the DLL/registration code ? I'm posting most of the code I'm using, if it's of any use.
Any help would be greatly appreciated.
static const WCHAR g_wszName[] = L"Custom Filter";
AMOVIESETUP_MEDIATYPE sudMediaTypes[] = {
{ &MEDIATYPE_Video, &MEDIASUBTYPE_NULL },
{ &MEDIATYPE_Audio, &MEDIASUBTYPE_NULL },
};
AMOVIESETUP_PIN sudPins[2] = {
{
L"Input", // Name
FALSE, // Is this pin rendered?
FALSE, // Is it an output pin?
FALSE, // Can the filter create zero instances?
FALSE, // Does the filter create multiple instances?
&GUID_NULL, // Obsolete.
NULL, // Obsolete.
2, // Number of media types.
sudMediaTypes // Pointer to media types.
},
{
L"Output", // Name
FALSE, // Is this pin rendered?
TRUE, // Is it an output pin?
FALSE, // Can the filter create zero instances?
FALSE, // Does the filter create multiple instances?
&GUID_NULL, // Obsolete.
NULL, // Obsolete.
2, // Number of media types.
sudMediaTypes // Pointer to media types.
}
};
AMOVIESETUP_FILTER sudFilterReg = {
&CLSID_Custom, // Filter CLSID.
g_wszName, // Filter name.
MERIT_DO_NOT_USE, // Merit.
2, // Number of pin types.
sudPins // Pointer to pin information.
};
CFactoryTemplate g_Templates[] =
{
{
g_wszName,
&CLSID_Custom,
CCustomFilter::CreateInstance,
NULL,
&sudFilterReg
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2( TRUE );
}
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2( FALSE );
}
extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);
BOOL WINAPI DllMain(HANDLE hDllHandle, DWORD dwReason, LPVOID lpReserved)
{
return DllEntryPoint(reinterpret_cast<HINSTANCE>(hDllHandle), dwReason, lpReserved);
}
// ---
// Meanwhile, in my filter class...
// ---
CUnknown * WINAPI CCustomFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *pHr)
{
CCustomFilter *pFilter = new CCustomFilter();
if (pFilter== NULL)
{
*pHr = E_OUTOFMEMORY;
}
return pFilter;
}