# HG changeset patch # User e165729 # Date 1568102596 -32400 # Node ID b86d445685c71366808c8a9d1840f0019f502c33 # Parent 0d11471e0b5b118a0b6f38de88eba8fd178a8f6a fix latest ZRLEDecoder diff -r 0d11471e0b5b -r b86d445685c7 .hgignore --- a/.hgignore Thu Sep 05 19:05:02 2019 +0900 +++ b/.hgignore Tue Sep 10 17:03:16 2019 +0900 @@ -3,3 +3,4 @@ .gradle regexp .*.orig +.idea \ No newline at end of file diff -r 0d11471e0b5b -r b86d445685c7 src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java --- a/src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java Thu Sep 05 19:05:02 2019 +0900 +++ b/src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java Tue Sep 10 17:03:16 2019 +0900 @@ -41,10 +41,11 @@ private int[] decodedBitmap; private int[] palette; + // TileLoopクラス 複数の関数持ち class TileLoop { private final boolean blocking; private final int half; - private int deflate_size = 55507; // 圧縮サイズ + private int deflate_size = 65507; // 圧縮サイズ private ByteBuffer c1; // パケット? private int width; // phase2 length private FramebufferUpdateRectangle c1rect; @@ -101,10 +102,10 @@ // ?: ブロッキングしたものをc1に渡している? private void zrleeBlocking(TreeRFBProto rfb, ByteBuffer header, FramebufferUpdateRectangle rect, byte bytes[]) { // dump32(inputs); - deflater = rfb.deflater; + deflater = rfb.deflater; // TreeRFBProtでoverrideしたdeflater(圧縮クラス)を使用 newMulticastPacket(rfb, rect); - c1.put(header.get(0)); - c1rect = new FramebufferUpdateRectangle(rect.x, rect.y, 0, 0); + c1.put(header.get(0)); // headerの0番目をc1に入れる + c1rect = new FramebufferUpdateRectangle(rect.x, rect.y, 0, 0); // rectangleのインスタンス生成 if (!blocking) { deflater.setInput(bytes,0,prevoffset); // bytesを圧縮データとして0からprevoffsetまでをdeflater内部にセットする deflater.deflate(c1); // setInputで入力したデータを圧縮してc1に入れる @@ -113,14 +114,15 @@ return; } - // ?: c1の値を設定している実部分? c1(=パケット)にheaderを設定してるっぽい? 要: TreeRFBProto読み + // ?: c1を初期化? 要: TreeRFBProto読み private void newMulticastPacket(TreeRFBProto rfb, FramebufferUpdateRectangle rect) { - c1 = rfb.multicastqueue.allocate(deflate_size); // ByteBufferのallocateと同等 - if (rfb.addSerialNum) + c1 = rfb.multicastqueue.allocate(deflate_size); // ByteBufferのallocateと同等 容量確保 + if (rfb.addSerialNum) // 有効時 c1.putLong(rfb.counter++); // 現在のByteBufferにlongの値を書き込み - if (rfb.checkDelay) + if (rfb.checkDelay) // 有効時 CheckDelay.checkDelay(c1, rect.x, rect.y, rect.width, rect.height, System.currentTimeMillis(), EncodingType.CHECK_DELAY); - c1headerPos = c1.position(); + c1headerPos = c1.position(); // c1の今の読み込み位置がどこにあるかを記憶 headerの位置 + // c1の初期化 c1.put((byte) 0); c1.put((byte) 0); c1.putShort((short) 0); @@ -191,11 +193,11 @@ // フェーズ分けして、ブロッキングを行なっている部分 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; - c1rect.width += tileW; width += tileW; - if (c1rect.x > rect.x) { // phase 0 + int span = offset - prevoffset; // 一つ前のオフセットと現在のオフセットの差を出す + deflater.setInput(bytes,prevoffset,span); // prevoffsetからspanまでに圧縮データを入れる + prevoffset = offset; // prevoffsetの更新 + c1rect.width += tileW; width += tileW; // prevoffsetが更新されたのでwidthもタイル一つ分更新? + if (c1rect.x > rect.x) { // phase 0 引数の場所よりも容量が大きい場合 = 行の途中から始まって行の最後までの間 if (c1rect.x+c1rect.width < rect.x+rect.width) { compressAndCheckFlush(rfb, rect, bytes, offset,false, last); } else { @@ -203,7 +205,7 @@ c1rect.height += tileH; compressAndCheckFlush(rfb,rect,bytes,offset,true, last); } - } else if (!last && c1.remaining() > spanGap) { // phase 1 + } else { // phase 1 if (width >= rect.width) { c1rect.width = rect.width; width = 0; @@ -214,83 +216,36 @@ } else { compressAndCheckFlush(rfb,rect,bytes,offset,false, last); } - } else { // phase2 - // rewind to the last line finish phase 1 - int savew = width; - c1.position(prevC1Offset); - flushRectangle(rect); - if (savew>0) { - // recompress overrun and flush phase 2 - c1rect.width = savew; - c1rect.height = tileH; - compressAndCheckFlush(rfb,rect,bytes,offset,true, last); - } } } + + // 圧縮とパケットへの書き込み private void compressAndCheckFlush(TreeRFBProto rfb, FramebufferUpdateRectangle rect, byte[] bytes, int offset, boolean flush, boolean last) { ztileInLine++; - if (!flush && ztileInLine < MAX_ZTILE) { - if (ztileInLine == MAX_ZTILE/2) { - hwidth = width; hc1width = c1rect.width; hoffset = offset; hc1offset = c1.position(); + deflater.deflate(c1, Deflater.NO_FLUSH); + int headerLength = 20; + if (!deflater.needsInput()) { + deflater.finish(); + if (offset != prevLineOffset) { // phase 2 + c1.limit(c1.limit() + headerLength); + // to make rectangle header shift last bytes + for (int i = 0; i < c1.position() - prevC1Offset; i++) { + c1.array()[prevC1Offset + headerLength - i] = c1.array()[prevC1Offset - i]; + } + c1.putShort(prevC1Offset + 1, (short) c1rect.x); + c1.putShort(rectPos + 3, (short) c1rect.y); + c1.putShort(rectPos + 5, (short) c1rect.width); + c1.putShort(rectPos + 7, (short) c1rect.height); + c1.putInt(rectPos + 9, EncodingType.ZRLEE.getId()); + c1.putInt(rectPos + 13, c1.position() - rectPos - 12); // data length + c1.putShort(2, (short) (c1.getShort(2) + 1)); // increment rectangle count } + flushMuticast(rfb); + newMulticastPacket(rfb, rect); deflater.deflate(c1, Deflater.NO_FLUSH); - } else { - deflater.deflate(c1, Deflater.SYNC_FLUSH); - if (!deflater.needsInput()) { - // too large, try half line - width = hwidth; - c1rect.width = hc1width; - c1.position(hc1offset); - deflater.setInput(bytes, prevLineOffset, hoffset - prevC1Offset); - deflater.deflate(c1, Deflater.SYNC_FLUSH); - int from, len; - if (!deflater.needsInput()) { - // flush previous line and start new packet - c1.position(prevC1Offset); - unputrectangle(); - flushMuticast(rfb); - newMulticastPacket(rfb, rect); - nextRectangle(rect); - // we already reached MIX_ZTILE do half of them, do compress right now - from = prevC1Offset; - len = offset - prevLineOffset; - deflater.setInput(bytes, from, len); - deflater.deflate(c1, Deflater.SYNC_FLUSH); - if (deflater.needsInput()) { - flushRectangle(rect); // we are the flushed last line - return; - } - // half size should always succeed - from = prevC1Offset; - len = hoffset - prevLineOffset; - 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); - } - return; - } else - flushRectangle(rect); // normal case - // later half is remain continue - } else { - flushMuticast(rfb); - newMulticastPacket(rfb,rect); - nextRectangle(rect); - } - // do later half in new Packet - from = hoffset ; len = offset - hoffset; - deflater.setInput(bytes, from, len); - deflater.deflate(c1, Deflater.NO_FLUSH); - hwidth = width; - hoffset = offset; - hc1offset = c1.position(); - ztileInLine = MAX_ZTILE/2; - } } + nextRectangle(rect); } /** @@ -312,10 +267,6 @@ ztileInLine = 0; } - private void unputrectangle() { - c1.putShort(2,(short)(c1.getShort(2)-1)); // last rectangle is canceled - } - private void nextRectangle(FramebufferUpdateRectangle rect) { if (c1rect.x+c1rect.width < rect.x+rect.width) { c1rect.x = c1rect.width; // next rectangle is phase 1