WDM クラス ドライバ フィルタ
キャプチャ デバイスで WDM (Windows Driver Model) ドライバを使う場合には、グラフ内のキャプチャ フィルタのアップストリームに一定のフィルタが必要になることがある。これらのフィルタは、"ストリームクラス ドライバ" フィルタまたは WDM フィルタと呼ばれる。これらのフィルタでは、ハードウェアが提供する追加機能がサポートされる。たとえば、TV チューナー カードにはチャンネルを設定するための機能がある。これに対応するフィルタは、IAMTVTuner インターフェイスを公開する TV チューナー フィルタである。アプリケーションからこの機能を利用できるようにするには、キャプチャ フィルタに TV チューナー フィルタを接続する必要がある。
ICaptureGraphBuilder2 インターフェイスは、グラフに WDM フィルタを追加するための最も簡単な手段である。グラフ作成のどこかで FindInterface または RenderStream を呼び出す。これらのメソッドは、どちらも必要な WDM フィルタを自動的に見つけてキャプチャ グラフに接続する。WDM フィルタを手動で追加する方法は、このセクションの後半で説明する。しかし、これらの ICaptureGraphBuilder2 メソッドの 1 つを呼び出す方法を推奨する。
WDM フィルタのピンは、1 つ以上の "メディア" をサポートする。メディアとは、通信の手段 (バスなど) を定義するものである。接続するピンでは、同じメディアがサポートされている必要がある。REGPINMEDIUM 構造体は、カーネル ストリーミング ドライバに使う KSPIN_MEDIUM 構造体に等しい。REGPINMEDIUM 構造体は DirectShow でメディアを定義する。REGPINMEDIUM 構造体の clsMedium メンバは、メディアのクラス識別子 (CLSID) を指定するものである。ピンのメディアを取得するには、IKsPin::KsQueryMediums メソッドを呼び出す。このメソッドは、KSMULTIPLE_ITEM 構造体と 0 個以上の REGPINMEDIUM 構造体が連続して格納されたメモリ ブロックへのポインタを返す。各 REGPINMEDIUM 構造体は、ピンがサポートするメディアを識別する。
メディアの CLSID が GUID_NULL または KSMEDIUMSETID_Standard の場合には、ピンを接続しないこと。これらの CLSID は、ピンがメディアをサポートしていないことを示すデフォルト値である。
また、フィルタにそのピンが接続されたインスタンスが 1 つだけ必要な場合にのみ、ピンを接続すること。そうしないと、接続すべきではない各種のピンをアプリケーションが接続しようとし、その結果、プログラムが応答しなくなる危険性がある。必要なインスタンスの数を調べるには、次のサンプル コードのように KSPROPERTY_PIN_NECESSARYINSTANCES プロパティ セットを取得する。 (簡潔にするため、この例では戻りコードをテストせず、インターフェイスを解放しない。もちろん、実際のアプリケーションではどちらも行う必要がある。)
// ピン ファクトリ識別子を取得する。
IKsPinFactory *pPinFactory;
hr = pPin->QueryInterface(IID_IKsPinFactory, (void **)&pPinFactory);
ULONG ulFactoryId;
hr = pPinFactory->KsPinFactory(&ulFactoryId);
// フィルタから "インスタンス" プロパティを取得する。
IKsControl *pKsControl;
hr = pFilter->QueryInterface(IID_IKsControl, (void **)&pKsControl);
KSP_PIN ksPin;
ksPin.Property.Set = KSPROPSETID_Pin;
ksPin.Property.Id = KSPROPERTY_PIN_NECESSARYINSTANCES;
ksPin.Property.Flags = KSPROPERTY_TYPE_GET;
ksPin.PinId = ulFactoryId;
ksPin.Reserved = 0;
KSPROPERTY ksProp;
ULONG ulInstances, bytes;
pKsControl->KsProperty((PKSPROPERTY)&ksPin, sizeof(ksPin),
&ulInstances, sizeof(ULONG), &bytes);
if (hr == S_OK && bytes == sizeof(ULONG))
{
if (ulInstances == 1)
{
// フィルタはこのピンの 1 つのインスタンスを必要とする。
// このピンは適正である。
}
}
次の擬似コードは、WDM フィルタを検索および接続する方法について、非常に簡単な概要のみを示したものである。このコードでは、細かい処理をすべて省略し、アプリケーションで実行すべき一般的な手順だけを示す。
Add supporting filters:
{
foreach input pin:
skip if (pin is connected)
Get pin medium
skip if (medium is GUID_NULL or KSMEDIUMSETID_Standard)
Query filter for KSPROPERTY_PIN_NECESSARYINSTANCES property
skip if (necessary instances != 1)
Match an existing pin || Find a matching filter
}
Match an existing pin:
{
foreach filter in the graph
foreach unconnected pin
Get pin medium
if (mediums match)
connect the pins
}
Find a matching filter:
{
Query the filter graph manager for IFilterMapper2.
Find a filter with an output pin that matches the medium.
Add the filter to the graph.
Connect the pins.
Add supporting filters. (Recursive call.)
}