blob: 0f60665a62109b418847629847c034e41ac2a51f [file] [log] [blame]
danielp54e997e2013-02-21 01:54:23 +00001package org.frc971;
2
danielpb3d24ee2013-02-22 19:47:11 +00003import java.io.BufferedInputStream;
danielpb3d24ee2013-02-22 19:47:11 +00004import java.io.File;
5import java.io.FileInputStream;
6import java.io.FileNotFoundException;
danielp54e997e2013-02-21 01:54:23 +00007import java.io.IOException;
danielpb3d24ee2013-02-22 19:47:11 +00008import java.io.InputStream;
danielp54e997e2013-02-21 01:54:23 +00009
danielpb3d24ee2013-02-22 19:47:11 +000010import java.net.InetSocketAddress;
danielpb3d24ee2013-02-22 19:47:11 +000011import java.nio.ByteBuffer;
danielpb3d24ee2013-02-22 19:47:11 +000012import java.nio.channels.ServerSocketChannel;
13import java.nio.channels.SocketChannel;
14
15import java.util.logging.Level;
16import java.util.logging.Logger;
17
18import com.googlecode.javacv.OpenCVFrameGrabber;
19import com.googlecode.javacv.cpp.opencv_core.*;
20import static com.googlecode.javacv.cpp.opencv_highgui.*;
danielp54e997e2013-02-21 01:54:23 +000021
22public class DebugServerRun {
danielpb3d24ee2013-02-22 19:47:11 +000023
24 private final static Logger LOG = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
25
26 final OpenCVFrameGrabber grabber = new OpenCVFrameGrabber(-1);
27
28 private ServerSocketChannel sock;
29 private SocketChannel client;
danielpb3d24ee2013-02-22 19:47:11 +000030
danielp64c4e052013-02-23 07:21:41 +000031 /** Constructs a formatted boundary header from a timestamp and content length. */
danielpb3d24ee2013-02-22 19:47:11 +000032 private ByteBuffer CreateTransmission(long content_length, double timestamp) {
33 StringBuilder ret = new StringBuilder();
34 ret.append("\r\n--boundarydonotcross\r\n");
35 ret.append("Content-Type: image/jpeg\r\n");
36 ret.append("Content-Length: ");
37 ret.append(content_length);
38 ret.append("\r\n");
39 ret.append("X-Timestamp: ");
40 ret.append(timestamp);
41 ret.append("\r\n\r\n");
42 return ByteBuffer.wrap(ret.toString().getBytes());
43 }
danielp64c4e052013-02-23 07:21:41 +000044
45 /** Loop that pushes a data stream to the client. */
danielpb3d24ee2013-02-22 19:47:11 +000046 private void push() {
danielp54e997e2013-02-21 01:54:23 +000047 try {
danielpb3d24ee2013-02-22 19:47:11 +000048 grabber.start();
danielp54e997e2013-02-21 01:54:23 +000049 }
danielpb3d24ee2013-02-22 19:47:11 +000050 catch (Exception e) {
51 LOG.severe("Could not start frame grabber.");
52 return;
danielp54e997e2013-02-21 01:54:23 +000053 }
danielpb3d24ee2013-02-22 19:47:11 +000054 IplImage img;
55 long content_size;
56 File buff_file;
57 InputStream input;
58 double timestamp;
59 while (true) {
60 //get some image data
61 try {
62 img = grabber.grab();
63 timestamp = System.currentTimeMillis();
danielp64c4e052013-02-23 07:21:41 +000064 /*We buffer through /dev/shm, just to make the conversion process easier.
65 * I know this is really ugly, but it works a lot better than what
66 * I was doing before, which segfaulted.
67 */
danielpb3d24ee2013-02-22 19:47:11 +000068 cvSaveImage("/dev/shm/DebugServerBuffer.jpg", img);
69 buff_file = new File("/dev/shm/DebugServerBuffer.jpg");
70 content_size = buff_file.length();
71 int totalBytesRead = 0;
72 input = new BufferedInputStream(new FileInputStream(buff_file));
73 byte[] result = new byte[(int)content_size];
74 while(totalBytesRead < result.length){
75 int bytesRemaining = result.length - totalBytesRead;
76 //input.read() returns -1, 0, or more :
77 int bytesRead = input.read(result, totalBytesRead, bytesRemaining);
78 if (bytesRead > 0){
79 totalBytesRead = totalBytesRead + bytesRead;
80 }
81 }
82 ByteBuffer header = CreateTransmission(content_size, timestamp);
83 ByteBuffer bbuf = ByteBuffer.wrap(result);
84 ByteBuffer to_send = ByteBuffer.allocate(header.capacity() + bbuf.capacity());
85 to_send.put(header);
86 to_send.put(bbuf);
87 to_send.rewind();
danielp64c4e052013-02-23 07:21:41 +000088 SocketCommon.sendAll(client, to_send);
danielpb3d24ee2013-02-22 19:47:11 +000089 }
90 catch (Exception e) {
91 LOG.warning("Could not grab frame.");
92 continue;
93 }
94 }
95 }
danielp64c4e052013-02-23 07:21:41 +000096 /** Constructor to start the server and bind it to a port. */
danielpb3d24ee2013-02-22 19:47:11 +000097 public DebugServerRun(final int port) throws IOException {
98 sock = ServerSocketChannel.open();
99 sock.socket().bind(new InetSocketAddress(9714));
danielp64c4e052013-02-23 07:21:41 +0000100 client = sock.accept();
101 client.configureBlocking(false);
102 //we are now connected to our client. Wait for them to send us a header.
103 LOG.info("Reading headers...");
104 SocketCommon.readtoBoundary(client, "\r\n\r\n");
105 //send one back
106 LOG.info("Writing headers...");
107 SocketCommon.sendAll(client, "donotcross\r\n");
danielpb3d24ee2013-02-22 19:47:11 +0000108 }
danielp64c4e052013-02-23 07:21:41 +0000109 /** Runs the server, and concurrently starts the vision processor with -vision flag. */
110 public static void main(final String args[]) throws IOException {
danielpb3d24ee2013-02-22 19:47:11 +0000111 //main function for server
danielpb3d24ee2013-02-22 19:47:11 +0000112 //set logger to log everything
113 LOG.setLevel(Level.ALL);
114 try {
danielp64c4e052013-02-23 07:21:41 +0000115 LogHandler handler = new LogHandler("ds_vision.log");
danielpb3d24ee2013-02-22 19:47:11 +0000116 TimeFormatter formatter = new TimeFormatter();
117 handler.setFormatter(formatter);
118 LOG.addHandler(handler);
119 }
120 catch (FileNotFoundException e) {
121 System.err.println("Warning: Logging initialization failed.");
122 }
123
danielp64c4e052013-02-23 07:21:41 +0000124 if (args[0].equals("-vision")) {
125 LOG.info("Starting vision processor.");
126 new TestClient();
127 }
128
danielpb3d24ee2013-02-22 19:47:11 +0000129 DebugServerRun server = new DebugServerRun(9714);
danielpb3d24ee2013-02-22 19:47:11 +0000130 server.push();
danielp54e997e2013-02-21 01:54:23 +0000131 }
132}