public synchronized void read() {
    // We loadPixels() first to ensure that at least we always have a non-null
    // pixels array, even if without any valid image inside.
    loadPixels();
    
    if (copyBufferMode) {
      // The native buffer from gstreamer is copies to the destination object.
      if (natBuffer == null || copyBufferMethod == null) {
        return;
      }    
      
      if (firstFrame) {
        super.init(bufWidth, bufHeight, RGB);
        loadPixels();
        firstFrame = false;
      }
      
      if (copyNatBuf) {
        // The native buffer is copied into a new rgb buffer created locally.
        IntBuffer temp = natBuffer.getByteBuffer().asIntBuffer();
        temp.rewind();
        if (rgbBuffer == null) {
          rgbBuffer = IntBuffer.allocate(bufWidth * bufHeight);
        }
        rgbBuffer.rewind();
        rgbBuffer.put(temp);
        rgbBuffer.rewind();
        
        natBuffer.dispose();
        natBuffer = null;
      } else {
        // The rgb buffer is just the native buffer viewed as
        // an int buffer.
        rgbBuffer = natBuffer.getByteBuffer().asIntBuffer();  
      }

      try {
        copyBufferMethod.invoke(copyHandler, new Object[] { natBuffer, rgbBuffer, bufWidth, bufHeight });
      } catch (Exception e) {
        e.printStackTrace();
      }
      
      natBuffer = null;         
    } else {
      if (copyPixels == null) {
        return;
      }    
      
      if (firstFrame) {
        super.init(bufWidth, bufHeight, RGB);
        loadPixels();
        firstFrame = false;
      }
      
      int[] temp = pixels;
      pixels = copyPixels;
      updatePixels();
      copyPixels = temp;  
      newFrame = true;
    }
    
    available = false;
  }