1. Introduction :
Ce document explique le fonctionnement interne de K!TV XP et la méthode
pour écrire un plugin Vidéo pour cette application. Vous êtes libre
de nous transmettre vos commentaires à E-nek@kastortv.com
ou Quenotte@kastortv.com
pour corriger, améliorer ou même ajouter vos propres lignes à ce document.
Ce document suppose que vous connaissiez quelques bases de programmations
C/C++ et que vous ayez au moins jetté un coup d'oeil au code de l'excellent
plugin Tutorial écrit pas AskyWhale (http://plugintv.free.fr/).
Bonne lecture.
Version de ce document : Version 0.46: 10 Juin 2002.
2. L'application K!TV XP :
K!TV XP permet de regarder la télévision sur votre PC en utilisant
votre carte Tuner (à base de chipset BT8x8), sur toutes les plateformes
Windows (95, 98, 2000, XP ...). Récemment, l'architecture a été modifiée
pour permettre d'ajouter ses propres plugins de traitement et de les
lancer à l'intérieur de K!TV XP.
3. Le fonctionnement interne de K!TV XP:
En mode normal (ie sans plugin lancé), l'affichage se déroule dans
un thread séparé :
for(;;)
{
Capturer l'image
Afficher l'image
}
|
La capture se fait par la carte télévision, au format 768 x 576 YUY2
(l'utilisateur peut aussi choisir de capture moins de 768 pixels), ce
qui correspond à deux trames de 768x288 (Rappel : le signal vidéo est
entrelacé).
Il faut savoir que les trames Even/Odd capturées ne correpondent pas
forcement aux trames Even/Odd du signal réél. En clair, il n'y a aucune
différence entre la trame Even et Odd avec K!TV XP.
Le format YUY2 utilisé est standard, les pixels sont stockés dans la
forme d'information de Luminance (Y) et de Chrominance (U et V). (Voir
http://www.webartz.com/fourcc/ pour plus d'informations)
(1 pixel sur 2 octets) (Y0-U0-Y1-V0)(Y2-U2-Y3-V2)(Y4-U4-Y5-V4)
Lorsque le plugin est chargé, le thread d'affichage est légèrement
modifié pour faire appel au plugin.
Capturer l'image
Traiter l'image
Afficher l'image
}
|
K!TV XP travaille avec plusieurs buffers vidéo, ainsi, lorsque le buffer
courant a été traité, on l'affiche avec ViewFrame=true et on travaille
sur un autre buffer.
-
Le thread d'affichage peut être arrêté et relancé
à tout moment par K!TV XP, par exemple lorsque l'utilisateur change
de résolution...
-
Le plugin doit travailler au format YUY2 (en entrée
et en sortie), K!TV XP se charge de la conversion si par exemple l'affichage
est au format RGB (l'utilisateur n'a pas choisit DirectX).
4. Le plugin vidéo:
Le plugin vidéo est une DLL classique qui contient plusieurs fonctions
de traitement.
K!TV XP accède au plugin par l'intermédiaire de l'objet QuenotteTV_VideoPlugin
qui contient les variables et fonctions utilisées pour le dialogue entre
K!TV XP et le plugin vidéo.
Lorsque l'utilisateur sélectionne un plugin, voici ce que fait K!TV
XP :
-
La DLL est chargée en mémoire
-
Le numéro de version du plugin est testé. (La structure
de l'objet QuenotteTV_VideoPlugin peut avoir changé). L'initialisation
des variables du plugin se fait dans la fonction GetVPlugin()
-
La fonction Start() est appelée au démarrage du plugin
(F3)
-
La fonction Stop() est appelée à l'arrêt (F2)
Voici ce qui se passe après l'appel de Start() (le thread est réinitialisé)
:
InitStuff ()
for(;;)
{
Capturer l'image
DoStuff()
CheckStuff() (appelé toutes les 960 ms ;-)
Afficher l'image
DetecteSignal()
}
|
Nous avons donc :
-
InitStuff :
Fonction appelée au départ pour initialiser le traitement
-
DoStuff :
Fonction appelée pour traiter la dernière image capturée
-
CheckStuff :
Fonction appelée pour la vérification interne du plugin (optionel)
5. Fonctionnement du plugin vidéo & DoStuff():
Le plugin peut choisir 2 modes de fonctionnement au travers de la variable
FullFields, de plus il décide seul ce qui doit être affiché à l'écran
et quand l'afficher (grâce aux variables UpdateBuffer et ViewBuffer).
Si l'utilisateur appuie sur la touche tabulation, la fenêtre d'affichage
passe du mode FF au mode HF (par défaut le plugin tourne en FF).
-
HF : Une trame
Appel du plugin après la capture de 1 trame et affichage sur une fenêtre
de 288 lignes.
Seul le buffer OutEvenLines est considéré valide lors de l'affichage.
-
FF : Deux trames
Appel du plugin après la capture de chaque trame et affichage sur
une fenêtre de 576 lignes (2x288), le plugin reçoit d'abord
la trame paire puis la trame impaire.
Les plugins de désentrelacement (ex Greedy2frame ...) ne sont disponibles
que dans ce mode.
K!TV XP fait appel au plugin avec la ligne de code suivante :
PluginVideo->DoStuff(IsOdd, &UpdateBuffer, &ViewBuffer);
Le plugin travaille sur les pointeurs EvenLines ou OddLines, ces pointeurs
sont du type short *EvenLines[5][288] et permettent d'accéder
à chaque ligne individuellement. Le plugin doit utiliser CurrentFrame ,
indicateur du buffer courant, en voici un exemple:
EvenLines[CurrentFrame][i].
Le résultat du traitement doit être enregistré
dans OutEvenLines ou OutOddLines.
Paramètres :
-
BOOL IsOdd :
La trame capturée est paire (FALSE) ou impaire, le plugin doit donc
utiliser les pointeurs correspondant (EvenLines ou OddLines).
-
BOOL UpdateBuffer :
Le plugin doit modifier cette variable !
Si TRUE, les lignes OutEvenLines/OutOddLines sont copiées dans le
buffer vidéo.
Si FALSE alors K!TV XP ne fait rien et passe à la trame suivante.
-
BOOL ViewBuffer :
Le plugin doit modifier cette variable !
Si TRUE le buffer vidéo est affiché à l'écran.
Il est évident qu'en mode FF il faut attendre de traiter 2
trames avant de lancer l'affichage.
Exemple type de fonctionnement :
Mode HF (FullFields=false)
Capture de la trame impaire
Traitement de la trame impaire (UpdateBuffer=false et
ViewBuffer=false)
Capture de la trame paire
Traitement de la trame (UpdateBuffer=true et ViewBuffer=true)
Copie vers le buffer vidéo de la trame paire
Le buffer est affiché
Mode FF (FullFields=true)
Capture de la trame paire
Traitement de la trame paire (UpdateBuffer=true et ViewBuffer=false)
Copie vers buffer vidéo
Capture de la trame impaire
Traitement de la trame impaire (UpdateBuffer=true et
ViewBuffer=true)
Copie vers le buffer vidéo
Remarques :
Si l'utilisateur sélectionne le mode DIB, les pointeurs vers les
lignes ne sont pas tous valides (la capture ne se fait pas en taille maximale
de 576 lignes). Il faut donc dans tous les cas tester avant de travailler
avec EvenLines ou OddLines .
if (EvenLines[CurrentFrame][i] != 0)
memcpy(dest, EvenLines[CurrentFrame][i], size);
6. La mémoire et EvenLines/OutEvenLines :
Analysons plus en détail la mémoire et la relation avec EvenLines
et OutEvenLines ...
A son démarrage l'application alloue un important bloc de mémoire pour
stocker 5 x 2 x 288 x 768 pixels, ce qui représente 10 trames ou 5 images
completes. La carte télé se charge de transférer directement vers cette
zone les trames capturées et K!TV XP retourne au plugin la derniere trame
capturée (CurrentFrame ).
Voici une représentation de cette mémoire :
Trame 0
Paire
|
Trame 0
Impaire
|
Trame 1
Paire
|
Trame 1
Impaire
|
Trame 2
Paire
|
Trame 2
Impaire
|
Trame 3
Paire
|
Trame 3
Impaire
|
Trame 4
Paire
|
Trame 4
Impaire
|
C'est pourquoi lorsque le plugin souhaite acceder ses images, nous devons
utiliser le code suivant :
EvenLines[CurrentFrame][i].
EvenLines : est un pointeur vers les trames Paires
CurrentFrame : est un entier variant de 0 a 4 indiquant la
derniere trame capturée.
Il en résulte donc que cette zone mémoire peut etre utilisé par le plugin
pour ses traitements internes. Par exemple, si l'on veut améliorer l'image,
il est inutile de copier les lignes vers une autre zone mémoire, nous
pouvons directement travailler dessus.
La seule contrainte c'est que la carte télé continue de travailler en
arriere plan, la même zone mémoire sera donc ecrasée au bout d'un
cycle de 5 images. Ca nous laisse donc une durée de 150-200 ms pendant
laquelle le buffer sera "intacte".
Et pour finir, OutEvenLines défini les lignes à
afficher par K!TV XP. Dans le cas le plus simple nous avons :
OutEvenLines = EvenLines
7. Lancement automatique du plugin vidéo :
BOOL DetecteSignal(BYTE *VBI)
Si le plugin peut détecter un signal vidéo alors il doit préciser
AutoProcessVideo=TRUE
25 fois par secondes K!TV XP fait appel à DetecteSignal()
pour qu'il analyse le flux vidéo, le plugin a donc la main pour analyser
le signal. Dès que le plugin souhaite se lancer DetecteSignal()
doit retourner TRUE (sinon retourner FALSE) .
En plus de * VBI le plugin a toujours accès aux variables :
Even/OddLines, CurrentFrame, CurrentX
Paramètres:
BYTE *VBI : Pointeur vers les données VBI (si pas de données
télétexte alors NULL)
8. Affichage de messages dans la barre d'état :
void GetStatus(char *Text, BOOL Nb)
Ces informations sont affichées par K!TV XP dans sa barre d'état.
Paramètres:
Nb : Indique l'emplacement où afficher dans la barre d'état.
Si Nb=false, la chaîne modifiée par GetStatus est affichée sur la gauche
de la barre d'état.
9. Interface utilisateur :
void ShowDialog() :
Demande au plugin d'afficher sa boite de dialogue.
HMENU GetPluginMenu(BOOL ContextMenu) :
Retourne un menu que K!TV XP va greffer à son propre menu.
Si ContextMenu=TRUE alors K!TV XP demande le menu contextuel (affiché
lors d'un clic gauche sur l'image) .
Exemple :
HMENU GetPluginMenu(BOOL ContextMenu)
{
static HMENU CurMenu;
CurMenu = LoadMenu(VideoPlugin.hDllInstance, "PLUGIN_MENU");
return CurMenu;
|
Attention, le menu doit avoir un titre, c'est a dire que le fichier
RC doit être comme :
PLUGIN_MENU MENU
BEGIN
POPUP "Popup" <<< important
BEGIN MENUITEM "&premier", IDM_4
MENUITEM "&second ", IDM_2
END
END
Finalement, le support multilingue étant désormais disponible
avec K!TV XP, les plugins peuvent savoir la langue courante en regardant
LangID avant d'afficher toute boite de dialogue ou message
destiné à l'utilisateur.
Par exemple K!TV peut vous donner :
Lang = IDMAKELANGID (LANG_FRENCH, SUBLANG_DEFAULT)
ou pour l'anglais :
Lang = MAKELANGID (LANG_ENGLISH, SUBLANG_DEFAULT)
10. Messages destinés au plugin :
BOOL ProcessMessage(UINT message, UINT wParam, LONG lParam,
char *OSDDisplay)
Tous les messages non traités par K!TV XP sont transmis d'abord au
plugin vidéo puis au plugin audio..
La valeur de retour de ProcessMessage est important, si
le plugin vidéo retourne TRUE, K!TV considère que OSDDisplay
est valide est affichera ce message à l'écran. S'il retourne
FALSE le plugin audio pourra traiter ce message.
Paramètres:
Il ne faut pas choisir les ID au hasard pour ne pas avoir
de conflit avec ceux de K!TV XP. Il est donc fortement conseillé
de respecter les règles suivantes :
> 40100 pour les plugins vidéo
> 40200 pour les plugins audio
Paramètres:
UINT message, UINT wParam, LONG lParam : Paramètres
classiques ...
OSDDisplay : Texte à afficher par l'OSD de K!TV XP.
11. Raccourcis claviers :
ACCEL *accel
int NbAccel
Voici un exemple d'utilisation de raccourcis claviers :
ACCEL AccTable[] =
{
|
|
|
|
// fVirt |
key |
cmd |
Touche |
0, |
'f', |
IDM_1 }, |
// F |
FVIRTKEY | FCONTROL, |
'F', |
IDM_2 }, |
// Control-F |
FVIRTKEY, |
VK_F12, |
IDM_3 }, |
// F12 |
}; |
|
|
|
...
NbAccel = 3;
|
|
|
|
Paramètres :
Et vous pourrez recevoir par exemple le message CONTROL_F qui
sera traité par ProcessMessage()
(comme ceci : ProcessMessage(WM_COMMAND, CONTROL_F, 0, *);)
12. Bandes noires :
int MovieBoost;
BOOL AutoMovieBoostFound()
Toutes les 5 secondes K!TV exécute AutoMovieBoostFound ()
, ceci permet au plugin de trouver les bandes noires pour les films
(comme 16/9e par exemple), ces zones noires ne sont pas affichées
par K!TV XP d'où un gain de temps.
Remarque :
AutoMovieBoostFound () doit être utilisé en
combinaison de MovieBoost , ce dernier représente le nombre
de lignes occupées par les bandes noires sur une seule trame.
Si la sortie de AutoMovieBoostFound est TRUE, K!TV XP s'attend
à ce que MovieBoost soit valide immédiatement.
void SetLow(unsigned char bBrightness)
permet d'être à jour lorsque l'utilisateur modifie le contraste.
13. Localisation et path des plugins :
A partir de la version 1.2.0.0 de K!TV XP, les plugins doivent se situer
dans le sous répertoire Plugins de K!TV XP. La recherche des
plugins se fait uniquement dans ce répertoire. De plus pour ne
pas que le répertoire Plugins ne devienne une forêt peu
hospitalière il est demandé que soit utilisée la
structure suivante:
Pour chaque plugin il ne doit y avoir dans le répertoire Plugins
que:
-
La dll du plugin principale (celle qui est chargée
par K!TV XP) (eg: PluginVideo.dll)
-
Un fichier de configuration du plugin portant le
même nom que la dll principale du plugin (eg: PluginVideo.ini)
-
Un sous répertoire portant le même nom
que la dll principale du plugin (eg: PluginVideo) regroupant tout
fichier supplémentaire du plugin.
Il faut donc prendre soin lors de l'appel à des fichiers utilisés
par les Plugins à ces quelques contraintes.
L'aide du plugin étant a placer dans le sous répertoire
Aide de K!TV XP.
|