Modèle de traitement MFT de base

Cette rubrique décrit comment un client utilise une transformation Media Foundation (MFT) pour traiter les données. Le client est tout ce qui appelle directement des méthodes sur le MFT. Il peut s’agir de l’application ou du pipeline Media Foundation.

Lisez cette rubrique si vous êtes :

  • Écriture d’une application qui effectue des appels directs à un ou plusieurs MFT.
  • Écriture d’un MFT personnalisé et souhaitez comprendre le comportement attendu d’un MFT.

Cette rubrique décrit un modèle de traitement synchrone . Dans ce modèle, toutes les méthodes de traitement des données bloquent jusqu’à ce qu’elles soient terminées. Les MFT peuvent également prendre en charge un modèle asynchrone , qui est décrit dans la rubrique MFT asynchrones.

Modèle de traitement de base

Créer le MFT

Il existe plusieurs façons de créer un MFT :

  • Appelez la fonction MFTEnum .
  • Appelez la fonction MFTEnumEx .
  • Si vous connaissez déjà le CLSID du MFT, appelez simplement CoCreateInstance.

Certains MFT peuvent fournir d’autres options, telles qu’une fonction de création spécialisée.

Obtenir des identificateurs de flux

Un MFT a un ou plusieurs flux. Les flux d’entrée reçoivent des données d’entrée et les flux de sortie génèrent des données de sortie. Flux ne sont pas représentés en tant qu’objets distincts. Au lieu de cela, différentes méthodes MFT prennent des identificateurs de flux en tant que paramètres.

Certains MFT permettent au client d’ajouter ou de supprimer des flux d’entrée. Pendant la diffusion en continu, un MFT peut ajouter ou supprimer des flux de sortie. (Le client ne peut pas ajouter ou supprimer des flux de sortie.)

  1. (Facultatif.) Appelez IMFTransform::GetStreamLimits pour obtenir le nombre minimal et maximal de flux que le MFT peut prendre en charge. Si le nombre minimal et maximal est identique, le MFT a un nombre fixe de flux.
  2. Appelez IMFTransform::GetStreamCount pour obtenir le nombre initial de flux.
  3. Appelez IMFTransform::GetStreamIDs pour obtenir les identificateurs de flux. Si cette méthode retourne E_NOTIMPL, cela signifie que le MFT a un nombre fixe de flux et que les identificateurs de flux sont consécutifs à partir de zéro.
  4. (Facultatif.) Si le MFT n’a pas de nombre fixe de flux, appelez IMFTransform::AddInputStreams pour ajouter d’autres flux d’entrée, ou IMFTransform::D eleteInputStream pour supprimer des flux d’entrée. (Vous ne pouvez pas ajouter ou supprimer des flux de sortie.)

Définir des types de média

Avant qu’un MFT puisse traiter des données, le client doit définir un type de média pour chacun des flux du MFT. Un MFT peut exiger que le client définisse les types d’entrée avant de définir les types de sortie ou nécessite l’ordre opposé (les types de sortie en premier). Certains MFT n’ont pas besoin de l’ordonnance.

Un MFT peut fournir une liste de types multimédias préférés pour un flux. En outre, les MFT peuvent indiquer les formats généraux qu’ils prennent en charge en ajoutant ces informations au Registre.

Pour définir les types de média, procédez comme suit :

  1. (Facultatif.) Pour chaque flux d’entrée, appelez IMFTransform::GetInputAvailableType pour obtenir la liste des types préférés pour ce flux.
    • Si cette méthode retourne MF_E_TRANSFORM_TYPE_NOT_SET, vous devez d’abord définir les types de sortie ; passez à l’étape 3.
    • Si la méthode retourne E_NOTIMPL, le MFT n’a pas de liste de types d’entrée préférés ; passez à l’étape 2.
  2. Pour chaque flux d’entrée, appelez IMFTransform::SetInputType pour définir le type d’entrée. Vous pouvez utiliser un type multimédia à partir de l’étape 1 ou un type qui décrit vos données d’entrée. Si un flux retourne MF_E_TRANSFORM_TYPE_NOT_SET, passez à l’étape 3.
  3. (Facultatif.) Pour chaque flux de sortie, appelez IMFTransform::GetOutputAvailableType pour obtenir la liste des types préférés pour ce flux.
    • Si cette méthode retourne MF_E_TRANSFORM_TYPE_NOT_SET, vous devez d’abord définir les types d’entrée ; revenez à l’étape 1.
    • Si un flux retourne E_NOTIMPL, le MFT n’a pas de liste de types de sortie préférés ; passez à l’étape 4.
  4. Pour chaque flux de sortie, appelez IMFTransform::SetOutputType pour définir le type de sortie. Vous pouvez utiliser un type multimédia à partir de l’étape 3 ou d’un type qui décrit votre format de sortie requis.
  5. Si des flux d’entrée n’ont pas de type multimédia, revenez à l’étape 1.

Obtenir les exigences en matière de mémoire tampon

Une fois que le client définit les types de média, il doit obtenir les exigences de mémoire tampon pour chaque flux :

Traiter les données

Un MFT est conçu pour être une machine à état fiable. Il n’effectue aucun appel au client.

  1. Appelez IMFTransform::P rocessMessage avec le message MFT_MESSAGE_NOTIFY_BEGIN_STREAMING . Ce message demande au MFT d’allouer les ressources dont il a besoin pendant la diffusion en continu.
  2. Appelez IMFTransform::P rocessInput sur au moins un flux d’entrée pour fournir un exemple d’entrée au MFT.
  3. (Facultatif.) Appelez IMFTransform::GetOutputStatus pour interroger si le MFT peut générer un exemple de sortie. Si la méthode retourne S_OK, vérifiez le paramètre pdwFlags . Si pdwFlags contient l’indicateur MFT_OUTPUT_STATUS_SAMPLE_READY , accédez à l’étape 4. Si pdwFlags est zéro, revenez à l’étape 2. Si la méthode retourne E_NOTIMPL, accédez à l’étape 4.
  4. Appelez IMFTransform::P rocessOutput pour obtenir des données de sortie.
    • Si la méthode retourne MF_E_TRANSFORM_NEED_MORE_INPUT, cela signifie que le MFT nécessite davantage de données d’entrée ; revenez à l’étape 2.
    • Si la méthode retourne MF_E_TRANSFORM_STREAM_CHANGE, cela signifie que le nombre de flux de sortie a changé ou que le format de sortie a changé. Le client peut avoir besoin d’interroger de nouveaux identificateurs de flux ou de définir de nouveaux types de média. Pour plus d’informations, consultez la documentation de ProcessOutput.
  5. S’il existe toujours des données d’entrée à traiter, accédez à l’étape 2. Si le MFT a consommé toutes les données d’entrée disponibles, passez à l’étape 6.
  6. Appelez ProcessMessage avec le message MFT_MESSAGE_NOTIFY_END_OF_STREAM .
  7. Appelez ProcessMessage avec le message MFT_MESSAGE_COMMAND_DRAIN .
  8. Appelez ProcessOutput pour obtenir la sortie restante. Répétez cette étape jusqu’à ce que la méthode retourne MF_E_TRANSFORM_NEED_MORE_INPUT. Cette valeur de retour signale que toutes les sorties ont été vidées du MFT. (Ne pas traiter cela comme une condition d’erreur.)

La séquence décrite ici conserve autant de données que possible dans le MFT. Après chaque appel à ProcessInput, le client tente d’obtenir la sortie. Plusieurs exemples d’entrée peuvent être nécessaires pour produire un exemple de sortie, ou un seul exemple d’entrée peut générer plusieurs exemples de sortie. Le comportement optimal pour le client consiste à extraire des échantillons de sortie du MFT jusqu’à ce que le MFT nécessite davantage d’entrée.

Toutefois, le MFT doit être en mesure de gérer un ordre différent d’appels de méthode par le client. Par exemple, le client peut simplement alterner entre les appels à ProcessInput et ProcessOutput. Le MFT doit limiter la quantité d’entrée qu’il obtient en retournant MF_E_NOTACCEPTING de ProcessInput chaque fois qu’il a une sortie à produire.

L’ordre des appels de méthode décrit ici n’est pas la seule séquence d’événements valide. Par exemple, les étapes 3 et 4 supposent que le client commence par les types d’entrée, puis tente les types de sortie. Le client peut également inverser cet ordre et commencer par les types de sortie. Dans les deux cas, si le MFT requiert l’ordre inverse, il doit retourner le code d’erreur MF_E_TRANSFORM_TYPE_NOT_SET.

Le client peut appeler des méthodes d’information, telles que GetInputCurrentType et GetOutputStreamInfo, à tout moment pendant la diffusion en continu. Le client peut également tenter de modifier les types de média à tout moment. Le MFT doit retourner un code d’erreur s’il ne s’agit pas d’une opération valide. En bref, les MFT doivent supposer très peu sur l’ordre des opérations, à part ce qui est documenté dans les appels eux-mêmes.

Le diagramme suivant montre un organigramme des procédures décrites dans cette rubrique.

flow chart that leads from get stream identifiers through loops that set input types, get input, and process output

Extensions du modèle de base

Si vous le souhaitez, un MFT peut prendre en charge certaines extensions du modèle de diffusion en continu de base.

  • Flux en lecture différée. Si la méthode IMFTransform::GetOutputStreamInfo retourne l’indicateur MFT_OUTPUT_STREAM_LAZY_READ pour un flux de sortie, le client n’a pas besoin de collecter des données à partir de ce flux de sortie. Le MFT continue d’accepter l’entrée, et à un moment donné, le MFT ignore les données de sortie de ce flux. Si tous les flux de sortie ont cet indicateur, le MFT ne parvient jamais à accepter l’entrée. Par exemple, il peut s’agir d’une transformation de visualisation, où le client obtient la sortie uniquement lorsqu’il dispose de cycles processeur de rechange pour dessiner la visualisation.
  • Flux ignorés. Si la méthode GetOutputStreamInfo retourne l’indicateur MFT_OUTPUT_STREAM_DISCARDABLE pour un flux de sortie, le client peut demander au MFT d’ignorer la sortie, mais le MFT n’ignore aucune sortie, sauf si elle est demandée. Lorsque le MFT atteint sa mémoire tampon d’entrée maximale, le client doit collecter des données de sortie ou demander au MFT d’ignorer la sortie.
  • Flux facultatifs. Si la méthode GetOutputStreamInfo retourne l’indicateur MFT_OUTPUT_STREAM_OPTIONAL pour un flux de sortie, ou si la méthode IMFTransform::GetInputStreamInfo retourne l’indicateur MFT_INPUT_STREAM_OPTIONAL pour un flux d’entrée, ce flux est facultatif. Le client n’a pas besoin de définir un type de média sur le flux. Si le client ne définit pas le type, le flux est désélectionné. Un flux de sortie désélectionné ne produit pas d’exemples et le client ne fournit pas de mémoire tampon pour le flux lorsqu’il appelle ProcessOutput. Un flux d’entrée désélectionné n’accepte pas les données d’entrée. Un MFT peut marquer tous ses flux d’entrée et de sortie comme facultatifs. Toutefois, il est prévu qu’au moins une entrée et une sortie doivent être sélectionnées pour que le MFT fonctionne.
  • Traitement asynchrone. Le modèle de traitement asynchrone a été introduit dans Windows 7. Il est décrit dans la rubrique MFT asynchrone.

IMF2DBuffer

Si un MFT traite des données vidéo non compressées, il doit utiliser l’interface IMF2DBuffer pour manipuler les exemples de mémoires tampons. Pour obtenir cette interface, interrogez l’interface IMFMediaBuffer sur n’importe quelle mémoire tampon d’entrée ou de sortie. L’utilisation de cette interface lorsqu’elle est disponible peut entraîner des copies de mémoire tampon supplémentaires. Pour utiliser correctement cette interface, la transformation ne doit pas verrouiller la mémoire tampon à l’aide de l’interface IMFMediaBuffer lorsque IMF2DBuffer est disponible.

Pour plus d’informations sur le traitement des données vidéo, consultez Mémoires tampons vidéo non compressées.

Vidage d’un MFT

Le vidage d’un MFT entraîne l’abandon de toutes ses données d’entrée par MFT. Cela peut entraîner une rupture dans le flux de sortie. Un client viderait généralement un MFT avant de rechercher un nouveau point dans le flux d’entrée ou de basculer vers un nouveau flux d’entrée, lorsque le client ne se soucie pas de perdre des données.

Pour vider un MFT, appelez IMFTransform::P rocessMessage avec le message MFT_MESSAGE_COMMAND_FLUSH .

Drainage d’un MFT

Le drainage d’un MFT entraîne l’envoi du MFT autant de sortie que possible à partir de toutes les données d’entrée déjà envoyées. Si le MFT ne peut pas produire un exemple de sortie complet à partir de l’entrée disponible, il supprime les données d’entrée. Un client viderait généralement un MFT lorsqu’il atteignait la fin du flux source ou immédiatement avant une modification de format dans le flux source. Pour drainer un MFT, procédez comme suit :

  1. Appelez ProcessMessage avec le message MFT_MESSAGE_COMMAND_DRAIN . Ce message informe le MFT qu’il doit fournir autant de données de sortie que possible à partir des données d’entrée qui ont déjà été envoyées.
  2. Appelez ProcessOutput pour obtenir des données de sortie jusqu’à ce que la méthode retourne MF_E_TRANSFORM_NEED_MORE_INPUT.

Bien que le MFT soit vidé, il n’accepte plus d’entrée.

Exemples d’attributs

Les exemples d’entrée peuvent avoir des attributs qui doivent être copiés dans les exemples de sortie correspondants.

Pour un MFT avec une entrée et une sortie, vous pouvez utiliser la règle générale suivante :

  • Si chaque exemple d’entrée produit exactement un exemple de sortie, vous pouvez laisser le client copier les attributs. Laissez la propriété MFPKEY_EXATTRIBUTE_SUPPORTED non définie.
  • S’il n’existe pas de correspondance un-à-un entre les échantillons d’entrée et les échantillons de sortie, le MFT doit déterminer les attributs appropriés pour les échantillons de sortie. Définissez la propriété MFPKEY_EXATTRIBUTE_SUPPORTED sur VARIANT_TRUE.

Discontinuités

Une discontinuité est une rupture dans un flux audio ou vidéo. Les discontinuités peuvent être provoquées par des paquets supprimés sur une connexion réseau, des données de fichier endommagées, un commutateur d’un flux source à un autre ou un large éventail d’autres causes. Les discontinuités sont signalées en définissant l’attribut MFSampleExtension_Discontinuity sur le premier échantillon après la discontinuité. Il n’est pas possible de signaler une discontinuité au milieu d’un échantillon. Par conséquent, toutes les données discontinues doivent être envoyées dans des échantillons distincts.

Certaines transformations, en particulier celles qui gèrent les données non compressées, telles que les effets audio et vidéo, doivent ignorer les discontinuités lorsqu’elles traitent les données d’entrée. Ces MFT sont généralement conçus pour gérer les données continues et doivent traiter les données qu’ils reçoivent comme continues, même après une discontinuité.

Si un MFT ignore une discontinuité sur les données d’entrée, il doit toujours définir l’indicateur de discontinuité sur l’exemple de sortie, si l’exemple de sortie a le même horodatage que l’exemple d’entrée. Toutefois, si l’exemple de sortie a un horodatage différent, le MFT ne doit pas propager la discontinuité. (Ce serait le cas dans certains rééchantillons audio, par exemple.) Une discontinuité au mauvais endroit dans le flux est pire qu’aucune discontinuité.

La plupart des décodeurs ne peuvent pas ignorer les discontinuités, car une discontinuité affecte l’interprétation de l’exemple suivant. Toute technologie d’encodage qui utilise la compression entre images, comme MPEG-2, se trouve dans cette catégorie. Certains schémas d’encodage utilisent uniquement la compression intra-frame, telle que DV et MJPEG. Ces décodeurs peuvent ignorer en toute sécurité les discontinuités.

Les transformations qui répondent aux discontinuités doivent généralement générer autant de données avant la discontinuité que possible et ignorer le reste. L’exemple d’entrée avec l’indicateur de discontinuité doit être traité comme s’il s’agissait du premier échantillon dans le flux. (Ce comportement correspond à ce qui est spécifié pour le message MFT_MESSAGE_COMMAND_DRAIN .) Toutefois, les détails exacts dépendent du format multimédia.

Si un décodeur ne fait rien pour atténuer une discontinuité, il doit copier l’indicateur de discontinuité dans les données de sortie. Les démultiplexeurs et d’autres MFT qui fonctionnent entièrement avec des données compressées doivent copier toutes les discontinuités dans leurs flux de sortie. Dans le cas contraire, les composants en aval ne peuvent pas décoder correctement les données compressées. En général, il est presque toujours correct de passer des discontinuités en aval, sauf si le MFT contient du code explicite pour faciliter les discontinuités.

Modifications de format dynamique

Les formats peuvent changer pendant la diffusion en continu. Par exemple, les proportions peuvent changer au milieu d’un flux vidéo.

Pour plus d’informations sur la façon dont les modifications de flux sont gérées par un MFT, consultez Gestion des modifications de flux.

Événements de flux

Pour envoyer un événement à un MFT, appelez IMFTransform::P rocessEvent. Si la méthode retourne MF_S_TRANSFORM_DO_NOT_PROPAGATE_EVENT, le MFT retourne l’événement à l’appelant lors d’un appel ultérieur à ProcessOutput. Si la méthode retourne une autre valeur HRESULT , MFT ne retourne pas l’événement au client dans ProcessOutput. Dans ce cas, le client est chargé de propager l’événement en aval au composant suivant du pipeline, le cas échéant. Pour plus d’informations, consultez IMFTransform::P rocessOutput.

Transformations Media Foundation