[JAVA] Extrême lenteur pour decoder et afficher un jpeg.

Extrême lenteur pour decoder et afficher un jpeg. [JAVA] - Java - Programmation

Marsh Posté le 25-04-2005 à 14:12:52    

Je suis en train de concevoir un programme java qui manipule des cameras IP. Celles-ci renvoyent un flux mjpeg, dont j'extrais des tableaux de bytes correspondant chacun à un fichier jpeg.
Le problème c'est que le décodage de ce byte[] est extrêmement lent (~ 100ms pour un petit jpeg de 12ko en 512*512) et fait ralentir toute l'application (conso CPU ~70% pour du 10 fps :/). J'ai testé différentes méthodes et libraries utilisant des méthodes natives pour arriver au même résultat.
Avec jmf et en utilisant le même tableau de byte au départ les performances sont très bonnes, je peux atteindre les 30 fps en gardant des utilisation CPU très faibles <10%.
Comment avoir de si bon résultats sans utiliser JMF ? Quel est le secret de JMF ? Je me remet à vous car ca fait 2 semaines que je craque sur ce problème :(
 
 
 
Je vous montre quand même le code, mais c'est basic ...
 

Code :
  1. private void createimage() {
  2.  Image image = null;
  3.  //m_rawImage correspond au byte[]
  4.  InputStream in = new ByteArrayInputStream(m_rawImage);
  5.  JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(in);
  6.  try {
  7.   try {
  8.    long t1 = System.currentTimeMillis();
  9.    image = decoder.decodeAsBufferedImage();
  10.    System.out
  11.      .println("Time: " + (System.currentTimeMillis() - t1));
  12.   } catch (IOException e2) {
  13.    e2.printStackTrace();
  14.   }
  15.  } catch (ImageFormatException e) {
  16.   e.printStackTrace();
  17.  }
  18.  try {
  19.   in.close();
  20.  } catch (IOException e1) {
  21.   e1.printStackTrace();
  22.  }
  23.  m_imain = image;
  24. }

Reply

Marsh Posté le 25-04-2005 à 14:12:52   

Reply

Marsh Posté le 25-04-2005 à 15:33:27    

spiderbanana a écrit :

et fait ralentir toute l'application (conso CPU ~70% pour du 10 fps :/).


je n'y crois pas. Ta caméra doit simplement être mal réglée (réglée avec un cadence de 10fps).
 
si vraiment le taquet venait du décodage, tu serais à 100%.
 
 
utilise-tu le même code avec JMF et sans JMF pour initialiser la caméra ?


---------------
trainoo.com, c'est fini
Reply

Marsh Posté le 25-04-2005 à 17:31:27    

En fait j'ai un thread qui tourne en permanance et récupère les images jpeg. J'utilise des callback pour indiquer au SourceStream JMF ou à mon panel qu'un nouvelle image est dispo. Dans le cas de JMF, je lui fait remonter le byte[] et il se debrouille avec ses codec, dans le cas de mon panel je decode moi même le byte[] (en fait dans ce cas là, c'est le thread de production qui va decoder l'image, pour jmf il a son propre thread). Tant que le decodage n'est pas en route j'ai un bon FPS ...
 

Citation :

si vraiment le taquet venait du décodage, tu serais à 100%.


J'ai un peu de mal à trouver des explication pour ca. C'est vrai que c'est étrange. En plus, quand je veux decoder pas mal d'images par secondes ET que je les affiches le temps de decodage varie enormement (passe de 100ms à 0 ms ??!!).


Message édité par spiderbanana le 25-04-2005 à 17:40:06
Reply

Marsh Posté le 27-04-2005 à 11:23:48    

Hello,
J'ai le meme souci que toi !!
je voudrais bien connaitre ta solution avec le JMF moi je ne m'en sort pas !
merci d'avance ;)

Reply

Marsh Posté le 27-04-2005 à 14:37:03    

guinoumi a écrit :

Hello,
J'ai le meme souci que toi !!
je voudrais bien connaitre ta solution avec le JMF moi je ne m'en sort pas !
merci d'avance ;)


 
Je te conseille d'aller voir ici: http://java.sun.com/products/java- [...] Movie.html
Tu y trouveras le code pour faire une vidéo .mov à partie d'images jpeg avec jmf.
Modifie le code et utilise un Player à la place du Processor, vire tout ce qui est utile au processing, et modifie DataStream pour que ca colle avec ton programme.
Bonne chance !

Reply

Marsh Posté le 27-04-2005 à 16:52:37    

Pourrais tu m'expliquer ce que tu entend par :
J'utilise des callback pour indiquer au SourceStream JMF ou à mon panel qu'un nouvelle image est dispo!

Reply

Marsh Posté le 27-04-2005 à 17:16:37    

De meme j'aimerais savoir comment tu crée ton tableau de byte m_rawImage (moi je detecte les caractere de debut et de fin d'un fichier JPEG :0xffd8 et 0xffd9 car je ne connais pas la taille du fichier a l'avance mais c'est vraiment la galere !!)

Reply

Marsh Posté le 27-04-2005 à 18:01:52    

guinoumi a écrit :

Pourrais tu m'expliquer ce que tu entend par :
J'utilise des callback pour indiquer au SourceStream JMF ou à mon panel qu'un nouvelle image est dispo!


 
En fait j'utilise le même principe que les evenements en java. En gros ma classe SourceStream implemente un listener (une interface) et la classe qui va chercher les images renseigne tout ses listeners connus qu'une nouvelle image est dispo.
C'est une methode très utilisée en java, fait une recherche sur les interface et les callbacks.
 

Citation :

De meme j'aimerais savoir comment tu crée ton tableau de byte m_rawImage (moi je detecte les caractere de debut et de fin d'un fichier JPEG :0xffd8 et 0xffd9 car je ne connais pas la taille du fichier a l'avance mais c'est vraiment la galere !!)


 
Ben moi je récupère un flux mjpeg, donc je cherche les balises --myboundary pour decouper le flux. Mais c'est vrai que c'est très chiant. Par contre y a la classe StreamTokeniser (chuis pas sûr du nom)  en java qui pourra bien t'être utile.


Message édité par spiderbanana le 27-04-2005 à 18:02:39
Reply

Marsh Posté le 27-04-2005 à 18:07:03    

Personne d'autre peut m'aider ?

Reply

Marsh Posté le 27-04-2005 à 18:08:46    

Merci pour tout ces renseignements je vais essayer de m'en sortir !

Reply

Marsh Posté le 27-04-2005 à 18:08:46   

Reply

Marsh Posté le 27-04-2005 à 18:10:29    

guinoumi a écrit :

Merci pour tout ces renseignements je vais essayer de m'en sortir !


Elles viennent d'ou tes images ?

Reply

Marsh Posté le 27-04-2005 à 21:35:25    

Mes image viennent de camera IP mais de differentes marque ! et la resolution et la vitesse d'affichage peuvent changer a tout moment !
J'ai regerder la classe StremTokenizer mais c'est plus de l'analyse lexical que "byte a byte" !
c'est donc aussi un flux MJPEG et j'utilise aussi ta methode pour delimiter les images mais je ne vois pas comment les mettre dans un tableau dont je ne peu connaitre la taille a l'avance ?
pour l'instant j"envoyai le flux directement dans  le decodeur  mais je doit sauvgarder les images et la je suis un peu bloquer !

Reply

Marsh Posté le 28-04-2005 à 10:09:16    

pourrais tu m'en dire plus sur ron listener que tu as mis sur ta classe DataStream ?
C'est la methode read qui'il faut lancer lorsque une nouvelle image est dispo ?

Reply

Marsh Posté le 28-04-2005 à 12:02:42    

Code :
  1. /**
  2.  * Retourne si la prochaine lecture sera blocante
  3.  */
  4. public boolean willReadBlock() {
  5.  return block;
  6. }
  7. Object wait = new Object();
  8. /**
  9.  * On bloque tant que la nouvelle image ne sera pas arrivée
  10.  */
  11. boolean waitUnblock() {
  12.  synchronized (wait) {
  13.   try {
  14.    while (block) {
  15.     wait.wait();
  16.    }
  17.   } catch (Exception e) {
  18.   }
  19.  }
  20.  return true;
  21. }
  22. /**
  23.  * Méthode appelée par le processeur (JMF Processor) pour lire la nouvelle image
  24.  *  
  25.  */
  26. public void read(Buffer buf) throws IOException {
  27.  waitUnblock(); //on attent la nouvelle image
  28.  block = true;
  29.  byte[] raw = cam.getRawImage();
  30.  buf.setData(raw);
  31.  buf.setOffset(0);
  32.  buf.setLength(raw.length);
  33.  buf.setFormat(format);
  34.  buf.setFlags(buf.getFlags() | Buffer.FLAG_KEY_FRAME);
  35.   long time = (long) (nextImage * (1000 / format.getFrameRate()) * 1000000);
  36.   buf.setTimeStamp(time);
  37.   buf.setSequenceNumber(nextImage);
  38.  nextImage++;
  39. }
  40. public void imageChanged(ImageChangeEvent ie) {
  41.  {
  42.    synchronized (wait) {
  43.    //System.out.println("CameraSourceStream: image ok" );
  44.     block = false;
  45.    wait.notifyAll();
  46.   }
  47.  }
  48. }


Voilà pour le stream
 
Sinon pour ton flux mjpeg, tu devrais regarde du côté là: http://www.charliemouse.com/code/cambozola/
Il y a absolument toutes les classes nécessaires (et les sources).
Sinon certaines camera envoient aussi la taille de chaques images avant celle ci, c'est un petit raccourci pour parser le flux.
Bonne chance !


Message édité par spiderbanana le 28-04-2005 à 12:06:27
Reply

Marsh Posté le 28-04-2005 à 17:11:39    

que faut t'il mettre dans :
public void controllerUpdate(ControllerEvent ce) ???

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed