Auteur : Stabylo / The Removers
2 août 1998 - 12 Août 2000
Table des matières
Chapitre 1 : Modules AVC et AAC
Chapitre 2 : Modules de format de fichier AFH
Ce document s'adresse aux programmeurs. Il décrit comment programmer un module d'extension pour Animator selon un des trois types suivants :
Afin d'intégrer plus facilement de nouveaux types de fichiers d'animation, Animator est modulaire. Nous décrirons ici toutes les règles de programmation à respecter pour construire soi-même un module. Le but de cette description est évident : des personnes autres que l'auteur peuvent améliorer Animator en écrivant des modules pour ce dernier.
L'élément fondateur de la complication de ces règles de programmation, c'est la gestion de la mémoire. En effet, chaque module a le droit d'allouer de la mémoire, par exemple pour faire des précalculs, mais dans le cas où Animator doit faire appel à plusieurs modules, pour jouer une série d'animations, n'est-il pas dommage de devoir toujours recréer les mêmes précalculs ?
Par ailleurs, si on choisi de conserver ces précalculs (comme le faisait AviPlayer) il serait dommage d'en venir à manquer de mémoire, alors qu'il est probable que certains d'entre eux ne sont pas utilisés dans l'animation en cours et qu'il constituent un gros bloc de mémoire perdue.
C'est pour répondre à la fois à ces deux problèmes qu'a été mise en place une micro-bibliothèque de fonctions mises à la disposition du programmeur de modules.
Ces modules doivent donc déclarer leurs précalculs au noyau au moyen de routines transmises en paramètres lors de l'initialisation du module. De même, l'allocation de mémoire se fera par le biais d'une fonction du noyau, afin de libérer un précalcul inutilisé en cas de manque de mémoire. De surcroît, Animator se chargera de générer un message d'erreur si rien n'a pu être fait pour réussir l'allocation d'un bloc. En reprenant la main, le noyau cesse alors le parcours de l'animation en cours et passe à la suivante, sauf si l'erreur est fatale ou si l'option 'Fail' a été positionnée dans la ligne de commande, auquel cas Animator effectue un retour au bureau GEM.
Si une erreur survient lors de la décompression d'une image ou d'un son, la routine'erreur_survenue' permet de le signaler au noyau. Une telle erreur n'affecte aucunement le noyau dans la restitution de l'animation.
Enfin, lorsqu'Animator a fini d'utiliser un module, il appelle une routine de ce dernier qui de charge de signaler que les précalculs compterons un utilisateur de moins.
En effet, il se peut qu'à un instant donné, plusieurs modules cohabitent en mémoire en utilisant les mêmes précalculs ! Cela se produit pour les fichiers AVI comportant plusieurs flux video. C'est pourquoi Animator compte le nombre d'utilisateurs d'un précalcul donné plutôt que de signaler si un précalcul est utilisé ou non.
Bien entendu, afin d'éviter que deux modules ne créent deux fois le même précalcul - celui de conversion YUV->RGB, par exemple -, il est associé un identifiant à chaque précalcul. Cet identifiant comporte quatre caractères : c'est un mot long du type '_YUV' ou bien 'HCCV' (Hi Color ConVert) ou '_URS'(UnsignedReSampling). Notez bien que tous les identificateurs commençant par le caractère '_' (caractère "underscore") sont réservés pour les identifiants officiels.
Bien sûr, elle initialise le module. Elle est située au début de celui-ci de telle sorte que l'on puisse l'appeler en sautant à la première instruction de la zone TEXT. Comme toutes les routines du module, elle se termine par l'instruction 'RTS'
En gros.
En détail.
'init_module' est appelée par un saut (JSR) sur le début de la zone TEXT du module.
Règles de programmation.
'init_module' n'a le droit de modifier QUE les registres d0/a0 (pour transmettre les valeurs de retour).
En cas d'erreur, elle s'occupe de désallouer les blocs qu'elle a réservé le cas échéant : la routine de libération du module n'est pas transmise, donc elle ne sera pas appelée.
La routine doit vérifier que le tableau est assez grand pour comporter les variables dont elle a besoin (voir le retour d'erreurs ci-dessous). Ceci permettra d'allonger ce tableau plus tard sans pénaliser les modules écrits auparavant.
Cette routine a la possibilité de créer des précalculs (voir méthode détaillée plus loin) à l'aide de ces variables. Les adresses des précalculs créés peuvent être gardées dans des variables internes au module pour être utilisé plus simplement, mais elles doivent systématiquement être réinitialisée par 'init_module'.
Important
Elle a l'obligation de copier toutes les valeurs qui peuvent lui être utile par la suite, car le contenu du tableau de paramètres est susceptible d'être modifié sans préavis.
Les valeurs ainsi copiées bénéficieront en outre d'un accès plus simple et plus rapide pour le module.
retours
INIT_MOD_OK equ 0 INIT_MOD_BAD_COMP equ -1 INIT_MOD_TOO_FEW_ARGS equ -2 INIT_MOD_MEMORY_ERROR equ -3 INIT_MOD_USER_DEFINED_ERROR equ -4 INIT_MOD_UNEXP_ERROR equ -5 INIT_MOD_BAD_FORMAT equ -6
info_init_codec rsstruct chemin_application rs.l 1 adr_recherche_precalc rs.l 1 ; \ adr_mem_alloc rs.l 1 ; |-> détaillés ci-dessous adr_libere_precalc rs.l 1 ; / type rs.b 4 sizeof rs 0
Voici des explication sur ces variables générales :
C'est l'adresse d'une routine qui recherche le précalcul correspondant à l'identificateur passé en argument.
Retour.
Modifications de registres.
... move.l taille,d0 move.w #3,d1 jsr mem_alloc tst.l d0 beq allocation_impossible ...
C'est l'adresse d'une routine qui recherche le précalcul correspondant à l'identificateur passé en argument. S'il existe, elle le signale comme non utilisé.
******* Si le type vaut 'vids' (flux vidéo : modules AVC) ******* compression rs.b 4 ; détaillé ci-dessous bits_par_pixel rs.w 1 ; 2, 4, 8, 16, 24 ou 32 adr_palette rs.l 1 largeur rs.w 1 ; \ dimensions du flux video hauteur rs.w 1 ; / adr_ecran_centre rs.l 1 ; détaillé ci-dessous x_ecran rs.w 1 ; dimensions de l'écran y_ecran rs.w 1 nb_bits_sortie rs.w 1 ; 16 ou 24 (avec restrictions) type_de_sortie rs.w 1 video_sizeof rs 0
Voici des explication sur ces variables spécifiques à la video :
ATARI equ 0 CARTE_GRAPHIQUE equ 1
Remarque :
Le format ATARI correspond au format HiColor Falcon. Seuls certains couples de (nb_bits_sortie , type_de_sortie ) sont valides :
******* Si le type vaut 'auds' (flux audio : modules AAC) ******* rsset info_init_codec.sizeof format rs.w 1 ; 0=inconnu, 1=PCM, 2=ADPCM, .... nb_voies rs.b 1 ; 1=mono, 2=stéréo bits_par_sample rs.b 1 ; en général égal à 4, 8 ou 16. frequence rs.l 1 ; en général égal à 11025, 22050 ou 44100 block_align rs.w 1 format_sortie rs.w 1 ; 1=PCM ATARI (signé) nb_voies_sortie rs.b 1 ; 1=mono, 2=stéréo bits_sortie rs.b 1 ; 8 ou 16 frequence_sortie rs.l 1 ; toujours supérieur à 'frequence' audio_sizeof rs 0 rsend
Voici des explication sur ces variables spécifiques à l'audio :
Les variables 'format', 'nb_voies', 'bits_par_sample' et 'frequence' définissent le format du son en entrée.
Les variables 'format_sortie', 'nb_voies_sortie', 'bits_sortie' et 'frequence_sortie' définissent le format du son en sortie. Notez que la frequence de sortie demandée au décodeur vérifie toujours les inégalités suivantes :
frequence_sortie/2 <= frequence < frequence_sortie
La routine encodeuse interprète à l'inverse : le PCM 8 bit est signé en entrée et non signé en sortie. Ceci permet la conversion au format PCM lors de la création d'un fichier AVI.
******* L'adresse de ce tableau est retournée dans a0. ******* information_module rsstruct adr_decodeur rs.l 1 adr_encodeur rs.l 1 adr_libere_module rs.l 1 auteur rs.l 1 description rs.l 1 version rs.l 1 sizeof rs 0
Si l'une des deux premières routines est absente du module, alors l'adresse correspondante doit être mise à zéro (NULL).
Si une erreur s'est produite lors de l'initialisation, on peut positionner 'adr_libere_module' à 0 (NULL).
******* Si le type vaut 'vids' (flux vidéo : modules AVC) ******* rsset information_module.sizeof adr_MFDB rs.l 1 video_sizeof rs 0
Contient l'adresse d'un bloc MFDB (20 octets) qui décrit le format de l'image crée par le module lorsqu'il décompresse une image. Voici cette structure :
MFDB rsstruct fd_addr rs.l 1 ; adresse mémoire (NULL = écran courant) fd_width rs.w 1 ; largeur en pixels de la zone fd_height rs.w 1 ; hauteur en pixels de la zone fd_wdwidth rs.w 1 ; largeur en mots de la zone (fdwisth +15)/16 fd_stand rs.w 1 ; format (0 = spécifique au périphérique, 1 = format VDI) fd_planes rs.w 1 ; nombre de plans reserved1 rs.w 1 ; \ reserved2 rs.w 1 ; | (mettre à 0) reserved3 rs.w 1 ; / sizeof rs 0 rsend
Typiquement, elle sera remplie ainsi :
fd_addr =info_init_codec.adr_ecran_centre fd_width =info_init_codec.x_ecran fd_height =info_init_codec.hauteur fd_wdwidth =info_init_codec.x_ecran fd_stand =0 fd_planes =16 reserved1 =0 reserved2 =0 reserved3 =0 ******* Si le type vaut 'auds' (flux audio : modules AAC) ******* rsset information_module.sizeof min_bit_rate rs.l 1 audio_sizeof rs 0 rsend
Il s'agit de la bande passante minimale en bit par seconde du son compressé. Cette valeur est ensuite utilisée pour calculer la taille utilisée par un son décompressé selon la formule suivante :
taille_non_compresse = taille_compresse * (bit_rate_sortie/min_bit_rate)
Pour calculer la valeur de min_bit_rate, il est possible de diviser la taille d'un block_align (bloc de son élémentaire insécable) en bits par la durée maximale du son qu'il code. Si le flux audio a un taux de compression constant, il est possible d'utiliser la formule suivante :
min_bit_rate = 8 * taille_echantillon * nombre_echantillons_par_seconde
Par exemple, si vous décompressez 65 octets en 384 octets contenant 192 échantillons de 8 bits rejoués à la fréquence 44100 Hz :
min_bit_rate = 8*65*(44100/192)
Attention : s'il faut arrondir certains calculs, il faut arrondir à l'unité inférieure.
Cette création se fait à l'aide des routines 'recherche_precalc' et 'mem_alloc'.
Dans le cas où le précalcul est déjà présent (d0<>0), il est à la charge de 'init_module' d'incrémenter d'une unité le nombre d'utilisateurs de ce précalcul pour signaler l'utilisation de ce dernier par le module.
Dans le cas où le précalcul n'est pas déjà en mémoire (d0=0), la routine d'initialisation doit remplir le descripteur vide pointé par a0.
descripteur_precalc rsstruct identificateur rs.b 4 adresse_bloc rs.l 1 nb_utilisateurs rs.w 1 sizeof rs 0 rsend
exemple de descripteur fraîchement créé.
dc.b '_YUV' ; Conversion YUV->RGB dc.l $35df54 ; adresse du précalcul dc.w 1 ; un seul utilisateur
Remarques
Les identificateurs commençant par le caractère de soulignement '_'sont réservés pour les identificateurs officiels.
Voici ci-dessous la liste des identifiants officiels pour la version actuelle d'Animator. Cette liste n'est donnée qu'à titre d'exemple car elle est amenée à changer profondément dans les futures versions d'Animator :
Modules video AVC :
Modules audio AAC :
Le module signale qu'il cesse d'utiliser un précalcul en appelant la routine 'libere_precalc' qui diminue d'une unité le nombre d'utilisateurs du précalcul.
Codecs video (AVC)
Codecs audio (AAC)
Pas de spécifications. Ne pas se servir de cette possibilité.
Elle a pour rôle essentiel de libérer chaque précalcul par un appel à la routine 'libere_precalc'.
En gros
Règles de programmation.
Cette routine ne doit modifier aucun registre.
CHAQUE précalcul utilisé par le module DOIT être l'objet d'un appel à 'libere_precalc'.
Toute mémoire allouée en douce avec le GEMDOS doit être libérée. (Nota : préférez 'Mxalloc #3' au traditionnel Malloc pour les allouer)
Pas de spécifications. Ne pas se servir de cette possibilité.
Devrait contenir :
Routines à transmettre :