changeset 535:17a2d0ea5c03

fix on ZRLEDecoder
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Wed, 08 May 2019 14:08:34 +0900
parents a3d0ba67e8cf
children 623e409c976a
files src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java
diffstat 1 files changed, 28 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- 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);