Main Page | Class Hierarchy | Class List | File List | Class Members | Related Pages

AxisSource.java

00001 /* 00002 * Created on December 12, 2003 00003 * 00004 */ 00005 package org.nees.rbnb; 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.rbnb.utility.ArgHandler; //for argument parsing 00019 //import COM.Creare.Utility.ArgHandler; //for argument parsing 00020 00032 public class AxisSource extends RBNBBase { 00033 00034 private final static String DEFAULT_RBNB_SOURCE_NANE = "SourceName"; 00035 private final static String DEFAULT_RBNB_SOURCE = "AxisVideo"; 00036 private final static String DEFAULT_RBNB_CHANNEL_NANE = "ChannelName"; 00037 private final static String DEFAULT_RBNB_CHANNEL = "video.jpg"; 00038 private final static String CAMERA_HOST_NAME = "AxisCameraHost"; 00039 private final static String CAMERA_HOST = "undefined"; 00040 00041 private final static long RETRY_INTERVAL = 1000; 00042 00043 private String cameraURLString; 00044 private String cameraHost = CAMERA_HOST; 00045 private String rbnbSourceName = DEFAULT_RBNB_SOURCE; 00046 private String rbnbChannelName = DEFAULT_RBNB_CHANNEL; 00047 00048 private final int requestedFPS = 30; 00049 00050 private static final String CACHE_SIZE_NAME = "CacheSize"; 00051 private static final int DEFAULT_CACHE_SIZE=30; 00052 00053 private int cacheSize = DEFAULT_CACHE_SIZE; 00054 00055 Source source = null; 00056 ChannelMap sMap; 00057 int index; 00058 boolean connected = false; 00059 00060 Thread timerThread; 00061 boolean runit = false; 00062 00063 private String[] parameterNameArray; 00064 private String[] parameterTypeArray; 00065 private Object[] parameterDefaultArray; 00066 00067 public static void main(String[] args) { 00068 // start from command line 00069 AxisSource a = new AxisSource(); 00070 if (a.setArgs(args)) 00071 { 00072 a.connect(); 00073 a.startThread(); 00074 } 00075 } 00076 00077 public void printUsage() 00078 { 00079 System.out.println("Usage for AxisSource..."); 00080 super.printUsage(); // uses h, s, p 00081 System.out.println("-A Axis camera host (required)"); 00082 System.out.println("[-S RBNB Source Name *" + DEFAULT_RBNB_SOURCE + "]"); 00083 System.out.println("[-C RBNB Source Channel Name *" + DEFAULT_RBNB_CHANNEL + "]"); 00084 System.out.println("[-z cache size *" + DEFAULT_CACHE_SIZE + "]"); 00085 System.out.println(); 00086 } 00087 00088 protected boolean setInstanceArgs(String[] args) throws IllegalArgumentException 00089 { 00090 //parse args 00091 try { 00092 ArgHandler ah=new ArgHandler(args); 00093 if (ah.checkFlag('A')) { 00094 String a=ah.getOption('A'); 00095 if (a!=null) cameraHost=a; 00096 } 00097 if (ah.checkFlag('S')) { 00098 String a=ah.getOption('S'); 00099 if (a!=null) rbnbSourceName=a; 00100 } 00101 if (ah.checkFlag('C')) { 00102 String a=ah.getOption('C'); 00103 if (a!=null) rbnbChannelName=a; 00104 } 00105 if (ah.checkFlag('z')) { 00106 String a=ah.getOption('z'); 00107 if (a!=null) 00108 try 00109 { 00110 Integer i = new Integer(a); 00111 int value = i.intValue(); 00112 cacheSize = value; 00113 } 00114 catch (Exception ignore) {} 00115 } 00116 } catch (Exception e) { 00117 throw new IllegalArgumentException("Argument Exception: " + e); 00118 } 00119 00120 if (cameraHost == null) 00121 { 00122 System.err.println("Axis Video Camera Host is required. Use AxisSource -h for help"); 00123 printUsage(); 00124 return false; 00125 } 00126 00127 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"; 00128 00129 System.out.println("Starting AxisSource with... \n" 00130 + " camera URL = " + cameraURLString 00131 + ";\n RBNB Server = " + getServer() 00132 + "; RBNB Source name = " + rbnbSourceName 00133 + "; RBNB Channel name = " + rbnbChannelName 00134 + "\nUse AxisSource -h to see optional arguments."); 00135 00136 return true; 00137 } 00138 00139 public AxisSource() 00140 { 00141 setParamterArrays(); 00142 initialize(); 00143 } 00144 00145 protected void setParamterArrays() { 00146 00147 String [] pNameArray = super.getBaseParameterNameArray(); 00148 String [] pTypeArray = super.getBaseParameterTypeArray(); 00149 Object [] pDefaultArray = super.getBaseParameterDefaultArray(); 00150 00151 int base = pNameArray.length; 00152 int numberOfparameters = 4; 00153 parameterNameArray = new String[base + numberOfparameters]; 00154 parameterTypeArray = new String[base + numberOfparameters]; 00155 parameterDefaultArray = new Object[base + numberOfparameters]; 00156 00157 for (int i = 0; i < base; i++) 00158 { 00159 parameterNameArray[i] = pNameArray[i]; 00160 parameterTypeArray[i] = pTypeArray[i]; 00161 parameterDefaultArray[i] = pDefaultArray[i]; 00162 } 00163 00164 parameterNameArray[base + 0] = DEFAULT_RBNB_SOURCE_NANE; 00165 parameterTypeArray[base + 0] = RBNBBaseParameterHolder.STRING_TYPE; 00166 parameterDefaultArray[base + 0] = new String(DEFAULT_RBNB_SOURCE); 00167 00168 parameterNameArray[base + 1] = DEFAULT_RBNB_CHANNEL_NANE; 00169 parameterTypeArray[base + 1] = RBNBBaseParameterHolder.STRING_TYPE; 00170 parameterDefaultArray[base + 1] = new String(DEFAULT_RBNB_CHANNEL); 00171 00172 parameterNameArray[base + 2] = CAMERA_HOST_NAME; 00173 parameterTypeArray[base + 2] = RBNBBaseParameterHolder.STRING_TYPE; 00174 parameterDefaultArray[base + 2] = new String(CAMERA_HOST); 00175 00176 parameterNameArray[base + 3] = CACHE_SIZE_NAME; 00177 parameterTypeArray[base + 3] = RBNBBaseParameterHolder.INTEGER_TYPE; 00178 parameterDefaultArray[base + 3] = new Integer(DEFAULT_CACHE_SIZE); 00179 00180 } 00181 00182 /* (non-Javadoc) 00183 * @see org.nees.rbnb.RBNBBase#setVariablesFromParameters() 00184 */ 00185 public void setVariablesFromParameters() { 00186 super.setBaseVarialbesFromParametes(); 00187 00188 rbnbSourceName = DEFAULT_RBNB_SOURCE; 00189 try{ 00190 Object obj = getValueWithDefault(DEFAULT_RBNB_SOURCE_NANE, DEFAULT_RBNB_SOURCE); 00191 rbnbSourceName = (String)obj; 00192 } catch (Throwable ignore){} 00193 00194 rbnbChannelName = DEFAULT_RBNB_CHANNEL; 00195 try{ 00196 Object obj = getValueWithDefault(DEFAULT_RBNB_CHANNEL_NANE, DEFAULT_RBNB_CHANNEL); 00197 rbnbChannelName = (String)obj; 00198 } catch (Throwable ignore){} 00199 00200 cameraHost = CAMERA_HOST; 00201 try{ 00202 Object obj = getValueWithDefault(CAMERA_HOST_NAME, CAMERA_HOST); 00203 cameraHost = (String)obj; 00204 } catch (Throwable ignore){} 00205 00206 cacheSize = DEFAULT_CACHE_SIZE; 00207 try{ 00208 Integer i = new Integer(DEFAULT_CACHE_SIZE); 00209 Object obj = getValueWithDefault(CACHE_SIZE_NAME, i); 00210 cacheSize = ((Integer)obj).intValue(); 00211 } catch (Throwable ignore){} 00212 00213 } 00214 00215 public void connect() 00216 { 00217 if (connected) return; 00218 try { 00219 // Create a source and connect: 00220 source=new Source(cacheSize, "none", 0); 00221 source.OpenRBNBConnection(getServer(),rbnbSourceName); 00222 connected = true; 00223 System.out.println("Starting AxisSource with... \n" 00224 + " camera URL = " + cameraURLString 00225 + ";\n RBNB Server = " + getServer() 00226 + "; RBNB Source name = " + rbnbSourceName 00227 + "; RBNB Channel name = " + rbnbChannelName 00228 + "/nUse AxisSource -h to see optional arguments."); 00229 } catch (SAPIException se) { se.printStackTrace(); } 00230 } 00231 00232 private void disconnect() { 00233 source.CloseRBNBConnection(); 00234 connected = false; 00235 source = null; 00236 } 00237 00238 public void startThread() 00239 { 00240 00241 if (!connected) return; 00242 00243 // Use this inner class to hide the public run method 00244 Runnable r = new Runnable() { 00245 public void run() { 00246 runWork(); 00247 } 00248 }; 00249 runit = true; 00250 timerThread = new Thread(r, "Timer"); 00251 timerThread.start(); 00252 System.out.println("WalkerSource: Started thread."); 00253 } 00254 00255 public void stopThread() 00256 { 00257 if (!connected) return; 00258 00259 runit = false; 00260 timerThread.interrupt(); 00261 System.out.println("WalkerSource: Stopped thread."); 00262 } 00263 00264 public void runWork() { 00265 00266 boolean done = false; 00267 while (!done) { 00268 done = !execute(); 00269 try {Thread.sleep(RETRY_INTERVAL); } catch (Exception e) {} 00270 } 00271 stop(); 00272 } 00273 00274 private boolean execute() 00275 { 00276 if (!connected) return false; 00277 00278 ChannelMap cmap = new ChannelMap(); 00279 int channelId = -1; 00280 try { 00281 channelId = cmap.Add(rbnbChannelName); 00282 } catch (SAPIException e) { 00283 System.err.println("Failed to add video channel to channel map; name = " 00284 + rbnbChannelName); 00285 disconnect(); 00286 return false; 00287 } 00288 cmap.PutTimeAuto("timeofday"); 00289 cmap.PutMime(channelId, "image/jpeg"); 00290 00291 URL cameraURL = null; 00292 try { 00293 cameraURL = new URL(cameraURLString); 00294 } catch (MalformedURLException e) { 00295 System.err.println("URL is malformed; URL = " + cameraURLString); 00296 disconnect(); 00297 return false; 00298 } 00299 00300 URLConnection cameraConnection = null; 00301 try { 00302 cameraConnection = cameraURL.openConnection(); 00303 } catch (IOException e) { 00304 System.err.println("Failed to connect to axis host with " + cameraURLString); 00305 disconnect(); 00306 return false; 00307 } 00308 00309 DataInputStream dis = null; 00310 try { 00311 dis = new DataInputStream(cameraConnection.getInputStream()); 00312 } catch (IOException e) { 00313 System.err.println("Failed to get data stream from axis host."); 00314 disconnect(); 00315 return false; 00316 } 00317 00318 String delimiter = ""; 00319 String contentType = ""; 00320 int contentLength = 0; 00321 int deltaTime = 0; 00322 byte[] imageData; 00323 00324 StringBuffer inputLine = new StringBuffer(); 00325 int currImage = 0; 00326 boolean readingData = false; 00327 boolean gotHeader = false; 00328 00329 double lastTime = 0; 00330 double time = 0; 00331 double frameRate = 0; 00332 double averageFrameRate = requestedFPS; 00333 00334 boolean failed = false; 00335 00336 while(currImage < 1000000) { 00337 00338 if (readingData) { 00339 00340 if (contentLength > 0) { 00341 imageData = new byte[contentLength]; 00342 try { 00343 dis.readFully(imageData); 00344 } catch (IOException e) { 00345 System.err.println("Failed to read JPEG image data from data stream."); 00346 failed = true; 00347 break; 00348 } 00349 } else { //this works but is could be implemented better 00350 int index = 0; 00351 imageData = new byte[100000]; 00352 00353 while (index < imageData.length) { 00354 if (index >= 4 && (char)imageData[index-4] == '\r' && (char)imageData[index-3] == '\n' && (char)imageData[index-2] == '\r' && (char)imageData[index-1] == '\n') { 00355 index = index - 4; 00356 break; 00357 } 00358 00359 try { 00360 imageData[index++] = dis.readByte(); 00361 } catch (IOException e) { 00362 System.err.println("Failed to read JPEG image data from data stream."); 00363 failed = true; 00364 break; 00365 } 00366 } 00367 00368 if (failed) break; 00369 00370 if (index == imageData.length) { 00371 System.err.println("Ran out of space in data buffer."); 00372 continue; 00373 } 00374 00375 } 00376 00377 if (currImage > 0) { 00378 frameRate = 1000/(double)deltaTime; 00379 averageFrameRate = 0.995*averageFrameRate + 0.005*frameRate; 00380 } 00381 00382 try { 00383 cmap.PutDataAsByteArray(channelId, imageData); 00384 } catch (SAPIException e) { 00385 System.err.println("Failed to put image data into channel map."); 00386 failed = true; 00387 break; 00388 } 00389 00390 try { 00391 source.Flush(cmap, true); 00392 } catch (SAPIException e) { 00393 System.err.println("Failed to flush output data to server."); 00394 failed = true; 00395 break; 00396 } 00397 00398 if (currImage % 30 == 0) System.out.print(((long)(averageFrameRate*10))/((double)10) + " fps \r"); 00399 00400 readingData = false; 00401 gotHeader = false; 00402 00403 delimiter = ""; 00404 contentType = ""; 00405 contentLength = 0; 00406 deltaTime = 0; 00407 00408 currImage++; 00409 00410 } else { 00411 char c; 00412 try { 00413 c = (char) dis.readByte(); 00414 } catch (IOException e) { 00415 System.err.println("Failed to read header data."); 00416 failed = true; 00417 break; 00418 } 00419 00420 if (c == '\r') { 00421 try { 00422 dis.readByte(); // get \n also 00423 } catch (IOException e) { 00424 System.err.println("Failed to read header data."); 00425 failed = true; 00426 break; 00427 } 00428 00429 if (inputLine.toString().startsWith("--")) { 00430 delimiter = inputLine.substring(2); 00431 gotHeader = true; 00432 } else if (inputLine.toString().toLowerCase().startsWith("content-type")) { 00433 contentType = inputLine.substring(14); 00434 } else if (inputLine.toString().toLowerCase().startsWith("content-length")) { 00435 contentLength = Integer.parseInt(inputLine.substring(16)); 00436 } else if (inputLine.toString().toLowerCase().startsWith("delta-time")) { 00437 deltaTime = Integer.parseInt(inputLine.substring(12)); 00438 } else if (gotHeader && inputLine.toString().trim().length() == 0) { 00439 readingData = true; 00440 } else if (inputLine.toString().trim().length() != 0){ 00441 System.out.println("Received unexpected data."); 00442 } 00443 00444 inputLine = new StringBuffer(); 00445 } else { 00446 inputLine.append(c); 00447 } 00448 } 00449 } 00450 00451 try { 00452 dis.close(); 00453 } catch (IOException e) { 00454 System.err.println("Failed to close connect to axis host."); 00455 } 00456 00457 return !failed; 00458 } 00459 00460 public boolean isRunning() 00461 { 00462 return (connected && runit); 00463 } 00464 00465 /* (non-Javadoc) 00466 * @see org.nees.rbnb.RBNBBase#getParameterNameArray() 00467 */ 00468 public String[] getParameterNameArray() { 00469 return parameterNameArray; 00470 } 00471 00472 /* (non-Javadoc) 00473 * @see org.nees.rbnb.RBNBBase#getParameterTypeArray() 00474 */ 00475 public String[] getParameterTypeArray() { 00476 return parameterTypeArray; 00477 } 00478 00479 /* (non-Javadoc) 00480 * @see org.nees.rbnb.RBNBBase#getParameterDefaultsArray() 00481 */ 00482 public Object[] getParameterDefaultArray() { 00483 return parameterDefaultArray; 00484 } 00485 00486 /* (non-Javadoc) 00487 * @see org.nees.rbnb.RBNBBase#start() 00488 */ 00489 public boolean start() { 00490 if (isRunning()) return false; 00491 if (connected) disconnect(); 00492 setVariablesFromParameters(); 00493 connect(); 00494 if (!connected) return false; 00495 startThread(); 00496 return true; 00497 } 00498 00499 /* (non-Javadoc) 00500 * @see org.nees.rbnb.RBNBBase#stop() 00501 */ 00502 public boolean stop() { 00503 if (!isRunning()) return false; 00504 stopThread(); 00505 disconnect(); 00506 return true; 00507 } 00508 00509 } 00510

Generated on Tue Aug 24 11:12:24 2004 for Data turbine for NEESGrid by doxygen 1.3.7