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 {
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                                for (File vfile : NixVideoDevUtils.getVideoFiles()) {
117                                        devices.add(new GStreamerDevice(vfile));
118                                }
119                        } else {
120                                throw new RuntimeException("Platform unsupported by GStreamer capture driver");
121                        }
122                } finally {
123                        if (dshowsrc != null) {
124                                dshowsrc.dispose();
125                        }
126                }
127
128                return devices;
129        }
130
131        @Override
132        public boolean isThreadSafe() {
133                return false;
134        }
135
136        @Override
137        public String toString() {
138                return getClass().getSimpleName();
139        }
140}