-Created a mock-up debug server to serve images from a webcam
to a single client. A cleaner version of this code will follow shortly.
-Updated the image handling system in HTTPclient to actually work.
NOTE: private_aos_camera_jar.jar is a custom jar file; I made changes
to the original java code to make it play better with this vision system. 
Replacing this jar with one compiled directly from the code currently in svn
will likely break this system.


git-svn-id: https://robotics.mvla.net/svn/frc971/2013/trunk/src@4145 f308d9b7-e957-4cde-b6ac-9a88185e7312
diff --git a/971CV/src/org/frc971/DebugServerRun.java b/971CV/src/org/frc971/DebugServerRun.java
index 14b5239..c8146b1 100644
--- a/971CV/src/org/frc971/DebugServerRun.java
+++ b/971CV/src/org/frc971/DebugServerRun.java
@@ -1,25 +1,191 @@
 package org.frc971;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
-import java.nio.channels.SocketChannel;
-import java.net.InetSocketAddress;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.InterruptedIOException;
+import java.io.PrintWriter;
 
-import aos.DebugServer;
-import aos.ChannelImageGetter;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.GatheringByteChannel;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import com.googlecode.javacv.OpenCVFrameGrabber;
+import com.googlecode.javacv.cpp.opencv_core.*;
+import static com.googlecode.javacv.cpp.opencv_highgui.*;
 
 public class DebugServerRun {
-	public static void main(final String args[]) {
+	
+		private final static Logger LOG = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
+		
+		final OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(-1);
+		
+		private ServerSocketChannel sock;
+		private SocketChannel client;
+		
+		private BufferedReader sock_in;
+		private PrintWriter sock_out;
+		
+		private String ReadtoBoundary(String boundary) {
+			//reads from socket until it encounters a specific character combination
+			//if boundary is null, it reads until it runs out of data
+			ByteBuffer recvd = ByteBuffer.allocate(1024);
+			StringBuilder sb = new StringBuilder();
+			String message = "";
+			try {
+				int ret = 0;
+				while (ret != -1) {
+					ret = client.read(recvd);
+					//System.out.println(ret);
+					if (ret == 0) {
+						//finished receiving
+						message = sb.toString();
+						if (boundary == null)
+							break;
+					}
+					else {
+						for (int i = 0; i < recvd.capacity() - recvd.remaining(); i++) {
+							sb.append((char)recvd.get(i));
+						}
+						recvd.clear();
+						if (boundary != null) {
+							if (sb.toString().contains(boundary)) {
+								message = sb.toString();
+								break;
+							}
+							else {
+								continue;
+							}
+						}
+					}
+				}
+			}
+			catch (IOException e) {
+				LOG.severe("Socket read failed.");
+				return null;
+			}
+			return message;
+		}
+	
+	private ByteBuffer CreateTransmission(long content_length, double timestamp) {
+		StringBuilder ret = new StringBuilder();
+		ret.append("\r\n--boundarydonotcross\r\n");
+        ret.append("Content-Type: image/jpeg\r\n");
+        ret.append("Content-Length: ");
+        ret.append(content_length);
+        ret.append("\r\n");
+        ret.append("X-Timestamp: ");
+        ret.append(timestamp);
+        ret.append("\r\n\r\n");
+        return ByteBuffer.wrap(ret.toString().getBytes());
+	}
+	private void push() {
+		//push data to client
 		try {
-			DebugServer server = new DebugServer(9714);
-			System.out.println("Debug Server running on port 9714.");
-			SocketChannel client_sock = SocketChannel.open();
-			client_sock.connect(new InetSocketAddress("192.168.0.137", 9714));
-			ChannelImageGetter client = new ChannelImageGetter(client_sock);
-			client.getJPEG();
-			System.out.println(client.getTimestamp());
+			grabber.start();
 		}
-		catch (IOException e) {
-			System.out.println(e.getMessage());
+		catch (Exception e) {
+			LOG.severe("Could not start frame grabber.");
+			return;
 		}
+		IplImage img;
+		long content_size;
+		File buff_file;
+		InputStream input;
+		double timestamp;
+		while (true) {
+			//get some image data
+			try {
+				img = grabber.grab();
+				timestamp = System.currentTimeMillis();
+				cvSaveImage("/dev/shm/DebugServerBuffer.jpg", img);
+				buff_file = new File("/dev/shm/DebugServerBuffer.jpg");
+				content_size = buff_file.length();
+				int totalBytesRead = 0;
+		        input = new BufferedInputStream(new FileInputStream(buff_file));
+		        byte[] result = new byte[(int)content_size];
+		        while(totalBytesRead < result.length){
+		          int bytesRemaining = result.length - totalBytesRead;
+		          //input.read() returns -1, 0, or more :
+		          int bytesRead = input.read(result, totalBytesRead, bytesRemaining); 
+		          if (bytesRead > 0){
+		            totalBytesRead = totalBytesRead + bytesRead;
+		          }
+		        }
+		        ByteBuffer header = CreateTransmission(content_size, timestamp);
+		        ByteBuffer bbuf = ByteBuffer.wrap(result);
+		        ByteBuffer to_send = ByteBuffer.allocate(header.capacity() + bbuf.capacity());
+		        to_send.put(header);
+		        to_send.put(bbuf);
+		        to_send.rewind();
+		        while (to_send.remaining() > 0) {
+		        	client.write(to_send);
+		        }
+			}
+			catch (Exception e) {
+				LOG.warning("Could not grab frame.");
+				continue;
+			}
+		}
+	}
+		
+	public void Connect() throws IOException {
+		client = sock.accept();
+		client.configureBlocking(false);
+		//sock_in = new BufferedReader(new InputStreamReader(client.socket().getInputStream()));
+		//sock_out = new PrintWriter(client.socket().getOutputStream(), true);
+		//we are now connected to our client. Wait for them to send us a header.
+		LOG.info("Reading headers...");
+		ReadtoBoundary("\r\n\r\n");
+		//send one back
+		LOG.info("Writing headers...");
+		String ending = "donotcross\r\n";
+		ByteBuffer buff = ByteBuffer.wrap(ending.getBytes());
+		while (buff.remaining() > 0) {
+			client.write(buff);
+		}
+	}
+	
+	public DebugServerRun(final int port) throws IOException {
+		sock = ServerSocketChannel.open();
+		sock.socket().bind(new InetSocketAddress(9714));
+	}
+	public static void main(final String args[]) throws IOException{
+		//main function for server
+		
+		//set logger to log everything
+        LOG.setLevel(Level.ALL);
+        try {
+        	LogHandler handler = new LogHandler("../src/org/frc971/ds_vision.log");
+        	TimeFormatter formatter = new TimeFormatter();
+            handler.setFormatter(formatter);
+            LOG.addHandler(handler);
+        }
+        catch (FileNotFoundException e) {
+        	System.err.println("Warning: Logging initialization failed.");
+        }
+        
+		DebugServerRun server = new DebugServerRun(9714);
+		new TestClient();
+		server.Connect();
+		server.push();
 	}
 }
diff --git a/971CV/src/org/frc971/HTTPClient.java b/971CV/src/org/frc971/HTTPClient.java
index e5ea204..4c7d0af 100644
--- a/971CV/src/org/frc971/HTTPClient.java
+++ b/971CV/src/org/frc971/HTTPClient.java
@@ -2,17 +2,28 @@
 
 //@author: daniel
 
+import static com.googlecode.javacv.cpp.opencv_highgui.cvEncodeImage;
+
 import java.io.*;
 import java.net.*;
 
 import java.awt.image.BufferedImage;
 
+import java.nio.channels.FileChannel;
 import java.nio.channels.SocketChannel;
 import java.nio.ByteBuffer;
 
+import java.util.Iterator;
 import java.util.logging.Logger;
 
 import javax.imageio.ImageIO;
+import javax.imageio.ImageReadParam;
+import javax.imageio.ImageReader;
+import javax.imageio.stream.ImageInputStream;
+
+import com.googlecode.javacv.cpp.opencv_core.CvArr;
+import com.googlecode.javacv.cpp.opencv_core.CvMat;
+import com.googlecode.javacv.cpp.opencv_core.IplImage;
 
 import aos.ChannelImageGetter;
 
@@ -30,7 +41,7 @@
 	private BufferedReader sock_in;
 	private PrintWriter sock_out;
 	
-	private final String ATOM_IP = "10.9.71.6";
+	private final String ATOM_IP = "192.168.0.137";
 	
 	private ChannelImageGetter cgetter;
 	
@@ -44,45 +55,42 @@
 	private String ReadtoBoundary(String boundary) {
 		//reads from socket until it encounters a specific character combination
 		//if boundary is null, it reads until it runs out of data
-		StringBuilder recvd = new StringBuilder();
+		ByteBuffer recvd = ByteBuffer.allocate(1024);
+		StringBuilder sb = new StringBuilder();
 		String message = "";
 		try {
-			core_sock.setSoTimeout(10000);
-		}
-		catch (SocketException e) {
-			LOG.warning("Could not set socket timeout.");
-		}
-		try {
 			int ret;
-			while ((ret = sock_in.read()) != -1) {
+			while ((ret = sock.read(recvd)) != -1) {
 				if (ret == 0) {
 					//finished receiving
-					message += recvd.toString();
-					recvd.setLength(0);
+					message = sb.toString();
 					if (boundary == null)
 						break;
 				}
 				else {
-					recvd.append((char)ret);
+					for (int i = 0; i < recvd.capacity() - recvd.remaining(); i++) {
+						sb.append((char)recvd.get(i));
+					}
+					recvd.clear();
 					if (boundary != null) {
-						if (message.contains(boundary))
+						if (sb.toString().contains(boundary)) {
+							message = sb.toString();
 							break;
-						else
+						}
+						else {
 							continue;
+						}
 					}
 				}
 			}
 		}
-		catch (InterruptedIOException e) {
-			LOG.warning("Image receive timed out.");
-			return null;
-		}
 		catch (IOException e) {
 			LOG.severe("Socket read failed.");
 			return null;
 		}
 		return message;
 	}
+	
 	public HTTPClient() {
 		//Initialize socket connection to robot
 		try {
@@ -90,12 +98,17 @@
 			core_sock = sock.socket();
 			WriteDebug("Connecting to server at " + ATOM_IP);
 			sock.connect(new InetSocketAddress(ATOM_IP, 9714));
-			sock_in = new BufferedReader(new InputStreamReader(core_sock.getInputStream()));
-			sock_out = new PrintWriter(core_sock.getOutputStream(), true);
+			sock.configureBlocking(false);
+			//sock_in = new BufferedReader(new InputStreamReader(core_sock.getInputStream()));
+			//sock_out = new PrintWriter(core_sock.getOutputStream(), true);
 			//Write headers
 			//HTTPStreamer does not actually use the headers, so we can just write terminating chars.
 			WriteDebug("Writing headers...");
-			sock_out.println("\r\n\r\n");
+			String ending = "\r\n\r\n";
+			ByteBuffer header = ByteBuffer.wrap(ending.getBytes());
+			while (header.remaining() > 0) {
+				sock.write(header);
+			}
 			//Receive headers
 			WriteDebug("Reading headers...");
 			ReadtoBoundary("donotcross\r\n");
@@ -107,7 +120,7 @@
 			System.exit(1);
 		}
 		catch (IOException e) {
-			LOG.severe("Socket IO failed.");
+			LOG.severe("Socket IO failed: " + e.getMessage());
 			System.exit(2);
 		}
 		
@@ -117,16 +130,17 @@
 		ImageWithTimestamp final_image = new ImageWithTimestamp();
 		ByteBuffer binary_image = cgetter.getJPEG();
 		//Decode ByteBuffer into an IplImage
-		InputStream in = new ByteArrayInputStream(binary_image.array());
+		byte[] b = new byte[binary_image.remaining()];
+		binary_image.get(b);
 		try {
-			BufferedImage bImageFromConvert = ImageIO.read(in);
+			InputStream iis = new ByteArrayInputStream(b);
+			BufferedImage bImageFromConvert = ImageIO.read(iis);
 			final_image.image = new WPIColorImage(bImageFromConvert);
 			final_image.timestamp = cgetter.getTimestamp();
 			WriteDebug("Image processing successful.");
 			return final_image;
 		}
 		catch (IOException e) {
-			LOG.warning("Image processing failed.");
 			return null;
 		}
 	}	
diff --git a/971CV/src/org/frc971/VisionTuner.java b/971CV/src/org/frc971/VisionTuner.java
index 4d062dc..a6f08c2 100644
--- a/971CV/src/org/frc971/VisionTuner.java
+++ b/971CV/src/org/frc971/VisionTuner.java
@@ -61,6 +61,8 @@
     private double maxMsec;

     

     private TestImageGetter getter;

+    

+    private WPIColorImage current;

 

     public VisionTuner() {

     	//set logger to log everything

@@ -94,7 +96,7 @@
                         hueMinSlider.getValue(), hueMaxSlider.getValue(),

                         satMinSlider.getValue(),

                         valMinSlider.getValue());

-                processImage(getter.GetCurrent());

+                processImage(current);

             }

         };

 

@@ -136,6 +138,7 @@
      */

 

     private void processImage(WPIColorImage cameraImage) {

+    	current = cameraImage;

         cameraFrame.setTitle("Input:");

 

         long startTime = System.nanoTime();

diff --git a/971CV/src/org/frc971/private_aos_camera_jar.jar b/971CV/src/org/frc971/private_aos_camera_jar.jar
index e675c2e..a1b8467 100644
--- a/971CV/src/org/frc971/private_aos_camera_jar.jar
+++ b/971CV/src/org/frc971/private_aos_camera_jar.jar
Binary files differ