一、获得filter的CLSID
获得filter的CLSID有三种方法:
1、通过注册表中记录的值获得。
HKEY_CURRENT_USER/Software/Microsoft/ActiveMovie/devenum下面有几个分 类,各个filter都在里面。
比如DivX MPEG-4 Fast-Motion这个filter就在{33D9A760-90C8-11D0-BD43-00A0C911CE86}下面的div4里面。可以看 到他的CLSID是D76E2820-1563-11CF-AC98-00AA004C0FA9。
2、通过代码枚举。
HRESULThr;
CComBSTR FilterName(name);
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void **)&pSysDevEnum);
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_LegacyAmFilterCategory,&pEnumCat, 0);
if (hr == S_OK)
{
// Enumerate the monikers.
IMoniker *pMoniker;
ULONG cFetched;
while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
{
IPropertyBag *pPropBag;
pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag);
VARIANT varName;
VariantInit(&varName);
hr = pPropBag->Read(L"FriendlyName", &varName, 0);
if ( (SUCCEEDED(hr) && wcscmp(FilterName, varName.bstrVal) == 0))
{
pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&pFilter);
hr=pGraph->AddFilter(pFilter, LPCWSTR (name));
break;
}
VariantClear(&varName);
pPropBag->Release();
pMoniker->Release();
}
pEnumCat->Release();
}
pSysDevEnum->Release();
name是一个字符串,用于存放要枚举的filter的FriendlyName。需要注意的是CreateClassEnumerator的时候的CLSID_LegacyAmFilterCategory这个参数是指filter的类型,这里是 枚举解码的filter。如果是编码的filter就应该是CLSID_VideoCompressorCategory。
CLSID_LegacyAmFilterCategory对应Directshow Filter,而CLSID_VideoCompressorCategory对应VideoCompressor目录。
3、directshow SDK头文件
通常情况下,filter的CLSID是不用我们去查找或枚举的,在directshowSDK的include目录下,有一个名为“uuids.h”的头文件,常用的或者说directshow自带的filter已经列中里面了。
二、将filter加入到graph中
在得到了filter后,我们要使用他们,还需要将filter加入到graph中,下面的代码演示了如何利用CLSID生成一个filter,然后将其加入到graph图中。
HRESULT AddFilterByCLSID(
IGraphBuilder *pGraph, // Pointer to the FilterGraph Manager.
const GUID& clsid, // CLSID of the filter tocreate.
LPCWSTR wszName, // A name for the filter.
IBaseFilter **ppF) // Receives a pointer to thefilter.
{
if (!pGraph || ! ppF) return E_POINTER;
*ppF = 0;
IBaseFilter *pF = 0;
HRESULT hr = CoCreateInstance(clsid, 0,CLSCTX_INPROC_SERVER,
IID_IBaseFilter,reinterpret_cast<void**>(&pF));
if (SUCCEEDED(hr))
{
hr = pGraph->AddFilter(pF, wszName);
if (SUCCEEDED(hr))
*ppF = pF;
else
pF->Release();
}
return hr;
}
在你的应用程序中,你可以这样用这个函数
IBaseFilter *pMux;
hr = AddFilterByCLSID(pGraph, CLSID_AviDest,L"AVI Mux", &pMux);
if (SUCCEEDED(hr))
{
/* ... */
pMux->Release();
}
注:有些filter是不能通过with CoCreateInstance方法创建的。例如AVI Compressor Filter和WDM VideoCapture filter。
其实这些方法在《directshow开发指南》一书中已经有详细的说明,将filter加入到graph的方法共有两种,静态加载和动态加载,具体内容也可在《directshow开发指南》中找到。