Index: src/codeanticode/gsvideo/GSCapture.java =================================================================== --- src/codeanticode/gsvideo/GSCapture.java (revision 145) +++ src/codeanticode/gsvideo/GSCapture.java (working copy) @@ -45,7 +45,7 @@ protected boolean firstFrame = true; protected int captureWidth; protected int captureHeight; - protected IntBuffer capturePixels; + protected IntBuffer capturePixels = null; protected Pipeline gpipe; public GSCapture(PApplet parent, int requestWidth, int requestHeight) { @@ -164,14 +164,29 @@ /** * Reads the current video frame. + * + * This method() and invokeEvent() are now synchronized, so that invokeEvent() + * can't be called whilst we're busy reading. In addition, I changed it so that + * now an internal buffer is allocated and maintained. Problematic frame error + * fixed by Charl P. Botha */ - public void read() { - if (firstFrame) { - // super.init(captureWidth, captureHeight, RGB); - loadPixels(); - firstFrame = false; - } + public synchronized void read() { + // can happen that read gets called before invokeEvent having been for + // the first time, i.e. capturePixels not allocated yet. + if (capturePixels == null) + return; + + // we're going to modify pixels, documentation says we have to do this every time + loadPixels(); + + // capturePixels is an IntBuffer (capture format is 32 bits per pixel, but depth 24) + // turns out pixels is a list of integers as well, so we should be ok + capturePixels.rewind(); + + // copy webcam image into our own PImage.pixels capturePixels.get(pixels); + + // we have modified the pixels so we have to call this updatePixels(); available = false; @@ -276,14 +291,29 @@ } /** + * invokeEvent() and read() are synchronized so that they can not be + * called simultaneously. when they were not synchronized, this caused + * the infamous problematic frame crash. + * found and fixed by Charl P. Botha * @invisible */ - protected void invokeEvent(int w, int h, IntBuffer buffer) { + protected synchronized void invokeEvent(int w, int h, IntBuffer buffer) { available = true; captureWidth = w; captureHeight = h; - capturePixels = buffer; + + // we're going to copy buffer to our own capturePixels buffer, because + // the capture pipeline could start filling it (before calling this + // handler) whilst we're still reading it in the read() method + if (capturePixels == null) + capturePixels = IntBuffer.allocate(width*height); + // now copy from buffer to capturePixels + // have to rewind both buffers as put is a relative bulk operation + buffer.rewind(); + capturePixels.rewind(); + capturePixels.put(buffer); + // Creates a movieEvent. if (captureEventMethod != null) { try {