Фильтры драйверов классов WDM
[Функция, связанная с этой страницей, DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngineи аудио и видеозахват в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать новый код MediaPlayer, IMFMediaEngine и аудио-видеозахват в Media Foundation вместо DirectShowпо возможности. Корпорация Майкрософт предлагает, что существующий код, использующий устаревшие API, будет перезаписан для использования новых API, если это возможно.]
Если устройство записи использует драйвер модели драйвера Windows (WDM), граф может потребовать определенных фильтров вышестоящего фильтра из фильтра захвата. Эти фильтры называются фильтрами драйверов потокового класса или фильтрами WDM. Они поддерживают дополнительные функциональные возможности, предоставляемые оборудованием. Например, карточка тв-мелодии имеет функции для настройки канала. Соответствующий фильтр — это фильтр tv Tuner, который предоставляет интерфейс IAMTVTuner. Чтобы сделать эту функцию доступной для приложения, необходимо подключить фильтр tv Tuner к фильтру записи.
Интерфейс 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.)
}