Sélection d’un décodeur dans DirectShow Editing Services

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

[Cette API n’est pas prise en charge et peut être modifiée ou indisponible à l’avenir.]

Lorsque DirectShow Editing Services (DES) affiche un projet de montage vidéo, le moteur de rendu sélectionne automatiquement les décodeurs nécessaires. Cela peut se produire à l’intérieur de la méthode IRenderEngine::ConnectFrontEnd , ou bien dynamiquement pendant le rendu.

Un utilisateur peut installer plusieurs décodeurs capables de décoder un fichier particulier. Lorsque plusieurs décodeurs sont disponibles, DES utilise l’algorithme Intelligent Connect pour sélectionner le décodeur.

Il n’existe aucun moyen pour l’application de spécifier directement le décodeur à utiliser. Toutefois, vous pouvez choisir le décodeur indirectement via l’interface de rappel IAMGraphBuilderCallback . En implémentant cette interface dans votre application, vous pouvez recevoir des notifications pendant le processus de création de graphiques et rejeter certains filtres du graphe.

Commencez par implémenter une classe qui expose l’interface IAMGraphBuilderCallback :

class GraphBuilderCB : public IAMGraphBuilderCallback
{
public:
     // Method declarations (not shown).
};

Ensuite, créez une instance du Gestionnaire de graphes de filtre et inscrivez votre classe pour recevoir des notifications de rappel :

// Declare an instance of the callback object.
GraphBuilderCB GraphCB; 

// Create the Filter Graph Manager.
CComPtr<IGraphBuilder> pGraph;
hr = pGraph.CoCreateInstance(CLSID_FilterGraph);
if (FAILED(hr))
{
    // Handle error (not shown).
}
// Register to receive the callbacks.
CComQIPtr<IObjectWithSite> pSite(pGraph);
if (pSite)
{
    hr = pSite->SetSite((IUnknown*)&GraphCB);
}

Ensuite, créez le moteur de rendu et appelez la méthode IRenderEngine::SetFilterGraph avec un pointeur vers le Gestionnaire de graphes de filtre. Cela garantit que le moteur de rendu ne crée pas son propre gestionnaire de graphes de filtre, mais utilise plutôt le instance que vous avez configuré pour les rappels.

CComPtr<IRenderEngine> pRender;
hr = pRender.CoCreateInstance(CLSID_RenderEngine);
if (FAILED(hr))
{
    // Handle error (not shown).
}

hr = pRender->SetFilterGraph(pGraph);

Lorsque le projet est rendu, la méthode IAMGraphBuilderCallback::SelectedFilter de l’application est appelée immédiatement avant que le Gestionnaire de graphes de filtre crée un nouveau filtre. La méthode SelectedFilter reçoit un pointeur vers une interface IMoniker qui représente un moniker pour le filtre. Examinez le moniker et, si vous décidez de rejeter le filtre, retournez un code d’échec à partir de la méthode SelectedFilter .

La partie difficile consiste à identifier quels monikers représentent des décodeurs, et en particulier quels monikers représentent des décodeurs que vous souhaitez rejeter. Une solution est la suivante :

  • Avant de rendre le projet, utilisez la méthode IFilterMapper2::EnumMatchingFilters pour créer une liste de filtres inscrits comme acceptant le type d’entrée souhaité. Pour les types de compression vidéo ou audio, cette liste doit être mappée à un ensemble de décodeurs.

  • La méthode EnumMatchingFilters retourne une collection de monikers. Pour chaque moniker de la collection, obtenez la propriété DisplayName , comme décrit dans Utilisation du mappeur de filtre.

  • Stockez la liste des noms d’affichage, mais omettez le nom d’affichage correspondant au filtre que vous souhaitez utiliser pour le décodage. Les noms d’affichage des filtres logiciels ont la forme suivante :

    OLESTR("@device:sw:{CategoryGUID}\{FilterCLSID}");
    

    where

    CategoryGUID
    

    est le GUID de la catégorie de filtre, et

    FilterCLSID
    

    est le CLSID du filtre. Pour les DMO, le format est le même, mais remplacez par swdmo.

    La liste contient désormais des noms d’affichage pour chaque filtre qui génère le type de média souhaité, mais qui n’est pas votre filtre préféré.

  • Dans la méthode SelectedFilter, récupérez la propriété DisplayName sur le moniker proposé et case activée-le par rapport à la liste stockée. Si le nom d’affichage correspond à une entrée de la liste, rejetez ce filtre. Sinon, acceptez-le en retournant S_OK.

Rendu d’un projet