Récepteurs multimédias

Les récepteurs multimédias sont les objets de pipeline qui reçoivent des données multimédias. Un récepteur multimédia est la destination d’un ou plusieurs flux multimédias. Les récepteurs multimédias se répartissent en deux catégories générales :

  • Un renderer est un récepteur multimédia qui présente des données pour la lecture. Le convertisseur vidéo amélioré (EVR) affiche des images vidéo et le convertisseur audio lit des flux audio via la carte audio ou un autre périphérique audio.

  • Un récepteur d’archive est un récepteur multimédia qui écrit des données dans un fichier ou un autre stockage.

La principale différence entre eux est qu’un récepteur d’archive ne consomme pas les données à un taux de lecture fixe. Au lieu de cela, il écrit les données qu’il reçoit le plus rapidement possible.

Les récepteurs multimédias exposent l’interface IMFMediaSink . Chaque récepteur multimédia contient un ou plusieurs récepteurs de flux. Chaque récepteur de flux reçoit les données d’un flux. Les récepteurs de flux exposent l’interface IMFStreamSink . En règle générale, une application ne crée pas directement de récepteurs multimédias. Au lieu de cela, l’application crée un ou plusieurs objets d’activation, que la session multimédia utilise pour créer le récepteur. Toutes les autres opérations sur le récepteur sont gérées par la session multimédia, et l’application n’appelle aucune méthode sur le récepteur multimédia ou l’un des récepteurs de flux. Pour plus d’informations sur les objets d’activation, consultez Activation Objects.

Vous devez lire le reste de cette rubrique si vous écrivez un récepteur multimédia personnalisé ou si vous souhaitez utiliser un récepteur multimédia directement sans la session multimédia.

Récepteurs de flux

Un récepteur multimédia peut avoir un nombre fixe de récepteurs de flux, ou il peut prendre en charge l’ajout et la suppression de récepteurs de flux. S’il a un nombre fixe de récepteurs de flux, la méthode IMFMediaSink::GetCharacteristics retourne l’indicateur MEDIASINK_FIXED_STREAMS. Sinon, vous pouvez ajouter et supprimer des récepteurs de flux. Pour ajouter un nouveau récepteur de flux, appelez IMFMediaSink::AddStreamSink. Pour supprimer un récepteur de flux, appelez IMFMediaSink::RemoveStreamSink. L’indicateur MEDIASINK_FIXED_STREAMS indique que le récepteur multimédia ne prend pas en charge ces deux méthodes. (Il peut prendre en charge un autre moyen de configurer le nombre de flux, par exemple en définissant des paramètres d’initialisation lors de la création du récepteur.) La liste des récepteurs de flux est triée. Pour les énumérer par valeur d’index, appelez la méthode IMFMediaSink::GetStreamSinkByIndex .

Les récepteurs de flux ont également des identificateurs. Les identificateurs de flux sont uniques dans le récepteur multimédia, mais ne doivent pas être consécutifs. Selon le récepteur multimédia, les identificateurs de flux peuvent avoir une certaine signification liée au contenu. Par exemple, un récepteur d’archive peut écrire les identificateurs de flux dans l’en-tête de fichier. Sinon, ils sont arbitraires. Pour obtenir un récepteur de flux par son identificateur, appelez IMFMediaSink::GetStreamSinkById.

Horloge de présentation

La vitesse à laquelle un récepteur multimédia consomme des échantillons est contrôlée par l’horloge de présentation. La session multimédia sélectionne l’horloge de présentation et la définit sur le récepteur multimédia en appelant la méthode IMFMediaSink::SetPresentationClock du récepteur multimédia. L’horloge de présentation doit être définie sur le récepteur multimédia avant que la diffusion en continu puisse commencer. Chaque récepteur multimédia nécessite une horloge de présentation à exécuter. Le récepteur multimédia utilise l’horloge de présentation à deux fins :

  • Pour recevoir des notifications au démarrage ou à l’arrêt de la diffusion en continu. Le récepteur multimédia reçoit ces notifications via l’interface IMFClockStateSink , que tous les récepteurs multimédias doivent implémenter.

  • Pour déterminer quand il doit afficher des échantillons. Lorsque le récepteur multimédia reçoit un nouvel exemple, il obtient l’horodatage de l’exemple et tente d’afficher l’exemple à l’heure de la présentation.

L’horloge de présentation dérive ses heures d’horloge d’un autre objet appelé source de l’heure de présentation. Les sources de temps de présentation exposent l’interface IMFPresentationTimeSource . Certains récepteurs multimédias ont accès à une horloge précise, de sorte qu’ils exposent cette interface. Cela signifie qu’un récepteur multimédia peut planifier des échantillons par rapport à une heure fournie par son propre horloge. Toutefois, le récepteur multimédia ne peut pas supposer qu’il s’agit du cas. Il doit toujours utiliser l’heure de l’horloge de présentation, que l’horloge de la présentation soit pilotée par le récepteur multimédia lui-même ou par une autre horloge.

Si un récepteur multimédia ne peut pas correspondre aux taux avec une horloge autre que son propre, la méthode GetCharacteristics retourne l’indicateur MEDIASINK_CANNOT_MATCH_CLOCK. Si cet indicateur est présent et que l’horloge de présentation utilise une source d’heure de présentation différente, le récepteur multimédia est susceptible de s’exécuter mal. Par exemple, elle peut glisser pendant la lecture.

Un récepteur sans débit est un récepteur multimédia qui ignore les horodatages sur les échantillons et consomme des données dès que chaque échantillon arrive. Un récepteur multimédia sans taux renvoie l’indicateur MEDIASINK_RATELESS de la méthode GetCharacteristics . En règle générale, cet indicateur s’applique aux récepteurs d’archivage. Si chaque récepteur multimédia du pipeline est sans taux, la session multimédia utilise une horloge de présentation sans débit spéciale. Cette horloge s’exécute aussi rapidement que les récepteurs consomment des échantillons.

Formats de flux

Pour que le récepteur multimédia puisse recevoir des échantillons, le client doit définir le type de média sur les récepteurs de flux. Pour définir le type de média, appelez la méthode IMFStreamSink::GetMediaTypeHandler du récepteur de flux. Cette méthode retourne un pointeur vers l’interface IMFMediaTypeHandler . Utilisez cette interface pour obtenir la liste des types multimédias préférés, obtenir le type de média actuel et définir le type de média.

Pour obtenir la liste des types de médias préférés, appelez IMFMediaTypeHandler::GetMediaTypeByIndex. Les types préférés doivent être pris comme indicateur pour le client. La liste peut être incomplète ou inclure des types de média partiels. Un type de média partiel est un type qui n’a pas tous les attributs nécessaires pour décrire un format valide. Par exemple, un type vidéo partiel peut spécifier l’espace de couleur et la profondeur du bit, mais pas la largeur ou la hauteur de l’image. Un type audio partiel peut spécifier le format de compression et le taux d’échantillonnage, mais pas le nombre de canaux audio.

Pour obtenir le type de média actuel du récepteur de flux, appelez IMFMediaTypeHandler::GetCurrentMediaType. Lorsqu’un récepteur de flux est créé pour la première fois, il peut avoir un type de média par défaut déjà défini, ou il n’a pas de type multimédia tant que le client n’en a pas défini un.

Pour définir le type de média, appelez IMFMediaTypeHandler::SetCurrentMediaType. Certains récepteurs de flux peuvent ne pas prendre en charge la modification du type après avoir été défini. Par conséquent, il est utile de tester les types de supports avant de les définir. Pour vérifier si le récepteur multimédia accepte un type de média (sans définir le type), appelez IMFMediaTypeHandler::IsMediaTypeSupported.

Data Flow

Les récepteurs multimédias utilisent un modèle d’extraction, ce qui signifie que les récepteurs de flux demandent des données à mesure qu’ils en ont besoin. Le client doit répondre en temps opportun afin d’éviter toute glitching.

Certains récepteurs multimédias prennent en charge la pré-inscription. La pré-inscription est le processus d’octroi de données au récepteur multimédia avant le démarrage de l’horloge de présentation. Si un récepteur multimédia prend en charge la prérolling, le récepteur multimédia expose l’interface IMFMediaSinkPreroll et la méthode GetCharacteristics retourne l’indicateur MEDIASINK_CAN_PREROLL. La pré-inscription garantit que le récepteur multimédia est prêt à présenter le premier exemple au démarrage de l’horloge de présentation. Il est recommandé que le client prérolle toujours si le récepteur multimédia le prend en charge, car il peut empêcher les glitchings ou les lacunes pendant la lecture.

Le flux de données vers un récepteur multimédia fonctionne comme suit :

  1. Le client définit les types de média et l’horloge de présentation. Le récepteur multimédia s’inscrit auprès de l’horloge de présentation pour recevoir des notifications sur les modifications d’état de l’horloge.
  2. Si vous le souhaitez, le client interroge IMFMediaSinkPreroll. Si le récepteur multimédia expose cette interface, le client appelle IMFMediaSinkPreroll::NotifyPreroll. Sinon, le client passe à l’étape 5.
  3. Chaque récepteur de flux envoie un ou plusieurs événements MEStreamSinkRequestSample . En réponse à chacun de ces événements, le client obtient l’exemple suivant de données pour ce flux et appelle IMFStreamSink::P rocessSample.
  4. Lorsque chaque récepteur de flux reçoit suffisamment de données de préroll, il envoie un événement MEStreamSinkPrerolled .
  5. Le client appelle IMFPresentationClock::Start pour démarrer l’horloge de présentation.
  6. L’horloge de présentation avertit le récepteur multimédia que l’horloge démarre, en appelant IMFClockStateSink::OnClockStart.
  7. Pour obtenir plus de données, chaque récepteur de flux envoie des événements MEStreamSinkRequestSample . En réponse à chacun de ces événements, le client obtient l’exemple suivant et appelle ProcessSample. Cette étape est répétée jusqu’à ce que la présentation se termine.

La plupart des récepteurs multimédias traitent des exemples de manière asynchrone, afin que les récepteurs de flux puissent envoyer plusieurs exemples de requête à la fois.

Pendant la diffusion en continu, le client peut appeler IMFStreamSink::P laceMarker et IMFStreamSink::Flush à tout moment. Les marqueurs sont décrits dans la section suivante. Le vidage entraîne le fait que le récepteur de flux supprime tous les échantillons qu’il a mis en file d’attente mais qu’il n’est pas encore rendu.

Marqueurs

Les marqueurs permettent au client d’indiquer des points spécifiques dans le flux. Un marqueur se compose des informations suivantes :

  • Type de marqueur, défini comme membre de l’énumération MFSTREAMSINK_MARKER_TYPE .
  • Données associées au marqueur. La signification des données dépend du type de marqueur. Certains types de marqueurs n’ont pas de données.
  • Données facultatives pour la propre utilisation du client.

Pour placer un marqueur, le client appelle IMFStreamSink::P laceMarker. Le récepteur de flux termine le traitement des échantillons qu’il a reçus avant l’appel PlaceMarker , puis envoie un événement MEStreamSinkMarker .

La plupart des récepteurs multimédias conservent une file d’attente d’exemples en attente, qu’ils traitent de manière asynchrone. Les événements de marqueur doivent être sérialisés avec un exemple de traitement. Le récepteur multimédia doit donc placer les marqueurs dans la même file d’attente. Par exemple, supposons que le client effectue les appels de méthode suivants :

  1. ProcessSample (exemple n° 1)
  2. ProcessSample (exemple n° 2)
  3. PlaceMarker (Marqueur n° 1)
  4. ProcessSample (exemple n° 3)
  5. PlaceMarker (Marqueur n° 2)

Dans cet exemple, le récepteur de flux doit envoyer l’événement MEStreamSinkMarker pour le marqueur #1 après qu’il traite l’exemple #2, et l’événement pour le marqueur #2 après qu’il traite l’exemple #3.

Si le client vide un récepteur de flux, le récepteur de flux traite immédiatement les marqueurs qui se trouvaient dans la file d’attente. Il définit le code d’état sur E_ABORT sur ces événements.

Certains marqueurs contiennent des informations pertinentes pour le récepteur multimédia :

  • MFSTREAMSINK_MARKER_TICK : indique qu’il existe un écart dans le flux. L’exemple suivant sera une discontinuité.
  • MFSTREAMSINK_MARKER_ENDOFSEGMENT : indique la fin d’un segment ou la fin d’un flux. L’exemple suivant (le cas échéant) peut être une discontinuité.
  • MFSTREAMSINK_MARKER_EVENT : contient un événement. Selon le type d’événement et l’implémentation du récepteur multimédia, le récepteur multimédia peut gérer l’événement ou l’ignorer.

Changements d'état

Un récepteur multimédia est averti des changements d’état dans l’horloge de présentation via l’interface IMFClockStateSink du récepteur multimédia. Lorsque le client définit l’horloge de présentation, le récepteur multimédia appelle IMFPresentationClock::AddClockStateSink pour s’inscrire à des notifications à partir de l’horloge. Le tableau suivant récapitule le comportement d’un récepteur multimédia en réponse aux changements d’état d’horloge.

Changement d’état de l’horloge Exemple de traitement Traitement des marqueurs
OnClockStart Traiter des exemples dont l’horodatage est égal ou ultérieur à l’heure de début de l’horloge. Envoyez l’événement MEStreamSinkMarker lorsque tous les échantillons reçus avant le traitement du marqueur.
OnClockPause Le récepteur multimédia peut échouer ProcessSample pendant la pause.
Si le récepteur multimédia accepte des échantillons en pause, il doit les mettre en file d’attente jusqu’à ce que l’horloge redémarre. Ne traitez aucun échantillon mis en file d’attente pendant la pause.
S’il existe des échantillons mis en file d’attente, placez les marqueurs dans la même file d’attente. Envoyez l’événement de marqueur lorsque l’horloge redémarre.
Sinon, envoyez immédiatement l’événement de marqueur.
OnClockRestart Traitez tous les exemples qui ont été mis en file d’attente en pause, puis traitez la même chose que OnClockStart. Envoyez les événements MEStreamSinkMarker pour les marqueurs mis en file d’attente (sérialisés avec un exemple de traitement), puis traitez la même chose que OnClockStart.
OnClockStop Supprimez tous les exemples mis en file d’attente. D’autres appels à ProcessSample peuvent échouer. Envoyer des événements de marqueur mis en file d’attente. Lors des appels suivants à PlaceMarker, envoyez immédiatement l’événement de marqueur.

 

En outre, les récepteurs de flux doivent envoyer les événements suivants lorsqu’ils ont terminé les transitions d’état :

En cours de finalisation

Certains récepteurs multimédias nécessitent une étape de traitement supplémentaire après la remise du dernier échantillon. En règle générale, cette exigence s’applique aux récepteurs d’archive, qui doivent écrire des en-têtes ou des index dans le fichier. Si un récepteur multimédia nécessite un traitement final, il expose l’interface IMFFinalizableMediaSink .

Une fois que le client a remise le dernier exemple, le client interroge cette interface. Si le récepteur multimédia prend en charge l’interface, le client appelle IMFFinalizableMediaSink::BeginFinalize pour effectuer le traitement final de manière asynchrone. Cette méthode suit le modèle asynchrone Media Foundation standard, décrit dans Méthodes de rappel asynchrones. Le récepteur multimédia peut supposer que le client appelle BeginFinalize. L’échec de l’appel de BeginFinalize peut entraîner un fichier créé de manière incorrecte.

Fermeture

Une fois le client terminé à l’aide du récepteur multimédia, le client appelle IMFMediaSink::Shutdown. À l’intérieur de cette méthode, le récepteur multimédia doit interrompre tout nombre de références circulaires. En règle générale, il y aura des références circulaires entre le récepteur multimédia et les récepteurs de flux.

Si vous utilisez l’objet d’assistance de file d’événements pour implémenter IMFMediaEventGenerator, appelez IMFMediaEventQueue::Shutdown sur la file d’attente d’événements. Cette méthode arrête la file d’attente d’événements et signale à tout appelant qui attend actuellement un événement.

Après l’arrêt, toutes les méthodes sur le récepteur multimédia retournent MF_E_SHUTDOWN, à l’exception des méthodes IUnknown .

Interfaces de récepteur multimédia

Le tableau suivant répertorie les interfaces standard que les récepteurs multimédias peuvent exposer via QueryInterface. Les récepteurs multimédias peuvent également exposer des interfaces personnalisées.

Interface Description
IMFMediaSink Interface principale pour les récepteurs multimédias. (Obligatoire.)
IMFClockStateSink Utilisé pour avertir le récepteur multimédia lorsque l’horloge de présentation change d’état. (Obligatoire.)
IMFFinalizableMediaSink Implémentez si le récepteur multimédia doit effectuer une dernière étape de traitement. (Facultatif.)
IMFGetService Implémentez si le récepteur multimédia expose des interfaces de service. (Facultatif.)
IMFMediaEventGenerator Implémentez si le récepteur multimédia envoie des événements. (Facultatif.)
IMFMediaSinkPreroll Implémentez si le récepteur multimédia prend en charge la pré-inscription. (Facultatif.)
IMFPresentationTimeSource Implémentez si le récepteur multimédia peut fournir une source de temps pour l’horloge de présentation. (Facultatif.)
IMFQualityAdvise Implémentez si le récepteur multimédia peut ajuster la qualité de lecture. (Facultatif.)

 

Si vous le souhaitez, un récepteur multimédia peut implémenter l’interface suivante en tant que service.

Interface de service Description
IMFRateSupport Signale la plage des taux de lecture pris en charge.

 

Pour plus d’informations sur les interfaces de service et IMFGetService, consultez Interfaces de service.

Interfaces de récepteur de flux

Les récepteurs de flux doivent exposer les interfaces suivantes via QueryInterface.

Interface Description
IMFStreamSink Interface principale pour les récepteurs de flux. (Obligatoire.)
IMFMediaEventGenerator Événements de files d’attente. L’interface IMFStreamSink hérite de cette interface. (Obligatoire.)

 

Actuellement, aucune interface de service n’est définie pour les récepteurs de flux.

Événements de récepteur de flux

Le tableau suivant répertorie les événements définis pour les récepteurs de flux génériques. Les récepteurs de flux peuvent également envoyer des événements personnalisés non répertoriés ici.

Événement Description
MEStreamSinkFormatChanged Le type de média du récepteur de flux n’est plus valide. (Facultatif.)
MEStreamSinkMarker Un marqueur a été traité. (Obligatoire.)
MEStreamSinkPaused Le récepteur de flux a été suspendu. (Obligatoire.)
MEStreamSinkPrerolled Le préroll est terminé. (Facultatif.)
MEStreamSinkRateChanged Le récepteur de flux a changé le taux de lecture. (Facultatif.)
MEStreamSinkRequestSample Un nouvel exemple est demandé. (Obligatoire.)
MEStreamSinkScrubSampleComplete Une demande de nettoyage a été effectuée. (Facultatif.)
MEStreamSinkStarted Le récepteur de flux a démarré. (Obligatoire.)
MEStreamSinkStopped Le récepteur de flux s’est arrêté. (Obligatoire.)

 

Actuellement, aucun événement à usage général n’est défini pour les récepteurs multimédias. Certains récepteurs multimédias peuvent envoyer des événements personnalisés.

Media Foundation Pipeline

Architecture Media Foundation