changeset 526:fcd833c2e148

Multicast Bloking in ZRLEDecoder
author riono210
date Thu, 02 May 2019 16:18:44 +0900
parents fea7651ca24f
children 96e15614a31f
files src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEESender.java src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java src/main/java/jp/ac/u_ryukyu/treevnc/TreeRFBProto.java
diffstat 4 files changed, 99 insertions(+), 104 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java	Tue Mar 05 19:33:33 2019 +0900
+++ b/src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java	Thu May 02 16:18:44 2019 +0900
@@ -26,26 +26,39 @@
 
 import com.glavsoft.drawing.Renderer;
 import com.glavsoft.exceptions.TransportException;
+import com.glavsoft.rfb.encoding.EncodingType;
 import com.glavsoft.transport.Reader;
+import jp.ac.u_ryukyu.treevnc.CheckDelay;
 import jp.ac.u_ryukyu.treevnc.TreeRFBProto;
 
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.util.zip.DataFormatException;
+import java.util.zip.Deflater;
+
 public class ZRLEDecoder extends ZlibDecoder {
 	private static final int MAX_TILE_SIZE = 64;
     private int[] decodedBitmap;
     private int[] palette;
 
-    @Override
+	private int deflate_size = 65507;
+	private ByteBuffer c1;
+	private FramebufferUpdateRectangle c1rect;
+	private int c1headerPos;
+
+	@Override
 	public void decode(Reader reader, Renderer renderer,
                        FramebufferUpdateRectangle rect) throws TransportException {
 		int zippedLength = (int) reader.readUInt32();
 		if (0 == zippedLength) return;
 		int length = rect.width * rect.height * renderer.getBytesPerPixel();
 		byte[] bytes = unzip(reader, zippedLength, length, rect.getEncodingType());
-		decode1(renderer, rect, bytes, zippedLength, null);
+		decode1(renderer, null, rect, bytes, zippedLength, null);
     }
     
-	public void decode1(Renderer renderer,
-						FramebufferUpdateRectangle rect, byte[] bytes, int zippedLength, TreeRFBProto rfbProto) throws TransportException {
+	public void decode1(Renderer renderer, ByteBuffer header, FramebufferUpdateRectangle rect, byte[] bytes, int zippedLength, TreeRFBProto rfbProto) throws TransportException {
 		int offset = zippedLength;
 		int maxX = rect.x + rect.width;
 		int maxY = rect.y + rect.height;
@@ -57,6 +70,14 @@
         if (null == decodedBitmap) {
             decodedBitmap = new int[MAX_TILE_SIZE * MAX_TILE_SIZE];
         }
+
+		if (rfbProto.multicastBlocking)  {
+			try {
+				zrleeBlocking(rfbProto, header, bytes, rect);
+			} catch (DataFormatException e) {
+				e.printStackTrace();
+			}
+		}
 		for (int tileY = rect.y; tileY < maxY; tileY += MAX_TILE_SIZE) {
 			int tileHeight = Math.min(maxY - tileY, MAX_TILE_SIZE);
 
@@ -86,7 +107,7 @@
 						offset += decodePacked(bytes, offset, renderer, paletteSize, tileX, tileY, tileWidth, tileHeight);
 					}
 				}
-				if (rfbProto != null && rfbProto.multicastBlocking) rfbProto.multicastPut(rect, bytes, prevoffset, offset, tileWidth, tileHeight);
+				if (rfbProto != null && rfbProto.multicastBlocking) multicastPut(rfbProto, rect, bytes, prevoffset, offset, tileX, tileY,tileWidth, tileHeight);
 				prevoffset = offset;
 			}
 		}
@@ -175,4 +196,62 @@
 		return paletteSize * bytesPerCPixel;
 	}
 
+
+	/**
+	 * Multicast framebufferUpdate to children.
+	 * read FrameBuffferUpdate. If it is ZLE, make it ZLEE which is self contained compressed packet.
+	 * put the packet to the multicastqueue. Then normal rendering engine read the same stream using is.reset().
+	 *
+	 * @throws TransportException
+	 * @throws UnsupportedEncodingException
+	 */
+
+
+	private void zrleeBlocking(TreeRFBProto rfb, ByteBuffer header, byte[] bytes, FramebufferUpdateRectangle rect) throws TransportException, DataFormatException {
+		// dump32(inputs);
+		c1 = rfb.multicastqueue.allocate(deflate_size);
+		if (rfb.addSerialNum)
+			c1.putLong(rfb.counter++);
+		if (rfb.checkDelay)
+			CheckDelay.checkDelay(c1, rect.x, rect.y, rect.width, rect.height, System.currentTimeMillis(), EncodingType.CHECK_DELAY);
+		c1headerPos = c1.position();
+		c1.put(header);
+		header.flip();
+		c1.putInt(0);
+		c1rect = new FramebufferUpdateRectangle(rect.x, rect.y, 0, 0);
+		return;
+	}
+
+	public void multicastPut(TreeRFBProto rfb, ByteBuffer header, FramebufferUpdateRectangle rect, byte[] bytes, int prevoffset, int offset, int tileX, int tileY, int tileW, int tileH) {
+		int span = offset - prevoffset;
+		rfb.deflater.setInput(bytes,prevoffset,span);
+		c1rect.height = tileH;
+		if (c1.remaining() < span || c1rect.x + c1rect.width + tileW >= rect.x + rect.width ) {
+			rfb.deflater.deflate(c1, Deflater.FULL_FLUSH);
+			rfb.deflater.finish();
+			c1.flip();
+			//System.out.println("multicastPut: " + c1rect + " length: " + (c1.remaining()-c1headerPos-header.limit()));
+			try {
+				rfb.writeUpdateRectangleWithHeader(c1, c1headerPos, c1.remaining()-c1headerPos-header.limit()-4, c1rect.x, c1rect.y, c1rect.width + tileW, c1rect.height + tileY);
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			}
+			c1rect.x += c1rect.width;
+			if (c1rect.x >= rect.x + rect.width) {
+				c1rect.x = rect.x;
+				c1rect.y += tileH;
+			}
+			c1rect.width = 0;
+			c1 = rfb.multicastqueue.allocate(deflate_size);
+			if (rfb.addSerialNum)
+				c1.putLong(rfb.counter++);
+			c1headerPos = c1.position();
+			c1.put(header);
+			header.flip();
+			c1.putInt(0);
+		} else {
+			rfb.deflater.deflate(c1, Deflater.SYNC_FLUSH);
+		}
+		c1rect.width += tileW;
+	}
 }
--- a/src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEESender.java	Tue Mar 05 19:33:33 2019 +0900
+++ b/src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEESender.java	Thu May 02 16:18:44 2019 +0900
@@ -1,6 +1,7 @@
 package com.glavsoft.rfb.encoding.decoder;
 
 import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
 
 import jp.ac.u_ryukyu.treevnc.TreeRFBProto;
 
@@ -33,8 +34,8 @@
                 // ReadSendData convert ZRLE to ZRLEE
                 // unzipped data in the bytes
                 byte[] bytes = new byte[rect.width * rect.height * renderer.getBytesPerPixel()];
-                rfb.readSendData(dataLen, reader, bytes, rect);
-                decoder.decode1(renderer, rect, bytes, 0, rfb);
+                ByteBuffer header = rfb.readSendData(dataLen, reader, bytes, rect);
+                decoder.decode1(renderer, header, rect, bytes, 0, rfb);
                 return;
             } else {
                 // no reencoding is required
--- a/src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java	Tue Mar 05 19:33:33 2019 +0900
+++ b/src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java	Thu May 02 16:18:44 2019 +0900
@@ -258,6 +258,7 @@
                 logger.finest(rect.toString() + (0 == numberOfRectangles ? "\n---" : ""));
                 if (decoder != null) {
                     try {
+                        System.out.println(rect);
                         decoder.decode(reader, renderer, rect);  // TreeVNC processing here
                         if (rfb.getCuiVersion()) continue;
                         repaintController.repaintBitmap(rect);
--- a/src/main/java/jp/ac/u_ryukyu/treevnc/TreeRFBProto.java	Tue Mar 05 19:33:33 2019 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/treevnc/TreeRFBProto.java	Thu May 02 16:18:44 2019 +0900
@@ -38,11 +38,11 @@
     public FindRoot findRoot;
     public int acceptPort = 0;
     private String myAddress;
-    private long counter = 0; // packet serial number
+    public long counter = 0; // packet serial number
     public ServerSocket servSock;
     private static final int INFLATE_BUFSIZE = 1024 * 100;
-    private Inflater inflater = new Inflater();
-    private Deflater deflater = new Deflater();
+    public  Inflater inflater = new Inflater();
+    public  Deflater deflater = new Deflater();
     ViewerInterface viewer;
     private short id = 0;  // my tree node id ( = 0 in root ), -1 means no parent
     private short sharingId = -1; // VNCServer's id. this is used control visivility
@@ -74,11 +74,7 @@
     private byte[] originalInitData = null;
     private boolean childrenMulticast = true;
     private static int uniqueNodeId = 0; // uniquenodeid in all trees (less than MAX_UNIQUE_NODE_ID)
-    private int deflate_size = 65507;
-    private ByteBuffer header;
-    private ByteBuffer c1;
-    private FramebufferUpdateRectangle c1rect;
-    private int c1headerPos;
+
     private boolean stopBroadcast;
     public boolean multicastBlocking = true;
 
@@ -639,7 +635,7 @@
      * @param reader
      * @throws TransportException
      */
-    public void readSendData(int dataLen, Reader reader, byte[] bytes, FramebufferUpdateRectangle rect)
+    public ByteBuffer readSendData(int dataLen, Reader reader, byte[] bytes, FramebufferUpdateRectangle rect)
             throws TransportException {
         LinkedList<ByteBuffer> bufs = new LinkedList<ByteBuffer>();
         int headerLen = rect.getEncodingType() == EncodingType.CHECK_DELAY ? 24 : 16;
@@ -657,14 +653,8 @@
 
             if (encoding == EncodingType.ZRLE.getId()
                     || encoding == EncodingType.ZLIB.getId()) {
-                if (multicastBlocking)  {
-                    try {
-                        zrleeBlocking(dataLen, reader, bytes, rect, context.getPixelFormat().bitsPerPixel/8, bufs, header);
-                    } catch (DataFormatException e) {
-                        e.printStackTrace();
-                    }
-                    return;
-                }
+
+                if (multicastBlocking) return header;
                 // recompress into ZREE
                 // uncompressed result is remain in bytes
                 ByteBuffer len = multicastqueue.allocate(4);
@@ -705,7 +695,7 @@
                 } catch (DataFormatException e) {
                     throw new TransportException(e);
                 }
-                return;
+                return header;
             }
 
             //    ZRLEE is already compressed
@@ -721,7 +711,7 @@
             }
             multicastqueue.put(bufs);
 
-            return;
+            return header;
         }
         // It may be compressed. We can inflate here to avoid repeating clients
         // decompressing here,
@@ -729,86 +719,10 @@
         // each client.
         // But we have do inflation for all input data, so we have to do it
         // here.
+        return header;
     }
 
-    /**
-     * Multicast framebufferUpdate to children.
-     * read FrameBuffferUpdate. If it is ZLE, make it ZLEE which is self contained compressed packet.
-     * put the packet to the multicastqueue. Then normal rendering engine read the same stream using is.reset().
-     *
-     * @param dataLen
-     * @param reader
-     * @throws TransportException
-     * @throws UnsupportedEncodingException
-     */
-
 
-    private void zrleeBlocking(int dataLen, Reader reader, byte[] bytes, FramebufferUpdateRectangle rect, int bytePerPixel, LinkedList<ByteBuffer> bufs, ByteBuffer header) throws TransportException, DataFormatException {
-        ByteBuffer len = multicastqueue.allocate(4);
-        reader.readBytes(len.array(), 0, 4);
-        len.limit(4);
-        ByteBuffer inputData = multicastqueue.allocate(dataLen - 20);
-        reader.readBytes(inputData.array(), 0, inputData.capacity());
-        inputData.limit(dataLen - 20);
-        LinkedList<ByteBuffer> inputs = new LinkedList<ByteBuffer>();
-        inputs.add(inputData);
-        header.putInt(12, EncodingType.ZRLEE.getId()); // means
-        // recompress
-        // every time
-        // using new Deflecter every time is incompatible with the
-        // protocol, clients have to be modified.
-        Deflater nDeflater = deflater; // new Deflater();
-        LinkedList<ByteBuffer> out = new LinkedList<ByteBuffer>();
-        int inflate_size = rect.width * rect.height * bytePerPixel;
-
-        unzip(inflater, inputs, 0, bytes, inflate_size);
-        this.header = header;
-        // dump32(inputs);
-        c1 = multicastqueue.allocate(deflate_size);
-        if (addSerialNum)
-            c1.putLong(counter++);
-        if (checkDelay)
-            CheckDelay.checkDelay(c1, rect.x, rect.y, rect.width, rect.height, System.currentTimeMillis(), EncodingType.CHECK_DELAY);
-        c1headerPos = c1.position();
-        c1.put(header);
-        header.flip();
-        c1.putInt(0);
-        c1rect = new FramebufferUpdateRectangle(rect.x, rect.y, 0, 0);
-        return;
-    }
-
-    public void multicastPut(FramebufferUpdateRectangle rect, byte[] bytes, int prevoffset, int offset, int tilex, int tiley) {
-        int span = offset - prevoffset;
-        deflater.setInput(bytes,prevoffset,span);
-        c1rect.height = tiley;
-        if (c1.remaining() < span || c1rect.x + c1rect.width + tilex >= rect.x + rect.width ) {
-            deflater.deflate(c1, Deflater.FULL_FLUSH);
-            deflater.finish();
-            c1.flip();
-            //System.out.println("multicastPut: " + c1rect + " length: " + (c1.remaining()-c1headerPos-header.limit()));
-            try {
-                writeUpdateRectangleWithHeader(c1, c1headerPos, c1.remaining()-c1headerPos-header.limit()-4, c1rect.x, c1rect.y, c1rect.width, c1rect.height);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
-            c1rect.x += c1rect.width;
-            if (c1rect.x >= rect.x + rect.width) {
-                c1rect.x = rect.x;
-                c1rect.y += tiley;
-            }
-            c1rect.width = 0;
-            c1 = multicastqueue.allocate(deflate_size);
-            if (addSerialNum)
-                c1.putLong(counter++);
-            c1headerPos = c1.position();
-            c1.put(header);
-            header.flip();
-            c1.putInt(0);
-        } else {
-            deflater.deflate(c1, Deflater.SYNC_FLUSH);
-        }
-        c1rect.width += tilex;
-    }
 
     /**
      * make and send frameBufferUpdateRectangle packet
@@ -833,7 +747,7 @@
      * 16  [int32]   datalen if zcompressed
      * 20  compressedData
      */
-    private void writeUpdateRectangleWithHeader(ByteBuffer c1, int headerPos, int len2, int x, int y, int w, int h) throws InterruptedException {
+    public void writeUpdateRectangleWithHeader(ByteBuffer c1, int headerPos, int len2, int x, int y, int w, int h) throws InterruptedException {
         deflater.reset();
 
         c1.putInt(headerPos + 16, len2);