diff --git a/.gitignore b/.gitignore index 96da8653..50105695 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,11 @@ .settings target -webcam-capture-civil-ds/.settings -webcam-capture-civil-ds/target -webcam-capture-jmf-ds/.settings -webcam-capture-jmf-ds/target +webcam-capture-driver-civil/.settings +webcam-capture-driver-civil/target +webcam-capture-driver-jmf/.settings +webcam-capture-driver-jmf/target webcam-capture/.settings webcam-capture/target -webcam-capture-openimaj-ds/.settings -webcam-capture-openimaj-ds/target +webcam-capture-driver-openimaj/.settings +webcam-capture-driver-openimaj/target diff --git a/webcam-capture/src/main/assembly/dist.xml b/distribution.xml similarity index 100% rename from webcam-capture/src/main/assembly/dist.xml rename to distribution.xml diff --git a/pom.xml b/pom.xml index aeffe568..f2d9cc96 100644 --- a/pom.xml +++ b/pom.xml @@ -6,17 +6,25 @@ com.github.sarxos webcam-capture-parent - 0.3 + 0.3.1 + pom Webcam Capture - Root POM This is Webcam Capture root POM - pom - SarXos Design - http://www.sarxos.pl + Bartosz Firyn (SarXos) + https://github.com/sarxos + + + MIT License + http://www.opensource.org/licenses/mit-license.html + repo + + + sarxos-ftp-repo @@ -24,27 +32,37 @@ - - - - org.apache.maven.plugins - maven-compiler-plugin - - 1.5 - 1.5 - - - + + scm:git:git@github.com:sarxos/webcam-capture.git + scm:git:git@github.com:sarxos/webcam-capture.git + git@github.com:sarxos/webcam-capture.git + - + + GitHub + https://github.com/sarxos/webcam-capture/issues + webcam-capture - webcam-capture-civil-ds - webcam-capture-jmf-ds - webcam-capture-openimaj-ds + webcam-capture-driver-civil + webcam-capture-driver-jmf + webcam-capture-driver-openimaj + + + org.slf4j + slf4j-api + 1.6.4 + + + ch.qos.logback + logback-classic + 0.9.18 + + + notest @@ -60,11 +78,189 @@ + + sign + + + performRelease + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + + + sign-artifacts + verify + + sign + + + + + + + - - - + + + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.apache.maven.plugins + maven-dependency-plugin + [1.0.0,) + + copy-dependencies + + + + + + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + 1.6 + 1.6 + + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.8.1 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 2.4 + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/dependencies + false + false + true + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.3 + + + distribution.xml + + + + + make-assembly + package + + single + + + + + + + + org.apache.maven.wagon + wagon-ftp + 1.0-beta-7 + + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.8.1 + + public + cam,webcam,camera,spycam,capture + + + + + + + org.apache.maven.plugins maven-jxr-plugin @@ -140,5 +335,6 @@ + --> - \ No newline at end of file + diff --git a/webcam-capture-jmf-ds/.classpath b/webcam-capture-driver-civil/.classpath similarity index 76% rename from webcam-capture-jmf-ds/.classpath rename to webcam-capture-driver-civil/.classpath index 966e2298..8fe0193e 100644 --- a/webcam-capture-jmf-ds/.classpath +++ b/webcam-capture-driver-civil/.classpath @@ -1,7 +1,8 @@ - + + diff --git a/webcam-capture-civil-ds/.project b/webcam-capture-driver-civil/.project similarity index 100% rename from webcam-capture-civil-ds/.project rename to webcam-capture-driver-civil/.project diff --git a/webcam-capture-civil-ds/pom.xml b/webcam-capture-driver-civil/pom.xml similarity index 60% rename from webcam-capture-civil-ds/pom.xml rename to webcam-capture-driver-civil/pom.xml index 45e4bded..d7a5b111 100644 --- a/webcam-capture-civil-ds/pom.xml +++ b/webcam-capture-driver-civil/pom.xml @@ -2,32 +2,21 @@ 4.0.0 - com.github.sarxos.webcam-capture - webcam-capture-civil-ds - 0.3-SNAPSHOT + + com.github.sarxos + webcam-capture-parent + 0.3.1 + + webcam-capture-driver-civil Webcam Capture - LTI CIVIL Data Source This is LTI Civil implementation of webcam data source. It allows you to capture webcam media without JMF installed. - - - sarxos-ftp-repo - ftp://ftp.sarxos.pl/maven2 - - - - - - sarxos-repo - http://repo.sarxos.pl/maven2 - - - com.github.sarxos webcam-capture - 0.3-SNAPSHOT + ${project.version} org.lti-civil diff --git a/webcam-capture-civil-ds/src/main/java/com/github/sarxos/webcam/ds/civil/CivilDevice.java b/webcam-capture-driver-civil/src/main/java/com/github/sarxos/webcam/ds/civil/LtiCivilDevice.java similarity index 87% rename from webcam-capture-civil-ds/src/main/java/com/github/sarxos/webcam/ds/civil/CivilDevice.java rename to webcam-capture-driver-civil/src/main/java/com/github/sarxos/webcam/ds/civil/LtiCivilDevice.java index 427ba415..110ae847 100644 --- a/webcam-capture-civil-ds/src/main/java/com/github/sarxos/webcam/ds/civil/CivilDevice.java +++ b/webcam-capture-driver-civil/src/main/java/com/github/sarxos/webcam/ds/civil/LtiCivilDevice.java @@ -28,9 +28,9 @@ * * @author Bartosz Firyn (SarXos) */ -public class CivilDevice implements WebcamDevice, CaptureObserver { +public class LtiCivilDevice implements WebcamDevice, CaptureObserver { - private static final Logger LOG = LoggerFactory.getLogger(CivilDevice.class); + private static final Logger LOG = LoggerFactory.getLogger(LtiCivilDevice.class); private CaptureDeviceInfo cdi = null; private List dimensions = null; @@ -40,7 +40,7 @@ public class CivilDevice implements WebcamDevice, CaptureObserver { private boolean open = false; private boolean capturing = false; - public CivilDevice(CaptureDeviceInfo cdi) { + public LtiCivilDevice(CaptureDeviceInfo cdi) { this.cdi = cdi; } @@ -53,7 +53,7 @@ public Dimension[] getSizes() { if (dimensions == null) { dimensions = new ArrayList(); - CaptureSystem system = CivilDataSource.getCaptureSystem(); + CaptureSystem system = LtiCivilDriver.getCaptureSystem(); Set set = new HashSet(); try { @@ -114,7 +114,7 @@ public void open() { return; } try { - stream = CivilDataSource.getCaptureSystem().openCaptureDeviceStream(cdi.getDeviceID()); + stream = LtiCivilDriver.getCaptureSystem().openCaptureDeviceStream(cdi.getDeviceID()); stream.setVideoFormat(findFormat()); stream.setObserver(this); stream.start(); diff --git a/webcam-capture-civil-ds/src/main/java/com/github/sarxos/webcam/ds/civil/CivilDataSource.java b/webcam-capture-driver-civil/src/main/java/com/github/sarxos/webcam/ds/civil/LtiCivilDriver.java similarity index 73% rename from webcam-capture-civil-ds/src/main/java/com/github/sarxos/webcam/ds/civil/CivilDataSource.java rename to webcam-capture-driver-civil/src/main/java/com/github/sarxos/webcam/ds/civil/LtiCivilDriver.java index b8e3cd33..7364a996 100644 --- a/webcam-capture-civil-ds/src/main/java/com/github/sarxos/webcam/ds/civil/CivilDataSource.java +++ b/webcam-capture-driver-civil/src/main/java/com/github/sarxos/webcam/ds/civil/LtiCivilDriver.java @@ -1,14 +1,13 @@ package com.github.sarxos.webcam.ds.civil; -import java.awt.Dimension; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.github.sarxos.webcam.WebcamDataSource; import com.github.sarxos.webcam.WebcamDevice; +import com.github.sarxos.webcam.WebcamDriver; import com.lti.civil.CaptureDeviceInfo; import com.lti.civil.CaptureException; import com.lti.civil.CaptureSystem; @@ -16,9 +15,14 @@ import com.lti.civil.DefaultCaptureSystemFactorySingleton; -public class CivilDataSource implements WebcamDataSource { +public class LtiCivilDriver implements WebcamDriver { - private static final Logger LOG = LoggerFactory.getLogger(CivilDataSource.class); + // load civil DLL + static { + LtiCivilLoader.load("civil"); + } + + private static final Logger LOG = LoggerFactory.getLogger(LtiCivilDriver.class); private static List devices = null; private static CaptureSystemFactory factory = null; @@ -30,6 +34,8 @@ private static void initialize() { try { system = factory.createCaptureSystem(); system.init(); + } catch (UnsatisfiedLinkError e) { + // ignore - it is already loaded } catch (CaptureException e) { LOG.error("Capture exception", e); } @@ -56,7 +62,7 @@ public List getDevices() { List infos = system.getCaptureDeviceInfoList(); for (CaptureDeviceInfo cdi : infos) { - devices.add(new CivilDevice(cdi)); + devices.add(new LtiCivilDevice(cdi)); } } catch (CaptureException e) { e.printStackTrace(); @@ -66,11 +72,4 @@ public List getDevices() { return devices; } - public static void main(String[] args) { - WebcamDevice device = new CivilDataSource().getDevices().get(0); - for (Dimension d : device.getSizes()) { - System.out.println(d); - } - - } } diff --git a/webcam-capture-driver-civil/src/main/java/com/github/sarxos/webcam/ds/civil/LtiCivilLoader.java b/webcam-capture-driver-civil/src/main/java/com/github/sarxos/webcam/ds/civil/LtiCivilLoader.java new file mode 100644 index 00000000..1eeb37ca --- /dev/null +++ b/webcam-capture-driver-civil/src/main/java/com/github/sarxos/webcam/ds/civil/LtiCivilLoader.java @@ -0,0 +1,111 @@ +package com.github.sarxos.webcam.ds.civil; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class LtiCivilLoader { + + private static final Logger LOG = LoggerFactory.getLogger(LtiCivilLoader.class); + + /** + * Copy bytes from a large (over 2GB) InputStream to an OutputStream. + * + * @param input the InputStream to read from + * @param output the OutputStream to write to + * @return the number of bytes copied + * @throws NullPointerException if the input or output is null + * @throws IOException if an I/O error occurs + */ + public static long copy(InputStream input, OutputStream output) throws IOException { + byte[] buffer = new byte[1024 * 4]; + long count = 0; + int n = 0; + while (-1 != (n = input.read(buffer))) { + output.write(buffer, 0, n); + count += n; + } + return count; + } + + public static void load(String lib) { + LOG.info("Loading DLL: " + lib); + try { + System.loadLibrary(lib); + LOG.info("DLL has been loaded from memory: " + lib); + } catch (UnsatisfiedLinkError e) { + try { + load("webcam-capture-lib-" + System.currentTimeMillis(), lib); + } catch (Exception e2) { + LOG.error("Exception when loading DLL library", e2); + throw new RuntimeException(e2); + } + } + } + + public static void load(String path, String name) { + + String libfile = name + ".dll"; + + File file = new File(System.getProperty("java.io.tmpdir") + "/" + path + libfile); + if (!file.exists()) { + boolean created; + try { + created = file.createNewFile(); + } catch (IOException e) { + throw new RuntimeException("It was not possible to create file " + file, e); + } + if (!created) { + throw new RuntimeException("It was not possible to create file " + file); + } + } + + String libbin = "/META-INF/lib/"; + String resname = libbin + libfile; + + InputStream in = LtiCivilDriver.class.getResourceAsStream(resname); + if (in == null) { + throw new RuntimeException("No resource with this name is found: " + resname); + } + + FileOutputStream fos = null; + + try { + fos = new FileOutputStream(file); + copy(in, fos); + } catch (FileNotFoundException e) { + throw new RuntimeException("File not found " + file, e); + } catch (IOException e) { + throw new RuntimeException("IO exception", e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + throw new RuntimeException("Cannot close input stream", e); + } + } + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + throw new RuntimeException("Cannot close file output stream", e); + } + } + } + + try { + System.load(file.getAbsolutePath()); + } catch (UnsatisfiedLinkError e) { + throw new RuntimeException("DLL file cannot be loaded " + file, e); + } + } + +} diff --git a/webcam-capture-driver-civil/src/main/java/com/lti/civil/impl/jni/NativeCaptureSystemFactory.java b/webcam-capture-driver-civil/src/main/java/com/lti/civil/impl/jni/NativeCaptureSystemFactory.java new file mode 100644 index 00000000..7e55b9ae --- /dev/null +++ b/webcam-capture-driver-civil/src/main/java/com/lti/civil/impl/jni/NativeCaptureSystemFactory.java @@ -0,0 +1,21 @@ +package com.lti.civil.impl.jni; + +import com.lti.civil.CaptureException; +import com.lti.civil.CaptureSystem; +import com.lti.civil.CaptureSystemFactory; + + +/** + * Original class tries to load it, but we have it already loaded. + * + * @author Bartosz Firyn (SarXos) + */ +public class NativeCaptureSystemFactory implements CaptureSystemFactory { + + public CaptureSystem createCaptureSystem() throws CaptureException { + return newCaptureSystemObj(); + } + + private static native CaptureSystem newCaptureSystemObj(); + +} diff --git a/webcam-capture-civil-ds/civil.dll b/webcam-capture-driver-civil/src/main/resources/META-INF/lib/civil.dll similarity index 100% rename from webcam-capture-civil-ds/civil.dll rename to webcam-capture-driver-civil/src/main/resources/META-INF/lib/civil.dll diff --git a/webcam-capture-openimaj-ds/.classpath b/webcam-capture-driver-jmf/.classpath similarity index 100% rename from webcam-capture-openimaj-ds/.classpath rename to webcam-capture-driver-jmf/.classpath diff --git a/webcam-capture-jmf-ds/.project b/webcam-capture-driver-jmf/.project similarity index 100% rename from webcam-capture-jmf-ds/.project rename to webcam-capture-driver-jmf/.project diff --git a/webcam-capture-jmf-ds/pom.xml b/webcam-capture-driver-jmf/pom.xml similarity index 58% rename from webcam-capture-jmf-ds/pom.xml rename to webcam-capture-driver-jmf/pom.xml index f75c6c9b..282a16c1 100644 --- a/webcam-capture-jmf-ds/pom.xml +++ b/webcam-capture-driver-jmf/pom.xml @@ -2,32 +2,21 @@ 4.0.0 - com.github.sarxos.webcam-capture - webcam-capture-jmf-ds - 0.3-SNAPSHOT - + + com.github.sarxos + webcam-capture-parent + 0.3.1 + + + webcam-capture-driver-jmf Webcam Capture - JMF Data Source This is JMF implementation of webcam data source. It allows you to capture webcam media with JMF or FMJ installed. - - - sarxos-ftp-repo - ftp://ftp.sarxos.pl/maven2 - - - - - - sarxos-repo - http://repo.sarxos.pl/maven2 - - - com.github.sarxos webcam-capture - 0.3-SNAPSHOT + ${project.version} javax.media @@ -36,4 +25,4 @@ - \ No newline at end of file + diff --git a/webcam-capture-jmf-ds/src/main/java/com/github/sarxos/webcam/ds/jmf/JMFDevice.java b/webcam-capture-driver-jmf/src/main/java/com/github/sarxos/webcam/ds/jmf/JMFDevice.java similarity index 93% rename from webcam-capture-jmf-ds/src/main/java/com/github/sarxos/webcam/ds/jmf/JMFDevice.java rename to webcam-capture-driver-jmf/src/main/java/com/github/sarxos/webcam/ds/jmf/JMFDevice.java index 0cbd0866..1b39e910 100644 --- a/webcam-capture-jmf-ds/src/main/java/com/github/sarxos/webcam/ds/jmf/JMFDevice.java +++ b/webcam-capture-driver-jmf/src/main/java/com/github/sarxos/webcam/ds/jmf/JMFDevice.java @@ -38,9 +38,9 @@ * * @author Bartosz Firyn (SarXos) */ -public class JMFDevice implements WebcamDevice { +public class JmfDevice implements WebcamDevice { - private static final Logger LOG = LoggerFactory.getLogger(JMFDevice.class); + private static final Logger LOG = LoggerFactory.getLogger(JmfDevice.class); /** * Control to control format. @@ -138,7 +138,7 @@ public void controllerUpdate(ControllerEvent ce) { private Dimension viewSize = null; - public JMFDevice(CaptureDeviceInfo cdi) { + public JmfDevice(CaptureDeviceInfo cdi) { this.cdi = cdi; } diff --git a/webcam-capture-jmf-ds/src/main/java/com/github/sarxos/webcam/ds/jmf/JMFDataSource.java b/webcam-capture-driver-jmf/src/main/java/com/github/sarxos/webcam/ds/jmf/JmfDriver.java similarity index 80% rename from webcam-capture-jmf-ds/src/main/java/com/github/sarxos/webcam/ds/jmf/JMFDataSource.java rename to webcam-capture-driver-jmf/src/main/java/com/github/sarxos/webcam/ds/jmf/JmfDriver.java index fcab6d09..6ababd7b 100644 --- a/webcam-capture-jmf-ds/src/main/java/com/github/sarxos/webcam/ds/jmf/JMFDataSource.java +++ b/webcam-capture-driver-jmf/src/main/java/com/github/sarxos/webcam/ds/jmf/JmfDriver.java @@ -9,11 +9,11 @@ import javax.media.CaptureDeviceManager; import javax.media.Format; -import com.github.sarxos.webcam.WebcamDataSource; +import com.github.sarxos.webcam.WebcamDriver; import com.github.sarxos.webcam.WebcamDevice; -public class JMFDataSource implements WebcamDataSource { +public class JmfDriver implements WebcamDriver { private static List devices = null; @@ -29,7 +29,7 @@ public List getDevices() { while (di.hasNext()) { CaptureDeviceInfo cdi = (CaptureDeviceInfo) di.next(); - devices.add(new JMFDevice(cdi)); + devices.add(new JmfDevice(cdi)); } } diff --git a/webcam-capture-civil-ds/.classpath b/webcam-capture-driver-openimaj/.classpath similarity index 94% rename from webcam-capture-civil-ds/.classpath rename to webcam-capture-driver-openimaj/.classpath index 966e2298..756245a6 100644 --- a/webcam-capture-civil-ds/.classpath +++ b/webcam-capture-driver-openimaj/.classpath @@ -1,7 +1,7 @@ - + diff --git a/webcam-capture-openimaj-ds/.project b/webcam-capture-driver-openimaj/.project similarity index 100% rename from webcam-capture-openimaj-ds/.project rename to webcam-capture-driver-openimaj/.project diff --git a/webcam-capture-openimaj-ds/pom.xml b/webcam-capture-driver-openimaj/pom.xml similarity index 53% rename from webcam-capture-openimaj-ds/pom.xml rename to webcam-capture-driver-openimaj/pom.xml index 34e96192..21238044 100644 --- a/webcam-capture-openimaj-ds/pom.xml +++ b/webcam-capture-driver-openimaj/pom.xml @@ -2,13 +2,16 @@ 4.0.0 - com.sarxos.webcam - webcam-capture-openimaj-ds - 0.3-SNAPSHOT + + com.github.sarxos + webcam-capture-parent + 0.3.1 + + webcam-capture-driver-openimaj Webcam Capture - OpenIMAJ Data Source Webcam Capture data source using OpenIMAJ libraries - + OpenIMAJ maven repository @@ -19,38 +22,16 @@ http://octopussy.ecs.soton.ac.uk/m2/thirdparty/ - sarxos-repo - http://repo.sarxos.pl/maven2 + OpenIMAJ Snapshots maven repository + http://octopussy.ecs.soton.ac.uk/m2/snapshots/ - - - - maven-compiler-plugin - 2.3.2 - - 1.6 - 1.6 - - - - maven-assembly-plugin - 2.2.1 - - - jar-with-dependencies - - - - - - - com.github.sarxos + com.github.sarxos webcam-capture - 0.3-SNAPSHOT + ${project.version} org.openimaj diff --git a/webcam-capture-openimaj-ds/src/main/java/com/github/sarxos/webcam/ds/openimaj/OpenImajWebcamDevice.java b/webcam-capture-driver-openimaj/src/main/java/com/github/sarxos/webcam/ds/openimaj/OpenImajDevice.java similarity index 90% rename from webcam-capture-openimaj-ds/src/main/java/com/github/sarxos/webcam/ds/openimaj/OpenImajWebcamDevice.java rename to webcam-capture-driver-openimaj/src/main/java/com/github/sarxos/webcam/ds/openimaj/OpenImajDevice.java index 880d88f9..8e43c42a 100644 --- a/webcam-capture-openimaj-ds/src/main/java/com/github/sarxos/webcam/ds/openimaj/OpenImajWebcamDevice.java +++ b/webcam-capture-driver-openimaj/src/main/java/com/github/sarxos/webcam/ds/openimaj/OpenImajDevice.java @@ -12,9 +12,9 @@ import com.github.sarxos.webcam.WebcamDevice; -public class OpenImajWebcamDevice implements WebcamDevice { +public class OpenImajDevice implements WebcamDevice { - private static final Logger LOG = LoggerFactory.getLogger(OpenImajDataSource.class); + private static final Logger LOG = LoggerFactory.getLogger(OpenImajDriver.class); /** * Artificial view sizes. I'm really not sure if will fit into other webcams @@ -34,7 +34,7 @@ public class OpenImajWebcamDevice implements WebcamDevice { private Dimension size = null; private boolean open = false; - public OpenImajWebcamDevice(Device device) { + public OpenImajDevice(Device device) { this.device = device; } diff --git a/webcam-capture-openimaj-ds/src/main/java/com/github/sarxos/webcam/ds/openimaj/OpenImajDataSource.java b/webcam-capture-driver-openimaj/src/main/java/com/github/sarxos/webcam/ds/openimaj/OpenImajDriver.java similarity index 76% rename from webcam-capture-openimaj-ds/src/main/java/com/github/sarxos/webcam/ds/openimaj/OpenImajDataSource.java rename to webcam-capture-driver-openimaj/src/main/java/com/github/sarxos/webcam/ds/openimaj/OpenImajDriver.java index 620d7843..e2c2cacd 100644 --- a/webcam-capture-openimaj-ds/src/main/java/com/github/sarxos/webcam/ds/openimaj/OpenImajDataSource.java +++ b/webcam-capture-driver-openimaj/src/main/java/com/github/sarxos/webcam/ds/openimaj/OpenImajDriver.java @@ -10,11 +10,11 @@ import org.openimaj.video.capture.Device; import org.openimaj.video.capture.VideoCapture; -import com.github.sarxos.webcam.WebcamDataSource; +import com.github.sarxos.webcam.WebcamDriver; import com.github.sarxos.webcam.WebcamDevice; -public class OpenImajDataSource implements WebcamDataSource { +public class OpenImajDriver implements WebcamDriver { List webcamDevices = null; @@ -25,7 +25,7 @@ public List getDevices() { webcamDevices = new ArrayList(); List devices = VideoCapture.getVideoDevices(); for (Device device : devices) { - webcamDevices.add(new OpenImajWebcamDevice(device)); + webcamDevices.add(new OpenImajDevice(device)); } } @@ -33,7 +33,7 @@ public List getDevices() { } public static void main(String[] args) throws IOException, InterruptedException { - WebcamDevice d = new OpenImajDataSource().getDevices().get(0); + WebcamDevice d = new OpenImajDriver().getDevices().get(0); d.setSize(d.getSizes()[0]); d.open(); for (int i = 0; i < 5; i++) { diff --git a/webcam-capture/.classpath b/webcam-capture/.classpath index 756245a6..575249a6 100644 --- a/webcam-capture/.classpath +++ b/webcam-capture/.classpath @@ -1,6 +1,8 @@ + + diff --git a/webcam-capture/pom.xml b/webcam-capture/pom.xml index 59086ba5..f5ac0aaf 100644 --- a/webcam-capture/pom.xml +++ b/webcam-capture/pom.xml @@ -2,251 +2,22 @@ 4.0.0 - com.github.sarxos - webcam-capture - 0.3-SNAPSHOT + + com.github.sarxos + webcam-capture-parent + 0.3.1 + + webcam-capture + Webcam Capture Use your webcam directly from Java - - Bartosz Firyn (SarXos) - https://github.com/sarxos - - - - - MIT License - http://www.opensource.org/licenses/mit-license.html - repo - - - - - scm:git:git@github.com:sarxos/webcam-capture.git - scm:git:git@github.com:sarxos/webcam-capture.git - git@github.com:sarxos/webcam-capture.git - - - - GitHub - https://github.com/sarxos/webcam-capture/issues - - - - github - - - - - sarxos-ftp-repo - ftp://ftp.sarxos.pl/maven2 - - - com.jhlabs filters 2.0.235 - - org.slf4j - slf4j-api - 1.6.4 - - - ch.qos.logback - logback-classic - 0.9.18 - - - org.jdom - jdom - 1.1.3 - - - - pgp-sign-artifacts - - - performRelease - true - - - - - - org.apache.maven.plugins - maven-gpg-plugin - - - sign-artifacts - verify - - sign - - - - - - - - - - - - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - org.apache.maven.plugins - maven-dependency-plugin - [1.0.0,) - - copy-dependencies - - - - - - - - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.3.2 - - 1.6 - 1.6 - - - - org.apache.maven.plugins - maven-source-plugin - 2.1.2 - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.8.1 - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 2.4 - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${project.build.directory}/dependencies - false - false - true - - - - - - maven-assembly-plugin - 2.3 - - - src/main/assembly/dist.xml - - - - - make-assembly - package - - single - - - - - - - - - - - - org.apache.maven.wagon - wagon-ftp - 1.0-beta-7 - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.8.1 - - public - cam,webcam,camera,spycam,capture - - - - - - Webcam Capture diff --git a/webcam-capture/src/example/java/com/github/sarxos/webcam/TakePictureExample.java b/webcam-capture/src/example/java/com/github/sarxos/webcam/TakePictureExample.java index 3fc3ff5c..609aa3de 100644 --- a/webcam-capture/src/example/java/com/github/sarxos/webcam/TakePictureExample.java +++ b/webcam-capture/src/example/java/com/github/sarxos/webcam/TakePictureExample.java @@ -1,5 +1,6 @@ package com.github.sarxos.webcam; +import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @@ -13,9 +14,7 @@ public class TakePictureExample { public static void main(String[] args) throws IOException { Webcam webcam = Webcam.getDefault(); - webcam.open(); - ImageIO.write(webcam.getImage(), "PNG", new File("test.png")); - webcam.close(); + BufferedImage image = webcam.getImage(); + ImageIO.write(image, "PNG", new File("test.png")); } - } diff --git a/webcam-capture/src/example/java/com/github/sarxos/webcam/WebcamPanelExample.java b/webcam-capture/src/example/java/com/github/sarxos/webcam/WebcamPanelExample.java new file mode 100644 index 00000000..27633917 --- /dev/null +++ b/webcam-capture/src/example/java/com/github/sarxos/webcam/WebcamPanelExample.java @@ -0,0 +1,20 @@ +package com.github.sarxos.webcam; + +import java.awt.Dimension; + +import javax.swing.JFrame; + + +public class WebcamPanelExample { + + public static void main(String[] args) { + WebcamPanel panel = new WebcamPanel(Webcam.getDefault()); + JFrame jframe = new JFrame("Test webcam panel"); + jframe.setPreferredSize(new Dimension(300, 200)); + jframe.add(panel); + jframe.pack(); + jframe.setVisible(true); + jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + +} diff --git a/webcam-capture/src/example/resources/logback.xml b/webcam-capture/src/example/resources/logback.xml index f9da1dbe..3811db88 100644 --- a/webcam-capture/src/example/resources/logback.xml +++ b/webcam-capture/src/example/resources/logback.xml @@ -6,7 +6,7 @@ - + diff --git a/webcam-capture/src/main/java/com/github/sarxos/webcam/Webcam.java b/webcam-capture/src/main/java/com/github/sarxos/webcam/Webcam.java index e66d892f..d9a3034d 100644 --- a/webcam-capture/src/main/java/com/github/sarxos/webcam/Webcam.java +++ b/webcam-capture/src/main/java/com/github/sarxos/webcam/Webcam.java @@ -5,6 +5,9 @@ import java.util.ArrayList; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Webcam class. @@ -13,7 +16,31 @@ */ public class Webcam { - private static WebcamDataSource dataSource = null; + private static final Logger LOG = LoggerFactory.getLogger(Webcam.class); + + private static class ShutdownHook extends Thread { + + private Webcam webcam = null; + + public ShutdownHook(Webcam webcam) { + this.webcam = webcam; + } + + @Override + public void run() { + LOG.info("Automatic webcam resource deallocation"); + super.run(); + webcam.close0(); + } + } + + private static final String[] DRIVERS = new String[] { + "civil", + "jmf", + "openimaj", + }; + + private static WebcamDriver driver = null; private static List webcams = null; /** @@ -21,6 +48,7 @@ public class Webcam { */ private List listeners = new ArrayList(); + private ShutdownHook hook = null; private WebcamDevice device = null; private boolean open = false; @@ -38,6 +66,14 @@ public Webcam(WebcamDevice device) { */ public synchronized void open() { + if (open) { + return; + } + + if (LOG.isInfoEnabled()) { + LOG.info("Opening webcam " + getName()); + } + if (device.getSize() == null) { device.setSize(device.getSizes()[0]); } @@ -45,6 +81,10 @@ public synchronized void open() { device.open(); open = true; + hook = new ShutdownHook(this); + + Runtime.getRuntime().addShutdownHook(hook); + WebcamEvent we = new WebcamEvent(this); for (WebcamListener l : listeners) { try { @@ -60,6 +100,27 @@ public synchronized void open() { */ public synchronized void close() { + if (!open) { + return; + } + + Runtime.getRuntime().removeShutdownHook(hook); + close0(); + } + + /** + * Close webcam. + */ + private void close0() { + + if (!open) { + return; + } + + if (LOG.isInfoEnabled()) { + LOG.info("Cosing webcam " + getName()); + } + device.close(); open = false; @@ -89,6 +150,12 @@ public Dimension getViewSize() { return device.getSize(); } + /** + * Return list of supported view sizes. It can differ between vary webcam + * data sources. + * + * @return + */ public Dimension[] getViewSizes() { return device.getSizes(); } @@ -115,6 +182,10 @@ public void setViewSize(Dimension size) { throw new IllegalArgumentException(sb.toString()); } + if (LOG.isDebugEnabled()) { + LOG.debug("Setting new view size " + size); + } + device.setSize(size); } @@ -124,6 +195,9 @@ public void setViewSize(Dimension size) { * @return Captured image */ public synchronized BufferedImage getImage() { + if (!open) { + open(); + } return device.getImage(); } @@ -134,9 +208,22 @@ public synchronized BufferedImage getImage() { */ public static List getWebcams() { if (webcams == null) { + webcams = new ArrayList(); - for (WebcamDevice device : dataSource.getDevices()) { - webcams.add(new Webcam(device)); + + if (driver == null) { + driver = WebcamDriverUtils.findDriver(DRIVERS); + } + + for (WebcamDevice device : driver.getDevices()) { + Webcam webcam = new Webcam(device); + webcams.add(webcam); + } + + if (LOG.isInfoEnabled()) { + for (Webcam webcam : webcams) { + LOG.info("Webcam found " + webcam.getName()); + } } } return webcams; @@ -154,7 +241,9 @@ public static Webcam getDefault() { } /** - * Get webcam name (actually device name). + * Get webcam name (device name). The name of device depends on the value + * returned by the underlying data source, so in some cases it can be + * human-readable value and sometimes it can be some strange number. * * @return Name */ @@ -190,8 +279,8 @@ public WebcamListener[] getWebcamListeners() { /** * @return Data source currently used by webcam */ - public static WebcamDataSource getDataSource() { - return dataSource; + public static WebcamDriver getDriver() { + return driver; } /** @@ -199,7 +288,8 @@ public static WebcamDataSource getDataSource() { * * @param ds new data source to use (e.g. Civil, JFM, FMJ, QTJ, etc) */ - public static void setDataSource(WebcamDataSource ds) { - Webcam.dataSource = ds; + public static void setDriver(WebcamDriver ds) { + Webcam.driver = ds; } + } diff --git a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDataSource.java b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDriver.java similarity index 69% rename from webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDataSource.java rename to webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDriver.java index b2fb5b19..bd702077 100644 --- a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDataSource.java +++ b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDriver.java @@ -3,7 +3,7 @@ import java.util.List; -public interface WebcamDataSource { +public interface WebcamDriver { public List getDevices(); diff --git a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDriverUtils.java b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDriverUtils.java new file mode 100644 index 00000000..2b48d2ab --- /dev/null +++ b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDriverUtils.java @@ -0,0 +1,146 @@ +package com.github.sarxos.webcam; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class WebcamDriverUtils { + + private static final Logger LOG = LoggerFactory.getLogger(WebcamDriverUtils.class); + + private WebcamDriverUtils() { + } + + /** + * Find webcam driver. Scan packages to search drivers specified in the + * argument. + * + * @param drivers array of driver names to search for + * @return Driver if found or throw exception + * @throw WebcamException + */ + protected static WebcamDriver findDriver(String[] drivers) { + + if (LOG.isInfoEnabled()) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < drivers.length; i++) { + sb.append(drivers[i]).append(i < drivers.length - 1 ? ", " : ""); + } + LOG.info("Searching for one of the webcam drivers [" + sb.toString() + "]"); + } + + for (String name : drivers) { + + String pkgname = "com.github.sarxos.webcam.ds." + name; + + WebcamDriver driver = null; + Class[] classes = WebcamDriverUtils.getClasses(pkgname, true); + + if (LOG.isDebugEnabled()) { + LOG.debug("Searching for classes in " + pkgname + ", found " + classes.length); + } + + if (classes.length == 0) { + continue; + } + + for (Class clazz : classes) { + if (WebcamDriver.class.isAssignableFrom(clazz)) { + try { + driver = (WebcamDriver) clazz.newInstance(); + } catch (InstantiationException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + break; + } + } + + LOG.info("Webcam driver has been found: " + name); + + return driver; + } + + LOG.error("Webcam driver has not been found! Please add one to the classpath!"); + + throw new WebcamException("No webcam driver available"); + } + + /** + * Scans all classes accessible from the context class loader which belong + * to the given package and subpackages. + * + * @param packageName The base package + * @param flat scan only one package level, do not dive into subdirectories + * @return The classes + * @throws ClassNotFoundException + * @throws IOException + */ + protected static Class[] getClasses(String pkgname, boolean flat) { + + List dirs = new ArrayList(); + List> classes = new ArrayList>(); + + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + String path = pkgname.replace('.', '/'); + + Enumeration resources = null; + try { + resources = classLoader.getResources(path); + } catch (IOException e) { + throw new RuntimeException("Cannot read path " + path, e); + } + + while (resources.hasMoreElements()) { + URL resource = resources.nextElement(); + dirs.add(new File(resource.getFile())); + } + + for (File directory : dirs) { + try { + classes.addAll(findClasses(directory, pkgname, flat)); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Class not found", e); + } + } + + return classes.toArray(new Class[classes.size()]); + } + + /** + * Recursive method used to find all classes in a given directory and + * subdirectories. + * + * @param dir base directory + * @param pkgname package name for classes found inside the base directory + * @param flat scan only one package level, do not dive into subdirectories + * @return Classes list + * @throws ClassNotFoundException + */ + private static List> findClasses(File dir, String pkgname, boolean flat) throws ClassNotFoundException { + + List> classes = new ArrayList>(); + if (!dir.exists()) { + return classes; + } + + File[] files = dir.listFiles(); + for (File file : files) { + if (file.isDirectory() && !flat) { + classes.addAll(findClasses(file, pkgname + "." + file.getName(), flat)); + } else if (file.getName().endsWith(".class")) { + classes.add(Class.forName(pkgname + '.' + file.getName().substring(0, file.getName().length() - 6))); + } + } + + return classes; + } +} diff --git a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamPanel.java b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamPanel.java index cc148117..04ab76d4 100644 --- a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamPanel.java +++ b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamPanel.java @@ -58,10 +58,12 @@ public WebcamPanel(Webcam webcam) { this.repainter = new Repainter(); - if (webcam.isOpen()) { - setPreferredSize(webcam.getViewSize()); - repainter.start(); + if (!webcam.isOpen()) { + webcam.open(); } + + setPreferredSize(webcam.getViewSize()); + repainter.start(); } @Override diff --git a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamUtils.java b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamUtils.java new file mode 100644 index 00000000..7f8d5b3a --- /dev/null +++ b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamUtils.java @@ -0,0 +1,20 @@ +package com.github.sarxos.webcam; + +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + + + +public class WebcamUtils { + + public static final void capture(Webcam webcam, String filename) { + try { + ImageIO.write(webcam.getImage(), "PNG", new File(filename + ".png")); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/webcam-capture/src/main/java/com/github/sarxos/webcam/log/WebcamLogConfigurator.java b/webcam-capture/src/main/java/com/github/sarxos/webcam/log/WebcamLogConfigurator.java index 92b40b79..5803e4a2 100644 --- a/webcam-capture/src/main/java/com/github/sarxos/webcam/log/WebcamLogConfigurator.java +++ b/webcam-capture/src/main/java/com/github/sarxos/webcam/log/WebcamLogConfigurator.java @@ -31,7 +31,7 @@ public class WebcamLogConfigurator { * * @param is input stream to logback configuration xml */ - public void configure(InputStream is) { + public static void configure(InputStream is) { LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); JoranConfigurator configurator = new JoranConfigurator(); @@ -51,7 +51,7 @@ public void configure(InputStream is) { * * @param file logback configuration file */ - public void configure(File file) { + public static void configure(File file) { FileInputStream fis = null; try { fis = new FileInputStream(file); @@ -76,7 +76,7 @@ public void configure(File file) { * * @param file logback configuration file path */ - public void configure(String file) { + public static void configure(String file) { configure(new File(file)); } }