Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1331 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  [C++/résolu] operator [][] () et types variants

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Précédente
Auteur Sujet :

[C++/résolu] operator [][] () et types variants

n°1327903
nargy
Posté le 18-03-2006 à 17:32:21  profilanswer
 

Salut les C++iens!
 
Alors voilà, je me demandais quelle méthode utiliser en C++ pour surcharger l'opérateur [][]: oui vous ne voyez pas double  :pt1cable: , il ne s'agit pas de [] mais de [][].
 
Quelque chose comme:
Tableau2D tab(10,10);
tab[2][1]=0;
 
Y a t-il une solution efficace?  :??:
 
solution 1 => un proxy: sucharger[] retourner un objet avec [] surchargé
solution 2 => surcharger plutôt operator()
 
Deuxièmement:
Comment faire retourner à l'opérateur un objet variant de plusieurs types convertissables entre eux?  :heink: (variant ~=~ union)
 
* Solutions résolvables à la compilation:
solution 1 => utiliser un template, et l'instancier avec toutes les conversions possibles. mots clés: Boost.Variant+Alexandrescu
solution 2 => plus facile à coder, plus lent: avoir un type de plus grande précision utilisé pour convertir de/vers les autres type. ex.: type string.
 
* Solutions complémentaires, résolvables à l'execution:
solution 1 => pour un nombre restreint de types variants: un switch,
solution 2 => pur C++, pour de gros objets: une classe conteneur d'un pointeur vers une classe abstraite pure. mots-clés ci-dessous: ++fab+SignalType
solution 3 => plus efficace sur des petits objets: une classe faisant appel à un tableau statique à 2 dimensions de pointeurs sur fonctions de conversion. mots clés ci-dessous: conversions+mytype


Message édité par nargy le 24-03-2006 à 00:04:25
mood
Publicité
Posté le 18-03-2006 à 17:32:21  profilanswer
 

n°1327908
skelter
Posté le 18-03-2006 à 18:03:04  profilanswer
 

tu surcharges operator[] et tu lui fait retourné un objet pour lequel tu peut appliquer []
 
dans le cas d'une matrice l'appel du premier [] retourne l'adresse de la ligne sur laquel on peut indexer la colonne voulue
 

Code :
  1. template<typename T>
  2. class matrix
  3. {
  4. public:
  5. typedef std::size_t size_type;
  6. typedef T value_type;
  7. typedef value_type * pointer;
  8. typedef const value_type * const_pointer;
  9. ...
  10. private:
  11. size_type lines, columns;
  12. pointer p;
  13. ...
  14. public:
  15. ...
  16. const_pointer operator [] (size_type n) const
  17. {
  18. return p + n * columns;
  19. }
  20. };


 
mais bon, ca existe deja  

n°1327911
nargy
Posté le 18-03-2006 à 18:27:45  profilanswer
 

skelter> merci
 
>mais bon, ca existe deja
 
En fait j ai un cas pratique, dans lequel j ai des classes polymorphes, auquelles il serait utile de fournir cet opérateur, mais les classes ont des tableaux différents en taille, en type, en nombre de dimensions. Parfois elles n ont pas du tout de tableaux (dans ce cas l opérateur renvoie une constante).

n°1328145
nargy
Posté le 19-03-2006 à 04:04:27  profilanswer
 

Bon, apparemment y a pas de solution simple.
Ça va être:
virtual const Val& get(uint, uint) const;
et:
virtual void set(uint, uint, const Val& );
 
à la bonne franquette!

n°1328190
Taz
bisounours-codeur
Posté le 19-03-2006 à 10:07:32  profilanswer
 

et pitié, au minimum mettez des vector<> derrière

n°1328195
nargy
Posté le 19-03-2006 à 10:19:10  profilanswer
 

haha, merci du conseil taz, mais je me suis fait mon propre autoptr et autoarray. Comme je le disais, ça va être à la bonne fanquette: programmé avec les doigts!

n°1328198
Taz
bisounours-codeur
Posté le 19-03-2006 à 10:47:51  profilanswer
 

sans doute complètement pourri donc ...

n°1328210
skelter
Posté le 19-03-2006 à 11:51:09  profilanswer
 

Taz a écrit :

et pitié, au minimum mettez des vector<> derrière


 
oui, ou valarray
 

Citation :


Bon, apparemment y a pas de solution simple.
Ça va être:
virtual const Val& get(uint, uint) const;
et:
virtual void set(uint, uint, const Val& );
 
à la bonne franquette!


 
ca marche ce que je t'ai montré et c'est simple
get/set c'est nul à utiliser (surtout le set avec la valeur en 3e parametre), tu pourrais également surcharger operator(), ca se fait aussi

n°1328223
nargy
Posté le 19-03-2006 à 12:31:59  profilanswer
 

> sans doute complètement pourri donc ...
non...!? j ai pas l impression d avoir besoin de vector. juste d allouer des blocs de mémoire partagés et détachables. j ai même pas d objets là dedans, c est des images.
 
les blocs mémoire peuvent par ailleurs être gérés par le hardware ou partagés en réseau.
 
je ne me sent pas assez confortable avec std:: pour trouver les bonnes classes pour faire ça.
 
> oui, ou valarray  
ça peut être interessant
 
> get/set c'est nul à utiliser
ouais!
 
> surcharger operator()
bonne idée!

n°1328259
skelter
Posté le 19-03-2006 à 14:11:47  profilanswer
 

Citation :

non...!? j ai pas l impression d avoir besoin de vector. juste d allouer des blocs de mémoire partagés et détachables. j ai même pas d objets là dedans, c est des images.
 
les blocs mémoire peuvent par ailleurs être gérés par le hardware ou partagés en réseau.
 
je ne me sent pas assez confortable avec std:: pour trouver les bonnes classes pour faire ça.


 
essaies quand meme avec std::vector ou autre et montre le code si il y a un probleme

mood
Publicité
Posté le 19-03-2006 à 14:11:47  profilanswer
 

n°1328301
nargy
Posté le 19-03-2006 à 15:41:24  profilanswer
 

C est possible de faire travailler std::vector sur de la mémoire déjà allouée via mmap()?

n°1328305
skelter
Posté le 19-03-2006 à 15:48:28  profilanswer
 

std::vector est parametrable au niveau de l'allocateur, ca permet pas mal de chose
 
mais je comprends pas pourquoi tu voudrais que ton vector utilises de la mémoire allouée par mmap, ca n'a pas de sens ? tu veux faire quoi ?

n°1328312
nargy
Posté le 19-03-2006 à 16:14:49  profilanswer
 

Le but, c est d arriver à faire dériver plusieurs classes de façon à pouvoir plugger entre eux des flux vidéos. Des flux vidéo sources:
- webcam (mmap)
- tv in (mmap mjpeg temps réel)
- fichier vidéo (décompression en mémoire),
des flux cibles:
- librairie graphique (soft)
- buffer carte vidéo (hard)
- overlay carte vidéo (hard)
- carte compression vidéo (hard)
- tv out (hard)
- fichier vidéo (soft)
 
Pour l instant, je me suis dit que pour factoriser au maximum les classes polymorphes, j aurai besoin d un gestion mémoire particulière qui puisse à la fois gérer un flux vidéo hardware en provenance d une webcam (souvent mmap) ou à destination d une carte video (buffer video), et avoir possibilité de détacher ou partager ces tampons mémoire pour des filtres software (resize notamment).

n°1328526
slash33
Posté le 19-03-2006 à 23:11:43  profilanswer
 

Taz avait présenté une solution exploitant un proxy dans une autre file. Ca s'applique ici aussi.

n°1328807
Taz
bisounours-codeur
Posté le 20-03-2006 à 14:18:27  profilanswer
 

http://forum.hardware.fr/hardwaref [...] 0942-1.htm
 
ouah je suis bon moi :) je m'en souvenais même plus.

n°1328872
slash33
Posté le 20-03-2006 à 15:46:26  profilanswer
 

Heureusement que je suis là pour te rappeler ton génie.  :o

n°1329042
nargy
Posté le 20-03-2006 à 20:02:17  profilanswer
 

Salut les génies :D
 
Bon, alors je me suis décidé pour utiliser l opérateur () (uint,uint), histoire d éviter à avoir à coder deux fois plus de classes polymorphes.
 
Pour std::vector, j ai étudié le doc publié par gnu gcc, très instructif les allocators. Mais je vais essayer de le placer là où il faut.
 
J ai d autres problèmes:
 
1°) mon compilateur préféré (gcc) aligne mes classes sur des mots: 1, 2 ou 4 octets, ce qui n est pas du tout du goût de ma webcam qui utilise une array de 3 octets par pixels.
 
2°) je suis un peu perdu dans les variants (il me semble que ça s appelle comme ça).
J encapsule les différents formats de pixels (ex: class GRAY/RGBA) dans une classe abstraite Signal pour pouvoir faire:
cartevideo(x,y)=webcam(x,y);
(rem: ça doit pas être trop optimisé tout ça)
 
un peu de code:

Code :
  1. class Signal
  2. {
  3.   protected:
  4.   static RGBA convertGRAY2RGBA(const GRAY v) { return v; }
  5.   static GRAY convertRGBA2GRAY(const RGBA v) { return v; }
  6.   public:
  7.   virtual Signal& operator=(RGBA)=0;
  8.   virtual Signal& operator=(GRAY)=0;
  9.   virtual operator RGBA () const =0;
  10.   virtual operator GRAY () const =0;
  11. };
  12. class SignalGRAY: public Signal
  13. {
  14.   GRAY& s;
  15.   public:
  16.   SignalGRAY(GRAY& v): s(v) {}
  17.   Signal& operator=(const Signal& o) { s=o; return *this; }
  18.   Signal& operator=(RGBA v) { s=convertRGBA2GRAY(v); return *this; }
  19.   Signal& operator=(GRAY v) { s=v; return *this; }
  20.   operator RGBA () const { return convertGRAY2RGBA(s); }
  21.   operator GRAY () const { return s; }
  22. };
  23. class Plot
  24. {
  25.   public:
  26.   virtual Signal& operator () (unsigned int, unsigned int)=0;
  27. };
  28. class PlotGray: public Plot
  29. {
  30.   GRAY _color;
  31.   public:
  32.   PlotGray(): _color(0) {}
  33.   Signal& operator () (unsigned int, unsigned int)
  34.   { return SignalGRAY(_color); }
  35. };


 
>  Signal& operator () (unsigned int, unsigned int)
>  { return SignalGRAY(_color); }
Ça c est une grosse connerie:

Code :
  1. plot_gray.h:19: error: invalid initialization of non-const reference of type 'Signal&'
  2. from a temporary of type 'SignalGRAY'


 
J ai comme l impression que je fait fausse route, non?

Message cité 1 fois
Message édité par nargy le 20-03-2006 à 20:03:13
n°1329053
++fab
victime du syndrome IH
Posté le 20-03-2006 à 20:30:02  profilanswer
 

nargy a écrit :


>  Signal& operator () (unsigned int, unsigned int)
>  { return SignalGRAY(_color); }
Ça c est une grosse connerie:

Code :
  1. plot_gray.h:19: error: invalid initialization of non-const reference of type 'Signal&'
  2. from a temporary of type 'SignalGRAY'


 
J ai comme l impression que je fait fausse route, non?


 
N-ième fois : Assigner un temporaire à une référence non const, c'est illégal.  
Assigner un temporaire à une référence constante, c'est légal mais *dans ton cas* stupide car le temporaire va cesser de vivre à la fin de sa scope.

n°1329056
nargy
Posté le 20-03-2006 à 20:44:43  profilanswer
 

oui, j ai bien précisé:
> Ça c est une grosse connerie:  
 
Seulement si je fait:
>  Signal operator () (unsigned int, unsigned int)
>  { return SignalGRAY(_color); }
 
c en est une autre: ma classe Signal possède des fonctions virtuelles pures.
 
je sèche sur la solution...

n°1329081
nargy
Posté le 20-03-2006 à 21:29:19  profilanswer
 

ha oauis, je fait fausse route, les variants se font avec des templates. je sens que ça va se terminer avec un gros switch ou une array de pointeurs de fonctions.

n°1329136
Taz
bisounours-codeur
Posté le 20-03-2006 à 22:19:26  profilanswer
 

#
virtual Signal& operator=(RGBA)=0;
#
 virtual Signal& operator=(GRAY)=0;
#
 virtual operator RGBA () const =0;
#
 virtual operator GRAY () const =0;
 
 
 
tu crois faire quoi là ?

n°1329166
nargy
Posté le 20-03-2006 à 23:05:25  profilanswer
 

convertir différents formats de pixels entre eux...

n°1329178
nargy
Posté le 20-03-2006 à 23:11:18  profilanswer
 

Enfin, ce sont des fonctions viruelle pures, réimplémentées dans SignalGRAY, par ex..
 
Ainsi, quand j ai une classe qui dérive de Signal, je peut convertir la valeur représenté de et vers n importe quelle autre palette.
 
Puis je pensais utiliser celà pour écrire:
cartevideo(x,y)=webcam(x,y);
 
Mais je me rends compte que pour utiliser les fonctions virtuelles, je dois à un moment donné avoir un pointeur (ou une ref) sur l objet signal.

n°1329185
nargy
Posté le 20-03-2006 à 23:22:54  profilanswer
 

ha ouais j ai pigé ce que tu voulais dire:
> tu crois faire quoi là ?
- j initialise un objet signal en mettant ces fonctions à nul.
 
Pour utiliser cette méthode, j en suis à <<où trouver un pointeur sur l objet SignalGray?>>
 
Je peut toujours le créer avec un new ou un delete, mais ça implique une allocation mémoire à gérer, et ça commence à faire beaucoup de pointeurs.edit:
 
edit:
 
j ai un peu googlé et je n ai trouvé que deux moyens de faire des objets ``variant``:
- un gros switch pabo,
- des templates qui se résolvent à la compilation.


Message édité par nargy le 20-03-2006 à 23:36:42
n°1329282
_darkalt3_
Proctopathe
Posté le 21-03-2006 à 10:23:14  profilanswer
 

[:drapal]

n°1329365
nargy
Posté le 21-03-2006 à 11:43:20  profilanswer
 

> [:drapal]
c est une blague, ou le sujet t interesse?
 
j ai renommé ma classe signal en basesignal, et j ai maintenant une classe signal qui contient un pointeur sur un new basesignal et des constructeurs/destructeurs & opérateurs =. ça compile, mais j ai pas encore testé. je le sens pas.
 
je teste demain, si ça marche, je publie un code propre.
 
> je peut toujours le créer avec un new ou un delete, mais ça implique une allocation mémoire à gérer, et ça commence à faire beaucoup de pointeurs.
- utiliser un pool? std::__pool_allocator?

n°1329371
_darkalt3_
Proctopathe
Posté le 21-03-2006 à 11:46:09  profilanswer
 

J'aime bien avoir des cas d'utilisation.

n°1329718
nargy
Posté le 21-03-2006 à 18:23:06  profilanswer
 

<Note>
Je cherche à connecter dans un premier temps 1 webcam, 1 carte tv-in, mixer le tout et envoyer le résultat sur 1 carte video-overlay et 1 carte vidéo-buffer via réseau. Je ne connais pas à l avance les palettes de couleur, les tailles et le fps des entrées-sorties vidéo. Chaque périphérique a sa gestion propre de son espace mémoire (sauf le réseau où j ai le choix).
</Note>
 
Ok, j ai élagé un max le code.
 
Normalement, je gère dans des fichiers à part les définitions/conversions de couleurs. J ai aussi un fichier pour les types qui dépendent du CPU (tailles/endienness).
 
Dans ce morceau je n ai gardé que 2 types de palettes graphiques: RGBA (4 channels=32bits), GRAY (1 channel=8bits), et un type NumericSignal (1 channel=flottant) (pour tester).
 
Mes ulucubrations de vocabulaire:
Signal = pixel,
Plot = réseau, mémoire ou périphérique vidéo.
 

Code :
  1. // code tout pourri: voir plus loin
  2. ////////////////////////// grosse classe signal
  3. class Signal
  4. {
  5.   // classe de base abtraite
  6.   class BaseSignal
  7.   {
  8. ..................
  9.     public:
  10.     virtual BaseSignal& operator=(const BaseSignal& o)=0;
  11.     virtual BaseSignal& operator=(RGBA)=0;
  12.     virtual BaseSignal& operator=(GRAY)=0;
  13.     virtual BaseSignal& operator=(NumericSignal)=0;
  14.     virtual operator RGBA () const =0;
  15.     virtual operator GRAY () const =0;
  16.     virtual operator NumericSignal () const =0;
  17.   };
  18.   class SignalRGBA: public BaseSignal
  19.   {
  20. ..................
  21.   };
  22.   class SignalGRAY: public BaseSignal
  23.   {
  24. ..................
  25.   };
  26.   class SignalSignal: public BaseSignal
  27.   {
  28. ..................
  29.   };
  30.   // utiliser un signal générique
  31.   BaseSignal* _s;
  32.   public:
  33.   // constructeurs/destructeur
  34.   Signal(NumericSignal& s): _s(new SignalSignal(s)) {}
  35.   Signal(GRAY& s): _s(new SignalGRAY(s)) {}
  36.   Signal(RGBA& s): _s(new SignalRGBA(s)) {}
  37.   ~Signal() { delete _s; }
  38.   // affectation
  39.   Signal& operator=(const Signal& o)
  40.   {
  41. fprintf(stderr,"Signal::=(Signal)\n" );
  42.     *_s=*(o._s); return *this; }
  43. ..................
  44. };
  45. ..................
  46. //////////////////////// petit test
  47. int main()
  48. {
  49.   PlotColor t1(0xffff00);
  50.   PlotSignal t2(0.25L);
  51.   PlotGray t3(0x7f);
  52.   PlotColor t4(0x00ffff);
  53.   PlotSignal t5(0.75L);
  54.   t1.dump();
  55.   t2.dump();
  56.   t3.dump();
  57.   t4.dump();
  58.   t5.dump();
  59.   t5(0,0)=t4(0,0)=t3(0,0)=t2(0,0)=t1(0,0);
  60.   t1.dump();
  61.   t2.dump();
  62.   t3.dump();
  63.   t4.dump();
  64.   t5.dump();
  65.   return 0;
  66. }


 
Ok, et ça marche :) :
 

Code :
  1. color: <255, 255, 0>
  2. numeric:0.25
  3. gray:127
  4. color: <255, 0, 255>
  5. numeric:0.75
  6. Signal::=(Signal)
  7. Signal::=(Signal)
  8. Signal::=(Signal)
  9. Signal::=(Signal)
  10. color: <255, 255, 0>
  11. numeric:0.666667
  12. gray:170
  13. color: <170, 170, 170>
  14. numeric:0.666667


 
Reste à faire quelques tests de rapidité, puis reproduire la méthode pour les périphériques pour pouvoir écrire directement quelquechose comme:

Code :
  1. VideoIn tv("/dev/video0" );
  2. WebCam webcam("/dev/video1" );
  3. VideoOverlay ecran( (XVideoPort) 61 );
  4. VideoBroadcast broadcast("localhost", 10107);
  5. while(1)
  6. {
  7.   Video temp=tv+webcam;
  8.   broadcast=temp;
  9.   ecran=temp;
  10. }


Message édité par nargy le 22-03-2006 à 14:40:37
n°1330088
nargy
Posté le 22-03-2006 à 11:58:26  profilanswer
 

> utiliser un pool? std::__pool_allocator?
 
Avec du debug sur les allocations du test précédent:

Code :
  1. new sig 0x804dc78
  2. new sig 0x804dc88
  3. new sig 0x804dc98
  4. new sig 0x804dca8
  5. del sig 0x804dca8
  6. del sig 0x804dc98
  7. del sig 0x804dc88
  8. del sig 0x804dc78


 
indique qu une pile est plus apropriée.

n°1330234
nargy
Posté le 22-03-2006 à 14:36:59  profilanswer
 

> J ai comme l impression que je fait fausse route, non?
 
oui: total space cette méthode de classe de variants avec fonctions virtuelles
 
j ai recodé en utilisant un tableau statique à deux dimensions avec des pointeurs sur les fonctions de convertion et une classe signal contenant:
  void* pval;
  unsigned int mytype;
  Signal& operator=(const Signal& o)
  {
    (conversions[mytype][o.mytype])(pval,o.pval);
    return *this;
  }
 
au lieu d un pointeur sur BaseSignal,
 
comparaison sur 30 millions d affectations: edit:

Code :
  1. sans optim               avec optim
  2. classes virtuelles : 0:09.47elapsed 93%CPU   0:06.25elapsed 95%CPU
  3. array de pfonctions: 0:03.46elapsed 96%CPU   0:01.26elapsed 90%CPU


C est pas très joli les void*, et c est presque plus du C++, mais il y a un facteur 2,6 à 5,2.

Message cité 1 fois
Message édité par nargy le 22-03-2006 à 15:09:05
n°1330513
++fab
victime du syndrome IH
Posté le 22-03-2006 à 19:44:24  profilanswer
 

nargy a écrit :

oui: total space cette méthode de classe de variants avec fonctions virtuelles


Comme tu dis. ça ne correspond en rien avec ce que j'ai l'habitude non seulement d'écrire, mais de voir. Déjà, variant, je ne sais pas d'où tu sors ce terme, mais je n'ai pas l'impression que tu te référes aux variants (à la Alexandrescu) que la littérature évoque -- et que Boost.Variant implémente, notament.
Après, j'ai du mal avec l'opertor= virtuel ...
 
Vu que tu as des conversion à faire, j'aurai utiliser les constructeurs pour convertir dans un sens, et les Proxy pour convertir dans l'autre sens.
 
 

Citation :

j ai recodé en utilisant un tableau statique à deux dimensions avec des pointeurs sur les fonctions de convertion et une classe signal contenant:
  void* pval;
  unsigned int mytype;
  Signal& operator=(const Signal& o)
  {
    (conversions[mytype][o.mytype])(pval,o.pval);
    return *this;
  }


 
Je ne comprends pas tout ce que tu essayes de faire, mais pour éviter le void*, et faire des conversions efficaces, quelquechose dans cet esprit doit pouvoir marcher :
 

Code :
  1. template<>
  2. struct Conversion<Signal,OtherSignal> // specialisation d'une classe template Conversion
  3. {
  4.     static Signal::valueType convert( Sig2 const& sig2 )
  5.         { .... }
  6. };
  7. template <class OtherSig>
  8. Signal( OtherSig const& sigP )
  9.     : sig_( Conversion<Signal,OtherSig>::convert( sigP ) )
  10. {}


 

Citation :

comparaison sur 30 millions d affectations: edit:

Code :
  1. sans optim               avec optim
  2. classes virtuelles : 0:09.47elapsed 93%CPU   0:06.25elapsed 95%CPU
  3. array de pfonctions: 0:03.46elapsed 96%CPU   0:01.26elapsed 90%CPU



Est-ce que ce test reflète parfaitement l'utilisation que tu en as ? Est-ce qu'un profiler ne serait pas plus précis pour mesurer les performances de ce code dans le contexte de ton application ?
 

Citation :

C est pas très joli les void*, et c est presque plus du C++


Ah

n°1330515
++fab
victime du syndrome IH
Posté le 22-03-2006 à 19:46:18  profilanswer
 

nargy a écrit :

[snip]
indique qu une pile est plus apropriée.


 
Pourquoi ?

n°1330570
nargy
Posté le 22-03-2006 à 21:18:46  profilanswer
 

++fab> merci de tees comments
 
> variant
- ouais, c est pas tout à fait ça, ça y ressemble vaguement, dans le sens où c est une classe qui est une union de plusieurs types.
 
> Après, j'ai du mal avec l'opertor= virtuel
- j en avais peut être pas besoin d ailleurs du virtuel
 
> pour éviter le void*, et faire des conversions efficaces, quelquechose dans cet esprit doit pouvoir marcher ...
- ouais la version template c est à peu ça, pour N types à convertir entre eux, il y a N*N fonctions de conversions (N=33).
 
> Est-ce que ce test reflète parfaitement l'utilisation que tu en as ?
- non, c est dans le pire des cas.
 
> C est pas très joli les void*, et c est presque plus du C++
- ...mais du C
 
> indique qu une pile est plus apropriée.
- parceque les allocations/désallocations de Signal ne se croisent pas (même si elles se croisaient la pile resterait dans des limites raisonnables), et une pile est ce qu il y a de plus rapide.
 
> Je ne comprends pas tout ce que tu essayes de faire
 
Ce que j essaye de faire: relier des périphériques vidéos.
 
Pour prendre un schema très simple: afficher la vidéo d une webcam sur un écran.
 
La webcam est gérée avec video4linux. Video4linux me donne un pointeur sur une zone mémoire contenant l image courante. Video4linux m informe aussi du codage de couleurs: Gray8 ou Bgr24.
 
Pour faire simple, l écran est géré par le serveur X. Le serveur me donne un pointeur vers la mémoire vidéo et m informe de la palette utilisée: Rgb24 ou Rgb32.
 
La webcam et l écran peuvent changer de palette, j ai donc besoin de fonctions de conversions de palette de la forme:
 
convertir(adressevideo* dest, adressevideo* source);
 
... pour toutes les combinaisons de palettes necessaires.
 
J ai déjà écrit un programme d affichage de webcam en C avec de gros switch et une interface C++, résultat: c est lent (sauts de frames) et pas pratique à réutiliser/modifier.
 
J ai divers morceaux de code pour faire pareil avec ma carte télé et une carte vidéo overlay. J ai plusieurs filtres vidéo aussi: écran bleu, détecteur de mouvement.
 
Je cherche à réunir ces morceaux de codes de façon homogène et réutilisable simplement, comme par exemple:
ecran(x,y)=webcam(x,y);
...sans se soucier des palettes à l extérieur des objets ``ecran`` et ``webcam``.

n°1330581
nargy
Posté le 22-03-2006 à 21:32:35  profilanswer
 

ha oui:
> convertir(adressevideo* dest, adressevideo* source);
>  ... pour toutes les combinaisons de palettes necessaires.  
 
D où mon idée de faire un tableau de N*N cases avec les fonctions de conversion dedans.
 
D où ces étranges lignes de code:
  void* pval;
  unsigned int mytype;
  Signal& operator=(const Signal& o)
  {
    (conversions[mytype][o.mytype])(pval,o.pval);
    return *this;
  }

n°1330602
++fab
victime du syndrome IH
Posté le 22-03-2006 à 22:00:39  profilanswer
 

Citation :

> variant
- ouais, c est pas tout à fait ça, ça y ressemble vaguement, dans le sens où c est une classe qui est une union de plusieurs types.


L'implémentation d'un variant est tellement traumatisante, que ton code aurait du m'y faire penser :)
 

Citation :

> Après, j'ai du mal avec l'opertor= virtuel
- j en avais peut être pas besoin d ailleurs du virtuel


Considère la solution Proxy pour émuler la surcharge du type de retour, et constructeur multiple peut-etre ?
 

Citation :

> pour éviter le void*, et faire des conversions efficaces, quelquechose dans cet esprit doit pouvoir marcher ...
- ouais la version template c est à peu ça, pour N types à convertir entre eux, il y a N*N fonctions de conversions (N=33).


Et comment tu regle ce coup avec ton tableau de pointeur de fonction ?
 

Citation :

> C est pas très joli les void*, et c est presque plus du C++
- ...mais du C


Ma remarque n'allait pas dans ce sens ...
 

Citation :

> indique qu une pile est plus apropriée.
- parceque les allocations/désallocations de Signal ne se croisent pas (même si elles se croisaient la pile resterait dans des limites raisonnables), et une pile est ce qu il y a de plus rapide.


Rien compris. Je n'arrive pas à comprendre comment tu peux présupposer du comportement de l'allocateur standard.
Mais si tu as le choix, et qu'une classe de stockage automatique fait l'affaire (C++ ne connait pas la pile), ne t'en prives pas.
 
 

Citation :

Je cherche à réunir ces morceaux de codes de façon homogène et réutilisable simplement, comme par exemple:
ecran(x,y)=webcam(x,y);
...sans se soucier des palettes à l extérieur des objets ``ecran`` et ``webcam``.


J'arrive pas à saisir la sémantique de ton operator=. ça veut dire "Chaque pixel de la webcam se retrouve sur l'écran" ?
 
Ce ne serait pas plus élégant de l'exprimer comme ça :

Code :
  1. Ecran ecran;
  2. Webcam webcam;
  3. ecran << webcam;
  4. // ou webcam >> ecran;


Message édité par ++fab le 22-03-2006 à 23:11:42
n°1330645
nargy
Posté le 22-03-2006 à 23:28:27  profilanswer
 

> Et comment tu regle ce coup avec ton tableau de pointeur de fonction ?
 
un peu de code, ça sera plus simple:

Code :
  1. // les fonctions de conversion:
  2. void convertGRAY2RGBA(void* pval, const void* p)
  3. { *((RGBA*)pval)=*((GRAY*)p); }
  4. void convertRGBA2GRAY(void* pval, const void* p)
  5. { *((GRAY*)pval)=*((RGBA*)p); }
  6. // etc.... de toute palette vers toute palette, ici 3*3
  7. // le type ``pointeur sur fonction de conversion``
  8. typedef void (*SignalConversion)(void*, const void*);
  9. // tableau statique de 3*3 fonctions de conversions
  10. // 0=GRAY, 1=RGBA, 2=Numeric
  11. // ex.: pour convertir de GRAY à RGBA:
  12. //    la fonction se trouve dans conversions[1][0]
  13. extern SignalConversion conversions[3][3];
  14. class Signal // la classe qui gère le niveau pixel
  15. {
  16.   void* pval; // pointeur vers la donnée
  17.   unsigned int mytype; // type de la donnée
  18.   public:
  19. // constructeurs
  20.   Signal(GRAY& s): pval(&s), mytype(0) {}
  21.   Signal(RGBA& s): pval(&s), mytype(1) {}
  22.   Signal(NumericSignal& s): pval(&s), mytype(2) {}
  23. // conversion générique
  24.   Signal& operator=(const Signal& o)
  25.   { (conversions[mytype][o.mytype])(pval,o.pval); return *this; }
  26. // etc...
  27. };


 
> ça veut dire "Chaque pixel de la télé se retrouve sur l'écran" ?
- juste le pixel situé à la position (x,y)
 

Code :
  1. Ecran ecran;
  2.     Webcam webcam;
  3.     ecran << webcam;


Oui, ça c est pour gérer le niveau flux vidéo. Mais avant d en arriver là, je doit gérer le niveau pixel: palettes de couleurs variables.
 
Après il y a le niveau image: tailles variables.
 
Enfin le niveau du flux vidéo: fps différents et entrelacements différents.
 
Dans l idéal, j ai des fonctions de conversion spécialisée vers tous les types possibles de périphériques avec toutes les tailles et tous les formats de pixel. Mais avant d en arriver là:

Code :
  1. for(unsigned int x=0;x<tailleX;x++)
  2.   for(unsigned int y=0;y<tailleY;y++)
  3.     ecran(x,y)=webcam(x,y);


...la copie pixel par pixel est obligatoire.

n°1330715
++fab
victime du syndrome IH
Posté le 23-03-2006 à 00:24:55  profilanswer
 

Je vois 2 autres techniques :
1 - modèle stratégie
 

Code :
  1. class Signal
  2. {
  3. public:
  4.     Signal( SignalType const& sig ) : sig_( sig.clone() ) {}
  5.     SignalType signal() const { return *sig_; }
  6. private:
  7.     SignalType* sig_;
  8.     Signal& operator=( Signal const& sig )
  9.     { sig_->convert( sig.signal() ); return *this; }
  10. };
  11. class SignalType
  12. {
  13. public:
  14.     void convert( SignalType const& s) { doConvert( s ); }
  15.     Signal* clone() const { return doClone(); }
  16.     virtual ~SignalType() {}
  17. private:
  18.     virtual Signal* doClone() const = 0;
  19.     virtual void doConvert( SignalType const& ) = 0;
  20. };
  21. class RGBA : public SignalType { ... };


 
2- classe template
 

Code :
  1. template <class SigT>
  2. class Signal
  3. {
  4.      SigT sig_;
  5. public:
  6.      SigT signal() const { return sig_; }
  7.      Signal( SigT const& sig )
  8.           : sig_( sig ) {}
  9.    
  10.      template <class SigT2>
  11.      Signal& operator=( Signal<SigT2> const& sig )
  12.           { sig_ = Converter<SigT,SigT2>::convert( sig.signal() ); return *this; }
  13. };


 
avec Converter comme décrit plus haut.
 
1- est souple à l'exécution.
2- n'est souple qu'à la compilation, mais est plus efficace. La, tu peux t'attendre à ce que le compilateur développe en ligne tout les appels.


Message édité par ++fab le 23-03-2006 à 00:42:11
n°1330724
nargy
Posté le 23-03-2006 à 01:07:45  profilanswer
 

Ha oui, je te suis. Mais, il y a un gros mais...
 
D abord en ce qui concerne la méthode 2, les templates se résolvent à la compilation, or il est tout à fait possible que le format de pixel change pendant l execution. Par exemple, en utilisant xrandr sur le serveur X.
 
 
Ensuite pour la méthode 2:
 
J'ai testé deux programmes, l'un avec des fonctions virtuelles, l'autre avec des pointeurs sur fonction.
Les pointeurs sur fonction sont 2 fois plus rapides. J'ai trouvé l'explication suivante:
 
objet -> vtable -> pfonction -> code
 
ça fait minimum 3 déréférences pour appeler une fonction virutelle, et:
 
objet -> pfonction -> code
 
donc minimum 2 déréférences avec les pointeurs sur fonction, or en assembleur i586+:
 
C = nbre cycles pour 1 déréférence = nbre cycles pour 2 déréférences
 
donc:
nbre cycles 3 déréférences = 2*C
 
=> les fonctions virtuelle sont au moins deux fois plus lentes que des pointeurs sur fonction.
 
Quand je fait:

Code :
  1. (conversions[mytype][o.mytype])(pval,o.pval);


j utilise 1 déférence pour le tableau, 1 pour le pointeur de fonction. L opérateur = lui même est en inline.
 
La méthode que j ai exposé plus haut ressemble à la tienne, à celà près que je mettais la classe SignalType en sous classe de Signal. Sinon du point de vue performances c est la même chose, le code assembleur doit être très proche sinon identique.
 
Je peut envisager la méthode 1 pour le niveau image, ou flux vidéo. Pour le niveau pixel je suis obligé de privilégier la performance. Pour une image 1MégaPixel les fonctions virtuelle me limitent à 8 fps et avec pointeur sur fonction 30 fps.
 
Ok, je te remercie, il me semble avoir fait le tour des méthodes pour avoir disons des classes convertibles entre elles.
 
Je vais me mettre la méthode des templates sous le coude pour les flux vidéo avec palette fixe.
 
Si tu aimes te prendre la tête sur les templates récursifs, une implémentation de variant que j ai étudié (j ai pas encore tout pigé...):
http://www.codeproject.com/cpp/union_list.asp

n°1330725
chrisbk
-
Posté le 23-03-2006 à 01:10:47  profilanswer
 

la difference entre une fonction virtuelle et un pointeur de fonction m'echappe pas mal

n°1330726
nargy
Posté le 23-03-2006 à 01:19:04  profilanswer
 

elles te permettent toutes les deux d effectuer un code différent en fonction d un type d objet, à l execution.

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Précédente

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  [C++/résolu] operator [][] () et types variants

 

Sujets relatifs
[Résolu][EXCEL] Recopie d'un fichier à l'autre par comparaison[RESOLU]Créer une Imputbox sur word avec VBA
[PHP] Comment éviter qu'un formulaire se vide si on revient ? [Résolu][resolu] suppression caracteres invisibles retour charriot
[Résolu] Erreur internet explorer sur forum phpbb[résolu] strtok, ou comment prendre ce qu'il ya apres un espace
[Résolu] Changement de port sur une page webprobleme avec DataSource [Resolu]
besion d'aide sur un tuto de tomcat avec jndi [resolu][Résolu] Image aléatoire
Plus de sujets relatifs à : [C++/résolu] operator [][] () et types variants


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR