package com.github.sarxos.spycam; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.lang.Thread.UncaughtExceptionHandler; import java.net.URI; import java.net.URISyntaxException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import javax.imageio.ImageIO; import javax.swing.JFrame; import javax.swing.SwingUtilities; import org.apache.http.HttpResponse; import org.apache.http.ParseException; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.github.sarxos.webcam.Webcam; import com.github.sarxos.webcam.WebcamEvent; import com.github.sarxos.webcam.WebcamListener; import com.github.sarxos.webcam.WebcamMotionDetector; import com.github.sarxos.webcam.WebcamMotionEvent; import com.github.sarxos.webcam.WebcamMotionListener; import com.github.sarxos.webcam.WebcamPanel; import com.github.sarxos.webcam.WebcamPicker; import com.github.sarxos.webcam.WebcamResolution; /** * Proof of concept of how to handle webcam video stream from Java * * @author Bartosz Firyn (SarXos) */ public class SpycamMain extends JFrame implements Runnable, WebcamListener, WindowListener, UncaughtExceptionHandler, ItemListener, ThreadFactory, WebcamMotionListener { private static final long serialVersionUID = 1L; private static final Logger LOG = LoggerFactory.getLogger(SpycamMain.class); private final ExecutorService executor = Executors.newCachedThreadPool(this); private final AtomicInteger counter = new AtomicInteger(0); private final AtomicLong idnum = new AtomicLong(1000000000); private final DefaultHttpClient client = new DefaultHttpClient(); private final String uri = "http://webcam-capture.sarxos.pl/upload-demo/upload.php"; private final Dimension size = WebcamResolution.QVGA.getSize(); private Webcam webcam = null; private WebcamPanel panel = null; private WebcamPicker picker = null; private WebcamMotionDetector detector = null; public SpycamMain() { super(); setTitle("Spy Camera Service"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLayout(new BorderLayout()); addWindowListener(this); picker = new WebcamPicker(); picker.addItemListener(this); webcam = Webcam.getDefault(); webcam.setViewSize(size); panel = new WebcamPanel(webcam, false); add(picker, BorderLayout.NORTH); add(panel, BorderLayout.CENTER); pack(); setVisible(true); executor.execute(new Runnable() { @Override public void run() { pick(picker.getSelectedWebcam()); } }); } @Override public void run() { } public static void main(String[] args) { if (Webcam.getWebcams().isEmpty()) { System.err.println("No webcams detected in the system"); System.exit(1); } SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new SpycamMain(); } }); } @Override public void webcamOpen(WebcamEvent we) { } @Override public void webcamClosed(WebcamEvent we) { } @Override public void webcamDisposed(WebcamEvent we) { } @Override public void webcamImageObtained(WebcamEvent we) { // do nothing } @Override public void windowActivated(WindowEvent e) { } @Override public void windowClosed(WindowEvent e) { LOG.debug("Spycam window has been closed"); webcam.close(); } @Override public void windowClosing(WindowEvent e) { } @Override public void windowOpened(WindowEvent e) { } @Override public void windowDeactivated(WindowEvent e) { } @Override public void windowIconified(WindowEvent e) { LOG.debug("Spycam window has been iconified"); panel.pause(); } @Override public void windowDeiconified(WindowEvent e) { LOG.debug("Spycam window has been deiconified"); panel.resume(); } @Override public void uncaughtException(Thread t, Throwable e) { System.err.println(String.format("Exception in thread %s", t.getName())); e.printStackTrace(); LOG.error("Exception when running spycam", e); } private void pick(Webcam w) { if (w == null) { throw new IllegalArgumentException("Selected webcam cannot be null"); } if (panel != null) { panel.stop(); } if (webcam != null) { webcam.removeWebcamListener(this); webcam.close(); } if (detector != null) { detector.removeMotionListener(this); detector.stop(); } LOG.info("Selected {}", webcam); webcam = w; webcam.setViewSize(size); webcam.addWebcamListener(this); detector = new WebcamMotionDetector(webcam); detector.setInterval(5000); detector.addMotionListener(this); detector.start(); executor.execute(new Runnable() { @Override public void run() { remove(panel); add(panel = new WebcamPanel(webcam), BorderLayout.CENTER); pack(); } }); } @Override public void itemStateChanged(ItemEvent e) { if (e.getItem() != webcam) { pick((Webcam) e.getItem()); } } @Override public Thread newThread(Runnable r) { Thread t = new Thread(r, String.format("gui-executor-thread-%d", counter.incrementAndGet())); t.setUncaughtExceptionHandler(this); t.setDaemon(true); return t; } @Override public void motionDetected(WebcamMotionEvent wme) { LOG.info("{}: motion {}", idnum.incrementAndGet(), wme.getArea()); BufferedImage image = webcam.getImage(); if (image == null) { return; } File tmp = null; try { tmp = File.createTempFile("spycam-tmp-picture", null); ImageIO.write(image, "JPG", tmp); upload(tmp); } catch (Exception e) { LOG.error("Exception while uploading picture", e); } finally { if (tmp != null && !tmp.delete()) { tmp.deleteOnExit(); } } } private void upload(File file) throws ClientProtocolException, IOException, ParseException, URISyntaxException { LOG.debug("Uploading picture {} to {}", file, uri); MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); entity.addPart("picture", new FileBody(file, "image/jpg")); entity.addPart("passwd", new StringBody("test1234")); HttpPost post = new HttpPost(new URI(uri)); post.setEntity(entity); HttpResponse response = client.execute(post); int code = response.getStatusLine().getStatusCode(); if (code == 200) { LOG.info("Tick picture stored as {} ", EntityUtils.toString(response.getEntity())); } else { LOG.error("Error {}", response.getStatusLine()); } } }