View Javadoc

1   package de.desy.video.sw;
2   
3   import java.util.Date;
4   import java.lang.System;
5   import de.desy.tine.types.IMAGE;
6   
7   /**
8   * <code>CVideoHeader2</code> implements marshalling of a Video System v2 (VSv2) data array 
9   * (usually just received via the network) to a Video System v3 TINE IMAGE datatype 
10  * for usage with the rest of Video System v3 Java code.<br> 
11  * <br>
12  * <b>Note:</b>This class is only a very basic construct and might be substantially changed
13  * in future. It fits its purpose currently but will not win a price for meaningful class 
14  * design! 
15  *    
16  * @author <a href="mailto:stefan.weisse@desy.de">Stefan Weisse</a>
17  * @version $Id: Templates.xml,v 1.10 2008/06/20 16:10:13 sweisse Exp $
18  *
19  */
20  
21  public final class CVideoHeader2 {
22  	/** size in bytes of a VSv2 header that each VSv2 data array starts off with */
23  	public static final int HDRSIZE=88;	
24  	/** video codec typical FOURCC (four character code) of HUFFYUV 'HFYU' */
25  	public static final long HUFFYUV_FOURCC = 0x55594648;	
26  	
27  	/** setting of VSv2 header: fourcc of used compression */
28  	private long compression;
29  	/** setting of VSv2 header: total length of VSv2 data array*/
30  	private int len_total;
31  	/** setting of VSv2 header: length of appended data (image bits) */
32  	private int len_data;
33  	/** setting of VSv2 header: length of an additional format header between global header and image bits */
34  	private int len_fmthdr;
35  	/** setting of VSv2 header: frame number */
36  	private long framenumber;
37  	/** transformed setting of VSv2 header: time at which image was taken */
38  	private Date timestamp=null;
39  	/** setting of VSv2 header: camera port where the image was taken at */
40  	private int cameraport;
41  	/** setting of VSv2 header: width of video image in pixels */
42  	private int width;
43  	/** setting of VSv2 header: height of video image in pixels */
44  	private int height;
45  	/** setting of VSv2 header: is compressed (1) or uncompressed (0) data appended*/
46  	private boolean compressed;
47  	/** setting of VSv2 header: current averaged(!) framerate */
48  	private double framerate;
49  	/** setting of VSv2 header: ratio (in x and y) between pixels and millimetres */
50  	private double scale;
51  	/** transformed setting of VSv2 header: bytes per pixel of appended image */
52  	private int bypp;
53  	/** setting of VSv2 header: effective bits per pixels of appended image */
54  	private int effective_bpp;
55  	
56  	/** setting of VSv2 header: magic at startup of header */
57  	private final long KENNUNG=0x11223344;
58  	
59  	/** maximum 32-bit integer value for validity checking */
60  	private final long MAX_INT=0x7FFFFFFF; // 2415919103
61  	
62  	/**
63  	 * performs default initialisation of private members
64  	 * 
65  	 *
66  	 */
67  	public CVideoHeader2()
68  	{
69  		init();
70  	}
71  
72  
73  	/**
74  	 * interprets an input array (aImageV2blob) as a Video System v2 data block 
75  	 * (header plus possibly additional format header plus image bits). In case
76  	 * validity checking succeeds, the contained image information is wrapped into 
77  	 * a VSv3 TINE IMAGE datatype for use with all other Java Video code parts. As 
78  	 * a Video System v2 header does not deliver a good string to be used as 
79  	 * VSv3 header camera port (mounting place e.g.) identification, this member in 
80  	 * IMAGE datatype is taken from aCamPort parameter.<br>
81  	 * <br>
82  	 * @param aCamPort camera port description to be put in resulting IMAGE aDestImage
83  	 * @param aImageV2blob input data set (should contain VSv2 image data block)
84  	 * @param aDestImage TINE IMAGE datatype output
85  	 * @return <ul><li>true - success
86  	 * 		   <li>false - error importing blob (most probably validity checking failed)</ul>
87  	 */
88  	public boolean packageV2BlobIntoIMAGE( String aCamPort, final byte [] aImageV2blob, IMAGE aDestImage)
89  	{
90  		if (import_from_bytebuf( aImageV2blob ) == false)
91  			return false;
92  		
93  		IMAGE.FrameHeader frameHeader = aDestImage.getFrameHeader();
94  		IMAGE.SourceHeader sourceHeader = aDestImage.getSourceHeader();
95  				
96  		//CVideoHeader3 hdr = new CVideoHeader3();
97  		frameHeader.aoiHeight = -1;
98  		frameHeader.aoiWidth = -1;
99  		frameHeader.bytesPerPixel = bypp;
100 		frameHeader.sourceWidth = width;
101 		frameHeader.sourceHeight = height;
102 		frameHeader.effectiveBitsPerPixel = effective_bpp;
103 		
104 		frameHeader.appendedFrameSize = frameHeader.sourceWidth*frameHeader.sourceHeight*frameHeader.bytesPerPixel;
105 		
106 		frameHeader.eventNumber = -1;
107 		frameHeader.frameNumber = (int) framenumber;
108 		frameHeader.fspare1 = (float) -1.0;
109 		frameHeader.fspare2 = (float) -1.0;
110 		frameHeader.fspare3 = (float) -1.0;
111 		frameHeader.horizontalBinning = 0;
112 		frameHeader.imageFlags = (int) CVideoHeader3.CF_IMAGE_FLAG_IMAGE_LOSSLESS | (int) CVideoHeader3.CF_IMAGE_FLAG_LITTLE_ENDIAN_BYTE_ORDER;
113 		
114 		frameHeader.imageFormat = (int) CVideoHeader3.CF_IMAGE_FORMAT_GRAY;
115 		if (compressed == true) 
116 		{
117 			frameHeader.imageFormat = (int) CVideoHeader3.CF_IMAGE_FORMAT_HUFFYUV;
118 			frameHeader.appendedFrameSize = len_data;
119 		}
120 		frameHeader.imageRotation = (float) 0.0;
121 		frameHeader.ispare1 = -1;
122 		frameHeader.ispare2 = -1;
123 		frameHeader.ispare3 = -1;
124 		frameHeader.sourceFormat = (int) CVideoHeader3.CF_IMAGE_FORMAT_GRAY;
125 		frameHeader.verticalBinning = 0;
126 		frameHeader.xScale = (float) scale;
127 		frameHeader.xStart = 0;
128 		frameHeader.yScale = (float) scale;
129 		frameHeader.yStart = 0;
130 		
131 		sourceHeader.baseTag = (int) CVideoHeader3.CF_IMAGE_MAGIC_01;
132 		sourceHeader.cameraPortName = aCamPort;
133 		sourceHeader.cameraPortId = (int) CVideoHeader3.CF_IMAGE_NO_CAMERA_PORT_ID;
134 		
135 		long temptime = timestamp.getTime();
136 		long temptime_msec = temptime % 1000;
137 		long temptime_sec = temptime / 1000;
138 
139 		sourceHeader.timestampMicroseconds = (int) temptime_msec*1000;
140 		sourceHeader.timestampSeconds = (int) temptime_sec;
141 		sourceHeader.totalLength = CVideoHeader3.HDRSIZE + frameHeader.appendedFrameSize;
142 		sourceHeader.versionTag = CVideoHeader3.CF_IMAGE_VERSION;
143 		
144 		byte[] destBuf = aDestImage.getImageFrameBuffer();
145 		
146 		byte[] srcBuf = aImageV2blob;
147 		int srcOffset = 0+HDRSIZE+len_fmthdr;
148 
149 		System.arraycopy(srcBuf, srcOffset, destBuf, 0, len_data ); 
150 
151 		return true;
152 	}
153 	
154 	private void init()
155 	{
156 		compression = 0;
157 		
158 		len_total = HDRSIZE;
159 		len_data = 0;
160 		len_fmthdr = 0;
161 		framenumber = -1;
162 		timestamp = new Date(0L);
163 		cameraport = -1;
164 		width=-1;
165 		height=-1;
166 		
167 		compressed = false;
168 		framerate = 5.0;
169 		scale = 1.000;
170 		bypp = 1;
171 		effective_bpp = 8;
172 	}
173 	
174 	// buf is in/out and first 88 bytes inside will surely be overwritten
175 	// (exception is false return)
176 	/*public boolean export_to_bytebuffer( byte[] buf )
177 	{
178 		// TODO this function is not yet tested. this needs to be done - sw dec 21, 2007
179 		if (buf == null) return false;
180 		if (buf.length < HDRSIZE) return false;
181 
182 		if (len_fmthdr < 0) return false;
183 		if (len_data < 0) return false;
184 		if (width <= 0) return false;
185 		if (height <= 0) return false;
186 		if (cameraport < 0) return false;
187 		if (framerate <= 0.0000) return false;
188 		if (scale <= 0.0000) return false;
189 		if ((bypp < 1) || (bypp > 3)) return false;
190 		if (timestamp == null) return false;
191 		if (timestamp.getTime() == 0) return false;
192 		if ((compression != 0) && (compression != HUFFYUV_FOURCC)) return false;
193 		
194 		if (effective_bpp > bypp*8) effective_bpp = bypp*8;
195 		len_total = len_fmthdr+len_data+HDRSIZE;
196 
197 		// okay, everything is fine, so export it now
198 
199 		for (int i=0;i<HDRSIZE;i++) buf[i] = 0;
200 		
201 		// kennung
202 		int offset = 0;
203 		buf[offset+0] = (byte) (KENNUNG&0xff);
204 		buf[offset+1] = (byte) ((KENNUNG>>8)&0xff);
205 		buf[offset+2] = (byte) ((KENNUNG>>16)&0xff);
206 		buf[offset+3] = (byte) ((KENNUNG>>24)&0xff);
207 		
208 		offset = 4;
209 		buf[offset+0] = (byte) (compression&0xff);
210 		buf[offset+1] = (byte) ((compression>>8)&0xff);
211 		buf[offset+2] = (byte) ((compression>>16)&0xff);
212 		buf[offset+3] = (byte) ((compression>>24)&0xff);
213 		
214 		offset = 8;
215 		buf[offset+0] = (byte) (len_total&0xff);
216 		buf[offset+1] = (byte) ((len_total>>8)&0xff);
217 		buf[offset+2] = (byte) ((len_total>>16)&0xff);
218 		buf[offset+3] = (byte) ((len_total>>24)&0xff);
219 		
220 		offset = 12;
221 		buf[offset+0] = (byte) (len_data&0xff);
222 		buf[offset+1] = (byte) ((len_data>>8)&0xff);
223 		buf[offset+2] = (byte) ((len_data>>16)&0xff);
224 		buf[offset+3] = (byte) ((len_data>>24)&0xff);
225 
226 		offset = 16;
227 		buf[offset+0] = (byte) (len_fmthdr&0xff);
228 		buf[offset+1] = (byte) ((len_fmthdr>>8)&0xff);
229 		buf[offset+2] = (byte) ((len_fmthdr>>16)&0xff);
230 		buf[offset+3] = (byte) ((len_fmthdr>>24)&0xff);
231 		
232 		offset = 20;
233 		buf[offset+0] = (byte) (framenumber&0xff);
234 		buf[offset+1] = (byte) ((framenumber>>8)&0xff);
235 		buf[offset+2] = (byte) ((framenumber>>16)&0xff);
236 		buf[offset+3] = (byte) ((framenumber>>24)&0xff);
237 
238 		long temptime = timestamp.getTime();
239 		long temptime_msec = temptime % 1000;
240 		long temptime_sec = temptime / 1000;
241 		
242 		offset = 24;
243 		buf[offset+0] = (byte) (temptime_sec&0xff);
244 		buf[offset+1] = (byte) ((temptime_sec>>8)&0xff);
245 		buf[offset+2] = (byte) ((temptime_sec>>16)&0xff);
246 		buf[offset+3] = (byte) ((temptime_sec>>24)&0xff);
247 
248 		offset = 28;
249 		buf[offset+0] = (byte) (temptime_msec&0xff);
250 		buf[offset+1] = (byte) ((temptime_msec>>8)&0xff);
251 		
252 		int tzoffset = java.util.TimeZone.getDefault().getRawOffset();
253 		boolean dstflag = java.util.TimeZone.getDefault().inDaylightTime(timestamp);
254 		
255 		offset = 30;
256 		// add timezone offset (short) 
257 		buf[offset+0] = (byte) (tzoffset&0xff);
258 		buf[offset+1] = (byte) ((tzoffset>>8)&0xff);
259 				
260 		offset = 32;
261 		int idstflag = 0;
262 		if (dstflag == true) idstflag = 1;
263 		// add dstflag (short)  
264 		buf[offset+0] = (byte) (idstflag&0xff);
265 		buf[offset+1] = (byte) ((idstflag>>8)&0xff);
266 				
267 		offset=36;
268 		buf[offset+0] = (byte) (cameraport&0xff);
269 		buf[offset+1] = (byte) ((cameraport>>8)&0xff);
270 		buf[offset+2] = (byte) ((cameraport>>16)&0xff);
271 		buf[offset+3] = (byte) ((cameraport>>24)&0xff);
272 
273 		offset=40;
274 		buf[offset+0] = (byte) (width&0xff);
275 		buf[offset+1] = (byte) ((width>>8)&0xff);
276 		buf[offset+2] = (byte) ((width>>16)&0xff);
277 		buf[offset+3] = (byte) ((width>>24)&0xff);
278 		
279 		offset=44;
280 		buf[offset+0] = (byte) (height&0xff);
281 		buf[offset+1] = (byte) ((height>>8)&0xff);
282 		buf[offset+2] = (byte) ((height>>16)&0xff);
283 		buf[offset+3] = (byte) ((height>>24)&0xff);
284 		
285 		int icompressed = 0;
286 		if (compressed == true) icompressed=1;
287 		offset=48;
288 		buf[offset+0] = (byte) (icompressed&0xff);
289 		buf[offset+1] = (byte) ((icompressed>>8)&0xff);
290 		buf[offset+2] = (byte) ((icompressed>>16)&0xff);
291 		buf[offset+3] = (byte) ((icompressed>>24)&0xff);
292 		
293 		long dbltobits = Double.doubleToLongBits(framerate);
294 		
295 		offset=56;
296 		buf[offset+0] = (byte) (dbltobits&0xff);
297 		buf[offset+1] = (byte) ((dbltobits>>8)&0xff);
298 		buf[offset+2] = (byte) ((dbltobits>>16)&0xff);
299 		buf[offset+3] = (byte) ((dbltobits>>24)&0xff);
300 		buf[offset+4] = (byte) ((dbltobits>>32)&0xff);
301 		buf[offset+5] = (byte) ((dbltobits>>40)&0xff);
302 		buf[offset+6] = (byte) ((dbltobits>>48)&0xff);
303 		buf[offset+7] = (byte) ((dbltobits>>56)&0xff);
304 		
305 		
306 		dbltobits = Double.doubleToLongBits(scale);
307 		
308 		offset=64;
309 		buf[offset+0] = (byte) (dbltobits&0xff);
310 		buf[offset+1] = (byte) ((dbltobits>>8)&0xff);
311 		buf[offset+2] = (byte) ((dbltobits>>16)&0xff);
312 		buf[offset+3] = (byte) ((dbltobits>>24)&0xff);		
313 		buf[offset+4] = (byte) ((dbltobits>>32)&0xff);
314 		buf[offset+5] = (byte) ((dbltobits>>40)&0xff);
315 		buf[offset+6] = (byte) ((dbltobits>>48)&0xff);
316 		buf[offset+7] = (byte) ((dbltobits>>56)&0xff);
317 		
318 		offset=72;
319 		int bitsperpixel = bypp*8;
320 		buf[offset+0] = (byte) (bitsperpixel&0xff);
321 		buf[offset+1] = (byte) ((bitsperpixel>>8)&0xff);
322 		buf[offset+2] = (byte) ((bitsperpixel>>16)&0xff);
323 		buf[offset+3] = (byte) ((bitsperpixel>>24)&0xff);		
324 
325 		offset=76;
326 		buf[offset+0] = (byte) (effective_bpp&0xff);
327 		buf[offset+1] = (byte) ((effective_bpp>>8)&0xff);
328 		buf[offset+2] = (byte) ((effective_bpp>>16)&0xff);
329 		buf[offset+3] = (byte) ((effective_bpp>>24)&0xff);
330 		
331 		return true;
332 	}
333 	*/
334 
335 
336 	/**
337 	 * interprets an input array (buf) as a Video System v2 header. In case
338 	 * validity checking succeeds, the contained image information is stored into 
339 	 * local class variables.<br>
340 	 * <br>
341 	 * @param buf VSv2 header as byte array
342 	 * 
343 	 * @return <ul><li>true - success<br>
344 	 * 		   <li>false - error, no class variable is updated (most probably validity 
345 	 *         checking failed)</ul>
346 	 */
347 	public boolean import_from_bytebuf( byte[] buf )
348 	{
349 		// strong validity checking!
350 		long l_kennung;
351 		long l_compression;
352 		long l_width;
353 		long l_height;
354 		long l_bypp;
355 		long l_effective_bpp;
356 		long l_len_total;
357 		long l_len_data;
358 		long l_len_fmthdr;
359 		long l_framenumber;
360 		long l_cameraport;
361 		long l_timestamp;
362 		long l_compressed;
363 		double l_scale;
364 		double l_framerate;
365 
366 		if (buf.length < HDRSIZE) return false;
367 		
368 		int off=0;
369 		l_kennung = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24);
370 		
371 		off = 4;
372 		l_compression = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24);
373 
374 		off = 8;
375 		l_len_total = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24); 
376 
377 		off = 12;
378 		l_len_data = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24);
379 		
380 		off = 16;
381 		l_len_fmthdr = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24);
382 		
383 		off = 20;
384 		l_framenumber = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24);
385 		
386 		off = 24;
387 		long l_timestamp_sec = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24);
388 		off = 28;
389 		long l_timestamp_msec = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8);
390 		
391 		l_timestamp = (l_timestamp_sec*1000L)+l_timestamp_msec; 
392 		
393 		off = 36;
394 		l_cameraport = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24);
395 		
396 		off = 40;
397 		l_width = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24); 
398 			
399 		off = 44;
400 		l_height = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24); 
401 
402 		off = 48;
403 		l_compressed = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24);
404 		
405 		off = 56;
406 		
407 		long l_framerate_long = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|
408 								((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24)| 
409 								((((long)buf[off+4])&0xFF)<<32)|((((long)buf[off+5])&0xFF)<<40)|
410 								((((long)buf[off+6])&0xFF)<<48)|((((long)buf[off+7])&0xFF)<<56);
411 		
412 		l_framerate = Double.longBitsToDouble(l_framerate_long);
413 		
414 		off = 64;
415 		long l_scale_long = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|
416 		((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24)| 
417 		((((long)buf[off+4])&0xFF)<<32)|((((long)buf[off+5])&0xFF)<<40)|
418 		((((long)buf[off+6])&0xFF)<<48)|((((long)buf[off+7])&0xFF)<<56);
419 
420 		l_scale = Double.longBitsToDouble(l_scale_long);
421 		
422 		off = 72;
423 		l_bypp = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24);
424 		l_bypp /= 8;
425 		
426 		off = 76;
427 		l_effective_bpp = (((long)buf[off+0])&0xFF)|((((long)buf[off+1])&0xFF)<<8)|((((long)buf[off+2])&0xFF)<<16)|((((long)buf[off+3])&0xFF)<<24);
428 		
429 		// safety because of buggy servers of mine :/
430 		if (l_effective_bpp >= l_bypp*8) l_effective_bpp = l_bypp*8;
431 		
432 		// check and copy into real class variables in case of success
433 		
434 		if 	((l_kennung == KENNUNG) &&
435 			((l_width >0) && (l_width<=MAX_INT)) &&
436 			((l_height > 0) && (l_height<=MAX_INT) ) &&
437 			((l_bypp == 1) || (l_bypp == 2) || (l_bypp == 4)) &&
438 			(l_effective_bpp <= l_bypp*8) &&
439 			(l_len_total <= buf.length) &&
440 			(l_len_data <= buf.length) &&
441 			(l_len_fmthdr <= buf.length) &&
442 			(l_len_total == l_len_data+l_len_fmthdr+HDRSIZE) &&
443 			(l_framenumber > 0) &&
444 			((l_cameraport >= 0) && (l_cameraport <= MAX_INT)) &&
445 			(l_timestamp > 0) &&
446 			((l_compressed == 0) || (l_compressed == 1)) &&
447 			(l_scale > 0.0) &&
448 			(l_framerate > 0.0))
449 		{
450 			compression = l_compression;
451 			width = (int) l_width;
452 			height = (int) l_height;
453 			bypp = (int) l_bypp;
454 			effective_bpp = (int) l_effective_bpp;
455 			len_total = (int) l_len_total;
456 			len_data = (int) l_len_data;
457 			len_fmthdr = (int) l_len_fmthdr;
458 			framenumber = l_framenumber;
459 			cameraport = (int) l_cameraport;
460 			timestamp = new Date(l_timestamp);
461 			framerate = l_framerate;
462 			scale = l_scale;
463 			compressed = false;
464 			if (l_compressed == 1) compressed = true;
465 		
466 			return true;
467 		}
468 		
469 		return false;
470 	}
471 	
472 }
473