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

JPEGThumbnailer.java

00001 package org.nees.rbnb; 00002 00003 import java.awt.geom.AffineTransform; 00004 import java.awt.image.AffineTransformOp; 00005 import java.awt.image.BufferedImage; 00006 import java.io.ByteArrayInputStream; 00007 import java.io.ByteArrayOutputStream; 00008 import java.io.IOException; 00009 00010 import java.util.Date; 00011 import java.util.TimeZone; 00012 import java.text.SimpleDateFormat; 00013 00014 import com.rbnb.sapi.ChannelMap; 00015 import com.rbnb.sapi.SAPIException; 00016 import com.rbnb.sapi.Sink; 00017 import com.rbnb.sapi.Source; 00018 00019 import com.sun.image.codec.jpeg.JPEGCodec; 00020 import com.sun.image.codec.jpeg.JPEGEncodeParam; 00021 import com.sun.image.codec.jpeg.JPEGImageDecoder; 00022 import com.sun.image.codec.jpeg.JPEGImageEncoder; 00023 00024 //import COM.Creare.Utility.ArgHandler; //for argument parsing 00025 import com.rbnb.utility.ArgHandler; //for argument parsing 00026 00047 public class JPEGThumbnailer extends RBNBBase { 00048 00052 public JPEGThumbnailer() { 00053 setParamterArrays(); 00054 initialize(); 00055 } 00056 00057 private final static String DEFAULT_RBNB_OUTPUT_NAME_NAME = "SourceName"; 00058 private final static String DEFAULT_RBNB_OUTPUT_NAME = "TSource"; 00059 private final static String DEFAULT_RBNB_OUTPUT_CHANNEL_NAME = "ChannelName"; 00060 private final static String DEFAULT_RBNB_OUTPUT_CHANNEL = "thumbnail.jpg"; 00061 private final static String DEFAULT_RBNB_SINK_NAME_NAME = "SinkName"; 00062 private final static String DEFAULT_RBNB_SINK_NAME = "JPEGThumbanilerSink"; 00063 private final static String REQUIRED_INPUT_PATH_NAME = "RequiredInputPath"; 00064 private final static String REQUIRED_INPUT_PATH = ""; 00065 private final static String DEFAULT_SAMPLE_RATE_NAME = "SampleRate"; 00066 private final static double DEFAULT_SAMPLE_RATE = 1.0; // secondes 00067 private static final String CACHE_SIZE_NAME = "CacheSize"; 00068 private static final int DEFAULT_CACHE_SIZE=10; 00069 00070 private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMM d, yyyy h:mm:ss aa"); 00071 private static final TimeZone TZ = TimeZone.getTimeZone("GMT"); 00072 00073 static 00074 { 00075 DATE_FORMAT.setTimeZone(TZ); 00076 } 00077 00078 private String rbnbSourceName = DEFAULT_RBNB_OUTPUT_NAME; 00079 private String rbnbSourceChannel = DEFAULT_RBNB_OUTPUT_CHANNEL; 00080 00081 private String rbnbSinkName = DEFAULT_RBNB_SINK_NAME; 00082 00083 private String rbnbInputPath = null; // required 00084 00085 private double outputSampleRate = DEFAULT_SAMPLE_RATE; // seconds 00086 00087 private int cacheSize = DEFAULT_CACHE_SIZE; 00088 00089 private String[] parameterNameArray; 00090 private String[] parameterTypeArray; 00091 private Object[] parameterDefaultArray; 00092 00093 Sink sink; 00094 Source source; 00095 ChannelMap getmap; 00096 ChannelMap reqmap; 00097 ChannelMap cmap; 00098 int outputChannelIndex; 00099 int inputChannelIndex; 00100 00101 private boolean connected = false; 00102 Thread theThread; 00103 boolean runit = false; 00104 00105 public void printUsage() 00106 { 00107 System.out.println("Usage for JPEGThumbnailer..."); 00108 super.printUsage(); 00109 System.out.println(" -v RBNB Sink path for input video (required) "); 00110 System.out.println(" [-s RBNB Source (output) Name *" + DEFAULT_RBNB_OUTPUT_NAME + "]"); 00111 System.out.println(" [-c RBNB Source (output) Channel *" + DEFAULT_RBNB_OUTPUT_CHANNEL + "]"); 00112 System.out.println(" [-f desired output frame rate (in seconds) *" + DEFAULT_SAMPLE_RATE + "]"); 00113 System.out.println(" [-z cache size *" + DEFAULT_CACHE_SIZE + "]"); 00114 } 00115 00116 /* (non-Javadoc) 00117 * @see org.nees.rbnb.RBNBBase#setInstanceArgs(java.lang.String[]) 00118 */ 00119 protected boolean setInstanceArgs(String[] args) throws IllegalArgumentException 00120 { 00121 //parse args 00122 try { 00123 ArgHandler ah=new ArgHandler(args); 00124 if (ah.checkFlag('s')) { 00125 String a=ah.getOption('s'); 00126 if (a!=null) rbnbSourceName=a; 00127 } 00128 if (ah.checkFlag('c')) { 00129 String a=ah.getOption('c'); 00130 if (a!=null) rbnbSourceChannel=a; 00131 } 00132 if (ah.checkFlag('v')) { 00133 String a=ah.getOption('v'); 00134 if (a!=null) rbnbInputPath=a; 00135 } 00136 if (ah.checkFlag('f')) { 00137 String a=ah.getOption('f'); 00138 if (a!=null) outputSampleRate = Double.parseDouble(a); 00139 } 00140 if (ah.checkFlag('z')) { 00141 String a=ah.getOption('z'); 00142 if (a!=null) 00143 try 00144 { 00145 Integer i = new Integer(a); 00146 int value = i.intValue(); 00147 cacheSize = value; 00148 } 00149 catch (Exception ignore) {} 00150 } 00151 } catch (Exception e) { 00152 System.err.println("JPEGThumbnailer argument exception "+e.getMessage()); 00153 e.printStackTrace(); 00154 throw new IllegalArgumentException("JPEGThumbnailer argument exception "+e.getMessage()); 00155 } 00156 00157 if ((rbnbInputPath == null) || (rbnbInputPath.equals(""))) 00158 { 00159 System.err.println("The source/channel path for the video source is required. " 00160 + "Use JPEGThumbnailer -h for help"); 00161 return false; 00162 } 00163 00164 return true; 00165 } 00166 00167 private void connect() 00168 { 00169 source = new Source(cacheSize, "none", 0); 00170 try { 00171 source.OpenRBNBConnection(getServer(), rbnbSourceName); 00172 } catch (SAPIException e) { 00173 System.err.println("Failed to connect to RBNB server for source."); 00174 e.printStackTrace(); 00175 return; 00176 } 00177 00178 // select channel to output data to 00179 cmap = new ChannelMap(); 00180 outputChannelIndex = -1; 00181 try { 00182 outputChannelIndex = cmap.Add(rbnbSourceChannel); 00183 } catch (SAPIException e) { 00184 System.err.println("Failed to add output channel to channel map."); 00185 e.printStackTrace(); 00186 return; 00187 } 00188 cmap.PutMime(outputChannelIndex, "image/jpeg"); 00189 00190 // The Sink to get the source images 00191 sink = new Sink(); 00192 reqmap = new ChannelMap(); 00193 inputChannelIndex = -1; 00194 try 00195 { 00196 // connect and set up with monitoring 00197 sink.OpenRBNBConnection(getServer(), rbnbSinkName); 00198 inputChannelIndex = reqmap.Add(rbnbInputPath); 00199 sink.Monitor(reqmap,0); 00200 System.out.println("JPGThumNailer: Connection made to server = " 00201 + getServer() + " as " + rbnbSinkName 00202 + " requesting " + rbnbInputPath + "."); 00203 } 00204 catch (SAPIException se) 00205 { 00206 se.printStackTrace(); 00207 return; 00208 } 00209 00210 connected = true; 00211 00212 } 00213 00214 private void disconnect() 00215 { 00216 sink.CloseRBNBConnection(); 00217 sink = null; 00218 source.CloseRBNBConnection(); 00219 source = null; 00220 connected = false; 00221 } 00222 00223 private void execute() { 00224 00225 byte[] imageData; 00226 double startTime = 0; 00227 double durationTime = 0; 00228 long sleepTime = (long) (1000.0 * outputSampleRate); // milliseconds 00229 long lastTime = System.currentTimeMillis(); 00230 long actualSleepTime; 00231 while (true) { //loop forever, receiving JPEG frames 00232 //adjsut sleep time by how long the look took 00233 actualSleepTime = sleepTime - (System.currentTimeMillis() - lastTime); 00234 if (actualSleepTime < 0) actualSleepTime = 0; 00235 try { Thread.sleep(actualSleepTime); } catch (Exception ignore) {} 00236 lastTime = System.currentTimeMillis(); 00237 // see if any data is available from source 00238 getmap = null; 00239 try { 00240 getmap = sink.Fetch(0); 00241 } catch (SAPIException e) { 00242 System.err.println("Failed to fetch input data, retrying."); 00243 continue; 00244 } 00245 00246 // no data received, try again 00247 if (getmap.GetIfFetchTimedOut()) { 00248 System.err.println("Failed to fetch input data, retrying."); 00249 continue; 00250 } 00251 00252 startTime = getmap.GetTimeStart(0); 00253 durationTime = getmap.GetTimeDuration(0); 00254 imageData = getmap.GetData(0); 00255 00256 JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new ByteArrayInputStream(imageData)); 00257 00258 // decode JPEG image to raw image 00259 BufferedImage bi; 00260 try { 00261 bi = decoder.decodeAsBufferedImage(); 00262 } catch (IOException e){ 00263 System.err.println("Failed to decode input JPEG image, skipping."); 00264 continue; 00265 } 00266 00267 // scale both width and height by 0.5 00268 AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(0.5, 0.5), null); 00269 bi = op.filter(bi, null); 00270 00271 // encode scaled image as JPEG image 00272 ByteArrayOutputStream out = new ByteArrayOutputStream(); 00273 JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); 00274 JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi); 00275 param.setQuality(0.75f, false); 00276 try { 00277 encoder.encode(bi, param); 00278 } catch (IOException e) { 00279 System.err.println("Failed to encode output JPEG image, skipping."); 00280 continue; 00281 } 00282 00283 // get JPEG image data as byte array 00284 imageData = out.toByteArray(); 00285 00286 // put data in channel map, preserving original time stamp 00287 try { 00288 cmap.PutTime(startTime, durationTime); 00289 cmap.PutDataAsByteArray(outputChannelIndex, imageData); 00290 } catch (SAPIException e) { 00291 System.err.println("Failed to put output data to channel map, skipping."); 00292 continue; 00293 } 00294 long unixTime = (long)(startTime * 1000.0); // convert sec to millisec 00295 String time = DATE_FORMAT.format(new Date(unixTime)); 00296 // System.out.println("Thumbnail sent for " + time + " GMT)"); 00297 00298 // send data to RBNB server 00299 try { 00300 source.Flush(cmap, true); 00301 } catch (SAPIException e) { 00302 System.err.println("Failed to flush output data to server, skipping."); 00303 continue; 00304 } 00305 } 00306 } 00307 00308 public static void main(String[] args) { 00309 JPEGThumbnailer t = new JPEGThumbnailer(); 00310 if (t.setArgs(args)) 00311 { 00312 t.connect(); 00313 t.startThread(); 00314 } 00315 } 00316 00317 public void startThread() 00318 { 00319 00320 if (!connected) return; 00321 00322 // Use this inner class to hide the public run method 00323 Runnable r = new Runnable() { 00324 public void run() { 00325 runWork(); 00326 } 00327 }; 00328 runit = true; 00329 theThread = new Thread(r, "Timer"); 00330 theThread.start(); 00331 System.out.println("WalkerSource: Started thread."); 00332 } 00333 00334 public void stopThread() 00335 { 00336 if (!connected) return; 00337 00338 runit = false; 00339 theThread.interrupt(); 00340 System.out.println("WalkerSource: Stopped thread."); 00341 } 00342 00343 private void runWork () 00344 { 00345 execute(); 00346 } 00347 00348 public boolean isRunning() 00349 { 00350 return (connected && runit); 00351 } 00352 00353 /* (non-Javadoc) 00354 * @see org.nees.rbnb.RBNBBase#setParamterArrays() 00355 */ 00356 protected void setParamterArrays() { 00357 String [] pNameArray = super.getBaseParameterNameArray(); 00358 String [] pTypeArray = super.getBaseParameterTypeArray(); 00359 Object [] pDefaultArray = super.getBaseParameterDefaultArray(); 00360 00361 int base = pNameArray.length; 00362 int numberOfparameters = 6; 00363 parameterNameArray = new String[base + numberOfparameters]; 00364 parameterTypeArray = new String[base + numberOfparameters]; 00365 parameterDefaultArray = new Object[base + numberOfparameters]; 00366 00367 for (int i = 0; i < base; i++) 00368 { 00369 parameterNameArray[i] = pNameArray[i]; 00370 parameterTypeArray[i] = pTypeArray[i]; 00371 parameterDefaultArray[i] = pDefaultArray[i]; 00372 } 00373 00374 parameterNameArray[base + 0] = DEFAULT_RBNB_OUTPUT_NAME_NAME; 00375 parameterTypeArray[base + 0] = RBNBBaseParameterHolder.STRING_TYPE; 00376 parameterDefaultArray[base + 0] = new String(DEFAULT_RBNB_OUTPUT_NAME); 00377 00378 parameterNameArray[base + 1] = DEFAULT_RBNB_OUTPUT_CHANNEL_NAME; 00379 parameterTypeArray[base + 1] = RBNBBaseParameterHolder.STRING_TYPE; 00380 parameterDefaultArray[base + 1] = new String(DEFAULT_RBNB_OUTPUT_CHANNEL); 00381 00382 parameterNameArray[base + 2] = DEFAULT_RBNB_SINK_NAME_NAME; 00383 parameterTypeArray[base + 2] = RBNBBaseParameterHolder.STRING_TYPE; 00384 parameterDefaultArray[base + 2] = new String(DEFAULT_RBNB_SINK_NAME); 00385 00386 parameterNameArray[base + 3] = REQUIRED_INPUT_PATH_NAME; 00387 parameterTypeArray[base + 3] = RBNBBaseParameterHolder.STRING_TYPE; 00388 parameterDefaultArray[base + 3] = new String(REQUIRED_INPUT_PATH); 00389 00390 parameterNameArray[base + 4] = DEFAULT_SAMPLE_RATE_NAME; 00391 parameterTypeArray[base + 4] = RBNBBaseParameterHolder.DOUBLE_TYPE; 00392 parameterDefaultArray[base + 4] = new Double(DEFAULT_SAMPLE_RATE); 00393 00394 parameterNameArray[base + 5] = CACHE_SIZE_NAME; 00395 parameterTypeArray[base + 5] = RBNBBaseParameterHolder.INTEGER_TYPE; 00396 parameterDefaultArray[base + 5] = new Integer(DEFAULT_CACHE_SIZE); 00397 00398 } 00399 00400 /* (non-Javadoc) 00401 * @see org.nees.rbnb.RBNBBase#setVariablesFromParameters() 00402 */ 00403 public void setVariablesFromParameters() { 00404 super.setBaseVarialbesFromParametes(); 00405 00406 rbnbSourceName = DEFAULT_RBNB_OUTPUT_NAME; 00407 try{ 00408 Object obj = getValueWithDefault(DEFAULT_RBNB_OUTPUT_NAME_NAME, DEFAULT_RBNB_OUTPUT_NAME); 00409 rbnbSourceName = (String)obj; 00410 } catch (Throwable ignore){} 00411 00412 rbnbSourceChannel = DEFAULT_RBNB_OUTPUT_CHANNEL; 00413 try{ 00414 Object obj = getValueWithDefault(DEFAULT_RBNB_OUTPUT_CHANNEL_NAME, DEFAULT_RBNB_OUTPUT_CHANNEL); 00415 rbnbSourceChannel = (String)obj; 00416 } catch (Throwable ignore){} 00417 00418 rbnbSinkName = DEFAULT_RBNB_SINK_NAME; 00419 try{ 00420 Object obj = getValueWithDefault(DEFAULT_RBNB_SINK_NAME_NAME, DEFAULT_RBNB_SINK_NAME); 00421 rbnbSinkName = (String)obj; 00422 } catch (Throwable ignore){} 00423 00424 rbnbInputPath = REQUIRED_INPUT_PATH; 00425 try{ 00426 Object obj = getValueWithDefault(REQUIRED_INPUT_PATH_NAME, REQUIRED_INPUT_PATH); 00427 rbnbInputPath = (String)obj; 00428 } catch (Throwable ignore){} 00429 00430 outputSampleRate = DEFAULT_SAMPLE_RATE; 00431 try{ 00432 Double d = new Double(DEFAULT_SAMPLE_RATE); 00433 Object obj = getValueWithDefault(DEFAULT_SAMPLE_RATE_NAME, d); 00434 outputSampleRate = ((Double)obj).doubleValue(); 00435 } catch (Throwable ignore){} 00436 00437 cacheSize = DEFAULT_CACHE_SIZE; 00438 try{ 00439 Integer i = new Integer(DEFAULT_CACHE_SIZE); 00440 Object obj = getValueWithDefault(CACHE_SIZE_NAME, i); 00441 cacheSize = ((Integer)obj).intValue(); 00442 } catch (Throwable ignore){} 00443 00444 } 00445 00446 /* (non-Javadoc) 00447 * @see org.nees.rbnb.RBNBBase#getParameterNameArray() 00448 */ 00449 public String[] getParameterNameArray() { 00450 return parameterNameArray; 00451 } 00452 00453 /* (non-Javadoc) 00454 * @see org.nees.rbnb.RBNBBase#getParameterTypeArray() 00455 */ 00456 public String[] getParameterTypeArray() { 00457 return parameterTypeArray; 00458 } 00459 00460 /* (non-Javadoc) 00461 * @see org.nees.rbnb.RBNBBase#getParameterDefaultArray() 00462 */ 00463 public Object[] getParameterDefaultArray() { 00464 return parameterDefaultArray; 00465 } 00466 00467 /* (non-Javadoc) 00468 * @see org.nees.rbnb.RBNBBase#start() 00469 */ 00470 public boolean start() { 00471 if (isRunning()) return false; 00472 if (connected) disconnect(); 00473 setVariablesFromParameters(); 00474 connect(); 00475 if (!connected) return false; 00476 startThread(); 00477 return true; 00478 } 00479 00480 /* (non-Javadoc) 00481 * @see org.nees.rbnb.RBNBBase#stop() 00482 */ 00483 public boolean stop() { 00484 if (!isRunning()) return false; 00485 stopThread(); 00486 disconnect(); 00487 return true; 00488 } 00489 }

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