Microsoft DirectX 8.0 |
This article describes how to make a Microsoft® DirectShow® filter self-registering. It contains the following sections:
This article does not describe how to create a DLL. For information on creating DLLs, see How to Create a DLL.
DirectShow filters are registered in two places:
The registry entry for the DLL is:
HKEY_CLASSES_ROOT CLSID Filter CLSID REG_SZ: (Default) = Friendly name InprocServer32 REG_SZ: (Default) = File name of the DLL REG_SZ: ThreadingModel = Both
The registry entry for the filter information is:
HKEY_CLASSES_ROOT CLSID Category Instance Filter CLSID REG_SZ: CLSID = Filter CLSID REG_BINARY: Filter Data = Filter information REG_SZ: FriendlyName = Friendly name
Category is the GUID of a filter category. The filter information is packed into a binary format. The IFilterMapper2 interface unpacks this data when it searches the registry for a filter.
To register a filter, perform the following steps:
The sections that follow describe these steps in detail.
The first step is to declare the filter information. DirectShow defines a set of structures for describing filters, pins, and media types:
AMOVIESETUP_FILTER | Describes a filter. |
AMOVIESETUP_PIN | Describes a pin. |
AMOVIESETUP_MEDIATYPE | Describes a media type. |
These structures are nested. The filter structure has a pointer to an array of pin structures, and each pin structure has a pointer to an array of media-type structures. The structures provide enough information for the IFilterMapper2 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, you should declare only one AMOVIESETUP_PIN structure for that pin. Also, a filter is not required to support every combination of media types that it registers.
Declare the set-up 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"", // Obsolete, not used. 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_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.
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 How to Create a DLL.
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]);
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 tool.
The following example shows a minimal implementation of DlLRegisterServer:
STDAPI DllRegisterServer(void) { return AMovieDllRegisterServer2(TRUE); }
The DirectShow function AMovieDllRegisterServer2 creates registry entries for every component in the g_Templates array. However, this function has some limitations. First, it assigns every filter to the CLSID_LegacyAmFilterCategory category. Not all filters belong in this category. Capture filters and compression filters, for example, have their own categories. (For a list of categories, see Filter Categories.) Second, if your filter supports a hardware device, you might need to register two pieces of information that AMovieDLLRegisterServer2 does not handle: the medium and the pin category. A medium defines a method of communication in a hardware device, such as a bus. The pin category defines the function of a pin. For information on mediums, see KSPIN_MEDIUM in the Microsoft® Windows® Driver Development Kit (DDK). For a list of pin categories, see Pin Property Set.
If you want to specify the filter category, the medium, or the pin category, call the IFilterMapper2::RegisterFilter method from within DllRegisterServer. This method takes a pointer to a REGFILTER2 structure, which specifies information about the filter.
To complicate matters somewhat, the REGFILTER2 structure supports two different formats for registering pins. The dwVersion member specifies the format:
The REGFILTERPINS2 structure includes entries for pin mediums and pin categories. Also, it uses bit flags for some items that AMOVIESETUP_PIN declares as Boolean values.
The following example shows how to call IFilterMapper2::RegisterFilter from inside DllRegisterServer:
REGFILTER2 rf2FilterReg = { 1, // Version 1 (no pin mediums or pin category). MERIT_NORMAL, // Merit. 1, // Number of pins. &sudPins // Pointer to pin information. }; STDAPI DllRegisterServer(void) { HRESULT hr; IFilterMapper2 *pFM2 = NULL; hr = AMovieDllRegisterServer2(TRUE); if (FAILED(hr)) return hr; hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, IID_IFilterMapper2, (void **)&pFM2); if (FAILED(hr)) return hr; hr = pFM2->RegisterFilter( CLSID_SomeFilter, // Filter CLSID. g_wszName, // Filter name. NULL, // Device moniker. &CLSID_VideoCompressorCategory, // Video compressor category. g_wszName, // Instance data. &rf2FilterReg // Pointer to filter information. ); pFM2->Release(); return hr; }
To unregister a filter, implement the DllUnregisterServer function. Within this function, call the DirectShow AMovieDllRegisterServer2 function with a value of FALSE. If you called IFilterMapper2::RegisterFilter when you registered the filter, call the IFilterMapper2::UnregisterFilter method here.
The following example shows how to unregister a filter:
STDAPI DllUnregisterServer() { HRESULT hr; IFilterMapper2 *pFM2 = NULL; hr = AMovieDllRegisterServer2(FALSE); if (FAILED(hr)) return hr; hr = CoCreateInstance(CLSID_FilterMapper2, NULL, CLSCTX_INPROC_SERVER, IID_IFilterMapper2, (void **)&pFM2); if (FAILED(hr)) return hr; hr = pFM2->UnregisterFilter(&CLSID_VideoCompressorCategory, g_wszName, CLSID_SomeFilter); pFM2->Release(); return hr; }