001    package com.github.sarxos.webcam.ds.gstreamer;
002    
003    import java.util.ArrayList;
004    import java.util.List;
005    import java.util.concurrent.atomic.AtomicBoolean;
006    
007    import org.gstreamer.Element;
008    import org.gstreamer.ElementFactory;
009    import org.gstreamer.Gst;
010    import org.gstreamer.interfaces.PropertyProbe;
011    import org.slf4j.Logger;
012    import org.slf4j.LoggerFactory;
013    
014    import com.github.sarxos.webcam.WebcamDevice;
015    import com.github.sarxos.webcam.WebcamDriver;
016    import com.github.sarxos.webcam.WebcamException;
017    import com.sun.jna.NativeLibrary;
018    import com.sun.jna.Platform;
019    
020    
021    public class GStreamerDriver implements WebcamDriver {
022    
023            private static final Logger LOG = LoggerFactory.getLogger(GStreamerDriver.class);
024    
025            private static final class GStreamerShutdownHook extends Thread {
026    
027                    public GStreamerShutdownHook() {
028                            super("gstreamer-shutdown-hook");
029                    }
030    
031                    @Override
032                    public void run() {
033                            LOG.debug("GStreamer deinitialization");
034                            Gst.deinit();
035                    }
036            }
037    
038            private static final AtomicBoolean INITIALIZED = new AtomicBoolean(false);
039    
040            public GStreamerDriver() {
041                    if (INITIALIZED.compareAndSet(false, true)) {
042                            init();
043                    }
044            }
045    
046            private static final void init() {
047    
048                    if (!Platform.isWindows()) {
049                            throw new WebcamException(String.format("%s has been designed to work only on Windows platforms", GStreamerDriver.class.getSimpleName()));
050                    }
051    
052                    LOG.debug("GStreamer initialization");
053    
054                    String gpath = null;
055    
056                    for (String path : System.getenv("PATH").split(";")) {
057                            LOG.trace("Search %PATH% for gstreamer bin {}", path);
058                            if (path.indexOf("GStreamer\\v0.10.") != -1) {
059                                    gpath = path;
060                                    break;
061                            }
062                    }
063    
064                    if (gpath != null) {
065                            LOG.debug("Add bin directory to JNA search paths {}", gpath);
066                            NativeLibrary.addSearchPath("gstreamer-0.10", gpath);
067                    } else {
068                            throw new WebcamException("GStreamer has not been installed or not in %PATH%");
069                    }
070    
071                    Gst.init(GStreamerDriver.class.getSimpleName(), new String[0]);
072                    Runtime.getRuntime().addShutdownHook(new GStreamerShutdownHook());
073            }
074    
075            @Override
076            public List<WebcamDevice> getDevices() {
077    
078                    List<WebcamDevice> devices = new ArrayList<WebcamDevice>();
079    
080                    Element dshowsrc = ElementFactory.make("dshowvideosrc", "source");
081                    try {
082                            PropertyProbe probe = PropertyProbe.wrap(dshowsrc);
083                            for (Object name : probe.getValues("device-name")) {
084                                    devices.add(new GStreamerDevice(name.toString()));
085                            }
086                    } finally {
087                            if (dshowsrc != null) {
088                                    dshowsrc.dispose();
089                            }
090                    }
091    
092                    return devices;
093            }
094    
095            @Override
096            public boolean isThreadSafe() {
097                    return false;
098            }
099    }