Creazione di filtri Kernel-Mode

[La funzionalità associata a questa pagina, DirectShow, è una funzionalità legacy. È stata sostituita da MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation. Queste funzionalità sono state ottimizzate per Windows 10 e Windows 11. Microsoft consiglia vivamente che il nuovo codice usi MediaPlayer, IMFMediaEngine e Audio/Video Capture in Media Foundation invece di DirectShow, quando possibile. Microsoft suggerisce che il codice esistente che usa le API legacy venga riscritto per usare le nuove API, se possibile.

Alcuni filtri in modalità kernel non possono essere creati tramite CoCreateInstance e pertanto non hanno CLSID. Questi filtri includono tee/sink-to-sink converter, il filtro CC Decoder e il filtro codec WST . Per creare uno di questi filtri, usare l'oggetto Enumeratore di dispositivi di sistema e cercare in base al nome del filtro.

  1. Creare l'enumeratore del dispositivo di sistema.
  2. Chiamare il metodo ICreateDevEnum::CreateClassEnumerator con il CLSID della categoria di filtro per tale filtro. Questo metodo crea un enumeratore per la categoria di filtri. Un enumeratore è semplicemente un oggetto che restituisce un elenco di altri oggetti, usando un'interfaccia COM definita. L'enumeratore restituisce puntatori IMoniker , che rappresentano i filtri in tale categoria.
  3. Per ogni moniker, chiama IMoniker::BindToStorage per ottenere un'interfaccia IPropertyBag .
  4. Chiamare IPropertyBag::Read per ottenere il nome del filtro.
  5. Se il nome corrisponde, chiamare IMoniker::BindToObject per creare il filtro.

Il codice seguente illustra una funzione che esegue questi passaggi:

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

L'esempio di codice seguente usa questa funzione per creare il filtro decodificatore CC e aggiungerlo al grafico del 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();
}

Argomenti relativi all'acquisizione avanzata

Uso dell'enumeratore del dispositivo di sistema