Partager via


États de filtre

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

Les filtres ont trois états possibles : arrêté, suspendu et en cours d’exécution. L’objectif de l’état suspendu est d’indiquer des données dans le graphique, afin qu’une commande d’exécution réponde immédiatement. Le Gestionnaire de graphes de filtre contrôle toutes les transitions d’état. Lorsqu’une application appelle IMediaControl::Run, IMediaControl::P ause ou IMediaControl::Stop, le Gestionnaire de graphes de filtre appelle la méthode IMediaFilter correspondante sur tous les filtres. Les transitions entre l’arrêt et l’exécution passent toujours par l’état suspendu. Par conséquent, si l’application appelle Exécuter sur un graphe arrêté, le Gestionnaire de graphes de filtre interrompt le graphe avant de l’exécuter.

Pour la plupart des filtres, les états en cours d’exécution et en pause sont identiques. Considérez le graphique de filtre suivant :

Convertisseur de transformation > source >

Supposons pour l’instant que le filtre source n’est pas une source de capture dynamique. Lorsque le filtre source s’interrompt, il crée un thread qui génère de nouvelles données et les écrit dans des exemples multimédias aussi rapidement que possible. Le thread « envoie » les exemples en aval en appelant IMemInputPin::Receive sur la broche d’entrée du filtre de transformation. Le filtre de transformation reçoit les exemples sur le thread du filtre source. Il peut utiliser un thread de travail pour remettre les exemples au renderer, mais il les livre généralement sur le même thread. Pendant que le convertisseur est suspendu, il attend de recevoir un exemple. Une fois qu’il en a reçu un, il bloque et conserve cet exemple indéfiniment. S’il s’agit d’un convertisseur vidéo, il affiche l’exemple en tant qu’image d’affiche, repeint l’image si nécessaire.

À ce stade, le flux est entièrement cueded et prêt pour le rendu. Si le graphe reste suspendu, les exemples « s’empilent » dans le graphe derrière le premier exemple, jusqu’à ce que chaque filtre soit bloqué dans Receive ou IMemAllocator::GetBuffer. Toutefois, aucune donnée n’est perdue. Une fois le thread source débloqué, il reprend simplement à partir du point où il a bloqué.

Le filtre source et le filtre de transformation ignorent la transition de la mise en pause à l’exécution. Ils continuent simplement à traiter les données aussi rapidement que possible. Toutefois, lorsque le convertisseur s’exécute, il commence à afficher des exemples. Tout d’abord, il restitue l’exemple qu’il a conservé pendant sa pause. Ensuite, chaque fois qu’il reçoit un nouvel exemple, il calcule le temps de présentation de l’exemple. (Pour plus d’informations, consultez Heure et horloges dans DirectShow.) Le convertisseur conserve chaque exemple jusqu’à l’heure de présentation, à laquelle il restitue l’exemple. Pendant qu’il attend l’heure de présentation, il se bloque dans la méthode Receive ou reçoit de nouveaux exemples sur un thread de travail avec une file d’attente. Les filtres amont du convertisseur ne sont pas impliqués dans la planification.

Les sources actives, telles que les appareils de capture, constituent une exception à cette architecture générale. Avec une source dynamique, il n’est pas approprié de faire un signal de données à l’avance. L’application peut suspendre le graphe, puis attendre longtemps avant de l’exécuter. Le graphique ne doit pas afficher les exemples « obsolètes ». Par conséquent, une source dynamique ne produit aucun échantillon pendant la pause, uniquement pendant l’exécution. Pour signaler ce fait au Gestionnaire de graphes de filtre, la méthode IMediaFilter::GetState du filtre source retourne VFW_S_CANT_CUE. Ce code de retour indique que le filtre est passé à l’état suspendu, même si le convertisseur n’a pas reçu de données.

Lorsqu’un filtre s’arrête, il rejette tous les autres exemples qui lui sont remis. Les filtres sources arrêtent leurs threads de diffusion en continu, et d’autres filtres arrêtent tous les threads de travail qu’ils peuvent avoir créés. Les épingles désengagent leurs allocateurs.

Transitions d’état

Le Gestionnaire de graphiques de filtre effectue toutes les transitions d’état dans amont ordre, en commençant par le convertisseur et en travaillant vers l’arrière jusqu’au filtre source. Ce classement est nécessaire pour empêcher la suppression d’échantillons et empêcher le graphe de s’interblocage. Les transitions d’état les plus cruciales sont entre suspendus et arrêtés :

  • Arrêté pour être suspendu : à mesure que chaque filtre s’interrompt, il devient prêt à recevoir des exemples du filtre suivant. Le filtre source est le dernier à suspendre. Il crée le thread de diffusion en continu et commence à fournir des exemples. Étant donné que tous les filtres en aval sont suspendus, aucun filtre ne rejette les exemples. Le Gestionnaire de graphiques de filtre n’effectue pas la transition tant que chaque convertisseur du graphique n’a pas reçu un exemple (à l’exception des sources actives, comme décrit précédemment).
  • Suspendu pour s’arrêter : lorsqu’un filtre s’arrête, il libère tous les exemples qu’il contient, ce qui débloque les filtres amont en attente dans GetBuffer. Si le filtre attend une ressource à l’intérieur de la méthode Receive , il cesse d’attendre et retourne à partir de Receive, ce qui débloque le filtre appelant. Par conséquent, lorsque le Gestionnaire de graphes de filtre arrête le filtre amont suivant, ce filtre n’est pas bloqué dans GetBuffer ou Receive et peut répondre à la commande stop. Le filtre amont peut fournir quelques exemples supplémentaires avant d’obtenir la commande stop, mais le filtre en aval les rejette simplement, car il s’est déjà arrêté.

Data Flow dans le graphe de filtre