Registering DirectShow Filters (Windows Embedded CE 6.0)
1/6/2010
This topic describes how to make a DirectShow filter self-registering. It addresses the following subjects:
- Layout of the Registry Keys
- Registering a Filter
- Unregistering a Filter
This topic does not describe how to create a DLL. For information about creating DLLs, see Creating a DLL in DirectShow.
Layout of the Registry Keys
The DLL that contains the filter is registered as the filter's COM server. When an application calls CoCreateInstance to create the filter, the Microsoft Windows COM library uses this registry entry to locate the DLL.
The registry entry for the DLL is as follows. See %_WINCEROOT%\Public\DirectX\Oak\Files\DirectX.reg for further examples.
DirectShow filter DLLs are registered by their class ID values. The complete registry entry for a DirectShow filter DLL begins with the HKEY_CLASSES_ROOT\CLSID\<Filter CLSID> key. The following table shows the values for this key.
Value : type | Description |
---|---|
@ : REG_SZ |
No default setting. The value of the <Filter CLSID> subkey is the friendly name of the filter. |
Merit : REG_DWORD |
Filter merit value. Filters with higher merit values are enumerated first. |
The registry key for the filter DLL's file is HKEY_CLASSES_ROOT\CLSID\<Filter CLSID>\InprocServer32. The following table shows the values for this key.
Value : type | Description |
---|---|
@ : REG_SZ |
No default setting. This is the file name of the filter DLL. |
ThreadingModel : REG_SZ |
You must set this value to "Both". |
Each filter pin is registered with its own registry key. The registry key for a pin is HKEY_CLASSES_ROOT\CLSID\<Filter CLSID>\Pins\<Pin Name>. Many filters just use a single input pin named "Input" and a single output pin named "Output". The following table shows the possible values for a filter pin subkey.
Value : type | Description |
---|---|
Direction : REG_DWORD |
No default setting. Set this value to 0 for input pins and 1 for output pins. |
IsRendered : REG_DWORD |
No default setting. Set this value to 0 if the pin renders its data and set to 1 if it does not. |
AllowedZero : REG_DWORD |
No default setting. Set this value to 0 if the filter requires this pin to be connected and set to 1 if it does not. |
AllowedMany : REG_DWORD |
No default setting. Set this value to 0 if the filter can only have a single pin of this type and set to 1 if it can have many pins of this type. |
ConnectsToPin : REG_SZ |
No default setting. Set this value to the name of the pin that this pin connects to. |
To register a media type and subtype that a pin supports, create the registry key HKEY_CLASSES_ROOT\CLSID\<Filter CLSID>\Pins\<Pin Name>\Types\{<Major type GUID>}\{<Subtype GUID>}. Use a subtype GUID of 00000000-0000-0000-0000-000000000000 (GUID_NULL) to indicate that the pin can be queried to accept connections with any subtype within the major type. A pin can have multiple entries for the Types subkey and a filter can have multiple pins.
The graph builder tries to assemble the correct filters to play back a specified source media during the intelligent connect process in the IGraphBuilder::RenderFile method. For more information, see Graph Building with Intelligent Connect. The graph builder enumerates the filter CLSIDs listed under the HKEY_CLASSES_ROOT\Filter\<Filter CLSID> registry key to find candidates for the filter graph. The following table shows the allowable values for this key.
Value : type | Description |
---|---|
@ : REG_SZ |
No default setting. The value of the <Filter CLSID> subkey is the friendly name of the filter. |
The HKEY_CLASSES_ROOT\CLSID\<Filter CLSID> registry key and subkeys are required to expose your filter to DirectShow and therefore make it available to applications through COM interfaces. The HKEY_CLASSES_ROOT\Filter\<Filter CLSID> is only required if you want to make your filter to be discoverable by the intelligent connect process.
The following example shows a filter graph registry entry from DirectX.reg.
; DV Video Codec
[HKEY_CLASSES_ROOT\Filter\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}]
@="DV Video Decoder"
[HKEY_CLASSES_ROOT\CLSID\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}]
@="DV Video Decoder"
"Merit"=dword:00600000
[HKEY_CLASSES_ROOT\CLSID\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}\InprocServer32]
@="quartz.DLL"
"ThreadingModel"="Both"
[HKEY_CLASSES_ROOT\CLSID\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}\Pins]
[HKEY_CLASSES_ROOT\CLSID\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}\Pins\Input]
"Direction"=dword:00000000
"IsRendered"=dword:00000000
"AllowedZero"=dword:00000000
"AllowedMany"=dword:00000000
"ConnectsToPin"="Output"
[HKEY_CLASSES_ROOT\CLSID\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}\Pins\Input\Types]
[HKEY_CLASSES_ROOT\CLSID\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}\Pins\Input\Types\{73646976-0000-0010-8000-00AA00389B71}]
[HKEY_CLASSES_ROOT\CLSID\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}\Pins\Input\Types\{73646976-0000-0010-8000-00AA00389B71}\]
[HKEY_CLASSES_ROOT\CLSID\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}\Pins\Input\Types\{73646976-0000-0010-8000-00AA00389B71}\{00000000-0000-0000-0000-000000000000}]
[HKEY_CLASSES_ROOT\CLSID\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}\Pins\Output]
"Direction"=dword:00000001
"IsRendered"=dword:00000000
"AllowedZero"=dword:00000000
"AllowedMany"=dword:00000000
"ConnectsToPin"="Input"
[HKEY_CLASSES_ROOT\CLSID\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}\Pins\Output\Types]
[HKEY_CLASSES_ROOT\CLSID\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}\Pins\Output\Types\{73646976-0000-0010-8000-00AA00389B71}]
[HKEY_CLASSES_ROOT\CLSID\{B1B77C00-C3E4-11cf-AF79-00AA00B67A42}\Pins\Output\Types\{73646976-0000-0010-8000-00AA00389B71}\{00000000-0000-0000-0000-000000000000}]
Registering a Filter
One can either register filters statically at run-time image creation time by adding appropriate entries to the Platform.reg file or dynamically as follows. Note that if the registry on the device in not in non-volatile RAM and one is registering filters dynamically, that Regsrv32.exe or RegsvrCE.exe must be explicitly called every time the registry information is lost or the filters will not be found by RenderFile and COM.
To register a filter
Declare filter information.
In the factory template for the filter, include a pointer to the filter information.
Implement the DllRegisterServer function.
The sections that follow describe these steps in detail.
Declare Filter Information
The first step is to declare the filter information. DirectShow defines a set of structures for describing filters, pins, and media types.
Structure | Description |
---|---|
AMOVIESETUP_FILTER |
Describes a filter. |
AMOVIESETUP_PIN |
Describes a pin. |
AMOVIESETUP_MEDIATYPE |
Describes a media type. |
These structures are nested. The AMOVIESETUP_FILTER structure has a pointer to an array of AMOVIESETUP_PIN structures, and each AMOVIESETUP_PIN structure has a pointer to an array of AMOVIESETUP_MEDIATYPE structures.
The structures provide enough information for the IFilterMapper interface to locate a filter. They are not a complete description of a filter. For example, if the filter creates multiple instances of the same pin, declare one AMOVIESETUP_PIN structure for that pin. Also, a filter is not required to support every combination of media types that it registers.
Declare these structures as global variables within your DLL. The following example shows a filter with one output pin.
static const WCHAR g_wszName[] = L"Some Filter";
AMOVIESETUP_MEDIATYPE sudMediaTypes[] = {
{ &MEDIATYPE_Video, &MEDIASUBTYPE_RGB24 },
{ &MEDIATYPE_Video, &MEDIASUBTYPE_RGB32 },
};
AMOVIESETUP_PIN sudOutputPin = {
L"Output", // Pin string 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, // Connects to filter.
NULL, // Connects to pin.
2, // Number of media types.
sudMediaTypes // Pointer to media types.
};
AMOVIESETUP_FILTER sudFilterReg = {
&CLSID_SomeFilter, // Filter CLSID.
g_wszName, // Filter name.
MERIT_NORMAL, // Merit.
1, // Number of pin types.
&sudPins // Pointer to pin information.
};
The filter name is declared as a static global variable, because it will be used again elsewhere.
Your filter must also override the base class GetSetupData method to return the setup data structure as shown.
LPAMOVIESETUP_FILTER CSomeFilter::GetSetupData()
{
return (LPAMOVIESETUP_FILTER) & sudFilterReg;
}
Declare the Factory Template
The next step is to declare the factory template for your filter. A factory template is a C++ class that contains information for the class factory. In your DLL, declare a global array of factory templates, one for each filter or COM component in your DLL. The array must be named g_Templates. For more information about factory templates, see Creating a DLL in DirectShow.
The m_pAMovieSetup_Filter member of the factory template is a pointer to the AMOVIESETUP_FILTER structure described previously. The following example shows a factory template, using the structure given in the previous example.
CFactoryTemplate g_Templates[] =
{
{
g_wszName, // Name.
&CLSID_SomeFilter, // CLSID.
CSomeFilter::CreateInstance, // Creation function.
NULL,
&sudFilterReg // Pointer to filter information.
}
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
Implement DllRegisterServer
The final step is to implement the DllRegisterServer function. The DLL that contains the component must export this function. The function will be called by a set-up application, or when the user runs the Regsvr32.exe or RegsvrCE.exe tool.
The following example shows a minimal implementation of DllRegisterServer.
STDAPI DllRegisterServer(void)
{
return AMovieDLLRegisterServer(TRUE);
}
The DirectShow function AMovieDLLRegisterServer creates registry entries for every component declared in the g_Templates array.
Filter categories introduced with AMovieDLLRegisterServer2 are not currently supported on Windows Embedded CE.
Unregistering a Filter
To unregister a filter, implement the DllUnregisterServer function. Within this function, call the DirectShow function AMovieDLLUnregisterServer.
The following example shows how to unregister a filter.
STDAPI DllUnregisterServer()
{
return AMovieDLLUnRegisterServer();
}