Partilhar via


Filtros de driver de classe WDM

[O recurso associado a esta página, DirectShow, é um recurso herdado. Foi substituído por MediaPlayer, IMFMediaEnginee Audio/Video Capture in Media Foundation. Esses recursos foram otimizados para Windows 10 e Windows 11. A Microsoft recomenda vivamente que o novo código utilize MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo no 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 usa um driver WDM (Windows Driver Model), o gráfico pode exigir determinados filtros a montante do filtro de captura. Esses filtros são chamados de filtros de driver de classe de fluxo ou filtros WDM. Eles suportam funcionalidades adicionais fornecidas pelo hardware. Por exemplo, uma placa sintonizadora de TV tem funções para definir o canal. O filtro correspondente é o filtro sintonizador de TV, que expõe a interfaceIAMTVTuner. Para disponibilizar essa funcionalidade para o aplicativo, você deve conectar o filtro do sintonizador de TV ao filtro de captura.

O interface de ICaptureGraphBuilder2 fornece a maneira mais fácil de adicionar filtros WDM ao gráfico. Em algum momento durante a criação do gráfico, 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, esteja ciente de que a abordagem recomendada é simplesmente chamar um desses ICaptureGraphBuilder2 métodos.

Os pinos em um filtro WDM suportam uma ou mais mídias. Um meio define um método de comunicação, como um barramento. Você deve conectar pinos que suportem a mesma mídia. O estrutura de REGPINMEDIUM, que é equivalente à estrutura KSPIN_MEDIUM usada para drivers de streaming do kernel, define um meio no DirectShow. O membro clsMedium da estrutura REGPINMEDIUM especifica o identificador de classe (CLSID) para a mídia. Para recuperar a mídia de um pino, chame o métodoIKsPin::KsQueryMediums. Esse método retorna um ponteiro para um bloco de memória que contém uma estrutura KSMULTIPLE_ITEM, seguida por zero ou mais estruturas REGPINMEDIUM. Cada estrutura de REGPINMEDIUM identifica um meio que o pino suporta.

Não conecte um pino se a mídia tiver um CLSID de GUID_NULL ou KSMEDIUMSETID_Standard. Estes são valores padrão que indicam que o pino não suporta mídias.

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. (Por uma questão de brevidade, este exemplo não testa nenhum código de retorno nem 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 é um esboço extremamente breve mostrando como localizar e conectar os filtros WDM. Ele omite muitos detalhes e destina-se apenas a mostrar as etapas gerais que seu aplicativo precisaria tomar.

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 de captura avançada