Compartir a través de


Creación de filtros de Kernel-Mode

[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.

Algunos filtros en modo kernel no se pueden crear a través de CoCreateInstance y, por tanto, no tienen CLSID. Estos filtros incluyen el convertidor tee/sink-to-sink, el filtro de descodificador CC y el filtro de códec WST . Para crear uno de estos filtros, use el objeto Enumerador de dispositivos del sistema y busque por el nombre del filtro.

  1. Cree el enumerador de dispositivos del sistema.
  2. Llame al método ICreateDevEnum::CreateClassEnumerator con el CLSID de la categoría de filtro para ese filtro. Este método crea un enumerador para la categoría de filtro. (Un enumerador es simplemente un objeto que devuelve una lista de otros objetos, mediante una interfaz COM definida). El enumerador devuelve punteros IMoniker , que representan los filtros de esa categoría.
  3. Para cada moniker, llame a IMoniker::BindToStorage para obtener una interfaz IPropertyBag .
  4. Llame a IPropertyBag::Read para obtener el nombre del filtro.
  5. Si el nombre coincide, llame a IMoniker::BindToObject para crear el filtro.

En el código siguiente se muestra una función que realiza estos pasos:

HRESULT CreateKernelFilter(
    const GUID &guidCategory,  // Filter category.
    LPCOLESTR szName,          // The name of the filter.
    IBaseFilter **ppFilter     // Receives a pointer to the filter.
)
{
    HRESULT hr;
    ICreateDevEnum *pDevEnum = NULL;
    IEnumMoniker *pEnum = NULL;
    if (!szName || !ppFilter) 
    {
        return E_POINTER;
    }

    // Create the system device enumerator.
    hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
        IID_ICreateDevEnum, (void**)&pDevEnum);
    if (FAILED(hr))
    {
        return hr;
    }

    // Create a class enumerator for the specified category.
    hr = pDevEnum->CreateClassEnumerator(guidCategory, &pEnum, 0);
    pDevEnum->Release();
    if (hr != S_OK) // S_FALSE means the category is empty.
    {
        return E_FAIL;
    }

    // Enumerate devices within this category.
    bool bFound = false;
    IMoniker *pMoniker;
    while (!bFound && (S_OK == pEnum->Next(1, &pMoniker, 0)))
    {
        IPropertyBag *pBag = NULL;
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
        if (FAILED(hr))
        {
            pMoniker->Release();
            continue; // Maybe the next one will work.
        }
        // Check the friendly name.
        VARIANT var;
        VariantInit(&var);
        hr = pBag->Read(L"FriendlyName", &var, NULL);
        if (SUCCEEDED(hr) && (lstrcmpiW(var.bstrVal, szName) == 0))
        {
            // This is the right filter.
            hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter,
                (void**)ppFilter);
            bFound = true;
        }
        VariantClear(&var);
        pBag->Release();
        pMoniker->Release();
    }
    pEnum->Release();
    return (bFound ? hr : E_FAIL);
}

En el ejemplo de código siguiente se usa esta función para crear el filtro de descodificador CC y agregarla al gráfico de filtros:

IBaseFilter *pCC = NULL;
hr = CreateKernelFilter(AM_KSCATEGORY_VBICODEC, 
    OLESTR("CC Decoder"), &pCC);
if (SUCCEEDED(hr))
{
    hr = pGraph->AddFilter(pCC, L"CC Decoder");
    pCC->Release();
}

Temas de captura avanzada

Uso del enumerador de dispositivos del sistema