Skip to content

Commit

Permalink
Use Kernel Streaming instead of Direct Show source
Browse files Browse the repository at this point in the history
  • Loading branch information
sarxos committed Sep 25, 2017
1 parent b6e9044 commit 5ff7c3c
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,11 @@ public class GStreamerDevice implements WebcamDevice, RGBDataSink.Listener, Webc
/**
* Device name, immutable. Used only on Windows platform.
*/
private final String name;
private final int deviceIndex;
/**
* Device name, immutable. Used only on Linux platform.
*/
private final File vfile;
private final File videoFile;

private final GStreamerDriver driver;

Expand All @@ -67,7 +67,7 @@ public class GStreamerDevice implements WebcamDevice, RGBDataSink.Listener, Webc
private Pipeline pipe = null;
private Element source = null;
private Element filter = null;
private Element jpegpar = null;
private Element jpegparse = null;
private Element jpegdec = null;
private Element[] elements = null;
private RGBDataSink sink = null;
Expand Down Expand Up @@ -95,16 +95,16 @@ public class GStreamerDevice implements WebcamDevice, RGBDataSink.Listener, Webc
*
* @param name the name of webcam device
*/
protected GStreamerDevice(GStreamerDriver driver, String name) {
protected GStreamerDevice(GStreamerDriver driver, int deviceIndex) {
this.driver = driver;
this.name = name;
this.vfile = null;
this.deviceIndex = deviceIndex;
this.videoFile = null;
}

protected GStreamerDevice(GStreamerDriver driver, File vfile) {
protected GStreamerDevice(GStreamerDriver driver, File videoFile) {
this.driver = driver;
this.name = null;
this.vfile = vfile;
this.deviceIndex = -1;
this.videoFile = videoFile;
}

/**
Expand All @@ -118,35 +118,30 @@ private synchronized void init() {

LOG.debug("GStreamer webcam device initialization");

pipe = new Pipeline(name);
pipe = new Pipeline(getName());
source = ElementFactory.make(GStreamerDriver.getSourceBySystem(), "source");

if (Platform.isWindows()) {
source = ElementFactory.make("dshowvideosrc", "dshowvideosrc");
source.set("device-name", name);
source.set("device-index", deviceIndex);
} else if (Platform.isLinux()) {
source = ElementFactory.make("v4l2src", "v4l2src");
source.set("device", vfile.getAbsolutePath());
source.set("device", videoFile.getAbsolutePath());
} else if (Platform.isMacOSX()) {
throw new IllegalStateException("not yet implemented");
}

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

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

jpegpar = ElementFactory.make("jpegparse", "jpegparse");
jpegparse = ElementFactory.make("jpegparse", "jpegparse");
jpegdec = ElementFactory.make("jpegdec", "jpegdec");

// if (Platform.isLinux()) {
pipelineReady();
// }

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

// if (Platform.isLinux()) {
pipelineStop();
// }
}

/**
Expand Down Expand Up @@ -233,9 +228,9 @@ private static Dimension capStructToResolution(Structure structure) {
@Override
public String getName() {
if (Platform.isWindows()) {
return name;
return Integer.toString(deviceIndex);
} else if (Platform.isLinux()) {
return vfile.getAbsolutePath();
return videoFile.getAbsolutePath();
} else {
throw new RuntimeException("Platform not supported by GStreamer capture driver");
}
Expand Down Expand Up @@ -311,7 +306,7 @@ private void pipelineElementsReset() {
private Element[] pipelineElementsPrepare() {
if (elements == null) {
if (FORMAT_MJPEG.equals(format)) {
elements = new Element[] { source, filter, jpegpar, jpegdec, sink };
elements = new Element[] { source, filter, jpegparse, jpegdec, sink };
} else {
elements = new Element[] { source, filter, sink };
}
Expand Down Expand Up @@ -376,7 +371,7 @@ public void dispose() {

source.dispose();
filter.dispose();
jpegpar.dispose();
jpegparse.dispose();
jpegdec.dispose();
caps.dispose();
sink.dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import org.gstreamer.Element;
import org.gstreamer.ElementFactory;
import org.gstreamer.Gst;
import org.gstreamer.interfaces.PropertyProbe;
import org.gstreamer.State;
import org.gstreamer.StateChangeReturn;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -104,6 +105,10 @@ private static final void init() {
public static final String FORMAT_YUV = "video/x-raw-yuv";
public static final String FORMAT_MJPEG = "image/jpeg";

protected static final String SRC_WINDOWS_KERNEL_STREAMING = "ksvideosrc";
protected static final String SRC_VIDEO_FOR_LINUX_2 = "v4l2src";
protected static final String SRC_QUICKTIME_KIT = "qtkitvideosrc";

private List<String> preferredFormats = new ArrayList<>(Arrays.asList(FORMAT_RGB, FORMAT_YUV, FORMAT_MJPEG));

/**
Expand All @@ -121,28 +126,41 @@ public List<String> getPreferredFormats() {
return preferredFormats;
}

@Override
public List<WebcamDevice> getDevices() {

List<WebcamDevice> devices = new ArrayList<WebcamDevice>();

String srcname = null;
protected static String getSourceBySystem() {
if (Platform.isWindows()) {
srcname = "dshowvideosrc";
return SRC_WINDOWS_KERNEL_STREAMING;
} else if (Platform.isLinux()) {
srcname = "v4l2src";
return SRC_VIDEO_FOR_LINUX_2;
} else if (Platform.isMac()) {
srcname = "qtkitvideosrc";
return SRC_QUICKTIME_KIT;
}
throw new IllegalStateException("Unsupported operating system");
}

@Override
public List<WebcamDevice> getDevices() {

List<WebcamDevice> devices = new ArrayList<WebcamDevice>();

final Element src = ElementFactory.make(srcname, "source");
final String srcName = getSourceBySystem();
final Element src = ElementFactory.make(srcName, srcName);

try {
if (Platform.isWindows()) {
PropertyProbe probe = PropertyProbe.wrap(src);
for (Object name : probe.getValues("device-name")) {
devices.add(new GStreamerDevice(this, name.toString()));
}

src.setState(State.NULL);

int m = 50;
int i = 0;
do {
src.set("device-index", i);
if (src.setState(State.READY) == StateChangeReturn.SUCCESS) {
devices.add(new GStreamerDevice(this, i));
} else {
break;
}
} while (i < m);

} else if (Platform.isLinux()) {
for (File vfile : NixVideoDevUtils.getVideoFiles()) {
devices.add(new GStreamerDevice(this, vfile));
Expand Down

0 comments on commit 5ff7c3c

Please sign in to comment.