Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Problème de design

16 réponses
Avatar
FR C++
Bonjour =E0 tous,

comme le titre l'indique, j'ai un souci de design de classe.

J'ai cr=E9=E9 trois classes qui me permettent d'afficher de la vid=E9o
gr=E2ce =E0 DirectShow.

J'ai une classe DS_InfosVideo, DS_AffichVideo, qui sont assez
explicites, et une derni=E8re classe TVideoAffich qui est la fen=EAtre
qui affichera la vid=E9o, et qui a comme membres priv=E9s les deux
classes pr=E9c=E9dentes...

Je peux afficher 3 types de vid=E9o: les fichiers vid=E9o, des fichiers
XML pour la pr=E9visualisation de montages vid=E9o, et de la vid=E9o en
temps-r=E9el provenant d'une cam=E9ra num=E9rique.

J'ai donc utilis=E9 l'idiome du constructeur nomm=E9 pour chacune de ces
3 classes, ce qui me permet de charger les bonnes infos.

Par exemple, pour un fichier vid=E9o:

class TVideoAffich
{
private:
DS_InfosVideo * Infos;
DS_AffichVideo * Affich;
public:
static TVideoAffich * CreateFromFile(const std::string & path)
{
Infos =3D DS_InfosVideo::CReateFromFile(path);
Affich =3D DS_AffichVideo::CReateFromFile(path);
}
};

Pour l'instant, je limite le rendu de la vid=E9o =E0 un renderer que j'ai
choisi.

Ce que j'aimerai faire maintenant, c'est proposer d'autres choix de
renderer.

Mais je ne me vois pas faire des fonctions du genre pour chacune des
classes:

static TVideoAffich * CreateFromFileVMRRenderer(const std::string &
path);
static TVideoAffich * CreateFromFileBasicRenderer(const std::string &
path);
static TVideoAffich * CreateFromSBEVMRRenderer(const std::string &
path);

etc...

Je voyais bien un truc du genre:

template <class Input>
class DS_InfosVideo : public Input
{
public:
DS_InfosVideo(const std::string & path);
};

template <class Input , class Renderer>
class TVideoAffich : public Input, public Renderer
{
private:
DS_InfosVideo<Input> * Infos;
DS_AffichVideo<Input,Renderer> * Affich;
public:
TVideoAffich(const std::string & path);
};

Seulement la classe Input pass=E9e =E0 TVideoAffich n'est pas la m=EAme
que celle que doit recevoir DS_InfosVideo ni celle de DS_AffichVideo...

Est-ce que c'est possible de poser des conditions =E0 la compilation, de
telle sorte qu'on ait un truc du genre:

pour TVideoAffich
si Input =3D=3D VideoAffichInputFile
{
DS_InfosVideo<Infos_Input_File> * Infos;
si Renderer =3D=3D VideoAffichVMRRenderer
DS_AffichVideo<Affich_Input_File,Affich_VMR_Renderer> * Affich;
sinon
DS_AffichVideo<Affich_Input_File,Affich_Basic_Renderer> *
Affich;
}
sinon
{
///
}

Voil=E0 tout :)

Merci d'avance

Mike

6 réponses

1 2
Avatar
Fabien LE LEZ
On 16 Jun 2006 14:28:17 -0700, "Michael" :

Elle utilise des interfaces COM


Hors-sujet. C'est un détail d'implémentation, et on parle ici de
design.

InfosVideo n'est pas une interface qu'on peut assimiler à une
source [...] récupération des infos d'une source vidéo.

Par contre AffichVideo est composée de deux "sous-objets": une source
(dont les interfaces COM sont différentes selon le type de la source :
XML, Fichier...) et un renderer, qui, peut-importe la source affiche le
rendu de cette source; Ce renderer peut lui aussi être de différents
types (VMR, Overlay, etc...)


Hé bien, tout va bien.

class Source { ... [cf mes autres messages] };
class Destination { ... [idem] };

class AffichVideo
{
Source* la_source;
Destination* la_destination;
};




class Source_XML: public Source
{
...
};

class Destination_Overlay: public Destination
{ ...
};


À aucun moment, AffichVideo ne doit savoir ce que "XML" ou "Overlay"
signifie.

Source et Destination contiennent des fonctions virtuelles pures.
Source_XML et ses potes implémentent ces fonctions, à grands coups de
COM et autres joyeusetés Win32.

Avatar
Sylvain
Michael wrote on 16/06/2006 21:08:

Mais je compte proposer un renderer de plus. Ca ne change rien aux
classes InfosVideo et dérivées, mais du coup ça multiplie le nombre
de classes AffichVideo par 2!


qu'est-ce un renderer ici ?

je le comprends comme le machin DirectX (un IGraphBuilder) qui affiche
effectivement le flux construit à partir de la source (un
ISampleGrabber). il est de fait unique (sauf peut être subtilitées
avancées) dans l'architecture DX en tant qu'objet de rendu.

ce qui peut changer est plus facilement les 'filtres' appliquées à la
source; cela peut inclure du mixage, de la décompression hard, de la
conversion (entre standards TV par ex.).

partant, je pense que le lieu des éventuelles adaptations est plus entre
la source et le visualisateur, mais ni l'un, ni l'autre; la gestion des
ces filtres pluggables revient vient à 'chapeau' qui saura mettre bout à
bout des filtres entre ses 2 maillons.

Sylvain.

Avatar
Michael
Bon, suivant vos conseils, j'en suis arrivé à ça:

class AV_Input
{
};

class AV_InputFile : public AV_Input
{
};

class AV_InputXML : public AV_Input
{
};

class AV_Renderer
{
};

class AV_RendererVMR : public AV_Renderer
{
};

class AV_RendererBasic : public AV_Renderer
{
};


class AffichVideo
{
private:
AV_Renderer * Renderer;
AV_Input * Input;
public:
AffichVideo(AV_Renderer * renderer, AV_Input * input)
: Renderer(renderer),Input(input)
{}
};

Ce qui m'oblige à l'utiliser comme ça:

AffichVideo * affich = new AffichVideo(new AV_RendererVMR(),new
AV_InputFile());
affich->toto();

Je suis un peu embêté avec les new...

J'aurais préféré, si c'est possible, utiliser une syntaxe comme celle-ci:

AffichVideo * affich = new AffichVideo(AV_RendererVMR(),AV_InputFile());

Et utiliser des références dans AffichVideo. Mais mes premiers essais ne
sont pas très concluants.

Mais je pense que je suis obligé avec le polymorphisme?
Avatar
Fabien LE LEZ
On 19 Jun 2006 17:21:14 GMT, Michael <michael.at.gmail.dot.com>:

Ce qui m'oblige à l'utiliser comme ça:

AffichVideo * affich = new AffichVideo(new AV_RendererVMR(),new
AV_InputFile());
[...]

Je suis un peu embêté avec les new...


Les "new" de "AV_RendererVMR" et "AV_InputFile" font pendant au "new"
de "AffichVideo".

Tu aurais pu écrire :

AV_RendererVMR mon_renderer;
AV_InputFile mon_input;
AffichVideo afficheur (&mon_renderer, &mon_input);


J'aurais préféré, si c'est possible, utiliser une syntaxe comme celle-ci:

AffichVideo * affich = new AffichVideo(AV_RendererVMR(),AV_InputFile());


Sauf que l'objet "AV_RendererVMR" est détruit à la fin de la ligne...

Et utiliser des références dans AffichVideo.


Ça, tu peux :

class AffichVideo
{
private:
AV_Renderer& renderer;
AV_Input const& input;
public:
AffichVideo(AV_Renderer& renderer_, AV_Input const& input_)
: renderer(renderer_),input(input_)
{}


Mais ça ne change rien au problème de durée de vie.


Mais je pense que je suis obligé avec le polymorphisme?


Tu as une alternative :

template <class Input, class Renderer> class AffichVideo
{
private:
Renderer renderer;
Input input;
...
};

Tu passes alors d'un polymorphisme d'héritage à un polymorphisme de
templates.

AMHA, ça ne se justifie pas ici, mais c'est une solution qui existe.

Avatar
Michael
AV_RendererVMR mon_renderer;
AV_InputFile mon_input;
AffichVideo afficheur (&mon_renderer, &mon_input);


Je préfère manipuler que AffichVideo...

Ça, tu peux :

class AffichVideo
{
private:
AV_Renderer& renderer;
AV_Input const& input;
public:
AffichVideo(AV_Renderer& renderer_, AV_Input const& input_)
: renderer(renderer_),input(input_)
{}


Mais ça ne change rien au problème de durée de vie.


J'avais tenté ça aussi, mais ça ne m'arrange pas non plus...

Tu as une alternative :

template <class Input, class Renderer> class AffichVideo
{
private:
Renderer renderer;
Input input;
...
};

Tu passes alors d'un polymorphisme d'héritage à un polymorphisme de
templates.

AMHA, ça ne se justifie pas ici, mais c'est une solution qui existe.


J'avais pensé à ça aussi, mais autant passer le type de source en paramètre
template ne pose pas de souci, puisque c'est décidé dès la compilation,
autant passer le type de renderer en template est un problème, puisque ce
choix est défini à l'exécution...

Avatar
Michael
J'avais pensé à ça aussi, mais autant passer le type de source en
paramètre template ne pose pas de souci, puisque c'est décidé dès la
compilation, autant passer le type de renderer en template est un
problème, puisque ce choix est défini à l'exécution...


Par exemple, à moins que je ne vois pas l'astuce, on ne peut pas faire ça si
je ne m'abuse?

class foo
{
private:
AffichVideo affich;
public:
foo();
};


foo::foo()
{
affich = Affich<InputFile,RendererVMR>();
}

1 2