Dans ce chapitre, nous présentons la deuxième partie du système de présentation : le gestionnaire de présentation qui fonctionne de façon complémentaire avec la machine d'exécution. Il se charge d'exécuter les fonctions de présentation de bas niveau, c'est-à-dire celles qui sont liées au système d'exploitation, au système de communication et aux périphériques de présentation. Ce composant se charge d'exécuter la présentation des objets média à travers le contrôle des codes binaires qui se chargent d'effectuer le traitement associé à chaque type et format de média. Il met en oeuvre les mécanismes de communication nécessaires entre les objets média d'une part et entre ces objets et l'ordonnanceur de Madeus d'autre part. Il gère également l'initialisation et le contrôle des périphériques de présentation ainsi que l'accès aux objets média locaux et distants. De par ces fonctions système de bas niveau, le gestionnaire de présentation dépend du type de plate-forme. Dans ce chapitre, nous présentons le gestionnaire de présentation pour Madeus version 1.0 qui a été réalisé pour le système Solaris 2.5 et le système Linux.
Le plan du chapitre est le suivant. Nous présentons d'abord l'architecture générale du gestionnaire de présentation (voir section 2) puis, nous décrivons les fonctions des différents composants du gestionnaire de présentation : le gestionnaire d'accès (voir la section 3), le gestionnaire d'exécution (voir la section 4) et, enfin, le gestionnaire de périphérique (voir la section 5).
Les traitements permettant la présentation des objets média à l'utilisateur dépendent de la nature du média (audio, vidéo, texte, image, etc.). Pour les données comme le texte et les interactions utilisateur, leur représentation interne dans le document est suffisante pour réaliser leur rendu à l'écran (voir cas 1 dans la Fig 1 ). Par contre, les objets comme l'audio, la vidéo et les images, les données sont stockées dans des bases de données externes sur un disque local ou un serveur distant (voir cas 2 dans la Fig 1 ). Ces différents objets nécessitent donc différents traitements avant leur restitution à l'écran ou sur les périphériques matériels. Ces traitements sont identifiés au moment de la création de chaque objet média par une opération appelée configuration d'un objet média. Cette configuration consiste à créer pour chaque objet les modules nécessaires à son exécution. Dans notre système, les traitements sont organisés en trois modules :
Fig 1. Modules de traitement des objets de base
Le gestionnaire de présentation se charge de créer les modules cités ci-dessus. Il effectue les fonctions de présentation qui dépendent des plates-formes, c'est-à-dire du système d'exploitation, des périphériques de présentation et du système de communication. Il gère également les interactions utilisateur en permettant la modification des paramètres comme la taille de la fenêtre de présentation et le volume audio. L'architecture du gestionnaire de présentation, illustrée dans la Fig 2 , est organisée autour de trois composants principaux : le gestionnaire d'accès, le gestionnaire d'exécution et le gestionnaire de périphérique qui créent respectivement le module source, le module de traitement et le module destination.
Fig 2. L'architecture du gestionnaire de présentation
Le gestionnaire d'accès est la partie de l'application qui est responsable du chargement des objets média et, à ce titre, il joue un rôle important dans la performance du système de présentation. Le temps qui s'écoule entre le lancement d'une requête de chargement et le chargement effectif (round trip) doit être le plus court possible.
Un objet média peut être stocké sur un serveur local ou sur un serveur distant. Afin de limiter ces délais, en particulier pour les objets média continus (comme l'audio et la vidéo), ils doivent être chargés et présentés au fur et à mesure sous forme d'un flot limité (en cas de clips enregistrés) ou infini (en cas de diffusion en direct). Un problème directement lié à ce processus cyclique consiste d'une part à assurer la disponibilité des données et d'autre part au respect des contraintes temps réel liées à leur traitement. Un flot irrégulier dont le débit est inférieur à la vitesse de présentation des objets média produit de la gigue. De même, un temps de traitement dépassant les contraintes temps réel requises produit également de la gigue. De plus, les traitements de données multimédia ne peuvent s'opérer à temps lorsque les données ne sont pas disponibles. Cela illustre le lien étroit qui existe entre les flots de données et les flots d'exécution (traitements) dans un système multimédia. Par conséquent, il est indispensable de pouvoir synchroniser ces deux flots. Un choix important est alors de déterminer le lieu où doit s'opérer cette synchronisation : du côté client ou du côté serveur.
Dans cette section, nous décrivons l'architecture du module de l'application chargé des accès réseau. En particulier, nous présentons le schéma de désignation des objets média distants et le principe de fonctionnement du gestionnaire d'accès. Deux protocoles complémentaires HTTP et RTSP sont à la base de la solution retenue. Le principe de fonctionnement de ces protocoles est présenté à travers l'expérimentation menée dans Madeus.
Madeus utilise le même schéma de désignation que celui employé par le World Wide Web : l'URI (Uniform Resource Identifier). Un URI est une adresse unique qui permet de localiser un objet d'information. De manière générale, un URI est composé de quatre parties principales :
Ces parties sont spécifiées dans l'ordre suivant :
protocole://adresse_machine/chemin_d'accès/nom_objetAinsi, un URI d'un objet média de notre système peut être :
http://samar.inria.fr/objets/video/video2.mpg rtsp://aruba.inria.fr/objets/audio/audio3.wavPar contre, les objets locaux sont désignés par leur simple chemin d'accès comme :
~/mmedia/audio/au/histoire.auLa Fig 3 illustre l'opération d'accès aux objets média qu'ils soient locaux ou distants. À partir d'une instance d'un objet média créé par le gestionnaire d'objets, l'opération d'accès aux données commence par l'envoi d'une demande adressée au gestionnaire d'accès. Ensuite, ce gestionnaire localise les données média (résolution du nom du serveur) et identifie le protocole à partir de l'URI fourni. Il crée alors un tampon de données qui stocke provisoirement les données récupérées. La taille de ce tampon est déterminée (calculée) soit par le gestionnaire de synchronisation si la technique de préchargement est appliquée (voir la section 4.2 du chapitre IV), soit par l'objet média lui-même si une stratégie spécifique lui est appliquée. Par exemple, certains plugins, comme mpegTV, prennent en charge la gestion de leur tampon. Dans ce cas, le gestionnaire d'accès se limite à transmettre les données au plugin dès leur réception.
Fig 3. Fonctionnement du Gestionnaire d'accès
Les besoins d'une application multimédia en terme d'accès distant peuvent être subdivisés en deux catégories. La première catégorie concerne les objets média dont la présentation ne dépend pas d'un flot continu de données externe (comme les objets média discrets et le fichier de spécification du document). Les images stockées sur des serveurs distants forment un cas particulier de cette catégorie. En effet, elles ne nécessitent qu'un seul accès distant mais leur traitement peut être effectué de façon progressive (comme le cas du format PNG [W3C 96]). La deuxième catégorie correspond aux média continus dont le traitement, et donc le transfert de leur contenu, est soumis à des contraintes temps réel. Ces catégories nécessitent des protocoles adaptés dont les caractéristiques diffèrent selon les critères suivants :
Les protocoles d'accès que nous avons choisis sont le protocole HTTP (HyperText Transfer Protocol) et le protocole RTSP (Real Time Streaming Protocol). Les caractéristiques de ces protocoles conviennent aux deux catégories citées ci-dessus. Dans la suite de cette section, nous décrivons ces deux protocoles ainsi que leur intégration aux sein du gestionnaire d'accès.
HTTP est un protocole du niveau application dans la classification des couches réseau. À ce titre, il a été conçu pour servir de support de base aux transferts réseau au sein des systèmes d'information distribués. C'est un protocole générique qui peut être utilisé pour des tâches diverses, telles que des serveurs de noms et des systèmes de gestion d'objets distribués, à travers l'extension de ses méthodes (commandes).
HTTP est basé sur le modèle client-serveur. L'interaction entre le client et le serveur est spécifiée dans le protocole à travers un ensemble de méthodes. Madeus, en tant qu'application cliente, utilise les méthodes clientes pour demander des services particuliers aux serveurs Web. Ces méthodes sont :
HTTP est un protocole dit sans état (version 1.1) parce qu'il n'existe pas de notion de session : un serveur n'a pas la possibilité de garder l'information d'un état après le traitement d'une requête. Cette caractéristique permet aux serveurs de traiter de nouvelles requêtes des clients indépendamment des autres requêtes émises précédemment. Si la notion d'état s'avère nécessaire, celle-ci doit être préservée par le client et doit être passée au serveur comme paramètre de la requête. Il s'agit dans ce cas d'un moyen détourné qui ne couvre pas tous les cas. En particulier, même en utilisant cette technique, il est impossible de gérer une session qui nécessite une exécution prolongée dans le temps et ayant des contraintes temps réel du côté serveur. La seule façon d'obtenir des transferts adaptatifs est de réaliser cette tâche du côté du client.
Un point fort du protocole HTTP est son indépendance par rapport au format de l'information qui est transmise. Cela permet l'extension des services des clients pour stocker de nouveaux formats de données et d'informer les clients sur ces nouveaux formats à travers le type MIME.
RTSP est un protocole temps réel qui a été conçu pour transférer et contrôler un ou plusieurs flux synchronisés d'objets média continus comme la vidéo et l'audio. Le protocole est fondé sur le modèle client-serveur. Il permet le contrôle de la présentation d'un objet média en agissant sur le flot de données transmis entre le client et le serveur. Autrement dit, les commandes de contrôle de la présentation d'un objet média (comme démarrer, stopper, faire une pause, etc.) sont traduites sous forme de requêtes d'accès RTSP envoyées par le client et exécutées par le serveur.
RTSP est un protocole avec états qui utilise la notion de session. Cette caractéristique est importante pour effectuer le transfert de média continus. En effet, la présentation d'objets de type média continus est caractérisée par une évolution entre différents états de présentation, comme les états Unmapped, Mapped, Active, Terminated et Suspended (voir les états d'exécution des objets en section 5.1.2). L'évolution des transferts de données effectués au moyen du protocole RTSP est décrit par une machine d'états associée au client et au serveur. Le serveur change d'état quand il reçoit une requête du client, et le client change d'état quand il envoie une requête au serveur.
Pour chaque transfert de données, le serveur RTSP maintient une session qui est désignée par un identificateur unique. Pendant une session, le client RTSP peut ouvrir et fermer plusieurs connexions de transport avec le serveur RTSP en utilisant l'identificateur de cette session et en gardant la correspondance entre l'état courant du côté client et celui du côté serveur. Ces connexions sont établies afin d'échanger les requêtes RTSP entre le client et le serveur. Ces requêtes peuvent être des requêtes d'initialisation de session, de transfert de données et de contrôle de ces flots de données.
Les différentes requêtes RTSP sont définies à travers un ensemble de méthodes (voir la Fig 4 ). Les principales méthodes sont :
Fig 4. Le fonctionnement de RTSP
La notion de session dans RTSP est très importante pour le transfert de données sous contraintes temporelles. Car, en plus du transfert de données proprement dit, RTSP maintient une horloge qui est associée à chaque objet média transmis. C'est cette horloge qui permet de déterminer, à chaque instant, si une portion de donnée à transmettre a déjà dépassé son échéance. Dans ce cas, il est inutile de l'envoyer au client qui la rejetterait à sa réception. RTSP permet donc la mise en oeuvre de stratégies de filtrage des données du côté du serveur et donc à la source.
Dans l'exemple de la Fig 5 , nous proposons une technique de filtrage dans Madeus. L'exemple présenté consiste à la transmission d'un flot audio encodé en WAV de fréquence 44.1 Khz (nécessite une bande passante de 28.8 Kbps) entre un serveur RTSP et le gestionnaire d'accès de Madeus. Pendant la transmission de ce flot de données, une baisse de la bande passante (à 19.2 Kbps) nécessite une adaptation de la qualité de l'audio pour éviter une perte brute d'un paquet sur 3.
Il existe alors plusieurs façons de réaliser cette adaptation pour maintenir la fluidité du transfert entre le client et le serveur. La première façon, que nous qualifions de méthode naïve, consiste à filtrer, du côté serveur, 2 paquets sur 3 à transmettre (cas 1 dans la Fig 5 ). Ce filtrage introduit des zones de silence dans l'audio avec des zones audio dont la qualité est de 44.1 Khz et produit le même résultat que le cas de perte. La deuxième façon consiste à réduire la qualité globale de l'audio en préservant tout son contenu. Pour atteindre cet objectif, nous proposons une technique fondée sur le remplissage des paquets de façon entrelacée (cas 2 dans la Fig 5 ). Le principe est que la perte d'un paquet ou son filtrage résulte sur une perte d'un échantillon de base (un octet) sur trois présentés à l'utilisateur du côté client. Mais une interpolation, effectuée par le client, permet de combler cette perte et ne résulte que sur une réduction limitée de la qualité de l'audio. Ce principe est appliqué pour l'audio sur des données compressées avec le même effet que sur des données non compressées. Le codage WAV ne porte pas cet entrelacement des échantillons dans son format. Le serveur que nous proposons prend donc en charge cette fonction d'entrelacement. Pour d'autres formats comme RealAudio qui contiennent un codage avec entrelacement, la tâche du serveur est alors allégée.
Pour les objets média comme la vidéo ce même principe peut être appliqué. La seule différence se situe au niveau des échantillons de base. Pour le cas du format Mpeg, un échantillon de base peut être l'image ou encore des pavés de 16X16 pixels appelés (Macro blocs). Ces données, étant plus structurées que l'audio, ils ne peuvent être dissociés au niveau de la transmission.
Fig 5. Adaptation de la qualité de l'audio dans Madeus
Au niveau du protocole, RTSP permet de surveiller la qualité de la transmission à travers RTCP. Pour cela, le client émet périodiquement à destination du serveur (boucle de contrôle ou feed-back) des rapports sur la qualité de la transmission, contenant le pourcentage et le nombre de paquets perdus, le délai de transmission, la gigue, etc. Le serveur reçoit ces rapports et apprécie s'il y a congestion. Dans ce cas, la source réduit alors le débit émis (contrôle de flux). Dans le gestionnaire d'accès, la diminution du débit, et donc l'adaptation qui en résulte, a lieu chaque fois qu'une résynchronisation avec le serveur est nécessaire.
Dans Madeus, l'adoption du protocole HTTP pour l'accès aux objets discrets (comme les images, le texte et les données média de plugins) et aux fichiers de spécification du document est justifié à plusieurs niveaux. En effet, la nature des traitements effectués sur ces données nécessite qu'ils soient récupérés en une seule transaction (comme la requête HTTP GET). Un protocole sans état est donc approprié car aucune contrainte temporelle sur ces transferts ne justifie la création d'une session, celle-ci servant essentiellement à la supervision des transferts sur une période de temps prolongée et à la synchronisation du client et du serveur. De plus, les données en question ne sont pas de nature à tolérer les pertes.
L'utilisation du protocole RTSP pour l'accès aux objets continus (comme la vidéo et l'audio) est une solution adaptée. D'une part, l'accès et la présentation de ces objets doivent être effectués de façon progressive. Il en résulte que les accès sont effectués au moyen de plusieurs requêtes : initialisation de session, de transfert de données et de contrôle de flots de données. D'autre part, le transfert de données de ces objets doit être effectué en respectant des contraintes temporelles, un protocole avec état est donc requis. Cela permet, en plus de la gestion de la synchronisation au niveau du transfert, de mettre en place une stratégie de filtrage de données du côté serveur, qui est une condition indispensable pour respecter les contraintes temporelles malgré les variations de débit. De plus, ces objets sont encodés de façon à tolérer les pertes.
RTSP procure une vision long terme pour la gestion de la qualité de service au sein de l'application Madeus. Car, si la gestion de la synchronisation est prise en compte dans le protocole, les techniques de filtrage des données sur le serveur peuvent être élaborées au fur et à mesure de l'apparition de nouveaux formats. La seule difficulté qui subsiste est l'identification de la technique d'adaptation qui convient le mieux à l'application cliente. En effet, un serveur RTSP ne peut prédire les besoins de l'ensemble des applications qui devront se restreindre aux techniques d'adaptation disponibles sur le serveur. Un exemple type de ce genre de situation est la technique de saut de paquets d'audio présentée en section 3.3.2. Si le serveur filtre les paquets selon le cas 1, il risque d'introduire de la gigue dans l'audio alors que le cas 2 préserve mieux son intelligibilité. Un serveur RTSP doit donc avoir une connaissance du format pour fournir de bonnes stratégies d'adaptation de la qualité. Et même dans ces conditions, un client peut avoir une stratégie différente qui n'est pas disponible au sein du serveur. C'est cet aspect qui constitue la principale limitation de la gestion de la qualité de service avec le protocole RTSP.
Le but du gestionnaire d'exécution est de fournir les mécanismes permettant l'exécution d'une présentation multimédia. Il sert aussi de support d'exécution pour les formats de documents comme celui de Madeus ou même de SMIL (voir les principes de Madeus en section III.2.1). L'utilisation de ce gestionnaire comme plate-forme pour le support d'exécution d'autres formats pourra être envisagée ultérieurement.
Afin d'être en mesure de supporter les différents formats, nous avons défini un modèle à objet primitif qui ne retient que les aspects essentiels des modèles fondés sur les notions d'objets média, d'objets composites et de synchronisation. Dans ce modèle, les principales abstractions définies sont les instances d'objets média, les classes, les types et les méthodes correspondant au comportement générique des objets média (par exemple PlayObject, PauseObjet, etc.). Nous présenterons par la suite la gestion des valeurs d'attributs au sein du gestionnaire d'exécution qui permet d'assurer leur mise à jour en fonction du temps.
Dans notre modèle, les classes et les instances sont séparées. Une instance est un exemplaire d'une seule et unique classe et contient une référence vers cet objet de type classe. La seule façon d'accéder à un objet est d'appeler une méthode sur cet objet. Ces méthodes correspondent, dans le modèle qui nous intéresse, aux primitives de synchronisation présentées dans le chapitre précédent, c'est-à-dire les méthodes définies dans la classe Interval comme MapObject, PlayObjet, PauseObject, ResumeObject, etc. Nous décrivons ici leur mise en oeuvre au sein du gestionnaire d'exécution de Madeus.
Les différents types d'objets média nécessitent des traitements variés lors de leur présentation (comme par exemple la décompression des données, l'allocation d'une table de couleurs, etc.). Au sein du gestionnaire d'exécution, ces différents traitements correspondent à des codes binaires différents. Afin de réaliser cette correspondance, un traitement particulier appelé opération de liaison lie un objet média aux codes binaires spécifiques permettant son exécution. Ce traitement est effectué en deux étapes :
L'opération de liaison permet de retrouver des informations plus précises que celles fournies par le gestionnaire d'objets qui se charge uniquement de déterminer le type des objets. La correspondance entre un objet de base et les modules de traitement offerts par l'application est réalisée par l'intermédiaire d'une table (voir la Fig 6 ) qui contient les informations sur les formats supportés (voir le médiateur d'objets en section 5.2). Chaque entrée de la table est composée des deux champs suivants :
Fig 6. Opération de liaison
Le code de traitement est intégré dans l'application de différentes façons en fonction de la caractéristique de chaque type d'objet média :
Dans les sous-sections suivantes, nous présentons la mise en oeuvre des opérations de liaison pour le cas des librairies dynamiques, ainsi que pour celui des processus externes.
La liaison dynamique est une opération par laquelle du code binaire, sous forme d'une librairie dynamique comme les plugins de Netscape [Netscape 98a], peut être attaché et détaché dynamiquement à une application pendant son exécution. Dans Madeus, la liaison dynamique ou la technique plugin est fondée sur l'emploi d'une interface standard des deux côtés : du côté de l'application Madeus et du côté du code de plugin. De chaque côté, l'interface est représentée sous forme d'un ensemble de fonctions dont le nom et l'adresse sont maintenus dans la table des symboles du code binaire. Cela permet au gestionnaire d'exécution d'avoir accès, à l'exécution, aux fonctions du plugin et vice versa. Ces fonctions (voir Fig 7 ) gèrent :
Le Plugin SDK (Plug-in Software Development Kit) [Netscape 98b] de Netscape est un exemple d'une interface générique entre le navigateur Netscape et les plugins.
Fig 7. La technique plugin
Le code de plugin est créé de telle sorte qu'il puisse être utilisable au sein d'une autre application, comme un autre navigateur web ou encore une application multimédia. Ce code est donc compilé avec les fonctions d'interface côté plugin afin de produire une librairie dynamique. Lors de la présentation, quand l'ordonnanceur donne la commande de démarrage d'un objet média supporté par un plugin, le gestionnaire d'exécution effectue dynamiquement l'édition de liens avec la librairie correspondante.
Le résultat de l'édition dynamique est la création de deux tableaux de fonctions : T1 du côté Madeus et T2 du côté plugin (voir la Fig 7 ). Le tableau T1, créé du côté Madeus, contient des pointeurs vers les fonctions d'interface du côté plugin. De même, le tableau T2, créé du côté plugin, contient des pointeurs vers les fonctions d'interface du côté Madeus. Pour faire cela, Madeus utilise les fonctions système qui manipulent les librairies dynamiques, comme par exemple :
dlopen
rend la librairie dynamique disponible pour un processus
en cours d'exécution,
dlsym
récupère l'adresse d'un symbole dans la
librairie dynamique,
dlerror
donne des diagnostics sur la dernière erreur qui a
eu lieu pendant l'édition de liens dynamique,
dlclose
détache la librairie dynamique du processus en
cours d'exécution.
Les plugins que nous avons testés au sein de Madeus sont les suivants :
Les processus externes sont utilisés pour les objets média qui nécessitent des ressources CPU importantes. Il s'agit principalement d'opérations de calcul permettant la décompression des données. L'emploi de processus externes permet de limiter les perturbations de ces calculs sur l'ordonnancement effectué par Madeus. En effet, la plupart des systèmes d'exploitation de type best effort tente d'allouer de façon équitable le temps de calcul entre les différents processus, en particulier, le processus de l'application Madeus dont on cherche ici à préserver au mieux le temps de calcul.
Dans cette sous-section, nous présentons la gestion de ces processus externes au sein du gestionnaire d'exécution de Madeus. Nous montrons comment ce procédé permet d'étendre les types d'objets de base tout en ayant la même flexibilité que les plugins.
Lancement de processus externes
Du point de vue de la réalisation, le gestionnaire d'exécution
s'appuie sur les primitives du système d'exploitation UNIX. En
particulier, les deux primitives vfork et execv sont
utilisées pour la création et le lancement des processus
externes. La primitive vfork [Rifflet 93] permet à un processus (appelé le processus
père) de créer un nouveau processus (appelé le
processus fils). L'avantage principal de cette primitive est
d'économiser l'espace mémoire car aucune copie des
données du processus père n'est effectuée, au contraire
du cas de la primitive fork
.
Au moment du lancement d'un processus externe, le processus fils a cependant besoin provisoirement des données physiques de son père afin d'initialiser un ensemble de variables, en particulier, les numéros des ports de communication entre Madeus et ce processus externe. Il faut donc résoudre les conflits d'accès à la mémoire (effectués en exclusion mutuelle) entre les deux processus pendant cette période de temps.
Une première solution consiste à bloquer le processus père jusqu'à ce que le processus fils se termine. Dans le cas de notre réalisation, cette solution n'est pas concevable car bloquer le processus Madeus revient à bloquer toutes les opérations d'ordonnancement produisant ainsi une désynchronisation importante.
La deuxième solution, qui est celle adoptée, consiste alors
à détacher le processus fils le plus tôt possible. La
primitive de détachement execv
permet à un
processus appelant, le processus fils dans ce cas, de charger en
mémoire un nouveau programme binaire. Madeus est alors bloqué
uniquement pour une courte période de temps afin que le processus fils
puisse préparer les arguments passés au nouveau programme (voir
la Fig 8 ). Ce chargement a pour effet d'écraser
l'espace d'adressage du processus appelant en chargeant le nouveau programme
dans le même espace d'adressage et en l'exécutant sur des
nouvelles données. Par ailleurs, il est important de noter qu'il n'y a
pas de création d'un processus supplémentaire au cours du
détachement. On obtient ainsi une perturbation très minime du
processus Madeus, en préservant au maximum la disponibilité de
son ordonnanceur.
creer_processus
()
{
switch
(vfork ()) {
case
0: /*** Le processus fils ***/
/*
Préparation des arguments passés au programme "player",
comme
le numéro de port de communication, etc. */
execv("player",
arguments);
default: /*** Le
processus père (Madeus) ***/
/* Madeus
continue son exécution en parallèle avec celle
de
player sans blocage */
}
Synchronisation du début de présentation de deux processus externes
De façon générale, la présentation d'un objet média est précédée par un certain nombre d'opérations comme l'accès aux données et à leur traitement. Ces opérations ne conduisent pas directement à une restitution de contenu à l'utilisateur. Elles sont effectuées pendant des délais ayant des valeurs aléatoires dues à une disponibilité imprévisible des ressources système. Ces délais peuvent causer un décalage entre les débuts de présentation des objets synchronisés par le début, comme dans les relations equals, starts et lipsync, surtout dans le cas où la présentation de chaque objet média est réalisée sous forme d'un processus externe.
Considérons l'exemple d'une relation de synchronisation par le début entre deux objets dont la présentation est réalisée sous forme de deux processus externes. Le début de la présentation des deux objets doit être déclenché au même instant (au sens du lancement de l'exécution).
Dans Madeus, nous résolvons ce problème en utilisant les tubes nommés (en anglais, named pipes ou fifos) [Rifflet 93] comme moyen de synchronisation. Ceux-ci ont les mêmes caractéristiques que les tubes ordinaires, c'est-à-dire :
Fig 9. Synchronisation du début de l'exécution de deux processus
Fig 10. Communication entre deux processus liés par une synchronisation fine
Les tubes nommés ont la propriété supplémentaire
de posséder des références dans le système de
gestion de fichiers. C'est cette propriété qui permet à
tout processus connaissant la référence d'un tube d'obtenir au
travers de la primitive open
un descripteur en lecture et/ou un
descripteur en écriture pour communiquer avec d'autres processus par
l'intermédiaire de ce tube. Ils se comportent de façon
particulière lors de leur ouverture : lorsqu'un processus ouvre un tube
nommé en écriture (open (fifo1,écriture) sur la
Fig 9 ) il se bloque jusqu'à ce qu'un autre
processus ouvre le même tube en lecture (open (fifo1,lecture)
sur la Fig 9 ), et vice versa. Cette
propriété est exploitée pour assurer la synchronisation
des débuts de processus. L'exemple de la Fig 9
montre deux processus proc1 et proc2 liés par une
relation de synchronisation par le début. Le processus Madeus s'occupe
de créer les deux tubes nommés fifo1 et fifo2
en utilisant la commande mkfifo et chaque processus les ouvre en
spécifiant le mode d'accès approprié. La primitive
open
dans la Fig 10 joue le rôle d'un
point de rendez-vous entre les deux processus pour synchroniser l'instant de
début de présentation. Ces tubes sont utilisés
également comme moyen de communication entre les deux processus pour
transmettre des commandes et des données de synchronisation entre un
maître et un esclave (voir section 4.2.).
Dans la section 4.2, nous avons montré que les objets média sont des objets actifs qui doivent communiquer entre eux et avec l'ordonnanceur pour des raisons de synchronisation. C'est le gestionnaire d'exécution qui fournit ce service.
Le mode de communication entre deux entités actives du gestionnaire d'exécution dépend du mode de codage de l'objet : librairie statique, librairie dynamique ou processus externe. Les librairies statiques ainsi que la librairies dynamiques partagent le même espace d'adressage que l'application Madeus (processus unique). Ils peuvent donc communiquer simplement à travers des appels de procédures qui gèrent l'échange d'informations entre ces objets. Par contre, chaque processus externe possède son propre espace d'adressage. Les techniques de communication entre processus (Inter Process Communication IPC) ainsi que les signaux et les tubes (pipes) sont alors les seuls moyens qui permettent d'établir une communication entre eux et avec le processus Madeus. Le tableau de la Fig 11 illustre les modes de communication possibles entre deux objets média en fonction de leur mode de codage.
Le gestionnaire d'exécution choisit le mode de communication adapté en fonction du mode de liaison du code des objets. Lors de la création d'un processus externe, le gestionnaire crée un moyen de communication avec le processus Madeus afin de permettre à l'ordonnanceur de le contrôler. Ce moyen de communication est mis en oeuvre sous forme de socket qui permettent une communication bidirectionnelle.
Les objets liés par une relation de synchronisation fine communiquent de deux façons : au moyen de tubes nommés pour transmettre les paramètres de synchronisation et au moyen d'un signal SIGNAL pour la notification de la fin des périodes de synchronisation Deltasync (voir la Fig 10 ). Les signaux permettent une prise en compte immédiate de la notification entre deux processus. Ils permettent ainsi de réduire au maximum les délais d'attente liés à l'acheminement de messages entre deux processus. Ce sont ces deux méthodes de communication qui permettent la mise en oeuvre de l'algorithme de synchronisation fine présenté en section 4.2.3. La Fig 12 montre le pseudo-code de la procédure qui gère la présentation d'un objet continu. Avant d'entrer dans la boucle de décompression et de présentation, la procédure Gestion_Sync est désignée pour être le traitant du signal de notification (voir lignes 2-4 de la figure Fig 12 ).
Jouer_Objet () {
1. ...
2. /* Définir la fonction
Gestion_Sync comme un
3. gestionnaire du
signal SIGNAL */
4. signal (SIGNAL,
Gestion_Sync);
5. ...
6. /* Initialiser le compteur
d'untiés présentées */
7. compte = 0;
8. /* Boucle de décompression
et de présentation */
9. Tandis que (VRAI)
{
10. ...
11. Si
(Maître) {
12. À
la fin de chaque Deltasync faire {
13. /*
Envoyer à l'Esclave les informations sur :
14. 1)
l'état actuel de la progression de la
15. présentation
du Maître
16. 2)
le temps courant au moment de l'envoi */
17. info.compte
= compte;
18. info.taux
= taux_de_présentation;
19. info.tei
= gettimeofday ();
20. write
(fifo1, info);
21. /*
Envoyer à l'Esclave une notification de
22. synchronisation
*/
23. kill
(Esclave.pid, SIGNAL);
24. }
25. }
26. ...
27. compte = compte + 1;
28. } }
Fig 12. Pseudo-code de la procédure gérant la présentation des objets continus
À la fin de chaque période de synchronisation Deltasync (ligne 12), le maître transmet les informations sur son état actuel au moyen d'un tube nommé fifo1 (lignes 13-20). Ensuite, le maître envoie à l'esclave le signal SIGNAL pour lui notifier l'arrivée d'informations de synchronisation sur le tube fifo1(lignes 21-23). À la réception de ce signal, l'esclave interrompe son exécution immédiatement et exécute la procédure Gestion_Sync.
La procédure Gestion_Sync permet à l'esclave de lire les informations sur le tube fifo1 (voir les lignes 2-4 de la figure Fig 13 ) et de calculer la dérive entre les deux objets (lignes 5-17). Ensuite, en fonction de la valeur de cette dérive, l'algorithme de synchronisation fine est appliqué pour aligner temporellement les deux objets (lignes 18-23). Si l'esclave est en retard par rapport au maître et aucune technique d'adaptation n'est employée (comme le préchargement ou le saut d'images vidéo), il demande au maître de se bloquer pour une période de temps calculée (lignes 24-28). Dans ce cas, l'esclave écrit la valeur de cette période dans le tube fifo2 qui est lue par le maître après la réception du signal SIGNAL déclenché par l'esclave (lignes 31-34).
Gestion_Sync () {
1. Si
(Esclave) {
2. /*
Recevoir les informations de synchronisation
3. envoyées
par le Maître */
4. read
(fifo1, info);
5. /* Obtenir le
temps courant au moment de la
6. réception*/
7. tri =
gettimeofday ();
8. /* Calculer les
temps de la progression de
9. présentation
du Maître (tmaître) et celui
10. de
l'Esclave (tesclave) en terme du nombre
11. d'unités
présentées par chacun */
12. tesclave=esclave.numéro_unité_courante/esclave.taux;
13. tmaître
= info.compte/info.taux;
14. /* Calculer le
délai de communication deltacom */
15. deltacom =
tri - info.tei;
16. /* Calculer la
dérive entre le Maître et l'Esclave */
17. dérive =
tesclave - tmaître - deltacom;
18. Si
(dérive > Deltadérive) { /* Esclave
en avance */
19. /*
Bloquer l'Esclave pour une période = dérive */
20. }
21. Si
(dérive < -Deltadérive) { /*
Esclave en retard */
22. Si
(Esclave est adaptable) {
23. Adapter_Esclave
();
24. }
Sinon { /* Ralentir le Maître */
25. info.délai
= |dérive|;
26. write
(fifo2, info);
27. kill
(Maître.pid, SIGNAL);
28. }
29. }
30. }
31. Si (Maître)
{
32. read
(fifo2, info, n);
33. /* Bloquer le
Maître pour une période = info.délai */
34. } }
Quand un objet atteint la fin de sa présentation, le gestionnaire d'exécution ferme et détruit le canal de communication qui le reliait à cet objet.
Les traitements liés à la synchronisation fine présentent un caractère d'urgence dans leur prise en compte par le système. Les signaux apparaissent alors comme la solution idéale. En fait, dans un système de type best effort, le temps qui sépare le déclenchement d'un signal et sa prise en compte dépend fortement de la charge de la machine. Ce délai varie entre 40 mu sec pour un système faiblement chargé à l'ordre de la seconde pour un système surchargé. Nous avons du prendre en compte ces délais de communication (lignes 14-15 de la figure Fig 13 ) pour aligner temporellement et de façon plus précise deux processus en synchronisation fine.
Une présentation Madeus possède comme principale caractéristique l'évolution de son état à travers le temps. Ce changement d'état peut être le résultat d'une interaction utilisateur ou encore d'un changement dans l'état d'exécution d'un objet média. Au niveau le plus bas du système, tous ces changement se traduisent par l'échange d'un ensemble d'événements. L'occurrence de chaque événement résulte sur le déclenchement d'un traitement particulier au sein du système de présentation. La gestion d'événements est donc un élément central dans la mise en oeuvre du gestionnaire d'exécution. Nous avons adopté un modèle de communication à base d'événements asynchrones dans Madeus car les entités actives du système d'exécution (ordonnanceur, objets média, accès aux flots de données) ne toléraient pas la notion d'attente [Lenormand 96]. En effet, ces entités obéissent à des contraintes temps réels qui doivent être respectées. Par exemple, l'arrêt de la présentation d'une vidéo dans le but de notifier l'apparition d'un personnage nuit à la qualité de la présentation.
Dans cette section, nous présentons le modèle d'événements qui permet la coordination des différentes activités de présentation dans Madeus. En particulier, nous décrivons le mode de fonctionnement de ce modèle ainsi que la manière dont les événements sont décrits, traités et utilisés au sein du gestionnaire d'exécution.
Un modèle d'événements permet de définir les types, les sources et les destinations des événements ainsi que les opérations qui leur sont appliquées. Le modèle est fondé sur deux principes simples.
Le principe de réaction est mis en oeuvre au moyen d'un ensemble de fonctions qui permettent de prendre en charge les différents événements produits par les différentes sources. Pour lier un événement à sa fonction de traitement, un ensemble de mécanismes doivent être fournis. Ces mécanismes sont la désignation, la déclaration et l'abonnement aux événements.
Fig 14. Modèle d'événements de Madeus
Les informations sur les événements déclarés et les objets abonnés sont maintenues par le gestionnaire d'événements au sein de l'ordonnanceur (voir Fig 14 -(1)). Ce gestionnaire se charge de véhiculer les messages de notification aux objets abonnés. Le gestionnaire d'exécution, à travers la boucle d'événements, permet de collecter les événements externes produit par l'environnement : le temporisateur, l'interface graphique et les ports de communication (voir Fig 14 -(2)). Par défaut, l'ordonnanceur est abonné à tous les événements de début et de fin des différents objets.
Dans la section 4, nous avons présenté l'ordonnanceur de Madeus qui est fondé sur une approche prédictive-réactive. L'aspect prédictif concerne tous les traitements qui ont besoin, à un instant donné de la présentation, d'une connaissance du futur (obtenue à partir de l'hypergraphe). L'aspect réactif, présenté ici, concerne la synchronisation inter- et intra-objets qui est fondée sur les événements et les traitements liés à leurs réactions.
Types et sources d'événements dans Madeus
En fonction de leur origine, les événements de présentation appartiennent à deux classes distinctes : les événements internes et les événements externes. Les événements internes sont générés de façon directe par les objets média pendant leur présentation. Un objet média peut générer principalement trois types d'événements :
Par contre, les événements externes sont générés par d'autres composants qui représentent l'environnement externe de l'application Madeus (lecteur du document, les accès réseau, l'horloge temps réel). Les sources d'événements externes sont les suivantes :
Désignation d'événements
Les événements de présentation sont échangés au sein du processus de l'application Madeus ainsi que dans toutes les activités créées lors d'une présentation multimédia. La représentation de ces événements au sein de l'ensemble de l'application est réalisée par des structures de données internes qui comportent les informations suivantes :
Avant de pouvoir utiliser un événement dans le système d'exécution, il est d'abord nécessaire de le déclarer. Cette opération est effectuée à partir des deux informations cités ci-dessus.
Déclaration d'événements
La déclaration d'un événement est effectuée en deux étapes : pendant la spécification d'un objet média et pendant sa création. Pendant la spécification d'un objet média, l'auteur déclare l'ensemble des événements susceptible d'intervenir dans la présentation sous forme de points de synchronisation. Chacun de ces points est désigné par un nom unique et daté par l'instant de son occurrence. Cette datation peut être effectuée de manière indirecte et rapportée à un des événement internes de l'objet. Par exemple, dans la Fig 15 , l'objet vidéo, nommé Clip, l'attribut Events permet de déclarer trois événements (ou points de synchronisation). Ces événements (evmnt1, evmnt2, evmnt3 et evmnt4) correspondent respectivement aux instants temporels qui correspondent à l'occurrence des 500, 750, 1000 et 1200ème images de la présentation de l'objet vidéo.
<Video Name = "Clip"
...
Events
= "evmnt1 500 image
evmnt2
750 image
evmnt3
1000 image
evmnt4
1200 image"
...
Actions
= "evmnt2 MOVE"
... />
<Text Name = "Titre"
...
Actions
= "evmnt1 START
evmnt3
STOP"
...
/>
Fig 15. Déclaration d'événements et abonnement d'objets aux événements
Pendant la création d'un objet, le gestionnaire d'événements indique les événements qu'il devra reporter. Par exemple, lors de la création de l'objet Clip, le gestionnaire indique dans la description interne de l'objet que les événements evmnt1, evmnt2, evmnt3 et evmnt4 doivent être produit. À ce stade, le destinataire de l'événement n'est pas encore précisé.
Abonnement d'objets aux événements
Le mécanisme d'abonnement permet à un objet d'être notifié lors de l'occurrence d'un événement particulier. L'événement peut être soit externe à l'objet comme une interaction utilisateur ou une synchronisation inter-objets (la source de l'événement et sa destination sont deux objets distincts), soit interne comme celui qui correspond au déclenchement d'un effet de style sur le même objet. L'exemple de la Fig 15 illustre ces deux cas. Dans le premier cas, l'objet Titre s'abonne aux événements evmnt1 et evmnt3 qui permettent de le démarrer et de le stopper respectivement. Dans le deuxième cas, l'événement evmnt2 correspond à un événement interne. Il permet simplement de déclencher un effet de style sur l'objet Clip. Dans ce cas il s'agit du déplacement de l'objet sur l'écran. Un objet peut donc s'abonner aux événements déclarés aussi bien par lui-même que par les autres objets. Les événements qui sont déclarés et pour lesquels aucun objet ne s'est abonné ne sont pas produits (Par exemple l'événement evmnt4). Cela permet de filtrer les événements inutiles à la source.
La mise en oeuvre de la gestion des événements externes est dépendante du système d'exploitation et du système de fenêtrage sous-jacent. Néanmoins, la plupart des systèmes reposent sur les mêmes principes. Pour les systèmes Solaris 2.5 et Linux, le système de fenêtrage X fournit une librairie de fonctions, appelée Xlib, qui permet la création et la gestion de l'interface utilisateur ainsi que la boucle d'événements. Au dessus de la Xlib [Xlib 90], un ensemble de librairies (comme Xt intrinsics [Xt 90], Motif [Motif 92], etc.) sont construites pour faciliter au concepteur d'applications l'exploitation des fonctions offertes par le système de fenêtrage X (voir le gestionnaire graphique en section 5.1).
La boucle d'événements de Madeus repose sur la librairie Xt intrinsics. Cette dernière fournit une interface des gestion des événements de plus haut niveau que celle de la Xlib et plus proche de celle du modèle d'événements adopté. La librairie Xt intrinsics offre un ensemble de fonctions qui permettent de sélectionner les événements qui répondent aux besoins de l'application. Cette sélection est opérée au moyen de procédures de réaction qui sont déclenchés suite à l'occurrence d'une classe précise d'événements. Il existe trois fonctions qui permettent d'attacher l'occurrence d'un événement à une procédure de réaction (fonction callback):
Lors de l'occurrence d'un événement externe, la boucle d'événements (La fonction XtAppMainLoop illustrée dans la Fig 16 ) sélectionne automatiquement la procédure de réaction correspondante. Dans Madeus, la boucle d'événements de la librairie Xt intrinsics permet de déclencher tous les événements dont nous avions besoin. En particulier, les événements liés aux accès réseau sont greffés à cette boucle au moyen de la fonction XtAppAddInput permettant ainsi la couverture de l'ensemble des événements externes. La fermeture d'un port de communication servant au transfert du contenu d'un objet média est alors aisément traduit sous forme d'événement de terminaison de l'objet en question.
1. while (TRUE) {
2. /* Attendre un
événement. En attendant,
3. appeler les
procédures de réaction
4. associées
:
5. -
aux événements non traités dans la
6. queue
d'événements,
7. -
à l'expiration d'un Timer, ou
8. -
à l'arrivée de données sur un port de
9. communication.
*/
10. XtAppNextEvent
(application_context, &event);
11. /* Envoyer les événements
reçus au gestionnaire
12. approprié
d'événements. */
13. XtDispatchEvent (&event);
}
Fig 16. La boucle d'événements XtAppMainLoop
L'identification du destinataire d'un événement est réalisée au moyen d'un paramètre de la fonction de réaction. Cette fonction, exécutée par le gestionnaire d'événements, permet d'attacher à un événement donné une procédure de réaction ainsi que le nom de son destinataire. Dans l'exemple ci-dessous, le gestionnaire d'événements est configuré de façon à ce que l'événement evmnt1 déclenche la procédure PlayObject sur l'objet Titre.
XtAddCallback (evmnt1, PlayObject, Titre)Le gestionnaire d'événements permet ainsi d'acheminer l'ensemble des événements du système de présentation vers leur destinataires. En particulier, les événements de terminaison d'objets sont remontés à l'ordonnanceur où ils générent les événements de démarrage d'autres objets produisant ainsi une présentation coordonnée.
La restitution des données à l'utilisateur à travers les périphériques de la machine est effectuée par deux gestionnaires : le gestionnaire graphique et le gestionnaire audio. Ces gestionnaires fonctionnent comme des serveurs qui reçoivent des demandes de création ou de suppression de modules destination attachés à chaque objet de base. Ils permettent aussi de prendre en compte les relations graphiques comme le recouvrement d'objet sur l'écran ainsi que sur le périphérique audio (mixage, musique de fond, etc.).
Le gestionnaire graphique se charge d'initialiser et de contrôler le périphérique graphique (c'est-à-dire la fenêtre graphique de l'application Madeus) afin de restituer les données visibles (comme le texte, l'image et la vidéo) sur ce périphérique. En particulier, il gère :
Dans Madeus, l'interface graphique est créée au moyen de la librairie Motif et la librairie Xt. Ces deux librairies offrent un ensemble de fonctions C qui facilite le développement de l'interface utilisateur pour le système de fenêtrage X en utilisant des composants prédéfinis appelés widgets.
La figure Fig 17 illustre les services offerts par le gestionnaire graphique de Madeus. En particulier, il permet des recouvrements complexes de zones non-rectangulaires sur la fenêtre d'affichage (voir Fig 17 -2). Chaque objet graphique est configuré de façon à ce que les opérations graphiques qui lui sont appliquées ne portent que sur sa partie visible. Une partie visible est déterminée au moyen d'un masque pouvant avoir une forme quelconque (circulaire dans le cas de la figure Fig 17 -2). Le gestionnaire d'affichage calcule les contours de cette forme pour chaque objet en prenant en compte le recouvrement. Il permet ainsi d'éviter le réaffichage des autres objets lorsque l'affichage de l'un d'entre eux est modifié. Cela permet de réduire le nombre d'opérations graphiques qui sont très coûteuses en terme de calcul.
Fig 17. Gestionnaire graphique
Le gestionnaire audio se charge d'initialiser et de contrôler le périphérique audio (c'est-à-dire la carte audio) afin de restituer les données audio (comme la musique et les commentaires) sur les haut-parleurs. En particulier, il gère :
Les données d'un objet audio peuvent être stockées sous deux formes : l'audio échantillonnée numérique et l'audio synthétisée.
La capacité à effectuer les différents types de traitements présentés ci-dessus dépend principalement de la capacité de la carte audio utilisée. Toutes les cartes audio peuvent supporter bien évidemment l'audio échantillonnée numérique. Pour supporter l'audio synthétisée, la carte doit avoir un synthétiseur intégré et la caractéristique d'être multi-timbral (capable de jouer simultanément différents instruments) et polyphonique (capable de jouer plusieurs notes à la fois). Actuellement, il existe des logiciels, comme le Unix MIDI plugin qui a été intégré au gestionnaire audio de Madeus, qui peuvent simuler les fonctions du synthétiseur et, par conséquent, jouer l'audio synthétisée sur des cartes audio n'ayant pas de synthétiseur intégré.
Dans la conception du gestionnaire audio, nous nous sommes focalisés principalement sur la gestion de la qualité de service. Le mécanisme de plugins de Madeus nous a permis d'intégrer une variété de formats ainsi que les techniques d'adaptation qui leur sont associées. Seuls les paramètres comme le volume, la vitesse et la balance sont appliqués par Madeus car ces derniers proviennent de spécifications contenues dans le document.
Les principaux avantages que nous retenons de cette réalisation sont les suivants :
De toutes les difficultés rencontrées, la connaissance des possibilités offertes par le système d'exploitation ainsi que le système graphique est la partie la plus cruciale dans la conception d'un gestionnaire de présentation. Au départ, nous avons du réaliser d'abord une version du gestionnaire complètement fonctionnelle. Cette version s'est avérée très peu performante principalement parce que les mécanismes système employés n'étaient pas adaptés. À titre d'exemple, la recopie des images entre un objet de type vidéo et le serveur du système graphique peut atteindre un débit de 11,25 Moctets par seconde pour une vidéo de taille 300 par 500 pixels en 24 plans et une vitesse de 25 images par seconde. Dans ce cas, le recours à la mémoire partagée entre processus est donc un impératif pour améliorer, dans ce cas, les performances du système. La communication à base de signaux, présentée en section 4.2, est un autre exemple de ce type d'améliorations.
La difficulté de prévoir une implantation performante dès le départ est liée au manque de données comparatives et chiffrées sur les mécanismes de base offerts par le système. De plus, il existe un ensemble d'extensions du système graphique pour le multimédia comme la création de fenêtres non-rectangulaires qui ne sont pas documentés. Une expertise des possibilités offertes apparaît donc comme un pré-requis à la conception de ce type de systèmes. La deuxième difficulté est liée à l'évolution très rapide de ce domaine. Il est parfois impossible d'avoir une connaissance précise des résultats obtenus par d'autres équipes.
Dans ce chapitre, nous avons présenté l'architecture, le fonctionnement ainsi que la mise en oeuvre du gestionnaire de présentation de Madeus. Le rôle de ce gestionnaire est d'effectuer tous les traitements de présentation requis au niveau du système d'exploitation, du système de communication et des périphériques de restitution.
Le gestionnaire de présentation permet de décrire les trois modules nécessaires à la présentation d'un objet média de base : le module source, le module de traitement et le module destination. Chaque module est réalisé par l'un des composants du gestionnaire de présentation : le gestionnaire d'accès, le gestionnaire d'exécution et le gestionnaire de périphérique.
Nous avons d'abord présenté le gestionnaire d'accès qui se charge de l'accès aux données média locales et distantes. En fonction des besoins identifiés, nous avons opté pour les protocoles HTTP et RTSP pour concevoir ce gestionnaire. Nous avons montré que ces deux protocoles suffisent pour couvrir les problèmes d'accès aux objets média de l'application Madeus qu'ils soient discrets ou continus. RTSP, pour sa part, permet une plus grande ouverture vers la gestion de la qualité de service au sein du système de présentation.
Ensuite, nous avons présenté le gestionnaire d'exécution qui permet l'implantation du modèle objet présenté dans le chapitre précédent. Ce gestionnaire permet de lier les objets média avec les entités actives du système. Nous avons montré, grâce au mécanisme de plugin, comment ce système pouvait être extensible sans recompilation de l'application.
Enfin, nous avons présenté le gestionnaire de périphériques qui permettent la restitution effective du contenu multimédia à l'utilisateur.
Le système de présentation de Madeus représente le noyau d'une application multimédia qui peut être utilisé pour supporter plusieurs formats et même plusieurs langages de programmation multimédia qui nécessitent ce type de fonctions. Il offre tous les services nécessaires pour les couches au-dessus : ordonnanceur, système d'édition, extension de langages de programmation au multimédia (Object Oriented Media Frameworks).