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.ds.gstreamer.impl.VideoDeviceFilenameFilter; 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 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}