Skip to content

Commit

Permalink
Java core dump when terminating Webcam Capture process
Browse files Browse the repository at this point in the history
fixes #13
  • Loading branch information
sarxos committed Jan 8, 2013
1 parent 9c8acf3 commit 6f9c770
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 30 deletions.
Expand Up @@ -8,11 +8,6 @@
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

import com.github.sarxos.webcam.Webcam;
import com.github.sarxos.webcam.WebcamEvent;
import com.github.sarxos.webcam.WebcamListener;
import com.github.sarxos.webcam.WebcamPanel;


/**
* Proof of concept of how to handle webcam video stream from Java
Expand Down Expand Up @@ -78,6 +73,10 @@ public void webcamClosed(WebcamEvent we) {
pack();
}

@Override
public void webcamDisposed(WebcamEvent we) {
}

@Override
public void windowActivated(WindowEvent e) {
// TODO Auto-generated method stub
Expand Down Expand Up @@ -109,4 +108,5 @@ public void windowDeiconified(WindowEvent e) {
public void windowIconified(WindowEvent e) {
view.pause();
}

}
50 changes: 36 additions & 14 deletions webcam-capture/src/main/java/com/github/sarxos/webcam/Webcam.java
Expand Up @@ -68,7 +68,9 @@ public void run() {

private ShutdownHook hook = null;
private WebcamDevice device = null;
private boolean open = false;

private volatile boolean open = false;
private volatile boolean disposed = false;

/**
* Webcam class.
Expand Down Expand Up @@ -264,12 +266,19 @@ public void setViewSize(Dimension size) {
*
* @return Captured image
*/
public synchronized BufferedImage getImage() {
if (!open) {
LOG.debug("Try to get image on closed webcam, opening it automatically");
open();
public BufferedImage getImage() {

if (disposed) {
return null;
}

synchronized (this) {
if (!open) {
LOG.debug("Try to get image on closed webcam, opening it automatically");
open();
}
return device.getImage();
}
return device.getImage();
}

/**
Expand All @@ -290,15 +299,13 @@ public static List<Webcam> getWebcams() {
driver = new WebcamDefaultDriver();
}

List<WebcamDevice> devices = driver.getDevices();
for (WebcamDevice device : driver.getDevices()) {
webcams.add(new Webcam(device));
}

if (deallocOnTermSignal) {
LOG.warn("Automated deallocation on TERM signal is enabled!");
WebcamDeallocator.store(devices.toArray(new WebcamDevice[devices.size()]));
}

for (WebcamDevice device : devices) {
webcams.add(new Webcam(device));
WebcamDeallocator.store(webcams.toArray(new Webcam[webcams.size()]));
}

if (LOG.isInfoEnabled()) {
Expand Down Expand Up @@ -471,8 +478,23 @@ public WebcamDevice getDevice() {
* used any more and reinstantiation is required.
*/
protected void dispose() {
device.close();
device.dispose();

open = false;
disposed = true;

WebcamEvent we = new WebcamEvent(this);
for (WebcamListener l : listeners) {
try {
l.webcamDisposed(we);
} catch (Exception e) {
LOG.error(String.format("Notify webcam disposed, exception when calling %s listener", l.getClass()), e);
}
}

synchronized (this) {
device.close();
device.dispose();
}
}

/**
Expand Down
Expand Up @@ -7,7 +7,6 @@
import java.util.Observer;



/**
* Deallocator which goal is to release all devices resources when SIGTERM
* signal is detected.
Expand All @@ -16,7 +15,7 @@
*/
class WebcamDeallocator implements Observer {

private WebcamDevice[] devices = null;
private Webcam[] webcams = null;
private WebcamSignalHandler handler = new WebcamSignalHandler();

/**
Expand All @@ -25,9 +24,9 @@ class WebcamDeallocator implements Observer {
*
* @param devices the devices to be stored in deallocator
*/
private WebcamDeallocator(WebcamDevice[] devices) {
private WebcamDeallocator(Webcam[] devices) {
if (devices != null && devices.length > 0) {
this.devices = devices;
this.webcams = devices;
this.handler.listen("TERM", this);
}
}
Expand All @@ -37,15 +36,15 @@ private WebcamDeallocator(WebcamDevice[] devices) {
*
* @param devices the devices array to be stored by deallocator
*/
protected static final void store(WebcamDevice[] devices) {
protected static final void store(Webcam[] devices) {
new WebcamDeallocator(devices);
}

@Override
public void update(Observable observable, Object object) {
for (WebcamDevice device : devices) {
for (Webcam device : webcams) {
try {
device.close();
device.dispose();
} catch (Throwable t) {
caugh(t);
}
Expand Down
Expand Up @@ -21,4 +21,10 @@ public interface WebcamListener {
*/
public void webcamClosed(WebcamEvent we);

/**
* Webcam has been disposed
*
* @param we a webcam event
*/
public void webcamDisposed(WebcamEvent we);
}
Expand Up @@ -313,6 +313,11 @@ public void webcamClosed(WebcamEvent we) {
}
}

@Override
public void webcamDisposed(WebcamEvent we) {
webcamClosed(we);
}

/**
* Open webcam and start rendering.
*/
Expand Down
Expand Up @@ -247,10 +247,15 @@ public void webcamOpen(WebcamEvent we) {
public void webcamClosed(WebcamEvent we) {
}

@Override
public void webcamDisposed(WebcamEvent we) {
}

public static void main(String[] args) throws InterruptedException {
new WebcamStreamer(8081, Webcam.getDefault(), 0.5, true);
do {
Thread.sleep(1000);
} while (true);
}

}
Expand Up @@ -109,13 +109,20 @@ public class WebcamDefaultDevice implements WebcamDevice {
private volatile boolean opening = false;
private volatile boolean disposed = false;

private String name = null;
private String id = null;
private String fullname = null;

protected WebcamDefaultDevice(Device device) {
this.device = device;
this.name = device.getNameStr();
this.id = device.getIdentifierStr();
this.fullname = String.format("%s %s", this.name, this.id);
}

@Override
public String getName() {
return String.format("%s %s", device.getNameStr(), device.getIdentifierStr());
return fullname;
}

@Override
Expand All @@ -136,8 +143,13 @@ public void setSize(Dimension size) {
@Override
public BufferedImage getImage() {

if (disposed) {
throw new WebcamException("Cannot get image since device is already disposed");
}

if (!open) {
throw new WebcamException("Cannot get image when webcam device is not open");
LOG.error("Cannot get image when device is closed");
return null;
}

frameTask.nextFrame();
Expand All @@ -163,8 +175,7 @@ public BufferedImage getImage() {
public void open() {

if (disposed) {
LOG.warn("Cannot open webcam when it's already disposed");
return;
throw new WebcamException("Cannot open webcam when device it's already disposed");
}

synchronized (device) {
Expand Down Expand Up @@ -223,6 +234,11 @@ public void open() {
frameTask.nextFrame();
imageTask.getImage(size);

if (disposed) {
opening = false;
return;
}

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Expand Down Expand Up @@ -257,6 +273,10 @@ public void close() {

@Override
public void dispose() {
if (disposed) {
return;
}
close();
disposed = true;
}

Expand Down

0 comments on commit 6f9c770

Please sign in to comment.