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

JPEGThumbnailer.java

00001 package org.nees.buffalo.video; 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.rbnb.utility.ArgHandler; //for argument parsing 00025 import com.rbnb.utility.RBNBProcess; //alternative to System.exit, so 00026 //don't bring down servlet engine 00027 //import COM.Creare.Utility.ArgHandler; //for argument parsing 00028 //import COM.Creare.Utility.RBNBProcess; //alternative to System.exit, so 00029 //don't bring down servlet engine 00030 00051 public class JPEGThumbnailer { 00052 00053 private final static String DEFAULT_RBNB_SERVER = "localhost"; 00054 private final static String DEFAULT_RBNB_PORT = "3333"; 00055 private final static String DEFAULT_RBNB_OUTPUT_NAME = "TSource"; 00056 private final static String DEFAULT_RBNB_OUTPUT_CHANNEL = "thumbnail.jpg"; 00057 private final static String DEFAULT_RBNB_SINK_NAME = "JPEGThumbanilerSink"; 00058 private final static double DEFAULT_SAMPLE_RATE = 1.0; // secondes 00059 00060 private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("MMM d, yyyy h:mm:ss aa"); 00061 private static final TimeZone TZ = TimeZone.getTimeZone("GMT"); 00062 00063 static 00064 { 00065 DATE_FORMAT.setTimeZone(TZ); 00066 } 00067 00068 private String rbnbServerName = DEFAULT_RBNB_SERVER; 00069 private String rbnbServerPort = DEFAULT_RBNB_PORT; 00070 private String rbnbHostName = rbnbServerName + ":" + rbnbServerPort; 00071 private String rbnbSourceName = DEFAULT_RBNB_OUTPUT_NAME; 00072 private String rbnbSourceChannel = DEFAULT_RBNB_OUTPUT_CHANNEL; 00073 00074 private String rbnbSinkName = DEFAULT_RBNB_SINK_NAME; 00075 00076 private String rbnbInputPath = null; // required 00077 00078 private double outputSampleRate = DEFAULT_SAMPLE_RATE; // seconds 00079 00080 private static final int DEFAULT_CACHE_SIZE=10; 00081 private int cacheSize = DEFAULT_CACHE_SIZE; 00082 00083 private static void printUsage() 00084 { 00085 System.out.println("Usage for JPEGThumbnailer..."); 00086 System.out.println(" -v RBNB Sink path for input video (required) "); 00087 System.out.println(" [-r RBNB Server Name *"+ DEFAULT_RBNB_SERVER + "]"); 00088 System.out.println(" [-p RBNB Server Port *" + DEFAULT_RBNB_PORT + "]"); 00089 System.out.println(" [-s RBNB Source (output) Name *" + DEFAULT_RBNB_OUTPUT_NAME + "]"); 00090 System.out.println(" [-c RBNB Source (output) Channel *" + DEFAULT_RBNB_OUTPUT_CHANNEL + "]"); 00091 System.out.println(" [-f desired output frame rate (in seconds) *" + DEFAULT_SAMPLE_RATE + "]"); 00092 System.out.println(" [-z cache size *" + DEFAULT_CACHE_SIZE + "]"); 00093 } 00094 00095 public JPEGThumbnailer(String[] args) 00096 { 00097 //parse args 00098 try { 00099 ArgHandler ah=new ArgHandler(args); 00100 if (ah.checkFlag('h')) { 00101 printUsage(); 00102 RBNBProcess.exit(0); 00103 } 00104 if (ah.checkFlag('r')) { 00105 String a=ah.getOption('r'); 00106 if (a!=null) rbnbServerName=a; 00107 } 00108 if (ah.checkFlag('p')) { 00109 String a=ah.getOption('p'); 00110 if (a!=null) rbnbServerPort=a; 00111 } 00112 if (ah.checkFlag('s')) { 00113 String a=ah.getOption('s'); 00114 if (a!=null) rbnbSourceName=a; 00115 } 00116 if (ah.checkFlag('c')) { 00117 String a=ah.getOption('c'); 00118 if (a!=null) rbnbSourceChannel=a; 00119 } 00120 if (ah.checkFlag('v')) { 00121 String a=ah.getOption('v'); 00122 if (a!=null) rbnbInputPath=a; 00123 } 00124 if (ah.checkFlag('f')) { 00125 String a=ah.getOption('f'); 00126 if (a!=null) outputSampleRate = Double.parseDouble(a); 00127 } 00128 if (ah.checkFlag('z')) { 00129 String a=ah.getOption('z'); 00130 if (a!=null) 00131 try 00132 { 00133 Integer i = new Integer(a); 00134 int value = i.intValue(); 00135 cacheSize = value; 00136 } 00137 catch (Exception ignore) {} 00138 } 00139 } catch (Exception e) { 00140 System.err.println("JPEGThumbnailer argument exception "+e.getMessage()); 00141 e.printStackTrace(); 00142 RBNBProcess.exit(0); 00143 } 00144 00145 if (rbnbInputPath == null) 00146 { 00147 System.err.println("The source/channel path for the video source is required. " 00148 + "Use JPEGThumbnailer -h for help"); 00149 RBNBProcess.exit(0); 00150 } 00151 00152 rbnbHostName = rbnbServerName + ":" + rbnbServerPort; 00153 } 00154 00155 private void execute() { 00156 00157 Source source = new Source(cacheSize, "none", 0); 00158 try { 00159 source.OpenRBNBConnection(rbnbHostName, rbnbSourceName); 00160 } catch (SAPIException e) { 00161 System.err.println("Failed to connect to RBNB server for source."); 00162 e.printStackTrace(); 00163 return; 00164 } 00165 00166 // select channel to output data to 00167 ChannelMap cmap = new ChannelMap(); 00168 int outputChannelIndex = -1; 00169 try { 00170 outputChannelIndex = cmap.Add(rbnbSourceChannel); 00171 } catch (SAPIException e) { 00172 System.err.println("Failed to add output channel to channel map."); 00173 e.printStackTrace(); 00174 return; 00175 } 00176 cmap.PutMime(outputChannelIndex, "image/jpeg"); 00177 00178 // The Sink to get the source images 00179 Sink sink = new Sink(); 00180 ChannelMap reqmap = new ChannelMap(); 00181 int inputChannelIndex = -1; 00182 try 00183 { 00184 // connect and set up with monitoring 00185 sink.OpenRBNBConnection(rbnbHostName, rbnbSinkName); 00186 inputChannelIndex = reqmap.Add(rbnbInputPath); 00187 sink.Monitor(reqmap,0); 00188 System.out.println("JPGThumNailer: Connection made to sever = " 00189 + rbnbHostName + " as " + rbnbSinkName 00190 + " requesting " + rbnbInputPath + "."); 00191 } 00192 catch (SAPIException se) 00193 { 00194 se.printStackTrace(); 00195 return; 00196 } 00197 00198 byte[] imageData; 00199 double startTime = 0; 00200 double durationTime = 0; 00201 long sleepTime = (long) (1000.0 * outputSampleRate); // milliseconds 00202 long lastTime = System.currentTimeMillis(); 00203 long actualSleepTime; 00204 while (true) { //loop forever, receiving JPEG frames 00205 //adjsut sleep time by how long the look took 00206 actualSleepTime = sleepTime - (System.currentTimeMillis() - lastTime); 00207 if (actualSleepTime < 0) actualSleepTime = 0; 00208 try { Thread.sleep(actualSleepTime); } catch (Exception ignore) {} 00209 lastTime = System.currentTimeMillis(); 00210 // see if any data is available from source 00211 ChannelMap getmap = null; 00212 try { 00213 getmap = sink.Fetch(0); 00214 } catch (SAPIException e) { 00215 System.err.println("Failed to fetch input data, retrying."); 00216 continue; 00217 } 00218 00219 // no data received, try again 00220 if (getmap.GetIfFetchTimedOut()) { 00221 System.err.println("Failed to fetch input data, retrying."); 00222 continue; 00223 } 00224 00225 startTime = getmap.GetTimeStart(inputChannelIndex); 00226 durationTime = getmap.GetTimeDuration(inputChannelIndex); 00227 imageData = getmap.GetData(inputChannelIndex); 00228 00229 JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(new ByteArrayInputStream(imageData)); 00230 00231 // decode JPEG image to raw image 00232 BufferedImage bi; 00233 try { 00234 bi = decoder.decodeAsBufferedImage(); 00235 } catch (IOException e){ 00236 System.err.println("Failed to decode input JPEG image, skipping."); 00237 continue; 00238 } 00239 00240 // scale both width and height by 0.5 00241 AffineTransformOp op = new AffineTransformOp(AffineTransform.getScaleInstance(0.5, 0.5), null); 00242 bi = op.filter(bi, null); 00243 00244 // encode scaled image as JPEG image 00245 ByteArrayOutputStream out = new ByteArrayOutputStream(); 00246 JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out); 00247 JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi); 00248 param.setQuality(0.75f, false); 00249 try { 00250 encoder.encode(bi, param); 00251 } catch (IOException e) { 00252 System.err.println("Failed to encode output JPEG image, skipping."); 00253 continue; 00254 } 00255 00256 // get JPEG image data as byte array 00257 imageData = out.toByteArray(); 00258 00259 // put data in channel map, preserving original time stamp 00260 try { 00261 cmap.PutTime(startTime, durationTime); 00262 cmap.PutDataAsByteArray(outputChannelIndex, imageData); 00263 } catch (SAPIException e) { 00264 System.err.println("Failed to put output data to channel map, skipping."); 00265 continue; 00266 } 00267 long unixTime = (long)(startTime * 1000.0); // convert sec to millisec 00268 String time = DATE_FORMAT.format(new Date(unixTime)); 00269 System.out.println("Thumbnail sent for " + time + " GMT)"); 00270 00271 // send data to RBNB server 00272 try { 00273 source.Flush(cmap, true); 00274 } catch (SAPIException e) { 00275 System.err.println("Failed to flush output data to server, skipping."); 00276 continue; 00277 } 00278 00279 } 00280 } 00281 00282 public static void main(String[] args) { 00283 JPEGThumbnailer t = new JPEGThumbnailer(args); 00284 t.execute(); 00285 } 00286 }

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