Skip to content

Commit

Permalink
GStreamer driver for Webcam-Capture, closes #57
Browse files Browse the repository at this point in the history
  • Loading branch information
sarxos committed May 6, 2013
1 parent 9f001b8 commit dbed631
Show file tree
Hide file tree
Showing 4 changed files with 226 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,6 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
package com.github.sarxos.webcam.ds.gstreamer;

import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import org.gstreamer.Caps;
import org.gstreamer.Element;
import org.gstreamer.ElementFactory;
import org.gstreamer.Pad;
import org.gstreamer.Pipeline;
import org.gstreamer.State;
import org.gstreamer.Structure;
import org.gstreamer.elements.RGBDataSink;

import com.github.sarxos.webcam.WebcamDevice;
import com.github.sarxos.webcam.WebcamResolution;


public class GStreamerDevice implements WebcamDevice, RGBDataSink.Listener {

/**
* Limit the lateness of frames to no more than 20ms (half a frame at 25fps)
*/
private static final long LATENESS = 20; // ms

private static final String FORMAT = "video/x-raw-yuv";

private final String name;
private final Dimension[] resolutions;

private Pipeline pipe = null;
private Element source = null;
private Element filter = null;
private RGBDataSink sink = null;
private BufferedImage image = null;
private Caps caps = null;

private AtomicBoolean open = new AtomicBoolean(false);
private AtomicBoolean disposed = new AtomicBoolean(false);
private Dimension resolution = WebcamResolution.VGA.getSize();

protected GStreamerDevice(String name) {

this.name = name;

pipe = new Pipeline(name);

sink = new RGBDataSink(name, this);
sink.setPassDirectBuffer(true);
sink.getSinkElement().setMaximumLateness(LATENESS, TimeUnit.MILLISECONDS);
sink.getSinkElement().setQOSEnabled(true);

source = ElementFactory.make("dshowvideosrc", "source");
source.set("device-name", name);

filter = ElementFactory.make("capsfilter", "filter");

resolutions = parseResolutions(source.getPads().get(0));
}

private static final Dimension[] parseResolutions(Pad pad) {

List<Dimension> dimensions = new ArrayList<Dimension>();

Caps caps = pad.getCaps();

Structure structure = null;
String format = null;

int n = caps.size();
int i = 0;

int w = -1;
int h = -1;

do {

structure = caps.getStructure(i++);
format = structure.getName();

if (format.equals(FORMAT)) {
w = structure.getRange("width").getMinInt();
h = structure.getRange("height").getMinInt();
dimensions.add(new Dimension(w, h));
}

} while (i < n);

return dimensions.toArray(new Dimension[dimensions.size()]);
}

@Override
public String getName() {
return name;
}

@Override
public Dimension[] getResolutions() {
return resolutions;
}

@Override
public Dimension getResolution() {
return resolution;
}

@Override
public void setResolution(Dimension size) {
this.resolution = size;
}

@Override
public BufferedImage getImage() {
return image;
}

@Override
public void open() {

if (!open.compareAndSet(false, true)) {
return;
}

Dimension size = getResolution();

image = new BufferedImage(size.width, size.height, BufferedImage.TYPE_INT_RGB);
image.setAccelerationPriority(0);
image.flush();

if (caps != null) {
caps.dispose();
} else {
caps = Caps.fromString(String.format("%s,width=%d,height=%d", FORMAT, size.width, size.height));
}

filter.setCaps(caps);

pipe.addMany(source, filter, sink);
Element.linkMany(source, filter, sink);
pipe.setState(State.PLAYING);
}

@Override
public void close() {

if (!open.compareAndSet(true, false)) {
return;
}

pipe.setState(State.NULL);
Element.unlinkMany(source, filter, sink);
pipe.removeMany(source, filter, sink);
}

@Override
public void dispose() {

if (!disposed.compareAndSet(false, true)) {
return;
}

close();

filter.dispose();
source.dispose();
sink.dispose();
pipe.dispose();
caps.dispose();
}

@Override
public boolean isOpen() {
return open.get();
}

@Override
public void rgbFrame(boolean preroll, int width, int height, IntBuffer rgb) {

BufferedImage tmp = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
tmp.setAccelerationPriority(0);
tmp.flush();

rgb.get(((DataBufferInt) tmp.getRaster().getDataBuffer()).getData(), 0, width * height);

image = tmp;
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
package com.github.sarxos.webcam.ds.gstreamer;

import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;

import org.gstreamer.Element;
import org.gstreamer.ElementFactory;
import org.gstreamer.Gst;
import org.gstreamer.Pipeline;
import org.gstreamer.State;
import org.gstreamer.interfaces.PropertyProbe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamDevice;
import com.github.sarxos.webcam.WebcamDriver;
import com.github.sarxos.webcam.WebcamPanel;
import com.sun.jna.NativeLibrary;


public class GStreamerDriver implements WebcamDriver {

private static final Logger LOG = LoggerFactory.getLogger(GStreamerDriver.class);

static {
init();
}

private static final class GStreamerShutdownHook extends Thread {

public GStreamerShutdownHook() {
Expand All @@ -28,40 +35,33 @@ public GStreamerShutdownHook() {

@Override
public void run() {
LOG.debug("GStreamer deinitialization");
Gst.deinit();
}
}

static {
private static final void init() {
LOG.debug("GStreamer initialization");
NativeLibrary.addSearchPath("gstreamer-0.10", "C:\\Program Files\\OSSBuild\\GStreamer\\v0.10.6\\bin");
Gst.init(GStreamerDriver.class.getSimpleName(), new String[0]);
Runtime.getRuntime().addShutdownHook(new GStreamerShutdownHook());
}

private static final Pipeline pipe = new Pipeline(GStreamerDriver.class.getSimpleName());

@Override
public List<WebcamDevice> getDevices() {

Element dshowsrc = ElementFactory.make("dshowvideosrc", "source");
dshowsrc.setState(State.READY);
List<WebcamDevice> devices = new ArrayList<WebcamDevice>();

Element dshowsrc = ElementFactory.make("dshowvideosrc", "source");
PropertyProbe probe = PropertyProbe.wrap(dshowsrc);
for (Object device : probe.getValues("device-name")) {
System.out.println(device);
}

dshowsrc.setState(State.NULL);
for (Object name : probe.getValues("device-name")) {
devices.add(new GStreamerDevice(name.toString()));
}

// final Element videosrc = ElementFactory.make("videotestsrc",
// "source");
// final Element videofilter = ElementFactory.make("capsfilter",
// "filter");
// videofilter.setCaps(Caps.fromString("video/x-raw-yuv, width=720, height=576"
// + ", bpp=32, depth=32, framerate=25/1"));
dshowsrc.dispose();

// TODO Auto-generated method stub
return null;
return devices;
}

@Override
Expand All @@ -70,6 +70,19 @@ public boolean isThreadSafe() {
}

public static void main(String[] args) {
new GStreamerDriver().getDevices();
// WebcamDriver driver = new GStreamerDriver();
// for (WebcamDevice device : driver.getDevices()) {
// System.out.println(device.getName());
// for (Dimension d : device.getResolutions()) {
// System.out.println(d);
// }
// }

Webcam.setDriver(new GStreamerDriver());
JFrame frame = new JFrame();
frame.add(new WebcamPanel(Webcam.getWebcams().get(1)));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamPanel;
import com.github.sarxos.webcam.ds.ipcam.IpCamDevice;
import com.github.sarxos.webcam.ds.ipcam.IpCamDeviceRegistry;
import com.github.sarxos.webcam.ds.ipcam.IpCamDriver;
import com.github.sarxos.webcam.ds.ipcam.IpCamMode;
Expand Down

0 comments on commit dbed631

Please sign in to comment.