/** * This package provides classes to handle video in Processing. The API is compatible with the built-in video library of Processing. * GSVideo uses the multimedia toolkit GStreamer (http://www.gstreamer.net/) through the gstreamer-java bindings by Wayne Meissener: * http://code.google.com/p/gstreamer-java/ * @author Andres Colubri * @version 0.5.1 * * Copyright (c) 2008 Andres Colubri * * This source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This code is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * A copy of the GNU General Public License is available on the World * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also * obtain it by writing to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package codeanticode.gsvideo; import processing.core.*; import java.nio.*; import java.lang.reflect.*; import java.util.ArrayList; import org.gstreamer.*; import org.gstreamer.elements.*; /** * This class allows to create a custom GStreamer pipeline. */ public class GSPipeline extends PImage implements PConstants { /** * Creates an instance of GSPipeline using the pipeline specified in the string pipe. * @param parent PApplet * @param pipe String */ public GSPipeline(PApplet parent, String pipeStr) { // this creates a fake image so that the first time this // attempts to draw, something happens that's not an exception super(1, 1, RGB); this.parent = parent; gpipe = null; GSVideo.init(); // register methods parent.registerDispose(this); try { pipelineEventMethod = parent.getClass().getMethod("pipelineEvent", new Class[] { GSPipeline.class }); } catch (Exception e) { // no such method, or an error.. which is fine, just ignore } // Determining if the last element is fakesink or filesink. int idx; String lastElem, lastElemName; String[] parts; idx = pipeStr.lastIndexOf('!'); lastElem = pipeStr.substring(idx + 1, pipeStr.length()).trim(); parts = lastElem.split(" "); if (0 < parts.length) lastElemName = parts[0]; else lastElemName = ""; boolean fakeSink = lastElemName.equals("fakesink"); boolean fileSink = lastElemName.equals("filesink"); if (fakeSink || fileSink) { // If the pipeline ends in a fakesink or filesink element, the RGBDataSink is not added at the end of it... gpipe = Pipeline.launch(pipeStr); } else { // ...otherwise it is. gpipe = Pipeline.launch(pipeStr + " ! fakesink name=VideoSink"); videoSink = new RGBDataSink("rgb", gpipe, new RGBDataSink.Listener() { public void rgbFrame(int w, int h, IntBuffer buffer) { invokeEvent(w, h, buffer); } } ); } gpipe.setState(State.PLAYING); } /** * Returns "true" when a new video frame is available to read. * @return String[] */ public boolean available() { return available; } /** * Return true or false depending on whether a new frame has been read. * @return boolean */ public boolean newFrame() { return newFrame; } /** * Sets the value of newFrame to false. */ public void oldFrame() { newFrame = false; } /** * Reads the current video frame. */ public void read() { if (firstFrame) { super.init(pipeWidth, pipeHeight, RGB); loadPixels(); firstFrame = false; } pipePixels.get(pixels); updatePixels(); available = false; newFrame = true; } /** * Resumes the pipeline. */ public void resume() { gpipe.setState(State.PLAYING); } /** * Stops the pipeline. */ public void stop() { gpipe.setState(State.PAUSED); } /** * @invisible */ protected void invokeEvent(int w, int h, IntBuffer buffer) { available = true; pipeWidth = w; pipeHeight = h; pipePixels = buffer; //parent.println("getting frame: " + w + " " + h); // Creates a pipelineEvent. if (pipelineEventMethod != null) { try { pipelineEventMethod.invoke(parent, new Object[] { this }); } catch (Exception e) { System.err.println("error, disabling pipelineEvent() for GSPipeline"); e.printStackTrace(); pipelineEventMethod = null; } } } /** * @invisible */ public void dispose() { } /** * @invisible */ Method pipelineEventMethod; /** * @invisible */ boolean available; /** * @invisible */ boolean firstFrame = true; /** * @invisible */ int pipeWidth; /** * @invisible */ int pipeHeight; /** * @invisible */ IntBuffer pipePixels; /** * @invisible */ Pipeline gpipe; /** * @invisible */ RGBDataSink videoSink; /** * @invisible */ protected boolean newFrame; }