diff --git a/webcam-capture/src/example/java/com/github/sarxos/webcam/example/CalculateFPSExample.java b/webcam-capture/src/example/java/com/github/sarxos/webcam/example/CalculateFPSExample.java
new file mode 100644
index 00000000..d6d3cc39
--- /dev/null
+++ b/webcam-capture/src/example/java/com/github/sarxos/webcam/example/CalculateFPSExample.java
@@ -0,0 +1,37 @@
+package com.github.sarxos.webcam.example;
+
+import com.github.sarxos.webcam.Webcam;
+import com.github.sarxos.webcam.log.WebcamLogConfigurator;
+
+
+public class CalculateFPSExample {
+
+ public static void main(String[] args) {
+
+ WebcamLogConfigurator.configure("src/example/resources/logback.xml");
+
+ long t1 = 0;
+ long t2 = 0;
+
+ int p = 10;
+ int r = 5;
+
+ Webcam webcam = Webcam.getDefault();
+
+ for (int k = 0; k < p; k++) {
+
+ webcam.open();
+ webcam.getImage();
+
+ t1 = System.currentTimeMillis();
+ for (int i = 0; ++i <= r; webcam.getImage()) {
+ }
+ t2 = System.currentTimeMillis();
+
+ System.out.println("FPS " + k + ": " + (1000 * r / (t2 - t1 + 1)));
+
+ webcam.close();
+ }
+
+ }
+}
diff --git a/webcam-capture/src/example/resources/logback.xml b/webcam-capture/src/example/resources/logback.xml
index baeded4b..8c4d33ce 100644
--- a/webcam-capture/src/example/resources/logback.xml
+++ b/webcam-capture/src/example/resources/logback.xml
@@ -4,7 +4,7 @@
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
-
+
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 5c2c839c..1aa18154 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
@@ -165,6 +165,8 @@ public boolean open(boolean async) {
if (open.compareAndSet(false, true)) {
+ assert updater != null;
+
WebcamOpenTask task = new WebcamOpenTask(driver, device);
try {
task.open();
@@ -216,6 +218,8 @@ public boolean close() {
if (open.compareAndSet(true, false)) {
+ assert updater != null;
+
// close webcam
WebcamCloseTask task = new WebcamCloseTask(driver, device);
@@ -293,6 +297,7 @@ public Dimension[] getViewSizes() {
* @param sizes the array of custom resolutions to be supported by webcam
*/
public void setCustomViewSizes(Dimension[] sizes) {
+ assert customSizes != null;
if (sizes == null) {
customSizes.clear();
return;
@@ -301,6 +306,7 @@ public void setCustomViewSizes(Dimension[] sizes) {
}
public Dimension[] getCustomViewSizes() {
+ assert customSizes != null;
return customSizes.toArray(new Dimension[customSizes.size()]);
}
@@ -334,6 +340,9 @@ public void setViewSize(Dimension size) {
Dimension[] predefined = getViewSizes();
Dimension[] custom = getCustomViewSizes();
+ assert predefined != null;
+ assert custom != null;
+
boolean ok = false;
for (Dimension d : predefined) {
if (d.width == size.width && d.height == size.height) {
@@ -394,6 +403,8 @@ public BufferedImage getImage() {
long t1 = 0;
long t2 = 0;
+ assert updater != null;
+
if (asynchronous) {
return updater.getImage();
} else {
@@ -422,6 +433,7 @@ public BufferedImage getImage() {
}
public boolean isImageNew() {
+ assert updater != null;
if (asynchronous) {
return updater.isImageNew();
}
@@ -429,6 +441,7 @@ public boolean isImageNew() {
}
protected double getFPS() {
+ assert updater != null;
if (asynchronous) {
return updater.getFPS();
} else {
@@ -456,6 +469,9 @@ public ByteBuffer getImageBytes() {
return null;
}
+ assert driver != null;
+ assert device != null;
+
// some devices can support direct image buffers, and for those call
// processor task, and for those which does not support direct image
// buffers, just convert image to RGB byte array
@@ -463,7 +479,12 @@ public ByteBuffer getImageBytes() {
if (device instanceof BufferAccess) {
return new WebcamReadBufferTask(driver, device).getBuffer();
} else {
- return ByteBuffer.wrap(ImageUtils.toRawByteArray(getImage()));
+ BufferedImage image = getImage();
+ if (image != null) {
+ return ByteBuffer.wrap(ImageUtils.toRawByteArray(image));
+ } else {
+ return null;
+ }
}
}
@@ -474,6 +495,9 @@ public ByteBuffer getImageBytes() {
*/
private boolean isReady() {
+ assert disposed != null;
+ assert open != null;
+
if (disposed.get()) {
LOG.warn("Cannot get image, webcam has been already disposed");
return false;
@@ -495,7 +519,7 @@ private boolean isReady() {
* interval for webcam devices to be discovered. By default this time is set
* to 1 minute.
*
- * @return List of webcams existing in the ssytem
+ * @return List of webcams existing in the system
* @throws WebcamException when something is wrong
* @see Webcam#getWebcams(long, TimeUnit)
*/
@@ -518,9 +542,13 @@ public static List getWebcams() throws WebcamException {
* @param timeout the time to wait for webcam devices to be discovered
* @return List of webcams existing in the ssytem
* @throws WebcamException when something is wrong
+ * @throws IllegalArgumentException when timeout is negative
* @see Webcam#getWebcams(long, TimeUnit)
*/
public static List getWebcams(long timeout) throws TimeoutException, WebcamException {
+ if (timeout < 0) {
+ throw new IllegalArgumentException(String.format("Timeout cannot be negative (%d)", timeout));
+ }
return getWebcams(timeout, TimeUnit.MILLISECONDS);
}
@@ -533,12 +561,22 @@ public static List getWebcams(long timeout) throws TimeoutException, Web
* @return List of webcams
* @throws TimeoutException when timeout has been exceeded
* @throws WebcamException when something is wrong
+ * @throws IllegalArgumentException when timeout is negative or tunit null
*/
public static synchronized List getWebcams(long timeout, TimeUnit tunit) throws TimeoutException, WebcamException {
+ if (timeout < 0) {
+ throw new IllegalArgumentException(String.format("Timeout cannot be negative (%d)", timeout));
+ }
+ if (tunit == null) {
+ throw new IllegalArgumentException("Time unit cannot be null!");
+ }
+
WebcamDiscoveryService discovery = getDiscoveryService();
- List webcams = discovery.getWebcams(timeout, tunit);
+ assert discovery != null;
+
+ List webcams = discovery.getWebcams(timeout, tunit);
if (!discovery.isRunning()) {
discovery.start();
}
@@ -571,9 +609,13 @@ public static Webcam getDefault() throws WebcamException {
* @return Default webcam (first from the list)
* @throws TimeoutException when discovery timeout has been exceeded
* @throws WebcamException if something is really wrong
+ * @throws IllegalArgumentException when timeout is negative
* @see Webcam#getWebcams(long)
*/
public static Webcam getDefault(long timeout) throws TimeoutException, WebcamException {
+ if (timeout < 0) {
+ throw new IllegalArgumentException(String.format("Timeout cannot be negative (%d)", timeout));
+ }
return getDefault(timeout, TimeUnit.MILLISECONDS);
}
@@ -585,12 +627,13 @@ public static Webcam getDefault(long timeout) throws TimeoutException, WebcamExc
* @return Default webcam (first from the list)
* @throws TimeoutException when discovery timeout has been exceeded
* @throws WebcamException if something is really wrong
+ * @throws IllegalArgumentException when timeout is negative or tunit null
* @see Webcam#getWebcams(long, TimeUnit)
*/
public static Webcam getDefault(long timeout, TimeUnit tunit) throws TimeoutException, WebcamException {
if (timeout < 0) {
- throw new IllegalArgumentException("Timeout cannot be negative");
+ throw new IllegalArgumentException(String.format("Timeout cannot be negative (%d)", timeout));
}
if (tunit == null) {
throw new IllegalArgumentException("Time unit cannot be null!");
@@ -598,6 +641,8 @@ public static Webcam getDefault(long timeout, TimeUnit tunit) throws TimeoutExce
List webcams = getWebcams(timeout, tunit);
+ assert webcams != null;
+
if (!webcams.isEmpty()) {
return webcams.get(0);
}
@@ -615,6 +660,7 @@ public static Webcam getDefault(long timeout, TimeUnit tunit) throws TimeoutExce
* @return Name
*/
public String getName() {
+ assert device != null;
return device.getName();
}
@@ -633,6 +679,7 @@ public boolean addWebcamListener(WebcamListener l) {
if (l == null) {
throw new IllegalArgumentException("Webcam listener cannot be null!");
}
+ assert listeners != null;
return listeners.add(l);
}
@@ -640,6 +687,7 @@ public boolean addWebcamListener(WebcamListener l) {
* @return All webcam listeners
*/
public WebcamListener[] getWebcamListeners() {
+ assert listeners != null;
return listeners.toArray(new WebcamListener[listeners.size()]);
}
@@ -647,6 +695,7 @@ public WebcamListener[] getWebcamListeners() {
* @return Number of webcam listeners
*/
public int getWebcamListenersCount() {
+ assert listeners != null;
return listeners.size();
}
@@ -657,6 +706,7 @@ public int getWebcamListenersCount() {
* @return True if listener has been removed, false otherwise
*/
public boolean removeWebcamListener(WebcamListener l) {
+ assert listeners != null;
return listeners.remove(l);
}
@@ -713,12 +763,12 @@ public static synchronized void setDriver(WebcamDriver driver) {
*/
public static synchronized void setDriver(Class extends WebcamDriver> driverClass) {
- resetDriver();
-
if (driverClass == null) {
throw new IllegalArgumentException("Webcam driver class cannot be null!");
}
+ resetDriver();
+
try {
driver = driverClass.newInstance();
} catch (InstantiationException e) {
@@ -780,6 +830,7 @@ public static void registerDriver(String clazzName) {
* @return Underlying webcam device instance
*/
public WebcamDevice getDevice() {
+ assert device != null;
return device;
}
@@ -789,6 +840,12 @@ public WebcamDevice getDevice() {
*/
protected void dispose() {
+ assert disposed != null;
+ assert open != null;
+ assert driver != null;
+ assert device != null;
+ assert listeners != null;
+
if (!disposed.compareAndSet(false, true)) {
return;
}
diff --git a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDiscoveryService.java b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDiscoveryService.java
index 49c510ff..f6aeea5b 100644
--- a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDiscoveryService.java
+++ b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamDiscoveryService.java
@@ -1,5 +1,6 @@
package com.github.sarxos.webcam;
+import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
@@ -18,11 +19,11 @@
import org.slf4j.LoggerFactory;
-public class WebcamDiscoveryService implements Runnable {
+public class WebcamDiscoveryService implements Runnable, UncaughtExceptionHandler {
private static final Logger LOG = LoggerFactory.getLogger(WebcamDiscoveryService.class);
- private static final class WebcamsDiscovery implements Callable>, ThreadFactory {
+ private static final class WebcamsDiscovery implements Callable>, ThreadFactory, UncaughtExceptionHandler {
private final WebcamDriver driver;
@@ -39,8 +40,14 @@ public List call() throws Exception {
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "webcam-discovery-service");
t.setDaemon(true);
+ t.setUncaughtExceptionHandler(this);
return t;
}
+
+ @Override
+ public void uncaughtException(Thread t, Throwable e) {
+ LOG.error(String.format("Exception in thread %s", t.getName()), e);
+ }
}
private final WebcamDriver driver;
@@ -53,6 +60,11 @@ public Thread newThread(Runnable r) {
private Thread runner = null;
protected WebcamDiscoveryService(WebcamDriver driver) {
+
+ if (driver == null) {
+ throw new IllegalArgumentException("Driver cannot be null!");
+ }
+
this.driver = driver;
this.support = (WebcamDiscoverySupport) (driver instanceof WebcamDiscoverySupport ? driver : null);
}
@@ -320,6 +332,7 @@ public synchronized void start() {
runner = new Thread(this, "webcam-discovery-service");
runner.setDaemon(true);
+ runner.setUncaughtExceptionHandler(this);
runner.start();
}
@@ -353,4 +366,9 @@ protected synchronized void shutdown() {
WebcamDeallocator.unstore();
}
}
+
+ @Override
+ public void uncaughtException(Thread t, Throwable e) {
+ LOG.error(String.format("Exception in thread %s", t.getName()), e);
+ }
}
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 9a370302..9a97473e 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
@@ -66,6 +66,9 @@ public class DefaultPainter implements Painter {
@Override
public void paintPanel(WebcamPanel owner, Graphics2D g2) {
+ assert owner != null;
+ assert g2 != null;
+
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setBackground(Color.BLACK);
g2.fillRect(0, 0, getWidth(), getHeight());
diff --git a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamUpdater.java b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamUpdater.java
index 220043e0..fd71e0ba 100644
--- a/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamUpdater.java
+++ b/webcam-capture/src/main/java/com/github/sarxos/webcam/WebcamUpdater.java
@@ -1,6 +1,7 @@
package com.github.sarxos.webcam;
import java.awt.image.BufferedImage;
+import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -22,7 +23,7 @@
*
* @author Bartosz Firyn (sarxos)
*/
-public class WebcamUpdater implements Runnable, ThreadFactory {
+public class WebcamUpdater implements Runnable, ThreadFactory, UncaughtExceptionHandler {
/**
* Class used to asynchronously notify all webcam listeners about new image
@@ -250,6 +251,12 @@ public double getFPS() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r, String.format("webcam-updater-thread-%d", number.incrementAndGet()));
t.setDaemon(true);
+ t.setUncaughtExceptionHandler(this);
return t;
}
+
+ @Override
+ public void uncaughtException(Thread t, Throwable e) {
+ LOG.error(String.format("Exception in thread %s", t.getName()), e);
+ }
}