Compartir a través de


Filtros de controlador de clase WDM

[La característica asociada a esta página, DirectShow, es una característica heredada. Se ha reemplazado por MediaPlayer, IMFMediaEngine y Captura de audio/vídeo en Media Foundation. Esas características se han optimizado para Windows 10 y Windows 11. Microsoft recomienda encarecidamente que el nuevo código use MediaPlayer, IMFMediaEngine y Audio/Video Capture en Media Foundation en lugar de DirectShow, siempre que sea posible. Microsoft sugiere que el código existente que usa las API heredadas se reescriba para usar las nuevas API si es posible.

Si un dispositivo de captura usa un controlador del modelo de controlador de Windows (WDM), es posible que el grafo requiera determinados filtros ascendentes del filtro de captura. Estos filtros se denominan filtros de controlador de clase de flujo o filtros WDM. Admiten funcionalidad adicional proporcionada por el hardware. Por ejemplo, una tarjeta de sintonizador de TV tiene funciones para establecer el canal. El filtro correspondiente es el filtro de tuner de TV , que expone la interfaz IAMTVTuner . Para que esta funcionalidad esté disponible para la aplicación, debe conectar el filtro De tuner de TV al filtro de captura.

La interfaz ICaptureGraphBuilder2 proporciona la manera más fácil de agregar filtros WDM al grafo. En algún momento al compilar el grafo, llame a FindInterface o RenderStream. Cualquiera de estos métodos localizará automáticamente los filtros WDM necesarios y los conectará al filtro de captura. En el resto de esta sección se describe cómo agregar filtros WDM manualmente. Sin embargo, tenga en cuenta que el enfoque recomendado es simplemente llamar a uno de estos métodos ICaptureGraphBuilder2 .

Las patillas de un filtro WDM admiten uno o varios medios. Un medio define un método de comunicación, como un bus. Debe conectar patillas que admitan el mismo medio. La estructura REGPINMEDIUM , que es equivalente a la estructura de KSPIN_MEDIUM utilizada para los controladores de streaming de kernel, define un medio en DirectShow. El miembro clsMedium de la estructura REGPINMEDIUM especifica el identificador de clase (CLSID) para el medio. Para recuperar el medio de un pin, llame al método IKsPin::KsQueryMediums . Este método devuelve un puntero a un bloque de memoria que contiene una estructura de KSMULTIPLE_ITEM , seguida de cero o más estructuras REGPINMEDIUM . Cada estructura REGPINMEDIUM identifica un medio que admite el pin.

No conecte un pin si el medio tiene un CLSID de GUID_NULL o KSMEDIUMSETID_Standard. Estos son valores predeterminados que indican que el pin no admite medios.

Además, no conecte un pin a menos que el filtro requiera exactamente una instancia conectada de ese pin. De lo contrario, la aplicación podría intentar conectar varios patillas que no deben tener conexiones, lo que puede hacer que el programa deje de responder. Para averiguar el número de instancias necesarias, recupere el conjunto de propiedades KSPROPERTY_PIN_NECESSARYINSTANCES, como se muestra en el ejemplo de código siguiente. (Por motivos de brevedad, este ejemplo no prueba ningún código de retorno ni libera ninguna interfaz. La aplicación debe hacer ambas cosas, por supuesto).

// 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.
    } 
}

El siguiente pseudocódigo es un breve esquema que muestra cómo buscar y conectar los filtros WDM. Omite muchos detalles y solo está pensado para mostrar los pasos generales que tendría que realizar la aplicación.

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.)
}

Temas de captura avanzada