Partager via


Création de graphiques avec le Générateur de graphiques de capture

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

Malgré son nom, le Générateur de graphiques de capture est utile pour créer de nombreux types de graphiques de filtres personnalisés, et pas seulement pour capturer des graphiques. Cet article fournit une brève vue d’ensemble de l’utilisation de cet objet.

Capture Graph Builder expose l’interface ICaptureGraphBuilder2 . Commencez par appeler CoCreateInstance pour créer le Générateur de graphiques de capture et le Gestionnaire de graphe de filtres. Initialisez ensuite le Générateur de graphes de capture en appelant ICaptureGraphBuilder2::SetFiltergraph avec un pointeur vers le Gestionnaire de graphe de filtre, comme suit :

IGraphBuilder *pGraph = NULL;
ICaptureGraphBuilder2 *pBuilder = NULL;

// Create the Filter Graph Manager.
HRESULT hr =  CoCreateInstance(CLSID_FilterGraph, NULL,
    CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

if (SUCCEEDED(hr))
{
    // Create the Capture Graph Builder.
    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
        CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, 
        (void **)&pBuilder);
    if (SUCCEEDED(hr))
    {
        pBuilder->SetFiltergraph(pGraph);
    }
};

Connexion de filtres

La méthode ICaptureGraphBuilder2::RenderStream connecte deux ou trois filtres dans une chaîne. En règle générale, la méthode fonctionne mieux lorsque chaque filtre n’a pas plus d’une broche d’entrée ou d’une broche de sortie du même type. Cette discussion commence par ignorer les deux premiers paramètres de RenderStream et se concentrer sur les trois derniers paramètres. Le troisième paramètre est un pointeur IUnknown , qui peut spécifier un filtre (en tant que pointeur d’interface IBaseFilter ) ou une broche de sortie (en tant que pointeur d’interface IPin ). Les quatrième et cinquième paramètres spécifient des pointeurs IBaseFilter . La méthode RenderStream connecte les trois filtres d’une chaîne. Par exemple, supposons que A, B et C soient des filtres. Supposons pour l’instant que chaque filtre possède exactement une broche d’entrée et une broche de sortie. L’appel suivant connecte A à B, puis B à C :

'RenderStream(NULL, NULL, A, B, C)'

Toutes les connexions sont « intelligentes », ce qui signifie que des filtres supplémentaires sont ajoutés au graphique en fonction des besoins. Pour plus d’informations, consultez Intelligent Connect. Pour connecter seulement deux filtres, définissez la valeur du milieu sur NULL. Par exemple, cet appel connecte A à C :

'RenderStream(NULL, NULL, A, NULL, C)'

Vous pouvez créer des chaînes plus longues en appelant la méthode deux fois :

'RenderStream(NULL, NULL, A, B, C)' 'RenderStream(NULL, NULL, C, D, E)'

Si le dernier paramètre est NULL, la méthode localise automatiquement un convertisseur par défaut. Il utilise le convertisseur vidéo pour la vidéo et le convertisseur DirectSound pour l’audio. Ainsi:

'RenderStream(NULL, NULL, A, NULL, NULL)'

équivaut à :

'RenderStream(NULL, NULL, A, NULL, R)'

R est le convertisseur approprié. Toutefois, pour connecter le filtre convertisseur de mixage vidéo au lieu du convertisseur vidéo, vous devez le spécifier explicitement.

Si vous spécifiez un filtre dans le troisième paramètre, plutôt qu’une broche, vous devrez peut-être indiquer quelle broche de sortie doit être utilisée pour la connexion. C’est l’objectif des deux premiers paramètres de la méthode. Le premier paramètre s’applique uniquement aux filtres de capture. Il spécifie un GUID qui indique une catégorie d’épingle. Pour obtenir la liste complète des catégories, consultez Pin Property Set. Deux des catégories sont valides pour tous les filtres de capture :

  • PIN_CATEGORY_CAPTURE
  • PIN_CATEGORY_PREVIEW

Si un filtre de capture ne fournit pas de broches distinctes pour la capture et l’aperçu, la méthode RenderStream insère un filtre Smart Tee , qui fractionne le flux en un flux de capture et un flux d’aperçu. Du point de vue de l’application, vous pouvez simplement traiter tous les filtres de capture comme ayant des broches distinctes et ignorer la topologie sous-jacente du graphe.

Pour la capture de fichiers, connectez la broche de capture à un filtre mux. Pour la préversion en direct, connectez l’épingle d’aperçu à un convertisseur. Si vous changez les deux catégories, le graphique peut supprimer un nombre excessif d’images pendant la capture de fichier ; mais si le graphique est connecté correctement, il supprime les images d’aperçu en fonction des besoins afin de maintenir le débit sur le flux de capture.

L’exemple suivant montre comment connecter les deux flux :

// Capture to file:
pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, NULL, pCapFilter, NULL, pMux);
// Preview:
pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, NULL, pCapFilter, NULL, NULL);

Certains filtres de capture prennent également en charge les sous-titres, indiqués par PIN_CATEGORY_VBI. Pour capturer les sous-titres dans un fichier, restituez cette catégorie au filtre mux. Pour afficher les sous-titres dans votre fenêtre d’aperçu, connectez-vous au convertisseur :

// Capture to file:
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter, NULL, pMux);
// Preview on screen:
pBuilder->RenderStream(&PIN_CATEGORY_VBI, NULL, pCapFilter, NULL, NULL);

Le deuxième paramètre de RenderStream identifie le type de média et est généralement l’un des éléments suivants :

  • MEDIATYPE_Audio
  • MEDIATYPE_Video
  • MEDIATYPE_Interleaved (DV)

Vous pouvez utiliser ce paramètre chaque fois que les broches de sortie du filtre prennent en charge l’énumération des types de médias préférés. Pour les sources de fichiers, le Générateur de graphiques de capture ajoute automatiquement un filtre d’analyseur si nécessaire, puis interroge les types de média sur l’analyseur. (Pour obtenir un exemple, consultez Recompression d’un fichier AVI.) En outre, si le dernier filtre de la chaîne comporte plusieurs broches d’entrée, la méthode tente d’énumérer leurs types de supports. Toutefois, tous les filtres ne prennent pas en charge cette fonctionnalité.

Recherche d’interfaces sur les filtres et les épingles

Une fois que vous avez créé un graphique, vous devez généralement localiser les différentes interfaces exposées par des filtres et des broches dans le graphique. Par exemple, un filtre de capture peut exposer l’interface IAMDroppedFrames , tandis que les broches de sortie du filtre peuvent exposer l’interface IAMStreamConfig .

Le moyen le plus simple de trouver une interface consiste à utiliser la méthode ICaptureGraphBuilder2::FindInterface . Cette méthode guide le graphique (filtres et épingles) jusqu’à ce qu’il localise l’interface souhaitée. Vous pouvez spécifier le point de départ de la recherche et limiter la recherche aux filtres amont ou en aval du point de départ.

L’exemple suivant recherche l’interface IAMStreamConfig sur une broche d’aperçu vidéo :

IAMStreamConfig *pConfig = NULL;
HRESULT hr = pBuild->FindInterface(
    &PIN_CATEGORY_PREVIEW, 
    &MEDIATYPE_Video,
    pVCap, 
    IID_IAMStreamConfig, 
    (void**)&pConfig
);
if (SUCCESSFUL(hr))
{
    /* ... */
    pConfig->Release();
}

Notes

La rubrique Rechercher une interface sur un filtre ou une épingle montre une autre approche qui utilise l’interface IGraphBuilder au lieu de ICaptureGraphBuilder2. L’approche à utiliser dépend de votre application. Si votre application utilise déjà ICaptureGraphBuilder2 pour générer le graphique, ICaptureGraphBuilder2::FindInterface est une bonne approche. Sinon, envisagez d’utiliser les méthodes IGraphBuilder .

 

Recherche d’épingles

Plus rarement, vous devrez peut-être localiser une épingle individuelle sur un filtre, bien que dans la plupart des cas, les méthodes RenderStream et FindInterface vous évitent les problèmes. Si vous avez besoin de trouver une épingle particulière sur un filtre, la méthode d’assistance ICaptureGraphBuilder2::FindPin est utile. Spécifiez la catégorie, le type de média (vidéo ou audio), la direction et si l’épingle ne doit pas être connectée.

Par exemple, le code suivant recherche une épingle d’aperçu vidéo non connectée sur un filtre de capture :

IPin *pPin = NULL;
hr = pBuild->FindPin(
    pCap,                   // Pointer to the filter to search.
    PINDIR_OUTPUT,          // Search for an output pin.
    &PIN_CATEGORY_PREVIEW,  // Search for a preview pin.
    &MEDIATYPE_Video,       // Search for a video pin.
    TRUE,                   // The pin must be unconnected. 
    0,                      // Return the first matching pin (index 0).
    &pPin);                 // This variable receives the IPin pointer.
if (SUCCESSFUL(hr))
{
    /* ... */
    pPin->Release();
}

Capture vidéo