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

FlexTpsSource.java

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

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