JMF acquisition des images saccadée

JMF acquisition des images saccadée - Java - Programmation

Marsh Posté le 20-03-2008 à 19:00:34    

Salut, je suis en train d'essayer de récupérer des images de ma webcam pour faire un traitement dessus avant affichage.
Mon problème est que mon flux devient saccadé par intermittences : pendant une seconde, je vais avoir un flux fluide et ensuite ça va bloquer pendant 2-3 secondes. Je ne sais pas trop d'où ça peut venir ni comment corriger donc je fais appel à vous.
 

Code :
  1. public class DeviceHandler {
  2.     private CaptureDeviceInfo device;
  3.     private Player player;
  4.     private FrameGrabbingControl frameGrabber;
  5.     private Buffer buffer;
  6.     private BufferToImage bufferUtil;
  7.     private boolean ready;
  8.     private int i;
  9.    
  10.     /** Creates a new instance of DeviceHandler */
  11.     public DeviceHandler(String deviceName) {//throws Exception {
  12.         this.ready = false;
  13.         this.device = null;
  14.         this.device = CaptureDeviceManager.getDevice(deviceName);
  15.         //if (this.device == null) { throw new Exception("Device : \"" + deviceName + "\" not found !" ); }
  16.         MediaLocator ml = this.device.getLocator();
  17.         //if (ml == null) { throw new Exception("Unable to find an appropriate media locator !" ); }
  18.         this.player = null;
  19.         try { this.player = Manager.createRealizedPlayer(ml); }
  20.         catch (NoPlayerException ex) {}// throw new Exception("Unable to find an appropriate player !", ex); }
  21.         catch (CannotRealizeException ex) {}// throw new Exception("Unable to get the player in realized state !", ex); }
  22.         catch (IOException ex) {}// throw new Exception("Unable to create a player !", ex); }
  23.         //if (this.player == null) { throw new Exception("Player is NULL !" ); }
  24.         this.player.start();
  25.         while ((this.player.getState() & Player.Started) == 0) {}
  26.         this.ready = true;
  27.         this.frameGrabber = (FrameGrabbingControl)this.player.getControl("javax.media.control.FrameGrabbingControl" );
  28.         this.buffer = frameGrabber.grabFrame();
  29.         this.bufferUtil = new BufferToImage((VideoFormat)buffer.getFormat());
  30.         this.i = 0;
  31.     }
  32.    
  33.     public Image grabImage() {
  34.         this.i++;
  35.         this.buffer = frameGrabber.grabFrame();
  36. // juste pour tester
  37. if (this.buffer.getData() != null) { System.out.println(this.buffer.getFormat().getEncoding() + " " + i); }
  38.         this.bufferUtil = new BufferToImage((VideoFormat)buffer.getFormat());
  39.         return this.bufferUtil.createImage(buffer);
  40.     }
  41.    
  42.     public boolean isReady() { return this.ready; }
  43. }
  44. // et le main
  45.     public static void main(String[] args) {
  46.         DeviceHandler dh = new DeviceHandler("vfw:Microsoft WDM Image Capture (Win32):0" );
  47.         while (!dh.isReady()) {}
  48.         JFrame jf = new JFrame("test" );
  49.         jf.setSize(400, 300);
  50.         JPanel jp = new JPanel();
  51.         jp.setSize(320, 240);
  52.         jf.getContentPane().add(jp);
  53.         jf.setVisible(true);
  54.         jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  55.         Graphics gc = jp.getGraphics();
  56. // j'ai essayé en ajoutant un controle sur le temps mais ça ne change rien
  57.         long time = System.currentTimeMillis();
  58.         while (true) {
  59.             if (System.currentTimeMillis() > time + 200) {
  60.                 time = System.currentTimeMillis();
  61. // ici je devrais faire un traitement sur l'image avant l'affichage (et même pas l'afficher au final)
  62.                 gc.drawImage(dh.grabImage(), 0, 0, jp);
  63.             }
  64.         }
  65.     }


 
Voilà, j'espère que vous avez des idées. Je peux éviter d'utiliser BufferToImage si besoin et m'attaquer directement au buffer si les données sont rangées correctement (j'imagine Byte[] RGBRGBRGBRGBRGB... d'après le "rgb" que me donne buffer.getFormat().getEncoding())

Reply

Marsh Posté le 20-03-2008 à 19:00:34   

Reply

Marsh Posté le 21-03-2008 à 20:37:03    

puisque je vois que ça passionne tout le monde (et surtout qu'il y a pas beaucoup de ressources sur ce sujet sur le net), voilà la solution : attaquer directement le flux
 
Par contre, c'est parfaitement fluide mais il y a un gros décalage (environ 1 sec), ce qui n'est pas très bon vu que c'est sensé être utilisé en temps réel.
Des idées ?

Code :
  1. public class DeviceHandler {
  2.     private boolean ready;
  3.     private CaptureDeviceInfo device;
  4.     private PushBufferDataSource dataSource;
  5.    
  6.     /** Creates a new instance of DeviceHandler */
  7.     public DeviceHandler(String deviceName) throws Exception {
  8.         this.ready = false;
  9.         this.device = null;
  10.         this.device = CaptureDeviceManager.getDevice(deviceName);
  11.         if (this.device == null) { throw new Exception("Device : \"" + deviceName + "\" not found !" ); }
  12.         MediaLocator ml = this.device.getLocator();
  13.         if (ml == null) { throw new Exception("Unable to find an appropriate media locator !" ); }
  14.         this.dataSource = null;
  15.         DataSource ds = null;
  16.         try { ds = Manager.createDataSource(ml); }
  17.         catch (NoDataSourceException ex) { throw new Exception("Unable to find an appropriate data source !", ex); }
  18.         catch (IOException ex) { throw new Exception("Unable to create an appropriate data source !", ex); }
  19.         if (ds == null) { throw new Exception("Data source is NULL !" ); }
  20. //System.out.println(ds.getClass());
  21. // pour ma webcam, c'est PushBufferDataSource
  22.         if (!(ds instanceof PushBufferDataSource)) { throw new Exception("Wrong type of data source !" ); }
  23.         this.dataSource = (PushBufferDataSource)ds;
  24.         try { this.dataSource.connect(); }
  25.         catch (IOException ex) {}
  26.         try { this.dataSource.start(); }
  27.         catch (IOException ex) { throw new Exception("Unable to start data transfert !", ex); }
  28.         this.ready = true;
  29.     }
  30.    
  31.     public boolean isReady() { return this.ready; }
  32.    
  33.     public Object getBuffer() {
  34.         Buffer buf = new Buffer();
  35.         try { this.dataSource.getStreams()[0].read(buf); }
  36.         catch (IOException ex) {
  37.             ex.printStackTrace();
  38.         }
  39.         return buf.getData();
  40.     }
  41. }
  42. // le main
  43.     public static void main(String[] args) {
  44.         DeviceHandler dh = null;
  45.         try { dh = new DeviceHandler("vfw:Microsoft WDM Image Capture (Win32):0" ); }
  46.         catch (Exception ex) {
  47.             ex.printStackTrace();
  48.             System.exit(0);
  49.         }
  50.         while (!dh.isReady()) {}
  51.         BufferedImage img = new BufferedImage(320, 240, BufferedImage.TYPE_INT_RGB);
  52.         int tre = 15;
  53.         while (true) {
  54.             Object o = dh.getBuffer();
  55.             if ((o != null) && (o instanceof byte[])) {
  56.                 byte[] b = (byte[])o;
  57.                 int[] ib = new int[76800];
  58.                 for (int i = 0; i < b.length / 3; i++) {
  59.                     // on parcours le buffer à l'envers (BGRBGRBGR... du bas droit vers haut gauche)
  60.                     ib [76800 - i - 1] = (b[3 * i + 2] << 16) + (b[3 * i + 1] << 8) + b[3 * i];
  61.                 }
  62.                 img.setRGB(0, 0, 320, 240, ib, 0, 320);
  63. // traitements sur l'image
  64.             }
  65.         }
  66.        
  67.     }


---------------
The Rom's, à votre service
Reply

Sujets relatifs:

Leave a Replay

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