Skip to content

Commit

Permalink
GStremaer capture use of video/x-raw-rgb to increase FPS
Browse files Browse the repository at this point in the history
  • Loading branch information
sarxos committed Aug 8, 2014
1 parent 9edbe37 commit c337b53
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 39 deletions.
8 changes: 1 addition & 7 deletions webcam-capture-drivers/driver-gstreamer/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,14 @@
<artifactId>gstreamer-java</artifactId>
<version>1.5</version>
</dependency>
<!-- uncomment if you would like debug prints to be visible -->
<!--
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.9</version>
<scope>provided</scope>
</dependency>
-->
<!-- end uncomment -->

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import javax.swing.JFrame;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamPanel;
import com.github.sarxos.webcam.WebcamResolution;
import com.github.sarxos.webcam.ds.gstreamer.GStreamerDriver;


public class WebcamPanelExample {

static {
Webcam.setDriver(new GStreamerDriver());
}

public static void main(String[] args) {

Webcam webcam = Webcam.getDefault();
webcam.setViewSize(WebcamResolution.HD720.getSize());

WebcamPanel panel = new WebcamPanel(webcam);
panel.setDisplayDebugInfo(true);
panel.setFPSDisplayed(true);
panel.setFillArea(true);

JFrame window = new JFrame("Test webcam panel");
window.add(panel);
window.setResizable(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.pack();
window.setVisible(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
</layout>
</appender>
<root level="debug">
<appender-ref ref="STDOUT" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import java.io.File;
import java.nio.IntBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

Expand Down Expand Up @@ -38,10 +39,21 @@ public class GStreamerDevice implements WebcamDevice, RGBDataSink.Listener, Webc
*/
private static final long LATENESS = 20; // ms

/**
* First formats are better. For example video/x-raw-rgb gives 30 FPS on
* HD720p where video/x-raw-yuv only 10 FPS on the same resolution. The goal
* is to use these "better" formats first, and then fallback to less
* efficient when not available.
*/
private static final String[] BEST_FORMATS = {
"video/x-raw-rgb",
"video/x-raw-yuv",
};

/**
* Video format to capture.
*/
private static final String FORMAT_MIME = "video/x-raw-yuv";
private String format;

/**
* All possible resolutions - populated while initialization phase.
Expand Down Expand Up @@ -146,46 +158,79 @@ private synchronized void init() {
* @param pad the pad to get resolutions from
* @return Array of resolutions supported by device connected with pad
*/
private static final Dimension[] parseResolutions(Pad pad) {

List<Dimension> dimensions = new ArrayList<Dimension>();
private Dimension[] parseResolutions(Pad pad) {

Caps caps = pad.getCaps();

Structure structure = null;
format = findBestFormat(caps);

LOG.debug("Best format is {}", format);

Dimension r = null;
Structure s = null;
String mime = null;

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

int w = -1;
int h = -1;
Map<String, Dimension> map = new HashMap<String, Dimension>();

do {

structure = caps.getStructure(i++);
s = caps.getStructure(i++);

LOG.debug("Found format structure {}", structure);
LOG.debug("Found format structure {}", s);

mime = structure.getName();
mime = s.getName();

if (mime.equals(FORMAT_MIME)) {
if (Platform.isWindows()) {
w = structure.getRange("width").getMinInt();
h = structure.getRange("height").getMinInt();
dimensions.add(new Dimension(w, h));
} else if (Platform.isLinux()) {
if ("YUY2".equals(structure.getFourccString("format"))) {
w = structure.getInteger("width");
h = structure.getInteger("height");
dimensions.add(new Dimension(w, h));
}
if (mime.equals(format)) {
if ((r = capStructToResolution(s)) != null) {
map.put(r.width + "x" + r.height, r);
}
}

} while (i < n);

return dimensions.toArray(new Dimension[dimensions.size()]);
Dimension[] resolutions = new ArrayList<Dimension>(map.values()).toArray(new Dimension[map.size()]);

if (LOG.isDebugEnabled()) {
for (Dimension d : resolutions) {
LOG.debug("Resolution detected {}", d);
}
}

return resolutions;
}

private static String findBestFormat(Caps caps) {
for (String f : BEST_FORMATS) {
for (int i = 0, n = caps.size(); i < n; i++) {
if (f.equals(caps.getStructure(i).getName())) {
return f;
}
}
}
return null;
}

private static Dimension capStructToResolution(Structure structure) {

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

if (Platform.isWindows()) {
w = structure.getRange("width").getMinInt();
h = structure.getRange("height").getMinInt();
} else if (Platform.isLinux()) {
w = structure.getInteger("width");
h = structure.getInteger("height");
}

if (w > 0 && h > 0) {
return new Dimension(w, h);
} else {
return null;
}
}

@Override
Expand Down Expand Up @@ -243,7 +288,7 @@ public void open() {
caps.dispose();
}

caps = Caps.fromString(String.format("%s,width=%d,height=%d", FORMAT_MIME, size.width, size.height));
caps = Caps.fromString(String.format("%s,width=%d,height=%d", format, size.width, size.height));

filter.setCaps(caps);

Expand Down Expand Up @@ -317,9 +362,8 @@ 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);
tmp.flush();

image = tmp;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,17 @@ public List<WebcamDevice> getDevices() {
String srcname = null;
if (Platform.isWindows()) {
srcname = "dshowvideosrc";
} else {
} else if (Platform.isLinux()) {
srcname = "v4l2src";
} else if (Platform.isMac()) {
srcname = "qtkitvideosrc";
}

Element dshowsrc = ElementFactory.make(srcname, "source");
Element src = ElementFactory.make(srcname, "source");

try {
if (Platform.isWindows()) {
PropertyProbe probe = PropertyProbe.wrap(dshowsrc);
PropertyProbe probe = PropertyProbe.wrap(src);
for (Object name : probe.getValues("device-name")) {
devices.add(new GStreamerDevice(name.toString()));
}
Expand All @@ -120,8 +122,8 @@ public List<WebcamDevice> getDevices() {
throw new RuntimeException("Platform unsupported by GStreamer capture driver");
}
} finally {
if (dshowsrc != null) {
dshowsrc.dispose();
if (src != null) {
src.dispose();
}
}

Expand Down

0 comments on commit c337b53

Please sign in to comment.