Utilisation de l’énumérateur d’appareil système

[La fonctionnalité associée à cette page, DirectShow, est une fonctionnalité héritée. Il a été remplacé par MediaPlayer, IMFMediaEngine et Audio/Video Capture dans Media Foundation. Ces fonctionnalités ont été optimisées pour Windows 10 et Windows 11. Microsoft recommande vivement au nouveau code d’utiliser MediaPlayer, IMFMediaEngine et La capture audio/vidéo dans Media Foundation au lieu de DirectShow, lorsque cela est 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.]

L’énumérateur d’appareil système fournit un moyen uniforme d’énumérer, par catégorie, les filtres inscrits sur le système d’un utilisateur. En outre, il différencie les appareils matériels individuels, même si le même filtre les prend en charge. Cela est particulièrement utile pour les appareils qui utilisent le modèle de pilote Windows (WDM) et le filtre KSProxy. Par exemple, l’utilisateur peut avoir plusieurs appareils de capture vidéo WDM, tous pris en charge par le même filtre. L’énumérateur d’appareil système les traite comme des instances d’appareil distinctes.

L’énumérateur de périphérique système fonctionne en créant un énumérateur pour une catégorie spécifique, telle que la capture audio ou la compression vidéo. L’énumérateur de catégorie retourne un moniker unique pour chaque appareil de la catégorie. L’énumérateur de catégorie inclut automatiquement tous les appareils Plug-and-Play appropriés dans la catégorie. Pour obtenir la liste des catégories, consultez Filtrer les catégories.

Pour utiliser l’énumérateur de périphérique système, procédez comme suit :

  1. Créez l’énumérateur d’appareil système en appelant CoCreateInstance. L’identificateur de classe (CLSID) est CLSID_SystemDeviceEnum.
  2. Obtenez un énumérateur de catégorie en appelant ICreateDevEnum::CreateClassEnumerator avec le CLSID de la catégorie souhaitée. Cette méthode retourne un pointeur d’interface IEnumMoniker . Si la catégorie est vide (ou n’existe pas), la méthode retourne S_FALSE plutôt qu’un code d’erreur. Si c’est le cas, le pointeur IEnumMoniker retourné a la valeur NULL et sa déréférencement entraîne une exception. Par conséquent, testez explicitement S_OK lorsque vous appelez CreateClassEnumerator, au lieu d’appeler la macro SUCCEEDED habituelle.
  3. Utilisez la méthode IEnumMoniker::Next pour énumérer chaque moniker. Cette méthode retourne un pointeur d’interface IMoniker . Lorsque la méthode Next atteint la fin de l’énumération, elle retourne également S_FALSE, de sorte qu’à nouveau case activée pour S_OK.
  4. Pour récupérer le nom convivial de l’appareil (par exemple, à afficher dans l’interface utilisateur), appelez la méthode IMoniker::BindToStorage .
  5. Pour créer et initialiser le filtre DirectShow qui gère l’appareil, appelez IMoniker::BindToObject sur le moniker. Appelez IFilterGraph::AddFilter pour ajouter le filtre au graphique.

Le diagramme suivant illustre ce processus.

énumération d’appareils

L’exemple suivant montre comment énumérer les compresseurs vidéo installés sur le système de l’utilisateur. Par souci de concision, l’exemple effectue une vérification des erreurs minimale.

// Create the System Device Enumerator.
HRESULT hr;
ICreateDevEnum *pSysDevEnum = NULL;
hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
    IID_ICreateDevEnum, (void **)&pSysDevEnum);
if (FAILED(hr))
{
    return hr;
}

// Obtain a class enumerator for the video compressor category.
IEnumMoniker *pEnumCat = NULL;
hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &pEnumCat, 0);

if (hr == S_OK) 
{
    // Enumerate the monikers.
    IMoniker *pMoniker = NULL;
    ULONG cFetched;
    while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK)
    {
        IPropertyBag *pPropBag;
        hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, 
            (void **)&pPropBag);
        if (SUCCEEDED(hr))
        {
            // To retrieve the filter's friendly name, do the following:
            VARIANT varName;
            VariantInit(&varName);
            hr = pPropBag->Read(L"FriendlyName", &varName, 0);
            if (SUCCEEDED(hr))
            {
                // Display the name in your UI somehow.
            }
            VariantClear(&varName);

            // To create an instance of the filter, do the following:
            IBaseFilter *pFilter;
            hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,
                (void**)&pFilter);
            // Now add the filter to the graph. 
            //Remember to release pFilter later.
            pPropBag->Release();
        }
        pMoniker->Release();
    }
    pEnumCat->Release();
}
pSysDevEnum->Release();

Monikers d’appareil

Pour les monikers d’appareil, vous pouvez passer le moniker à la méthode IFilterGraph2::AddSourceFilterForMoniker pour créer un filtre de capture pour l’appareil. Pour obtenir un exemple de code, consultez la documentation relative à cette méthode.

La méthode IMoniker::GetDisplayName retourne le nom d’affichage du moniker. Bien que le nom d’affichage soit lisible, vous ne l’affichez généralement pas à un utilisateur final. Obtenez le nom convivial du conteneur de propriétés à la place, comme décrit précédemment.

La méthode IMoniker::P arseDisplayName ou la fonction MkParseDisplayName peuvent être utilisées pour créer un moniker d’appareil par défaut pour une catégorie de filtre donnée. Utilisez un nom d’affichage sous la forme @device:*:{category-clsid}, où category-clsid est la représentation sous forme de chaîne du GUID de catégorie. Le moniker par défaut est le premier moniker retourné par l’énumérateur d’appareil pour cette catégorie.