Creating Kernel-Mode Filters
Microsoft DirectShow 9.0 |
Creating Kernel-Mode Filters
Certain kernel-mode filters cannot be created through CoCreateInstance, and thus do not have CLSIDs. These filters include the Tee/Sink-to-Sink Converter, the CC Decoder filter, and the WST Codec filter. To create one of these filters, use the System Device Enumerator object and search by the filter's name.
- Create the System Device Enumerator.
- Call the ICreateDevEnum::CreateClassEnumerator method with the CLSID of the filter category for that filter. This method creates an enumerator for the filter category. (An enumerator is simply an object that returns a list of other objects, using a defined COM interface.) The enumerator returns IMoniker pointers, which represent the filters in that category.
- For each moniker, call IMoniker::BindToStorage to get an IPropertyBag interface.
- Call IPropertyBag::Read to get the name of the filter.
- If the name matches, call IMoniker::BindToObject to create the filter.
The following code shows a function that performs these steps:
HRESULT CreateKernelFilter( const GUID &guidCategory, // Filter category. LPCOLESTR szName, // The name of the filter. IBaseFilter **ppFilter // Receives a pointer to the filter. ) { HRESULT hr; ICreateDevEnum *pDevEnum = NULL; IEnumMoniker *pEnum = NULL; if (!szName || !ppFilter) { return E_POINTER; } // Create the system device enumerator. hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void**)&pDevEnum); if (FAILED(hr)) { return hr; } // Create a class enumerator for the specified category. hr = pDevEnum->CreateClassEnumerator(guidCategory, &pEnum, 0); pDevEnum->Release(); if (hr != S_OK) // S_FALSE means the category is empty. { return E_FAIL; } // Enumerate devices within this category. bool bFound = false; IMoniker *pMoniker; while (!bFound && (S_OK == pEnum->Next(1, &pMoniker, 0))) { IPropertyBag *pBag = NULL; hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag); if (FAILED(hr)) { pMoniker->Release(); continue; // Maybe the next one will work. } // Check the friendly name. VARIANT var; VariantInit(&var); hr = pBag->Read(L"FriendlyName", &var, NULL); if (SUCCEEDED(hr) && (lstrcmpiW(var.bstrVal, szName) == 0)) { // This is the right filter. hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)ppFilter); bFound = true; } VariantClear(&var); pBag->Release(); pMoniker->Release(); } pEnum->Release(); return (bFound ? hr : E_FAIL); }
The following code example uses this function to create the CC Decoder filter and add it to the filter graph:
IBaseFilter *pCC = NULL; hr = CreateKernelFilter(AM_KSCATEGORY_VBICODEC, OLESTR("CC Decoder"), &pCC); if (SUCCEEDED(hr)) { hr = pGraph->AddFilter(pCC, L"CC Decoder"); pCC->Release(); }
See Also