WDM 类驱动程序筛选器

[与此页面关联的功能(DirectShow)是一项旧功能。 它已被 MediaPlayerIMFMediaEngine取代,并在媒体基金会 音频/视频捕获。 这些功能已针对 Windows 10 和 Windows 11 进行了优化。 Microsoft强烈建议新代码尽可能使用 MediaPlayerIMFMediaEngineMedia Foundation 中的音频/视频捕获,而不是 DirectShow。 Microsoft建议重写使用旧 API 的现有代码,以尽可能使用新 API。]

如果捕获设备使用 Windows 驱动程序模型(WDM)驱动程序,则图形可能需要捕获筛选器上游的某些筛选器。 这些筛选器称为流类驱动程序筛选器或 WDM 筛选器。 它们支持硬件提供的其他功能。 例如,电视优化器卡具有用于设置频道的功能。 相应的筛选器是 TV Tuner 筛选器,该筛选器公开 IAMTVTuner 接口。 若要使此功能可供应用程序使用,必须将 TV Tuner 筛选器连接到捕获筛选器。

ICaptureGraphBuilder2 接口提供了将 WDM 筛选器添加到图形的最简单方法。 在生成图形时,调用 FindInterfaceRenderStream。 其中任一方法将自动找到所需的 WDM 筛选器,并将其连接到捕获筛选器。 本部分的其余部分介绍如何手动添加 WDM 筛选器。 但是,请注意,建议的方法只是调用其中一个 ICaptureGraphBuilder2 方法。

WDM 筛选器上的引脚支持一个或多个介质。 媒体定义通信方法,例如总线。 必须连接支持相同介质的引脚。 REGPINMEDIUM 结构(相当于用于内核流式处理驱动程序的 KSPIN_MEDIUM 结构)在 DirectShow 中定义介质。 clsMediumREGPINMEDIUM 结构的成员指定介质的类标识符(CLSID)。 若要检索引脚的介质,请调用 IKsPin::KsQueryMediums 方法。 此方法返回指向包含 KSMULTIPLE_ITEM 结构的内存块的指针,后跟零个或多个 REGPINMEDIUM 结构。 每个 REGPINMEDIUM 结构标识引脚支持的介质。

如果介质的 CLSID 为 GUID_NULL 或KSMEDIUMSETID_Standard,请不要连接引脚。 这些是默认值,指示引脚不支持介质。

此外,请勿连接引脚,除非筛选器需要该引脚的一个连接实例。 否则,应用程序可能会尝试连接不应具有连接的各种引脚,这可能导致程序停止响应。 若要了解所需的实例数,请检索KSPROPERTY_PIN_NECESSARYINSTANCES属性集,如以下代码示例所示。 (为简洁起见,此示例不测试任何返回代码或释放任何接口。当然,应用程序应同时执行这两项作。

// Obtain the pin factory identifier.
IKsPinFactory *pPinFactory;
hr = pPin->QueryInterface(IID_IKsPinFactory, (void **)&pPinFactory);

ULONG ulFactoryId;
hr = pPinFactory->KsPinFactory(&ulFactoryId);

// Get the "instance" property from the filter.
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) 
    {
        // Filter requires one instance of this pin.
        // This pin is OK.
    } 
}

以下伪代码是一个极其简短的轮廓,演示如何查找和连接 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.)
}

高级捕获主题