001package com.github.sarxos.webcam.ds.gstreamer;
002
003import java.io.File;
004import java.util.ArrayList;
005import java.util.List;
006import java.util.concurrent.atomic.AtomicBoolean;
007
008import org.gstreamer.Element;
009import org.gstreamer.ElementFactory;
010import org.gstreamer.Gst;
011import org.gstreamer.interfaces.PropertyProbe;
012import org.slf4j.Logger;
013import org.slf4j.LoggerFactory;
014
015import com.github.sarxos.webcam.WebcamDevice;
016import com.github.sarxos.webcam.WebcamDriver;
017import com.github.sarxos.webcam.WebcamException;
018import com.github.sarxos.webcam.util.NixVideoDevUtils;
019import com.sun.jna.NativeLibrary;
020import com.sun.jna.Platform;
021
022
023/**
024 * GStreamer capture driver.
025 * 
026 * @author Bartosz Firyn (sarxos)
027 */
028public 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 if (Platform.isLinux()) {
104                        srcname = "v4l2src";
105                } else if (Platform.isMac()) {
106                        srcname = "qtkitvideosrc";
107                }
108
109                Element src = ElementFactory.make(srcname, "source");
110
111                try {
112                        if (Platform.isWindows()) {
113                                PropertyProbe probe = PropertyProbe.wrap(src);
114                                for (Object name : probe.getValues("device-name")) {
115                                        devices.add(new GStreamerDevice(name.toString()));
116                                }
117                        } else if (Platform.isLinux()) {
118                                for (File vfile : NixVideoDevUtils.getVideoFiles()) {
119                                        devices.add(new GStreamerDevice(vfile));
120                                }
121                        } else {
122                                throw new RuntimeException("Platform unsupported by GStreamer capture driver");
123                        }
124                } finally {
125                        if (src != null) {
126                                src.dispose();
127                        }
128                }
129
130                return devices;
131        }
132
133        @Override
134        public boolean isThreadSafe() {
135                return false;
136        }
137
138        @Override
139        public String toString() {
140                return getClass().getSimpleName();
141        }
142}