Partager via


Comment lire un fichier

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

Cet article est destiné à vous donner la saveur de la programmation DirectShow. Il présente une application console simple qui lit un fichier audio ou vidéo. Le programme ne dure que quelques lignes, mais il montre une partie de la puissance de la programmation DirectShow.

Comme décrit dans l’article Présentation de la programmation d’applications DirectShow , une application DirectShow effectue toujours les mêmes étapes de base :

  1. Créez une instance du Gestionnaire de graphe de filtres.
  2. Utilisez le Gestionnaire de graphe de filtres pour générer un graphique de filtre.
  3. Exécutez le graphique, ce qui entraîne le déplacement des données dans les filtres.

Pour compiler et lier le code de cette rubrique, incluez le fichier d’en-tête Dshow.h et créez un lien vers le fichier de bibliothèque statique strmiids.lib. Pour plus d’informations, consultez Génération d’applications DirectShow.

Commencez par appeler CoInitialize ou CoInitializeEx pour initialiser la bibliothèque COM :

HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
    // Add error-handling code here. (Omitted for clarity.)
}

Pour simplifier les choses, cet exemple ignore la valeur de retour, mais vous devez toujours case activée la valeur HRESULT de n’importe quel appel de méthode.

Ensuite, appelez CoCreateInstance pour créer le Gestionnaire de graphe de filtres :

IGraphBuilder *pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, 
    CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);

Comme indiqué, l’identificateur de classe (CLSID) est CLSID_FilterGraph. Le Gestionnaire de graphe de filtres est fourni par une DLL in-process, de sorte que le contexte d’exécution est CLSCTX_INPROC_SERVER. DirectShow prend en charge le modèle de thread libre. Vous pouvez donc également appeler CoInitializeEx avec l’indicateur COINIT_MULTITHREADED .

L’appel à CoCreateInstance retourne l’interface IGraphBuilder , qui contient principalement des méthodes pour générer le graphe de filtres. Deux autres interfaces sont nécessaires pour cet exemple :

  • IMediaControl contrôle la diffusion en continu. Il contient des méthodes permettant d’arrêter et de démarrer le graphique.
  • IMediaEvent propose des méthodes permettant d’obtenir des événements à partir du Gestionnaire de graphe de filtres. Dans cet exemple, l’interface est utilisée pour attendre la fin de la lecture.

Ces deux interfaces sont exposées par le Gestionnaire de graphe de filtres. Utilisez le pointeur IGraphBuilder retourné pour les interroger :

IMediaControl *pControl;
IMediaEvent   *pEvent;
hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

Vous pouvez maintenant générer le graphique de filtre. Pour la lecture de fichiers, cela est effectué par un seul appel de méthode :

hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);

La méthode IGraphBuilder::RenderFile génère un graphique de filtre qui peut lire le fichier spécifié. Le premier paramètre est le nom de fichier, représenté sous la forme d’une chaîne de caractères larges (2 octets). Le deuxième paramètre est réservé et doit être égal à NULL.

Cette méthode peut échouer si le fichier spécifié n’existe pas ou si le format de fichier n’est pas reconnu. En supposant que la méthode réussit, toutefois, le graphique de filtre est maintenant prêt pour la lecture. Pour exécuter le graphique, appelez la méthode IMediaControl::Run :

hr = pControl->Run();

Lorsque le graphe de filtres s’exécute, les données se déplacent dans les filtres et sont rendues sous forme de vidéo et d’audio. La lecture se produit sur un thread distinct. Vous pouvez attendre la fin de la lecture en appelant la méthode IMediaEvent::WaitForCompletion :

long evCode = 0;
pEvent->WaitForCompletion(INFINITE, &evCode);

Cette méthode se bloque jusqu’à ce que la lecture du fichier soit terminée, ou jusqu’à ce que l’intervalle de délai d’attente spécifié s’écoule. La valeur INFINITE signifie que l’application se bloque indéfiniment jusqu’à ce que la lecture du fichier soit terminée. Pour obtenir un exemple plus réaliste de gestion des événements, consultez Réponse aux événements.

Lorsque l’application est terminée, relâchez les pointeurs d’interface et fermez la bibliothèque COM :

pControl->Release();
pEvent->Release();
pGraph->Release();
CoUninitialize();

Exemple de code

Voici le code complet de l’exemple décrit dans cet article :

#include <dshow.h>
void main(void)
{
    IGraphBuilder *pGraph = NULL;
    IMediaControl *pControl = NULL;
    IMediaEvent   *pEvent = NULL;

    // Initialize the COM library.
    HRESULT hr = CoInitialize(NULL);
    if (FAILED(hr))
    {
        printf("ERROR - Could not initialize COM library");
        return;
    }

    // Create the filter graph manager and query for interfaces.
    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
                        IID_IGraphBuilder, (void **)&pGraph);
    if (FAILED(hr))
    {
        printf("ERROR - Could not create the Filter Graph Manager.");
        return;
    }

    hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);

    // Build the graph. IMPORTANT: Change this string to a file on your system.
    hr = pGraph->RenderFile(L"C:\\Example.avi", NULL);
    if (SUCCEEDED(hr))
    {
        // Run the graph.
        hr = pControl->Run();
        if (SUCCEEDED(hr))
        {
            // Wait for completion.
            long evCode;
            pEvent->WaitForCompletion(INFINITE, &evCode);

            // Note: Do not use INFINITE in a real application, because it
            // can block indefinitely.
        }
    }
    pControl->Release();
    pEvent->Release();
    pGraph->Release();
    CoUninitialize();
}

Tâches DirectShow de base