Поделиться через


Фильтры драйвера класса WDM

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать в новом коде MediaPlayer, IMFMediaEngine и аудио/видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, в котором используются устаревшие API, чтобы по возможности использовать новые API.]

Если устройство захвата использует драйвер модели драйвера Windows (WDM), графу могут потребоваться определенные фильтры, вышестоящий из фильтра захвата. Эти фильтры называются фильтрами драйвера потокового класса или фильтрами WDM. Они поддерживают дополнительные функциональные возможности, предоставляемые оборудованием. Например, тв-тюнер карта имеет функции для настройки канала. Соответствующий фильтр — это фильтр ТВ-тюнера , который предоставляет интерфейс IAMTVTuner . Чтобы сделать эту функцию доступной для приложения, необходимо подключить фильтр ТВ-тюнера к фильтру захвата.

Интерфейс ICaptureGraphBuilder2 предоставляет самый простой способ добавления фильтров WDM в граф. В какой-то момент при построении графа вызовите Метод FindInterface или RenderStream. Любой из этих методов автоматически найдет необходимые фильтры WDM и подключит их к фильтру записи. В оставшейся части этого раздела описывается добавление фильтров WDM вручную. Однако имейте в виду, что рекомендуемый подход — просто вызвать один из этих методов ICaptureGraphBuilder2 .

Контакты на фильтре WDM поддерживают один или несколько носителей. Среда определяет метод связи, например шину. Необходимо подключить контакты, поддерживающие один и тот же носитель. Структура REGPINMEDIUM , эквивалентная структуре KSPIN_MEDIUM , используемой для драйверов потоковой передачи ядра, определяет среду в DirectShow. Элемент clsMedium структуры REGPINMEDIUM указывает идентификатор класса (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.)
}

Расширенные разделы по сбору данных