00001
00002
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;
00019
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
00043
00044
00045
00046
00047
00048
00049
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
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();
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
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
00260
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
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
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 {
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();
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
00551
00552
00553 public String[]
getParameterNameArray() {
00554
return parameterNameArray;
00555 }
00556
00557
00558
00559
00560 public String[]
getParameterTypeArray() {
00561
return parameterTypeArray;
00562 }
00563
00564
00565
00566
00567 public Object[]
getParameterDefaultArray() {
00568
return parameterDefaultArray;
00569 }
00570
00571
00572
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
00585
00586
00587 public boolean stop() {
00588
if (!
isRunning())
return false;
00589 stopThread();
00590 disconnect();
00591
return true;
00592 }
00593
00594 }
00595