diff --git a/webcam-capture-drivers/driver-gstreamer/pom.xml b/webcam-capture-drivers/driver-gstreamer/pom.xml
index 64acc2c5..12780e9c 100644
--- a/webcam-capture-drivers/driver-gstreamer/pom.xml
+++ b/webcam-capture-drivers/driver-gstreamer/pom.xml
@@ -25,20 +25,14 @@
gstreamer-java
1.5
-
-
-
-
junit
junit
- 4.11
test
diff --git a/webcam-capture-drivers/driver-gstreamer/src/example/java/WebcamPanelExample.java b/webcam-capture-drivers/driver-gstreamer/src/example/java/WebcamPanelExample.java
new file mode 100644
index 00000000..d7838271
--- /dev/null
+++ b/webcam-capture-drivers/driver-gstreamer/src/example/java/WebcamPanelExample.java
@@ -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);
+ }
+}
diff --git a/webcam-capture-drivers/driver-gstreamer/src/example/resources/logback.xml b/webcam-capture-drivers/driver-gstreamer/src/example/resources/logback.xml
index 2bb01a64..30ec27f8 100644
--- a/webcam-capture-drivers/driver-gstreamer/src/example/resources/logback.xml
+++ b/webcam-capture-drivers/driver-gstreamer/src/example/resources/logback.xml
@@ -5,6 +5,6 @@
-
+
diff --git a/webcam-capture-drivers/driver-gstreamer/src/main/java/com/github/sarxos/webcam/ds/gstreamer/GStreamerDevice.java b/webcam-capture-drivers/driver-gstreamer/src/main/java/com/github/sarxos/webcam/ds/gstreamer/GStreamerDevice.java
index 9d0306e6..fa436c3d 100644
--- a/webcam-capture-drivers/driver-gstreamer/src/main/java/com/github/sarxos/webcam/ds/gstreamer/GStreamerDevice.java
+++ b/webcam-capture-drivers/driver-gstreamer/src/main/java/com/github/sarxos/webcam/ds/gstreamer/GStreamerDevice.java
@@ -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;
@@ -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.
@@ -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 dimensions = new ArrayList();
+ 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 map = new HashMap();
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(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
@@ -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);
@@ -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;
diff --git a/webcam-capture-drivers/driver-gstreamer/src/main/java/com/github/sarxos/webcam/ds/gstreamer/GStreamerDriver.java b/webcam-capture-drivers/driver-gstreamer/src/main/java/com/github/sarxos/webcam/ds/gstreamer/GStreamerDriver.java
index 37559174..ec7e2137 100644
--- a/webcam-capture-drivers/driver-gstreamer/src/main/java/com/github/sarxos/webcam/ds/gstreamer/GStreamerDriver.java
+++ b/webcam-capture-drivers/driver-gstreamer/src/main/java/com/github/sarxos/webcam/ds/gstreamer/GStreamerDriver.java
@@ -100,15 +100,17 @@ public List 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()));
}
@@ -120,8 +122,8 @@ public List getDevices() {
throw new RuntimeException("Platform unsupported by GStreamer capture driver");
}
} finally {
- if (dshowsrc != null) {
- dshowsrc.dispose();
+ if (src != null) {
+ src.dispose();
}
}