/**
* 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;
}