MFT asynchrones

Cette rubrique décrit le traitement asynchrone des données pour les transformations Media Foundation (MFT).

Remarque

Cette rubrique s’applique à Windows 7 ou version ultérieure.

 

À propos des MFT asynchrones

Lorsque les MFT ont été introduits dans Windows Vista, l’API a été conçue pour le traitement synchrone des données. Dans ce modèle, le MFT attend toujours d’obtenir une entrée ou d’attendre de produire une sortie.

Considérez un décodeur vidéo classique. Pour obtenir une trame décodée, le client appelle IMFTransform::P rocessOutput. Si le décodeur dispose de suffisamment de données pour décoder une trame, ProcessOutput bloque pendant que le MFT décode l’image. Sinon, ProcessOutput retourne MF_E_TRANSFORM_NEED_MORE_INPUT, indiquant que le client doit appeler IMFTransform::P rocessInput.

Ce modèle fonctionne bien si le décodeur effectue toutes ses opérations de décodage sur un thread. Mais supposons que le décodeur utilise plusieurs threads pour décoder des images en parallèle. Pour obtenir les meilleures performances, le décodeur doit recevoir de nouvelles entrées chaque fois qu’un thread de décodage devient inactif. Mais le taux auquel les threads terminent les opérations de décodage ne s’alignent pas exactement sur les appels du client à ProcessInput et ProcessOutput, ce qui entraîne des threads en attente de travail.

Windows 7 introduit le traitement asynchrone piloté par les événements pour les MFT. Dans ce modèle, chaque fois que le MFT a besoin d’une entrée ou d’une sortie, il envoie un événement au client.

Exigences générales

Cette rubrique décrit comment les MFT asynchrones diffèrent de MFT synchrone. Sauf dans cette rubrique, les deux modèles de traitement sont identiques. (En particulier, la négociation de format est identique.)

Un MFT asynchrone doit implémenter les interfaces suivantes :

Événements

Un MFT asynchrone utilise les événements suivants pour signaler son état de traitement des données :

Événement Description
METransformNeedInput Envoyé lorsque le MFT peut accepter plus d’entrée.
METransformHaveOutput Envoyé lorsque MFT a la sortie.
METransformDrainComplete Envoyé lorsqu’une opération de drainage se termine. Voir Draining.
METransformMarker Envoyé lorsqu’un marqueur est traité. Voir marqueurs.

 

Ces événements sont envoyés hors bande. Il est important de comprendre la différence entre les événements en bande et hors bande dans le contexte d’un MFT.

La conception MFT d’origine prend en charge les événements en bande . Un événement en bande contient des informations sur le flux de données, telles que des informations sur une modification de format. Le client envoie des événements en bande au MFT en appelant IMFTransform::P rocessEvent. MFT peut renvoyer des événements en bande au client dans la méthode ProcessOutput . (Plus précisément, les événements sont transmis dans le membre pEvents de la structure MFT_OUTPUT_DATA_BUFFER .)

Un MFT envoie des événements hors bande via l’interface IMFMediaEventGenerator comme suit :

  1. Le MFT implémente l’interface IMFMediaEventGenerator , comme décrit dans Media Event Generators.
  2. Le client appelle IUnknown::QueryInterface sur le MFT pour l’interface IMFMediaEventGenerator . Un MFT asynchrone doit exposer cette interface. Les MFT synchrones ne doivent pas exposer cette interface.
  3. Le client appelle IMFMediaEventGenerator::BeginGetEvent et IMFMediaEventGenerator::EndGetEvent pour recevoir des événements hors bande à partir du MFT.

ProcessInput

La méthode IMFTransform::P rocessInput est modifiée comme suit :

  1. Au démarrage de la diffusion en continu, le client envoie le message MFT_MESSAGE_NOTIFY_START_OF_STREAM .
  2. Pendant la diffusion en continu, MFT demande des données en envoyant un événement METransformNeedInput . Les données d’événement sont l’identificateur de flux.
  3. Pour chaque événement METransformNeedInput , le client appelle ProcessInput pour le flux spécifié.
  4. À la fin de la diffusion en continu, le client peut appeler ProcessMessage avec le message MFT_MESSAGE_NOTIFY_END_OF_STREAM .

Notes d’implémentation :

ProcessOutput

La méthode IMFTransform::P rocessOutput est modifiée comme suit :

  1. Chaque fois que le MFT a une sortie, il envoie un événement METransformHaveOutput .
  2. Pour chaque événement METransformHaveOutput , le client appelle ProcessOutput.

Notes d’implémentation :

  • Si le client appelle ProcessOutput à tout autre moment, la méthode retourne E_UNEXPECTED.
  • Un MFT asynchrone ne doit jamais retourner MF_E_TRANSFORM_NEED_MORE_INPUT à partir de la méthode ProcessOutput . Si le MFT nécessite davantage d’entrée, il envoie un événement METransformNeedInput .

Drainage

Le drainage d’un MFT entraîne l’envoi du MFT autant de sortie que possible à partir des données d’entrée déjà envoyées. Le drainage d’un MFT asynchrone fonctionne comme suit :

  1. Le client envoie le message MFT_MESSAGE_COMMAND_DRAIN .
  2. Le MFT continue d’envoyer des événements METransformHaveOutput jusqu’à ce qu’il n’ait plus de données à traiter. Il n’envoie pas d’événements METransformNeedInput pendant cette période.
  3. Une fois que le MFT envoie le dernier événement METransformHaveOutput , il envoie un événement METransformDrainComplete .

Une fois le drain terminé, le MFT n’envoie pas d’autre événement METransformNeedInput tant qu’il ne reçoit pas de message MFT_MESSAGE_NOTIFY_START_OF_STREAM du client.

Rinçage

Le client peut vider le MFT en envoyant le message MFT_MESSAGE_COMMAND_FLUSH . Le MFT supprime tous les échantillons d’entrée et de sortie qu’il contient.

MFT n’envoie pas d’autre événement METransformNeedInput tant qu’il ne reçoit pas de message MFT_MESSAGE_NOTIFY_START_OF_STREAM du client.

Marqueurs

Le client peut marquer un point dans le flux en envoyant le message MFT_MESSAGE_COMMAND_MARKER . Le MFT répond comme suit :

  1. MFT génère autant d’exemples de sortie que possible à partir des données d’entrée existantes, en envoyant un événement METransformHaveOutput pour chaque exemple de sortie.
  2. Une fois la sortie générée, MFT envoie un événement METransformMarker . Cet événement doit être envoyé après tous les événements METransformHaveOutput .

Par exemple, supposons qu’un décodeur dispose de suffisamment de données d’entrée pour produire quatre exemples de sortie. Si le client envoie le message MFT_MESSAGE_COMMAND_MARKER , MFT met en file d’attente quatre événements METransformHaveOutput (un par exemple de sortie), suivi d’un événement METransformMarker .

Le message de marqueur est similaire au message de drain. Toutefois, un drain est considéré comme un saut dans le flux, tandis qu’un marqueur n’est pas. Le drainage et les marqueurs présentent les différences suivantes.

Vidange:

  • Lors du drainage, le MFT n’envoie pas d’événements METransformNeedInput .
  • MFT ignore toutes les données d’entrée qui ne peuvent pas être utilisées pour créer un exemple de sortie.
  • Certains MFT produisent une « queue » à la fin des données. Par exemple, les effets audio tels que la réverbération ou l’écho produisent des données supplémentaires après l’arrêt des données d’entrée. Un MFT qui génère une queue doit le faire à la fin d’une opération de drain.
  • Une fois que le MFT a terminé de drainer, il marque l’exemple de sortie suivant avec l’attribut MFSampleExtension_Discontinuity , pour indiquer une discontinuité dans le flux.

Marqueur:

  • MFT continue d’envoyer des événements METransformNeedInput avant d’envoyer l’événement de marqueur.
  • Le MFT n’ignore aucune donnée d’entrée. S’il existe des données partielles, il doit être traité après le point de marqueur.
  • Le MFT ne produit pas de queue au point de marqueur.
  • Le MFT ne définit pas l’indicateur de discontinuité après le point de marqueur.

Modifications de format

Un MFT asynchrone doit prendre en charge les modifications de format dynamique, comme décrit dans Gestion des modifications de flux.

Attributs

Un MFT asynchrone doit implémenter la méthode IMFTransform::GetAttributes pour retourner un magasin d’attributs valide. Les attributs suivants s’appliquent aux MFT asynchrones :

Attribut Description
MF_TRANSFORM_ASYNC MFT doit définir cet attribut sur TRUE (1). Le client peut interroger cet attribut pour déterminer si MFT est asynchrone.
MF_TRANSFORM_ASYNC_UNLOCK
MFT_SUPPORT_DYNAMIC_FORMAT_CHANGE MFT doit définir cet attribut sur TRUE (1). Le client peut supposer que cet attribut est défini.

 

Déverrouillage des MFT asynchrones

Les MFT asynchrones ne sont pas compatibles avec le modèle de traitement des données MFT d’origine. Pour empêcher les MFT asynchrones de briser les applications existantes, le mécanisme suivant est défini :

Le client appelle IMFTransform::GetAttributes sur le MFT. Le client interroge cet attribut MF_TRANSFORM_ASYNC . Pour un MFT asynchrone, la valeur de cet attribut est **TRUE**. Pour déverrouiller le MFT, le client doit définir l’attribut MF_TRANSFORM_ASYNC_UNLOCK sur **TRUE**.

Jusqu’à ce que le client déverrouille le MFT, toutes les méthodes IMFTransform doivent retourner MF_E_TRANSFORM_ASYNC_LOCKED, avec les exceptions suivantes :

Le code suivant montre comment déverrouiller un MFT asynchrone :

HRESULT UnlockAsyncMFT(IMFTransform *pMFT)
{
    IMFAttributes *pAttributes = NULL;

    HRESULT hr = hr = pMFT->GetAttributes(&pAttributes);

    if (SUCCEEDED(hr))
    {
        hr = pAttributes->SetUINT32(MF_TRANSFORM_ASYNC_UNLOCK, TRUE);
        pAttributes->Release();
    }
    
    return hr;
}

Arrêt du MFT

Les MFT asynchrones doivent implémenter l’interface IMFShutdown .

  • Arrêt : MFT doit arrêter sa file d’attente d’événements. Si vous utilisez la file d’attente d’événements standard, appelez IMFMediaEventQueue::Shutdown. Si vous le souhaitez, le MFT peut libérer d’autres ressources. Le client ne doit pas utiliser le MFT après l’appel de l’arrêt.
  • GetShutdownStatus : une fois l’arrêt appelé, le MFT doit retourner la valeur MFSHUTDOWN_COMPLETED dans le paramètre pStatus . Elle ne doit pas retourner la valeur MFSHUTDOWN_INITIATED.

Inscription et énumération

Pour inscrire un MFT asynchrone, appelez la fonction MFTRegister et définissez l’indicateur MFT_ENUM_FLAG_ASYNCMFT dans le paramètre Indicateurs . (Auparavant, cet indicateur était réservé.)

Pour énumérer les MFT asynchrones, appelez la fonction MFTEnumEx et définissez l’indicateur MFT_ENUM_FLAG_ASYNCMFT dans le paramètre Flags . Pour la compatibilité descendante, la fonction MFTEnum n’énumère pas les MFT asynchrones. Sinon, l’installation d’un MFT asynchrone sur l’ordinateur de l’utilisateur peut interrompre les applications existantes.

Transformations de Media Foundation