WDM 类驱动程序筛选器

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

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

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

WDM 筛选器上的引脚支持一个或多个介质。 媒体定义通信方法,例如总线。 必须连接支持同一媒体的引脚。 REGPINMEDIUM 结构等效于用于内核流式处理驱动程序的 KSPIN_MEDIUM 结构,它定义了 DirectShow 中的媒体。 REGPINMEDIUM 结构的 clsMedium 成员指定介质的类标识符 (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.)
}

高级捕获主题