00001
00002
00003
00004
00005 package org.nees.buffalo.video;
00006
00007 import java.io.DataInputStream;
00008 import java.io.IOException;
00009
00010 import java.net.URL;
00011 import java.net.URLConnection;
00012 import java.net.MalformedURLException;
00013
00014 import com.rbnb.sapi.ChannelMap;
00015 import com.rbnb.sapi.Source;
00016 import com.rbnb.sapi.SAPIException;
00017
00018 import COM.Creare.Utility.ArgHandler;
00019 import COM.Creare.Utility.RBNBProcess;
00020
00021
00037 public class AxisSource {
00038
00039 private final static String DEFAULT_RBNB_SERVER = "localhost";
00040 private final static String DEFAULT_RBNB_PORT = "3333";
00041 private final static String DEFAULT_RBNB_SOURCE = "AxisVideo";
00042 private final static String DEFAULT_RBNB_CHANNEL = "video.jpg";
00043
00044 private String cameraURLString = null;
00045 private String cameraHost = null;
00046 private String rbnbServerName = DEFAULT_RBNB_SERVER;
00047 private String rbnbServerPort = DEFAULT_RBNB_PORT;
00048 private String rbnbHostName = rbnbServerName + ":" + rbnbServerPort;
00049 private String rbnbSourceName = DEFAULT_RBNB_SOURCE;
00050 private String rbnbChannelName = DEFAULT_RBNB_CHANNEL;
00051
00052 private final int requestedFPS = 30;
00053
00054 public AxisSource(String[] args)
00055 {
00056
00057 try {
00058 ArgHandler ah=new ArgHandler(args);
00059 if (ah.checkFlag('h')) {
00060 printUsage();
00061 RBNBProcess.exit(0);
00062 }
00063 if (ah.checkFlag('v')) {
00064 String a=ah.getOption('v');
00065 if (a!=null) cameraHost=a;
00066 }
00067 if (ah.checkFlag('r')) {
00068 String a=ah.getOption('r');
00069 if (a!=null) rbnbServerName=a;
00070 }
00071 if (ah.checkFlag('p')) {
00072 String a=ah.getOption('p');
00073 if (a!=null) rbnbServerPort=a;
00074 }
00075 if (ah.checkFlag('s')) {
00076 String a=ah.getOption('s');
00077 if (a!=null) rbnbSourceName=a;
00078 }
00079 if (ah.checkFlag('c')) {
00080 String a=ah.getOption('c');
00081 if (a!=null) rbnbChannelName=a;
00082 }
00083 } catch (Exception e) {
00084 System.err.println("AxisSource argument exception "+e.getMessage());
00085 e.printStackTrace();
00086 RBNBProcess.exit(0);
00087 }
00088
00089 if (cameraHost == null)
00090 {
00091 System.err.println("Axis Video Camera Host is required. Use AxisSource -h for help");
00092 printUsage();
00093 }
00094
00095 rbnbHostName = rbnbServerName + ":" + rbnbServerPort;
00096 cameraURLString = "http://" + cameraHost + "/axis-cgi/mjpg/video.cgi?camera=1&resolution=352x240&showlength=1&compression=25&clock=0&date=0&text=0&req_fps=30&deltatime=1";
00097
00098 }
00099
00100 public void start() {
00101
00102 System.out.println("Starting AxisSource with... \n"
00103 + " camera URL = " + cameraURLString
00104 + ";\n RBNB Server = " + rbnbHostName
00105 + "; RBNB Soruce name = " + rbnbSourceName
00106 + "; RBNB Channel name = " + rbnbChannelName
00107 + "/nUse AxisSource -h to see optional arguments.");
00108
00109
00110 boolean done = false;
00111 while (!done) {
00112 done = !execute();
00113 try { new java.lang.Thread().wait(1000); } catch (Exception e) {}
00114 }
00115 }
00116
00117 private static void printUsage()
00118 {
00119 System.out.println("Usage for AxisSoruce...");
00120 System.out.println(" -v Axis camera host (required)");
00121 System.out.println(" [-r RBNB Server Name *"+ DEFAULT_RBNB_SERVER + "]");
00122 System.out.println(" [-p RBNB Server Port *" + DEFAULT_RBNB_PORT + "]");
00123 System.out.println(" [-s RBNB Source Name *" + DEFAULT_RBNB_SOURCE + "]");
00124 System.out.println(" [-c RBNB Source Channel Name *" + DEFAULT_RBNB_CHANNEL + "]");
00125
00126 }
00127
00128 private boolean execute() {
00129 Source mySource = new Source(30, "none", 0);
00130 try {
00131 mySource.OpenRBNBConnection(rbnbHostName, rbnbSourceName);
00132 } catch (SAPIException e) {
00133 System.err.println("Failed to connect to RBNB server with host = "
00134 + rbnbHostName + " and Source = " + rbnbSourceName);
00135 return false;
00136 }
00137
00138 ChannelMap cmap = new ChannelMap();
00139 int channelId = -1;
00140 try {
00141 channelId = cmap.Add(rbnbChannelName);
00142 } catch (SAPIException e) {
00143 System.err.println("Failed to add video channel to channel map; name = "
00144 + rbnbChannelName);
00145 mySource.CloseRBNBConnection();
00146 return false;
00147 }
00148 cmap.PutTimeAuto("timeofday");
00149 cmap.PutMime(channelId, "image/jpeg");
00150
00151 URL cameraURL = null;
00152 try {
00153 cameraURL = new URL(cameraURLString);
00154 } catch (MalformedURLException e) {
00155 System.err.println("URL is malformed; URL = " + cameraURLString);
00156 mySource.CloseRBNBConnection();
00157 return false;
00158 }
00159
00160 URLConnection cameraConnection = null;
00161 try {
00162 cameraConnection = cameraURL.openConnection();
00163 } catch (IOException e) {
00164 System.err.println("Failed to connect to axis host with " + cameraURLString);
00165 mySource.CloseRBNBConnection();
00166 return false;
00167 }
00168
00169 DataInputStream dis = null;
00170 try {
00171 dis = new DataInputStream(cameraConnection.getInputStream());
00172 } catch (IOException e) {
00173 System.err.println("Failed to get data stream from axis host.");
00174 mySource.CloseRBNBConnection();
00175 return false;
00176 }
00177
00178 String delimiter = "";
00179 String contentType = "";
00180 int contentLength = 0;
00181 int deltaTime = 0;
00182 byte[] imageData;
00183
00184 StringBuffer inputLine = new StringBuffer();
00185 int currImage = 0;
00186 boolean readingData = false;
00187 boolean gotHeader = false;
00188
00189 double lastTime = 0;
00190 double time = 0;
00191 double frameRate = 0;
00192 double averageFrameRate = requestedFPS;
00193
00194 boolean failed = false;
00195
00196 while(currImage < 1000000) {
00197
00198 if (readingData) {
00199
00200 if (contentLength > 0) {
00201 imageData = new byte[contentLength];
00202 try {
00203 dis.readFully(imageData);
00204 } catch (IOException e) {
00205 System.err.println("Failed to read JPEG image data from data stream.");
00206 failed = true;
00207 break;
00208 }
00209 } else {
00210 int index = 0;
00211 imageData = new byte[100000];
00212
00213 while (index < imageData.length) {
00214 if (index >= 4 && (char)imageData[index-4] == '\r' && (char)imageData[index-3] == '\n' && (char)imageData[index-2] == '\r' && (char)imageData[index-1] == '\n') {
00215 index = index - 4;
00216 break;
00217 }
00218
00219 try {
00220 imageData[index++] = dis.readByte();
00221 } catch (IOException e) {
00222 System.err.println("Failed to read JPEG image data from data stream.");
00223 failed = true;
00224 break;
00225 }
00226 }
00227
00228 if (failed) break;
00229
00230 if (index == imageData.length) {
00231 System.err.println("Ran out of space in data buffer.");
00232 continue;
00233 }
00234
00235 }
00236
00237 if (currImage > 0) {
00238 frameRate = 1000/(double)deltaTime;
00239 averageFrameRate = 0.995*averageFrameRate + 0.005*frameRate;
00240 }
00241
00242 try {
00243 cmap.PutDataAsByteArray(channelId, imageData);
00244 } catch (SAPIException e) {
00245 System.err.println("Failed to put image data into channel map.");
00246 failed = true;
00247 break;
00248 }
00249
00250 try {
00251 mySource.Flush(cmap, true);
00252 } catch (SAPIException e) {
00253 System.err.println("Failed to flush output data to server.");
00254 failed = true;
00255 break;
00256 }
00257
00258 if (currImage % 30 == 0) System.out.print(((long)(averageFrameRate*10))/((double)10) + " fps \r");
00259
00260 readingData = false;
00261 gotHeader = false;
00262
00263 delimiter = "";
00264 contentType = "";
00265 contentLength = 0;
00266 deltaTime = 0;
00267
00268 currImage++;
00269
00270 } else {
00271 char c;
00272 try {
00273 c = (char) dis.readByte();
00274 } catch (IOException e) {
00275 System.err.println("Failed to read header data.");
00276 failed = true;
00277 break;
00278 }
00279
00280 if (c == '\r') {
00281 try {
00282 dis.readByte();
00283 } catch (IOException e) {
00284 System.err.println("Failed to read header data.");
00285 failed = true;
00286 break;
00287 }
00288
00289 if (inputLine.toString().startsWith("--")) {
00290 delimiter = inputLine.substring(2);
00291 gotHeader = true;
00292 } else if (inputLine.toString().toLowerCase().startsWith("content-type")) {
00293 contentType = inputLine.substring(14);
00294 } else if (inputLine.toString().toLowerCase().startsWith("content-length")) {
00295 contentLength = Integer.parseInt(inputLine.substring(16));
00296 } else if (inputLine.toString().toLowerCase().startsWith("delta-time")) {
00297 deltaTime = Integer.parseInt(inputLine.substring(12));
00298 } else if (gotHeader && inputLine.toString().trim().length() == 0) {
00299 readingData = true;
00300 } else if (inputLine.toString().trim().length() != 0){
00301 System.out.println("Received unexpected data.");
00302 }
00303
00304 inputLine = new StringBuffer();
00305 } else {
00306 inputLine.append(c);
00307 }
00308 }
00309 }
00310
00311 try {
00312 dis.close();
00313 } catch (IOException e) {
00314 System.err.println("Failed to close connect to axis host.");
00315 }
00316
00317 mySource.CloseRBNBConnection();
00318
00319 return !failed;
00320
00321 }
00322
00323 public static void main(String[] args) {
00324 AxisSource s = new AxisSource(args);
00325 s.start();
00326 }
00327 }
00328