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}