# HG changeset patch # User Shinji KONO # Date 1557292114 -32400 # Node ID 17a2d0ea5c035d89cff4fb5a867e1421d89345b7 # Parent a3d0ba67e8cf4d1e34782d3c0b7486c29987f772 fix on ZRLEDecoder diff -r a3d0ba67e8cf -r 17a2d0ea5c03 src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java --- a/src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java Mon May 06 16:59:25 2019 +0900 +++ b/src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java Wed May 08 14:08:34 2019 +0900 @@ -42,6 +42,8 @@ private int[] palette; class TileLoop { + private final boolean blocking; + private final int half; private int deflate_size = 65507; private ByteBuffer c1; private int width; // phase2 length @@ -57,6 +59,7 @@ private int hc1width; private int hoffset; private int hc1offset; + private int discard; /** * Multicast framebufferUpdate to children. @@ -81,14 +84,25 @@ public TileLoop(int offset) { prevoffset = prevLineOffset = prevC1Offset = offset; + if (offset < deflate_size+spanGap) { + // packet size fit in broadcast send it all at once + blocking = false; + } else + blocking = true; + discard = 0; half = 0; } - private void zrleeBlocking(TreeRFBProto rfb, ByteBuffer header, FramebufferUpdateRectangle rect) { + private void zrleeBlocking(TreeRFBProto rfb, ByteBuffer header, FramebufferUpdateRectangle rect, byte bytes[]) { // dump32(inputs); deflater = rfb.deflater; newMulticastPacket(rfb, rect); c1.put(header.get(0)); c1rect = new FramebufferUpdateRectangle(rect.x, rect.y, 0, 0); + if (!blocking) { + deflater.setInput(bytes,0,prevoffset); + deflater.deflate(c1); + flushMuticast(rfb); + } return; } @@ -124,14 +138,17 @@ * +----+ * * Broadcast packet have to less than 64kbytes - * A tile 8x8x3 192byte, a packet can contain 340 raw tiles, when these are - * compressed 500 to 2000 tiles can be stored. It is impossible to predict the + * A tile 64x64x3 11288byte, a packet can contain 5 raw tiles, when these are + * compressed 10 to 100 tiles can be stored. It is impossible to predict the * compression rate. To check the compressed capacity, Deflate.needsInputs() can * be used. If needsInputs() is false on SYNC_FLUSH, smaller input is necessary. * - * We'll try 512 tiles before SYNC_FLUSH in a phase, if it fails try 256. - * If it will failed again, flush the previous line and try again. - * If 256 tiles are failed in new packet, discard it. + * We'll try 512 tiles before SYNC_FLUSH in a phase, if it fails try flush former 256 tiles. + * If it will failed again, flush the previous line and do flush 512 tiles in new Packet. + * If it failed again try former 256 tiles flushed, if this failes again dicard the former half. + * The last case cannot happen but former 256 tiles have to be flushed, because the next 256 lines + * may failed again and restart the from this point. + * The next packet start with later 256 tiles filled and unflushed. * * @param rfb * @param last @@ -145,6 +162,7 @@ int MAX_ZTILE = 512; public void multicastPut(TreeRFBProto rfb, boolean last, FramebufferUpdateRectangle rect, byte[] bytes, int offset, int tileW, int tileH) { + if (!blocking) return; int span = offset - prevoffset; deflater.setInput(bytes,prevoffset,span); prevoffset = offset; @@ -183,7 +201,8 @@ } private void compressAndCheckFlush(TreeRFBProto rfb, FramebufferUpdateRectangle rect, byte[] bytes, int offset, boolean flush, boolean last) { - if (!flush && ztileInLine++ < MAX_ZTILE) { + ztileInLine++; + if (!flush && ztileInLine < MAX_ZTILE) { if (ztileInLine == MAX_ZTILE/2) { hwidth = width; hc1width = c1rect.width; hoffset = offset; hc1offset = c1.position(); } @@ -220,6 +239,7 @@ deflater.setInput(bytes, from, len); deflater.deflate(c1, Deflater.SYNC_FLUSH); if (!deflater.needsInput()) { /* fatal error discard this line */ + discard++; if (!last) { newMulticastPacket(rfb, rect); nextRectangle(rect); @@ -337,7 +357,7 @@ } if (rfbProto.multicastBlocking) { - tileloop.zrleeBlocking(rfbProto, header, rect); + tileloop.zrleeBlocking(rfbProto, header, rect,bytes); } for (int tileY = rect.y; tileY < maxY; tileY += MAX_TILE_SIZE) { int tileHeight = Math.min(maxY - tileY, MAX_TILE_SIZE);