Criando filtros de Kernel-Mode

[O recurso associado a esta página, DirectShow, é um recurso herdado. Ele foi substituído por MediaPlayer, IMFMediaEngine e Captura de Áudio/Vídeo na 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 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.]

Determinados filtros de modo kernel não podem ser criados por meio de CoCreateInstance e, portanto, não têm CLSIDs. Esses filtros incluem o Conversor tee/coletor para coletor, o filtro de decodificador CC e o filtro do Codec do WST . Para criar um desses filtros, use o objeto Enumerador de Dispositivo do Sistema e pesquise pelo nome do filtro.

  1. Crie o Enumerador de Dispositivo do Sistema.
  2. Chame o método ICreateDevEnum::CreateClassEnumerator com o CLSID da categoria de filtro para esse filtro. Esse método cria um enumerador para a categoria de filtro. (Um enumerador é simplesmente um objeto que retorna uma lista de outros objetos, usando uma interface COM definida.) O enumerador retorna ponteiros IMoniker , que representam os filtros nessa categoria.
  3. Para cada moniker, chame IMoniker::BindToStorage para obter uma interface IPropertyBag .
  4. Chame IPropertyBag::Read para obter o nome do filtro.
  5. Se o nome corresponder, chame IMoniker::BindToObject para criar o filtro.

O código a seguir mostra uma função que executa estas etapas:

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

O exemplo de código a seguir usa essa função para criar o filtro de Decodificador CC e adicioná-lo ao grafo de filtro:

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

Tópicos avançados de captura

Usando o Enumerador de Dispositivo do Sistema