/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package it.freedomotic.plugins.webcam;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGImageDecoder;
import it.freedomotic.app.Freedomotic;
import java.awt.Dimension;
import java.awt.Image;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.net.PasswordAuthentication;
import java.net.URL;
/**
*
* @author Enrico Nicoletti
*/
public class MjpegWebcamConnector extends Thread {
DataInputStream stream;
private Image image = null;
private MyAuthenticator authenticator;
private String username = "user";
private String password = "pwd";
private String url;
private Dimension imageSize = null;
private boolean isConnected = false;
private HttpURLConnection httpConnection = null;
MotionDetector motionDetector;
CamMotionDetector plugin;
public MjpegWebcamConnector(String url, MotionDetector detectorAlgorithm, CamMotionDetector plugin) {
this.url = url;
this.plugin = plugin;
this.motionDetector = detectorAlgorithm;
}
public synchronized boolean connect() throws IOException {
try {
URL httpUrl = new URL(url);
httpConnection = (HttpURLConnection) httpUrl.openConnection();
// Verifica della connesione
System.out.println("HTTP-HEADER:" + httpConnection.getHeaderFields().toString()); // multipart/x-mixed-replace; boundary=--myboundary
InputStream is = httpConnection.getInputStream();
isConnected = true;
BufferedInputStream bis = new BufferedInputStream(is);
stream = new DataInputStream(bis);
this.start();
} catch (IOException iOException) {
return false;
}
return true;
}
public synchronized void disconnect() {
try {
if (isConnected) {
stream.close();
isConnected = false;
}
} catch (Exception e) {
}
}
public void parseMJPGStream() {
// preprocess the mjpg stream to remove the mjpg encapsulation
readLines(4, stream); // reads and discards the first 4 lines
parseJPGImage();
readLines(1, stream); // reads and discards the last line
}
public void parseJPGImage() { // read the embedded jpeg image
try {
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(stream);
image = decoder.decodeAsBufferedImage();
int motionLevel = motionDetector.enqueueImage(image);
plugin.setMotionLevel(motionLevel);
} catch (Exception e) {
e.printStackTrace();
disconnect();
}
}
public void readLines(int n, DataInputStream dis) {
for (int i = 0; i < n; i++) {
try {
boolean end = false;
String lineEnd = "\n"; // assumes that the end of the line is marked with this
byte[] lineEndBytes = lineEnd.getBytes();
byte[] byteBuf = new byte[lineEndBytes.length];
while (!end) {
dis.read(byteBuf, 0, lineEndBytes.length);
String t = new String(byteBuf);
// System.out.print(t); //uncomment if you want to see what the lines actually look like
if (t.equals(lineEnd)) {
end = true;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
if (!isConnected) {
try {
connect();
} catch (IOException iOException) {
Freedomotic.logger.severe(Freedomotic.getStackTraceInfo(iOException));
}
}
try {
while (true) {
parseMJPGStream();
}
} catch (Exception e) {
plugin.stop();
Freedomotic.logger.severe(Freedomotic.getStackTraceInfo(e));
}
}
public Image getImage() {
return image;
}
private class MyAuthenticator extends Authenticator {
private String username;
private String password;
public MyAuthenticator(String username, String password) {
this.username = username;
this.password = password;
}
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(this.username, this.password.toCharArray());
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}
// http://www.damonkohler.com/2010/10/mjpeg-streaming-protocol.html
// public void streamAMjpeg(Socket socket, JpegProvider jpegProvider) throws Exception {
// byte[] data = jpegProvider.getJpeg();
// OutputStream outputStream = socket.getOutputStream();
// outputStream.write((
// "HTTP/1.0 200 OK\r\n" +
// "Server: YourServerName\r\n" +
// "Connection: close\r\n" +
// "Max-Age: 0\r\n" +
// "Expires: 0\r\n" +
// "Cache-Control: no-cache, private\r\n" +
// "Pragma: no-cache\r\n" +
// "Content-Type: multipart/x-mixed-replace; " +
// "boundary=--BoundaryString\r\n\r\n").getBytes());
// while (true) {
// data = jpegProvider.getJpeg();
// outputStream.write((
// "--BoundaryString\r\n" +
// "Content-type: image/jpg\r\n". +
// "Content-Length: " +
// data.length +
// "\r\n\r\n").getBytes());
// outputStream.write(data);
// outputStream.write("\r\n\r\n".getBytes());
// outputStream.flush();
// }
//}
}