次の方法で共有


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.)
}