Kernel-Mode フィルターの作成
[このページに関連付けられている機能 DirectShow は、従来の機能です。 MediaPlayer、IMFMediaEngine、Media Foundation のオーディオ/ビデオ キャプチャに置き換わりました。 これらの機能は、Windows 10とWindows 11用に最適化されています。 新しいコードでは、可能であれば、DirectShow ではなく Media Foundation で MediaPlayer、IMFMediaEngine、Audio/Video Capture を使用することを強くお勧めします。 Microsoft は、レガシ API を使用する既存のコードを、可能であれば新しい API を使用するように書き換えるよう提案しています。]
特定のカーネル モード フィルターは CoCreateInstance を使用して作成できないため、CLSID はありません。 これらのフィルターには、 Tee/Sink-to-Sink Converter、 CC デコーダー フィルター、 WST コーデック フィルターが含まれます。 これらのフィルターのいずれかを作成するには、 System Device Enumerator オブジェクトを使用し、フィルターの名前で検索します。
- システム デバイス列挙子を作成します。
- そのフィルターのフィルター カテゴリの CLSID を使用して 、ICreateDevEnum::CreateClassEnumerator メソッドを呼び出します。 このメソッドは、フィルター カテゴリの列挙子を作成します。 ( 列挙子 は、定義された COM インターフェイスを使用して、他のオブジェクトのリストを返す単なるオブジェクトです)。列挙子は、そのカテゴリのフィルターを表す IMoniker ポインターを返します。
- モニカーごとに、 IMoniker::BindToStorage を呼び出して IPropertyBag インターフェイスを取得します。
- フィルターの名前を取得するには 、IPropertyBag::Read を呼び出します。
- 名前が一致する場合は、 IMoniker::BindToObject を呼び出してフィルターを作成します。
次のコードは、これらの手順を実行する関数を示しています。
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);
}
次のコード例では、この関数を使用して CC デコーダー フィルターを作成し、フィルター グラフに追加します。
IBaseFilter *pCC = NULL;
hr = CreateKernelFilter(AM_KSCATEGORY_VBICODEC,
OLESTR("CC Decoder"), &pCC);
if (SUCCEEDED(hr))
{
hr = pGraph->AddFilter(pCC, L"CC Decoder");
pCC->Release();
}
関連トピック