MfT asynchrones

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

Notes

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 attend 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 a suffisamment de données pour décoder une image, ProcessOutput bloque tandis que le MFT décode le frame. 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 les trames en parallèle. Pour de meilleures performances, le décodeur doit recevoir une nouvelle entrée chaque fois qu’un thread de décodage devient inactif. Mais la vitesse à laquelle les threads terminent les opérations de décodage ne s’aligne pas exactement sur les appels du client à ProcessInput et ProcessOutput, ce qui entraîne des threads en attente de travail.

Windows 7 introduit un traitement asynchrone piloté par les événements pour les mfts. 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 indication contraire 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 status de traitement des données :

Événement Description
METransformNeedInput Envoyé lorsque le MFT peut accepter davantage d’entrée.
METransformHaveOutput Envoyé lorsque le MFT a une sortie.
METransformDrainComplete Envoyé à la fin d’une opération de drainage. Voir Drainage.
METransformMarker Envoyé lorsqu’un marqueur est traité. Consultez 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 in-band . Un événement in-band contient des informations sur le flux de données, telles que des informations sur un changement de format. Le client envoie des événements in-band au MFT en appelant IMFTransform::P rocessEvent. Le MFT peut renvoyer des événements in-band 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 Générateurs d’événements multimédias.
  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 les événements hors bande du MFT.

ProcessInput

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

  1. Lorsque la diffusion en continu démarre, le client envoie le message MFT_MESSAGE_NOTIFY_START_OF_STREAM .
  2. Pendant la diffusion en continu, le 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.
  • Une MFT asynchrone ne doit jamais retourner MF_E_TRANSFORM_NEED_MORE_INPUT de la méthode ProcessOutput . Si le MFT nécessite plus d’entrée, il envoie un événement METransformNeedInput .

Drainage

Si vous drainez un MFT, le MFT produit 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 a envoyé le dernier événement METransformHaveOutput , il envoie un événement METransformDrainComplete .

Une fois le drainage terminé, le MFT n’envoie pas d’autre événement METransformNeedInput tant qu’il n’a pas reçu un 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.

Le MFT n’envoie pas d’autre événement METransformNeedInput tant qu’il n’a pas reçu un 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. Le 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 , le MFT met en file d’attente quatre événements METransformHaveOutput (un par exemple de sortie), suivis d’un événement METransformMarker .

Le message de marqueur est similaire au message de drainage. Toutefois, un drain est considéré comme une rupture dans le cours d’eau, alors qu’un marqueur ne l’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 .
  • Le 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. Une MFT qui génère une queue doit le faire à la fin d’une opération de drainage.
  • Une fois le drainage du MFT terminé, il marque l’exemple de sortie suivant avec l’attribut MFSampleExtension_Discontinuity , pour indiquer une discontinuité dans le flux.

Marqueur:

  • Le 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, elles doivent être traitées 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

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

Attributs

Une 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écouvrir si le 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 casser des applications existantes, le mécanisme suivant est défini :

Le client appelle IMFTransform::GetAttributes sur le MFT. Le client interroge pour 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 : le 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 avoir appelé Shutdown.
  • 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 une MFT asynchrone, appelez la fonction MFTRegister et définissez l’indicateur MFT_ENUM_FLAG_ASYNCMFT dans le paramètre Flags . (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 Media Foundation