Mercurial > hg > Applications > TreeVNC
changeset 582:f01eef88010f
new blocking scheme
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 08 Feb 2020 10:34:46 +0900 |
parents | aef7d24b430d |
children | 2fe1be5476a6 ef5033b06019 |
files | src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java |
diffstat | 2 files changed, 68 insertions(+), 46 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java Sat Feb 08 06:24:26 2020 +0900 +++ b/src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java Sat Feb 08 10:34:46 2020 +0900 @@ -27,9 +27,12 @@ import com.glavsoft.drawing.Renderer; import com.glavsoft.exceptions.TransportException; import com.glavsoft.rfb.encoding.EncodingType; +import com.glavsoft.rfb.protocol.ReceiverTask; import com.glavsoft.transport.Reader; import jp.ac.u_ryukyu.treevnc.CheckDelay; import jp.ac.u_ryukyu.treevnc.TreeRFBProto; + +import java.awt.*; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.util.LinkedList; @@ -46,7 +49,7 @@ final int deflate_size = 60000-MARGIN; private ByteBuffer c1; private int width; // phase2 length - private FramebufferUpdateRectangle c1rect; + private FramebufferUpdateRectangle c0rect,c1rect,rect; private int prevLineOffset; private int prevC1Offset; private int prevC1LineOffset; @@ -88,8 +91,10 @@ private void zrleeBlocking(TreeRFBProto rfb, ByteBuffer header, FramebufferUpdateRectangle rect, byte bytes[]) { // dump32(inputs); deflater = rfb.deflater; + this.rect = rect; + c0rect = null; c1rect = new FramebufferUpdateRectangle(rect.x, rect.y, 0, 0); - newMulticastPacket(rfb, rect); + newMulticastPacket(rfb); //c1.put(header.get(0)); if (!blocking) { deflater.setInput(bytes, 0,(int) prevoffset); @@ -99,7 +104,7 @@ return; } - private void newMulticastPacket(TreeRFBProto rfb, FramebufferUpdateRectangle rect) { + private void newMulticastPacket(TreeRFBProto rfb) { c1 = rfb.multicastqueue.allocate(deflate_size + MARGIN); c1.limit(deflate_size); if (rfb.addSerialNum) @@ -113,15 +118,15 @@ c1.putInt(0); // should be data length prevC1Offset = c1.position(); prevC1LineOffset = prevC1Offset; - width = 0; c1rect.width = c1rect.height = 0; + c0rect = null; } int spanGap = 128; /** * Series of tiles compose at most three rectangles. SYNC_FLUSH is necessary on * rectangle boundaries. - * <p> + * * +----+ * | | phase 0 * +---------------+ @@ -129,73 +134,97 @@ * +----+----------+ * | | phase 2 * +----+ - * <p> - * Broadcast packet have to less than 64kbytes - * 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. - * <p> - * 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. + * + * Broadcast packet have to be less than 64kbytes + * A tile 64x64x4 166384byte + * + * we cannot rewind zlib stream, zlib stream have to be flushed at the end of rectangles + * if we leave 16kbytes space margin, zlib stream can be flushed safely + * + * keep completed previous rectangle in c0rect, which is possibly none. + * at the last or packet full, flush c0rect first, then flush c1rect if it exists * * @param rfb * @param last - * @param rect * @param bytes * @param offset * @param tileW * @param tileH */ - public void multicastPut(TreeRFBProto rfb, boolean last, FramebufferUpdateRectangle rect, byte[] bytes, int offset, int tileW, int tileH) { + public void multicastPut(TreeRFBProto rfb, boolean last, byte[] bytes, int offset, int tileW, int tileH) { if (!blocking) return; int span = offset - prevoffset; deflater.setInput(bytes, prevoffset, span); do { deflater.deflate(c1, Deflater. SYNC_FLUSH); if (!deflater.needsInput()) { - // compression failed + // packet full flushDeflator(); prevoffset = flushOffset+(int)deflater.getBytesRead(); assert(prevoffset==offset); System.out.println("od prevOffset = "+prevoffset+" span = "+(prevoffset-flushOffset)); - flushRectangle(rect); + if (c0rect!=null) { flushRectangle(c0rect); moveNext(); } // finish pahse 1 + flushRectangle(c1rect); // phase 2 flushMuticast(rfb, bytes); if (last) { return; } else { - newMulticastPacket(rfb, rect); + newMulticastPacket(rfb); + if (width<rect.width) { // phase 0 + c1rect.x = rect.x + width; + } else { + c1rect.x = 0; // phase 1 + c1rect.y += tileH; + } + return; } } } while (! deflater.needsInput()); prevoffset = offset; if (last) { flushDeflator(); - flushRectangle(rect); + if (c0rect!=null) { flushRectangle(c0rect); moveNext(); } + flushRectangle(c1rect); flushMuticast(rfb, bytes); + return; } width += tileW; + if (c1rect.height==0) c1rect.height = tileH; if (c1rect.x > rect.x) { // phase 0 + assert(c0rect==null); if (c1rect.x + c1rect.width < rect.x + rect.width) { + c1rect.x += tileW; } else { // end of phase 0 - c1rect.width = rect.x + rect.width - c1rect.x; - prevC1LineOffset = c1.position(); + flushRectangle(c1rect); + c1.position((c1.position()+16)); // make next header space + c1rect = new FramebufferUpdateRectangle(rect.x,c1rect.y+tileH,0,0); } } else { // phase 1 if (width >= rect.width) { // next line + deflater.deflate(c1,Deflater.FULL_FLUSH); + prevC1LineOffset = c1.position(); c1rect.width = rect.width; + if (c0rect!=null) { // extend phase 1 + c0rect.height += tileH; + c1rect = new FramebufferUpdateRectangle(rect.x, c0rect.y+c0rect.height,0,0); + } else { // first phase 1 case + c1rect.height = tileH; + c0rect = c1rect; + c1rect = new FramebufferUpdateRectangle(rect.x, c1rect.y+c1rect.height,0,0); + } width = 0; prevLineOffset = offset; - prevC1LineOffset = c1.position(); } } } + public void moveNext() { + // previous rectangle is finished, make next header space and copy already compressed part + c1.limit(c1.limit()+16); + System.arraycopy(c1.array(),prevC1LineOffset,16,prevC1LineOffset+16,c1.position()-prevC1LineOffset); + } + private void flushDeflator() { c1.limit(c1.limit() + MARGIN); deflater.deflate(c1, Deflater.FULL_FLUSH); @@ -204,6 +233,10 @@ } } + private void bufdump(byte[] bytes,int beigin, int end) { + ReceiverTask.dump("in ",bytes,beigin,8); ReceiverTask.dump("... ",bytes,end,8); + System.out.println(); + } /** * fix rectangle header @@ -212,25 +245,14 @@ * send muticast pacate if nessesally */ private void flushRectangle(FramebufferUpdateRectangle rect) { - c1.putShort(prevC1Offset - 16, (short) c1rect.x); - c1.putShort(prevC1Offset - 14, (short) c1rect.y); - c1.putShort(prevC1Offset - 12, (short) c1rect.width); - c1.putShort(prevC1Offset - 10, (short) c1rect.height); + c1.putShort(prevC1Offset - 16, (short) rect.x); + c1.putShort(prevC1Offset - 14, (short) rect.y); + c1.putShort(prevC1Offset - 12, (short) rect.width); + c1.putShort(prevC1Offset - 10, (short) rect.height); c1.putInt(prevC1Offset - 8, EncodingType.ZRLEE.getId()); c1.putInt(prevC1Offset - 4, c1.position() - prevC1Offset - 12); // data length c1.putShort(2, (short) (c1.getShort(2) + 1)); // increment rectangle count prevC1Offset = c1.position(); - nextPhase(rect); - } - - private void nextPhase(FramebufferUpdateRectangle rect) { - if (c1rect.x + c1rect.width < rect.x + rect.width) { - c1rect.x = c1rect.width; // next rectangle is phase 1 - } else { - c1rect.x = rect.x; - c1rect.y += c1rect.height; - } - width = 0; } private void flushMuticast(TreeRFBProto rfb, byte[] bytes) { @@ -324,15 +346,15 @@ } } if (rfbProto != null && rfbProto.multicastBlocking) - tileloop.multicastPut(rfbProto, false, rect, bytes, offset, tileWidth, tileHeight); + tileloop.multicastPut(rfbProto, false, bytes, offset, tileWidth, tileHeight); } } if (rfbProto != null && rfbProto.multicastBlocking) - tileloop.multicastPut(rfbProto, true, rect, bytes, offset, 0, 0); + tileloop.multicastPut(rfbProto, true, bytes, offset, 0, 0); } catch (Exception e) { e.printStackTrace(); if (rfbProto != null && rfbProto.multicastBlocking) - tileloop.multicastPut(rfbProto, true, rect, bytes, offset, 0, 0); + tileloop.multicastPut(rfbProto, true, bytes, offset, 0, 0); throw e; } }
--- a/src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java Sat Feb 08 06:24:26 2020 +0900 +++ b/src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java Sat Feb 08 10:34:46 2020 +0900 @@ -422,7 +422,7 @@ System.out.println(); } - private void dump(String s, byte[] bytes, int begin, int len) { + public static void dump(String s, byte[] bytes, int begin, int len) { System.out.print(s); while(len > 0 && begin < bytes.length) { System.out.print(bytes[begin] + " ");