001 package com.github.sarxos.webcam.ds.gstreamer;
002
003 import java.io.File;
004 import java.util.ArrayList;
005 import java.util.List;
006 import java.util.concurrent.atomic.AtomicBoolean;
007
008 import org.gstreamer.Element;
009 import org.gstreamer.ElementFactory;
010 import org.gstreamer.Gst;
011 import org.gstreamer.interfaces.PropertyProbe;
012 import org.slf4j.Logger;
013 import org.slf4j.LoggerFactory;
014
015 import com.github.sarxos.webcam.WebcamDevice;
016 import com.github.sarxos.webcam.WebcamDriver;
017 import com.github.sarxos.webcam.WebcamException;
018 import com.github.sarxos.webcam.ds.gstreamer.impl.VideoDeviceFilenameFilter;
019 import com.sun.jna.NativeLibrary;
020 import com.sun.jna.Platform;
021
022
023 /**
024 * GStreamer capture driver.
025 *
026 * @author Bartosz Firyn (sarxos)
027 */
028 public class GStreamerDriver implements WebcamDriver {
029
030 private static final Logger LOG = LoggerFactory.getLogger(GStreamerDriver.class);
031
032 private static final class GStreamerShutdownHook extends Thread {
033
034 public GStreamerShutdownHook() {
035 super("gstreamer-shutdown-hook");
036 }
037
038 @Override
039 public void run() {
040 LOG.debug("GStreamer deinitialization");
041 Gst.deinit();
042 }
043 }
044
045 private static final AtomicBoolean INITIALIZED = new AtomicBoolean(false);
046
047 public GStreamerDriver() {
048 if (INITIALIZED.compareAndSet(false, true)) {
049 init();
050 }
051 }
052
053 private static final void init() {
054
055 if (!Platform.isWindows() && !Platform.isLinux()) {
056 throw new WebcamException(String.format("%s has been designed to work only on Windows and Linux platforms", GStreamerDriver.class.getSimpleName()));
057 }
058
059 LOG.debug("GStreamer initialization");
060
061 String gpath = null;
062
063 if (Platform.isWindows()) {
064
065 String path = System.getenv("PATH");
066
067 for (String p : path.split(";")) {
068 LOG.trace("Search %PATH% for gstreamer bin {}", p);
069 if (p.indexOf("GStreamer\\v0.10.") != -1) {
070 gpath = p;
071 break;
072 }
073 }
074
075 if (gpath != null) {
076 LOG.debug("Add bin directory to JNA search paths {}", gpath);
077 NativeLibrary.addSearchPath("gstreamer-0.10", gpath);
078 } else {
079 throw new WebcamException(String.format("GStreamer has not been installed or not available in PATH: %s", path));
080 }
081 }
082
083 //@formatter:off
084 String[] args = new String[] {
085 // "--gst-plugin-path", new File(".").getAbsolutePath(),
086 // "--gst-debug-level=3",
087 };
088 //@formatter:on
089
090 Gst.init(GStreamerDriver.class.getSimpleName(), args);
091
092 Runtime.getRuntime().addShutdownHook(new GStreamerShutdownHook());
093 }
094
095 @Override
096 public List<WebcamDevice> getDevices() {
097
098 List<WebcamDevice> devices = new ArrayList<WebcamDevice>();
099
100 String srcname = null;
101 if (Platform.isWindows()) {
102 srcname = "dshowvideosrc";
103 } else {
104 srcname = "v4l2src";
105 }
106
107 Element dshowsrc = ElementFactory.make(srcname, "source");
108
109 try {
110 if (Platform.isWindows()) {
111 PropertyProbe probe = PropertyProbe.wrap(dshowsrc);
112 for (Object name : probe.getValues("device-name")) {
113 devices.add(new GStreamerDevice(name.toString()));
114 }
115 } else if (Platform.isLinux()) {
116 VideoDeviceFilenameFilter vfilter = new VideoDeviceFilenameFilter();
117 for (File vfile : vfilter.getVideoFiles()) {
118 devices.add(new GStreamerDevice(vfile));
119 }
120 } else {
121 throw new RuntimeException("Platform unsupported by GStreamer capture driver");
122 }
123 } finally {
124 if (dshowsrc != null) {
125 dshowsrc.dispose();
126 }
127 }
128
129 return devices;
130 }
131
132 @Override
133 public boolean isThreadSafe() {
134 return false;
135 }
136
137 @Override
138 public String toString() {
139 return getClass().getSimpleName();
140 }
141 }