Partager via


Exemples et allocateurs

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

Lorsqu’une broche transmet des données multimédias à une autre broche, elle ne passe pas de pointeur direct vers la mémoire tampon. Au lieu de cela, il fournit un pointeur vers un objet COM qui gère la mémoire. Cet objet, appelé exemple multimédia, expose l’interface IMediaSample . L’épingle de réception accède à la mémoire tampon en appelant des méthodes IMediaSample , telles que IMediaSample::GetPointer, IMediaSample::GetSize et IMediaSample::GetActualDataLength.

Les échantillons circulent toujours en aval, de la broche de sortie à la broche d’entrée. Dans le modèle push, la broche de sortie fournit un exemple en appelant IMemInputPin::Receive sur la broche d’entrée. La broche d’entrée traite les données de manière synchrone (c’est-à-dire entièrement à l’intérieur de la méthode Receive ), ou les traite de manière asynchrone sur un thread de travail. La broche d’entrée est autorisée à se bloquer dans la méthode Receive , si elle doit attendre des ressources.

Un autre objet COM, appelé allocator, est responsable de la création et de la gestion des exemples multimédias. Les allocateurs exposent l’interface IMemAllocator . Chaque fois qu’un filtre a besoin d’un exemple multimédia avec une mémoire tampon vide, il appelle la méthode IMemAllocator::GetBuffer , qui retourne un pointeur vers l’exemple. Chaque connexion de broche partage un seul allocateur. Lorsque deux broches se connectent, ils décident du filtre qui fournira l’allocateur. Les broches définissent également des propriétés sur l’allocateur, telles que le nombre de mémoires tampons et la taille de chaque mémoire tampon. (Pour plus d’informations, consultez Comment les filtres se connectent et négocient les allocateurs.)

L’illustration suivante montre les relations entre l’répartiteur, les exemples multimédias et le filtre.

exemples multimédias et allocateurs

Nombre de références d’exemples multimédias

Un allocateur crée un pool fini d’exemples. À tout moment, certains exemples peuvent être utilisés, tandis que d’autres sont disponibles pour les appels GetBuffer . L’allocateur utilise le comptage des références pour effectuer le suivi des exemples. La méthode GetBuffer retourne un exemple avec un nombre de références de 1. Si le nombre de références est égal à zéro, l’exemple revient dans le pool de l’allocator, où il peut être utilisé dans l’appel GetBuffer suivant. Tant que le nombre de références reste supérieur à zéro, l’exemple n’est pas disponible pour GetBuffer. Si chaque exemple appartenant à l’allocateur est en cours d’utilisation, la méthode GetBuffer se bloque jusqu’à ce qu’un exemple soit disponible.

Par exemple, supposons qu’une broche d’entrée reçoit un exemple. S’il traite l’exemple de manière synchrone, à l’intérieur de la méthode Receive , il n’incrémente pas le nombre de références. Une fois réception retournée, la broche de sortie libère l’exemple, le nombre de références passe à zéro et l’exemple retourne au pool de l’allocator. En revanche, si la broche d’entrée traite l’exemple sur un thread worker, elle incrémente le nombre de références avant de quitter la méthode Receive . Le nombre de références est désormais de 2. Lorsque la broche de sortie libère l’exemple, le nombre passe à 1 ; l’exemple ne retourne pas encore au pool. Une fois le thread de travail terminé avec l’exemple, il appelle Release pour libérer l’exemple. L’exemple retourne maintenant au pool.

Lorsqu’un code pin reçoit un exemple, il peut copier les données dans un autre exemple, ou il peut modifier l’exemple d’origine et le remettre au filtre suivant. Potentiellement, un exemple peut parcourir toute la longueur du graphe, chaque filtre appelant à tour de rôle AddRef et Release . Par conséquent, la broche de sortie ne doit jamais réutiliser un exemple après avoir appelé Receive, car un filtre en aval peut utiliser l’exemple. La broche de sortie doit toujours appeler GetBuffer pour obtenir un nouvel exemple.

Ce mécanisme réduit la quantité d’allocation de mémoire, car les filtres utilisent à nouveau les mêmes mémoires tampons. Il empêche également les filtres d’écrire accidentellement des données qui n’ont pas été traitées, car l’allocateur gère une liste d’exemples disponibles.

Un filtre peut utiliser des répartiteurs distincts pour l’entrée et la sortie. Il peut le faire s’il développe les données d’entrée (par exemple, en les décompressant). Si la sortie n’est pas supérieure à l’entrée, un filtre peut traiter les données en place, sans les copier dans un nouvel exemple. Dans ce cas, deux connexions de broche ou plus peuvent partager un seul allocateur.

Validation et désengagement des allocateurs

Lorsqu’un filtre crée d’abord un allocator, l’allocateur n’a réservé aucune mémoire tampon. À ce stade, tous les appels à la méthode GetBuffer échouent. Lorsque la diffusion en continu démarre, la broche de sortie appelle IMemAllocator::Commit, qui valide l’allocateur, ce qui l’oblige à allouer de la mémoire. Les épingles peuvent désormais appeler GetBuffer.

Lorsque la diffusion en continu s’arrête, l’épingle appelle IMemAllocator::D ecommit, ce qui désengage l’allocator. Tous les appels suivants à GetBuffer échouent jusqu’à ce que l’allocator soit à nouveau validée. En outre, si des appels à GetBuffer sont actuellement bloqués en attente d’un exemple, ils retournent immédiatement un code d’échec. La méthode Decommit peut libérer ou non la mémoire, en fonction de l’implémentation. Par exemple, la classe CMemAllocator attend que sa méthode destructeur libère de la mémoire.

Data Flow dans le graphe de filtre