comparison src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java @ 611:9a2bef3f3020

blocking fix broadcast mode
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 21 Feb 2020 11:52:14 +0900
parents e986dad88692
children 994a710100fd
comparison
equal deleted inserted replaced
610:705fd8d79378 611:9a2bef3f3020
36 import java.util.LinkedList; 36 import java.util.LinkedList;
37 import java.util.zip.Deflater; 37 import java.util.zip.Deflater;
38 38
39 public class ZRLEDecoder extends ZlibDecoder { 39 public class ZRLEDecoder extends ZlibDecoder {
40 private static final int MAX_TILE_SIZE = 64; 40 private static final int MAX_TILE_SIZE = 64;
41 private static final int RECT_HEADER_SIZE = 16;
41 private int[] decodedBitmap; 42 private int[] decodedBitmap;
42 private int[] palette; 43 private int[] palette;
44 private boolean WifiMulticast;
43 45
44 class TileLoop { 46 class TileLoop {
45 private final boolean blocking; 47 private final boolean blocking;
46 final int MARGIN = 18000; 48 final int MARGIN = 25000;
47 final int deflate_size = 60000-MARGIN; 49 final int deflate_size = 62000-MARGIN;
48 private ByteBuffer c1; 50 private ByteBuffer c1;
49 private int width; // phase2 length 51 private int width; // phase2 length
50 private FramebufferUpdateRectangle c0rect,c1rect,rect; 52 private FramebufferUpdateRectangle c0rect,c1rect,rect;
51 private int prevLineOffset; 53 private int prevLineOffset;
52 private int prevC1Offset; 54 private int prevC1Offset;
77 */ 79 */
78 80
79 public TileLoop(TreeRFBProto rfb, int offset) { 81 public TileLoop(TreeRFBProto rfb, int offset) {
80 prevoffset = prevLineOffset = flushOffset = offset; 82 prevoffset = prevLineOffset = flushOffset = offset;
81 prevC1Offset = 0; 83 prevC1Offset = 0;
82 if (rfb == null || offset < deflate_size + spanGap) { 84 if (rfb == null || offset < deflate_size + MARGIN) {
83 // packet size fit in broadcast send it all at once 85 // packet size fit in broadcast send it all at once
84 blocking = false; 86 blocking = false;
85 } else 87 } else
86 blocking = true; 88 blocking = true;
87 } 89 }
118 prevC1LineOffset = prevC1Offset; 120 prevC1LineOffset = prevC1Offset;
119 c1rect.width = c1rect.height = 0; 121 c1rect.width = c1rect.height = 0;
120 c0rect = null; 122 c0rect = null;
121 } 123 }
122 124
123 int spanGap = 128;
124 /** 125 /**
125 * Series of tiles compose at most three rectangles. SYNC_FLUSH is necessary on 126 * Series of tiles compose at most three rectangles. SYNC_FLUSH is necessary on
126 * rectangle boundaries. 127 * rectangle boundaries.
127 * 128 *
128 * +----+ 129 * +----+
208 flushRectangle(c1rect,c1.position()); 209 flushRectangle(c1rect,c1.position());
209 if (end) { 210 if (end) {
210 flushMuticast(rfb,bytes); 211 flushMuticast(rfb,bytes);
211 return; 212 return;
212 } 213 }
213 c1.position(c1.position()+16); // header space 214 c1.position(c1.position()+ RECT_HEADER_SIZE); // header space
214 prevC1Offset = c1.position(); 215 prevC1Offset = c1.position();
215 c1rect = new FramebufferUpdateRectangle(rect.x,c1rect.y+tileH,0,0); 216 c1rect = new FramebufferUpdateRectangle(rect.x,c1rect.y+tileH,0,0);
216 } 217 }
217 } else { // phase 1 218 } else { // phase 1
218 if (width >= rect.width) { // next line 219 if (width >= rect.width) { // next line
222 if (c0rect!=null) { // extend phase 1 223 if (c0rect!=null) { // extend phase 1
223 c0rect.height += tileH; 224 c0rect.height += tileH;
224 } else { // first phase 1 case 225 } else { // first phase 1 case
225 c0rect = c1rect; 226 c0rect = c1rect;
226 } 227 }
228 c1rect = new FramebufferUpdateRectangle(rect.x, c0rect.y+c0rect.height, 0, 0);
227 if (end) { 229 if (end) {
230 c0rect = null; // next will be first phase 1 case
228 flushMuticast(rfb,bytes); 231 flushMuticast(rfb,bytes);
229 return; 232 return;
230 } 233 }
231 c1rect = new FramebufferUpdateRectangle(rect.x, c0rect.y+c0rect.height, 0, 0);
232 prevLineOffset = offset; 234 prevLineOffset = offset;
233 } 235 }
234 } 236 }
235 } 237 }
236 238
237 public void makeHeaderSpace() { 239 public void makeHeaderSpace() {
238 // previous rectangle is finished, make next header space and copy already compressed part 240 // previous rectangle is finished, make next header space and copy already compressed part
239 System.arraycopy(c1.array(),prevC1LineOffset,c1.array(),prevC1LineOffset+16,c1.position()-prevC1LineOffset); 241 System.arraycopy(c1.array(),prevC1LineOffset,c1.array(),prevC1LineOffset+ RECT_HEADER_SIZE,c1.position()-prevC1LineOffset);
240 c1.position(c1.position()+16); 242 c1.position(c1.position()+ RECT_HEADER_SIZE);
241 prevC1Offset = prevC1LineOffset+16; 243 prevC1Offset = prevC1LineOffset+ RECT_HEADER_SIZE;
242 } 244 }
243 245
246 /**
247 *
248 * @param extend use MARGIN
249 * @param what reason of flush (debug purpose)
250 * @return packet full
251 * @throws TransportException
252 */
244 private boolean flushDeflator(boolean extend,String what) throws TransportException { 253 private boolean flushDeflator(boolean extend,String what) throws TransportException {
245 // System.out.println("flusing "+what+c1); 254 // System.out.println("flusing "+what+c1);
246 if (extend) c1.limit(c1.capacity()-16); 255 if (extend) c1.limit(c1.capacity()- RECT_HEADER_SIZE);
247 deflater.deflate(c1, Deflater.FULL_FLUSH); 256 deflater.deflate(c1, Deflater.FULL_FLUSH);
248 if (c1.remaining()==0) { 257 if (c1.remaining()==0) {
249 if (!extend) { 258 if (!extend) {
250 c1.limit(c1.capacity()-16); 259 c1.limit(c1.capacity()- RECT_HEADER_SIZE);
251 deflater.deflate(c1, Deflater.FULL_FLUSH); 260 deflater.deflate(c1, Deflater.FULL_FLUSH);
252 } 261 }
253 if (c1.remaining() == 0) 262 if (c1.remaining() == 0) {
254 throw new TransportException("Multicast packet overrun", null); 263 ByteBuffer tmp = ByteBuffer.allocate(65536);
264 deflater.deflate(tmp,Deflater.FULL_FLUSH);
265 throw new TransportException("Multicast packet overrun "+(c1.limit()+tmp.position())+" bytes required", null);
266 }
255 return true; 267 return true;
256 } 268 }
257 return false; 269 return false;
258 } 270 }
259 271
280 deflater.reset(); 292 deflater.reset();
281 LinkedList<ByteBuffer> bufs = new LinkedList<ByteBuffer>(); 293 LinkedList<ByteBuffer> bufs = new LinkedList<ByteBuffer>();
282 bufs.add(c1); 294 bufs.add(c1);
283 // rfb.getContext().checkFrameBufferRectanble(c1, bytes, flushOffset, prevoffset); 295 // rfb.getContext().checkFrameBufferRectanble(c1, bytes, flushOffset, prevoffset);
284 flushOffset = prevoffset; 296 flushOffset = prevoffset;
285 if (rfb.isTreeManager() && rfb.connectionPresenter.isUseMulticast()) { 297 if (WifiMulticast) {
286 for (ByteBuffer buf : bufs) 298 for (ByteBuffer buf : bufs)
287 rfb.getViewer().getRfbBroadcastListener().multicastUpdateRectangle(buf); 299 rfb.getViewer().getRfbBroadcastListener().multicastUpdateRectangle(buf);
288 } else { 300 } else if (rfb.multicastBlocking) {
289 rfb.multicastqueue.put(bufs); 301 rfb.multicastqueue.put(bufs); // debug purpose
290 } 302 }
291 } 303 }
292 } 304 }
293 305
294 @Override 306 @Override
302 } 314 }
303 315
304 316
305 public void multicastDecode(Reader reader, Renderer renderer, 317 public void multicastDecode(Reader reader, Renderer renderer,
306 FramebufferUpdateRectangle rect, TreeRFBProto rfb) throws TransportException { 318 FramebufferUpdateRectangle rect, TreeRFBProto rfb) throws TransportException {
307 ByteBuffer header = ByteBuffer.allocate(16); 319 ByteBuffer header = ByteBuffer.allocate(16); // FBU header
308 reader.read(header.array()); 320 reader.read(header.array());
309 int zippedLength = (int) reader.readUInt32(); 321 int zippedLength = (int) reader.readUInt32();
310 if (0 == zippedLength) return; 322 if (0 == zippedLength) return;
311 int length = rect.width * rect.height * renderer.getBytesPerPixel(); 323 int length = rect.width * rect.height * renderer.getBytesPerPixel();
312 ByteBuffer buf = unzip(reader, zippedLength, length, rect.getEncodingType()); 324 ByteBuffer buf = unzip(reader, zippedLength, length, rect.getEncodingType());
318 public void decode1(Renderer renderer, ByteBuffer header, FramebufferUpdateRectangle rect, ByteBuffer buf, int zippedLength, TreeRFBProto rfbProto) throws TransportException { 330 public void decode1(Renderer renderer, ByteBuffer header, FramebufferUpdateRectangle rect, ByteBuffer buf, int zippedLength, TreeRFBProto rfbProto) throws TransportException {
319 int offset = zippedLength; 331 int offset = zippedLength;
320 int maxX = rect.x + rect.width; 332 int maxX = rect.x + rect.width;
321 int maxY = rect.y + rect.height; 333 int maxY = rect.y + rect.height;
322 byte[] bytes = buf.array(); 334 byte[] bytes = buf.array();
323 boolean WifiMulticast = rfbProto !=null && (rfbProto.multicastBlocking || rfbProto.getViewer().getUseMulticast()); 335 WifiMulticast = rfbProto !=null && (rfbProto.multicastBlocking ||(rfbProto.isTreeManager()&&rfbProto.getViewer().getUseMulticast()));
324 336
325 TileLoop tileloop = new TileLoop(rfbProto, zippedLength); 337 TileLoop tileloop = new TileLoop(rfbProto, zippedLength);
326 //System.out.println("decode1: "+rect.toString()); 338 //System.out.println("decode1: "+rect.toString());
327 if (null == palette) { 339 if (null == palette) {
328 palette = new int[128]; 340 palette = new int[128];