Création de filtres Kernel-Mode

[La fonctionnalité associée à cette page, DirectShow, est une fonctionnalité héritée. Il a été remplacé par MediaPlayer, IMFMediaEngine et Audio/Video Capture in Media Foundation. Ces fonctionnalités ont été optimisées pour Windows 10 et Windows 11. Microsoft recommande vivement que le nouveau code utilise MediaPlayer, IMFMediaEngine et Audio/Video Capture dans Media Foundation au lieu de DirectShow, si possible. Microsoft suggère que le code existant qui utilise les API héritées soit réécrit pour utiliser les nouvelles API si possible.]

Certains filtres en mode noyau ne peuvent pas être créés via CoCreateInstance et n’ont donc pas de CLSID. Ces filtres incluent le convertisseur Tee/Sink-to-Sink, le filtre CC Decoder et le filtre WST Codec . Pour créer l’un de ces filtres, utilisez l’objet Énumérateur d’appareils système et recherchez le nom du filtre.

  1. Créez l’énumérateur de périphérique système.
  2. Appelez la méthode ICreateDevEnum::CreateClassEnumerator avec le CLSID de la catégorie de filtre pour ce filtre. Cette méthode crée un énumérateur pour la catégorie de filtre. (Un énumérateur est simplement un objet qui retourne une liste d’autres objets, à l’aide d’une interface COM définie.) L’énumérateur retourne des pointeurs IMoniker , qui représentent les filtres de cette catégorie.
  3. Pour chaque moniker, appelez IMoniker::BindToStorage pour obtenir une interface IPropertyBag .
  4. Appelez IPropertyBag::Read pour obtenir le nom du filtre.
  5. Si le nom correspond, appelez IMoniker::BindToObject pour créer le filtre.

Le code suivant montre une fonction qui effectue ces étapes :

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’exemple de code suivant utilise cette fonction pour créer le filtre CC Décodeur et l’ajouter au graphique de filtre :

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

Rubriques de capture avancée

Utilisation de l’énumérateur de périphérique système