Filtros de driver de classe WDM
[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda fortemente que o novo código use MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation em vez de DirectShow, quando possível. A Microsoft sugere que o código existente que usa as APIs herdadas seja reescrito para usar as novas APIs, se possível.]
Se um dispositivo de captura usar um driver WDM (Modelo de Driver do Windows), o grafo poderá exigir determinados filtros upstream do filtro de captura. Esses filtros são chamados de filtros de driver de classe de fluxo ou filtros WDM. Eles dão suporte a funcionalidades adicionais fornecidas pelo hardware. Por exemplo, um sintonizador de TV cartão tem funções para definir o canal. O filtro correspondente é o filtro sintonizador de TV , que expõe a interface IAMTVTuner . Para disponibilizar essa funcionalidade para o aplicativo, você deve conectar o filtro sintonizador de TV ao filtro de captura.
A interface ICaptureGraphBuilder2 fornece a maneira mais fácil de adicionar filtros WDM ao grafo. Em algum momento durante a criação do grafo, chame FindInterface ou RenderStream. Qualquer um desses métodos localizará automaticamente os filtros WDM necessários e os conectará ao filtro de captura. O restante desta seção descreve como adicionar filtros WDM manualmente. No entanto, lembre-se de que a abordagem recomendada é simplesmente chamar um desses métodos ICaptureGraphBuilder2 .
Os pinos em um filtro WDM dão suporte a um ou mais meios. Um meio define um método de comunicação, como um ônibus. Você deve conectar pinos que dão suporte ao mesmo meio. A estrutura REGPINMEDIUM , que é equivalente à estrutura KSPIN_MEDIUM usada para drivers de streaming de kernel, define um meio no DirectShow. O membro clsMedium da estrutura REGPINMEDIUM especifica o CLSID (identificador de classe) para o meio. Para recuperar o meio de um pino, chame o método IKsPin::KsQueryMediums . Esse método retorna um ponteiro para um bloco de memória que contém uma estrutura KSMULTIPLE_ITEM , seguido por zero ou mais estruturas REGPINMEDIUM . Cada estrutura REGPINMEDIUM identifica um meio compatível com o pino.
Não conecte um pino se o meio tiver um CLSID de GUID_NULL ou KSMEDIUMSETID_Standard. Esses são valores padrão que indicam que o pino não dá suporte a meios.
Além disso, não conecte um pino, a menos que o filtro exija exatamente uma instância conectada desse pino. Caso contrário, seu aplicativo pode tentar conectar vários pinos que não devem ter conexões, o que pode fazer com que o programa pare de responder. Para descobrir o número de instâncias necessárias, recupere o conjunto de propriedades KSPROPERTY_PIN_NECESSARYINSTANCES, conforme mostrado no exemplo de código a seguir. (Para fins de brevidade, este exemplo não testa nenhum código de retorno ou libera nenhuma interface. Seu aplicativo deve fazer as duas coisas, é claro.)
// 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.
}
}
O pseudocódigo a seguir é uma estrutura de tópicos extremamente breve mostrando como localizar e conectar os filtros do WDM. Ele omite muitos detalhes e destina-se apenas a mostrar as etapas gerais que seu aplicativo precisaria executar.
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.)
}
Tópicos relacionados