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 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    }