comparison src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java @ 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 6620e04f994c
comparison
equal deleted inserted replaced
534:a3d0ba67e8cf 535:17a2d0ea5c03
40 private static final int MAX_TILE_SIZE = 64; 40 private static final int MAX_TILE_SIZE = 64;
41 private int[] decodedBitmap; 41 private int[] decodedBitmap;
42 private int[] palette; 42 private int[] palette;
43 43
44 class TileLoop { 44 class TileLoop {
45 private final boolean blocking;
46 private final int half;
45 private int deflate_size = 65507; 47 private int deflate_size = 65507;
46 private ByteBuffer c1; 48 private ByteBuffer c1;
47 private int width; // phase2 length 49 private int width; // phase2 length
48 private FramebufferUpdateRectangle c1rect; 50 private FramebufferUpdateRectangle c1rect;
49 private int c1headerPos; 51 private int c1headerPos;
55 private int ztileInLine; 57 private int ztileInLine;
56 private int hwidth; 58 private int hwidth;
57 private int hc1width; 59 private int hc1width;
58 private int hoffset; 60 private int hoffset;
59 private int hc1offset; 61 private int hc1offset;
62 private int discard;
60 63
61 /** 64 /**
62 * Multicast framebufferUpdate to children. 65 * Multicast framebufferUpdate to children.
63 * read FrameBuffferUpdate. If it is ZLE, make it ZLEE which is self contained compressed packet. 66 * read FrameBuffferUpdate. If it is ZLE, make it ZLEE which is self contained compressed packet.
64 * put the packet to the multicastqueue. Then normal rendering engine read the same stream using is.reset(). 67 * put the packet to the multicastqueue. Then normal rendering engine read the same stream using is.reset().
79 * @throws UnsupportedEncodingException 82 * @throws UnsupportedEncodingException
80 */ 83 */
81 84
82 public TileLoop(int offset) { 85 public TileLoop(int offset) {
83 prevoffset = prevLineOffset = prevC1Offset = offset; 86 prevoffset = prevLineOffset = prevC1Offset = offset;
84 } 87 if (offset < deflate_size+spanGap) {
85 88 // packet size fit in broadcast send it all at once
86 private void zrleeBlocking(TreeRFBProto rfb, ByteBuffer header, FramebufferUpdateRectangle rect) { 89 blocking = false;
90 } else
91 blocking = true;
92 discard = 0; half = 0;
93 }
94
95 private void zrleeBlocking(TreeRFBProto rfb, ByteBuffer header, FramebufferUpdateRectangle rect, byte bytes[]) {
87 // dump32(inputs); 96 // dump32(inputs);
88 deflater = rfb.deflater; 97 deflater = rfb.deflater;
89 newMulticastPacket(rfb, rect); 98 newMulticastPacket(rfb, rect);
90 c1.put(header.get(0)); 99 c1.put(header.get(0));
91 c1rect = new FramebufferUpdateRectangle(rect.x, rect.y, 0, 0); 100 c1rect = new FramebufferUpdateRectangle(rect.x, rect.y, 0, 0);
101 if (!blocking) {
102 deflater.setInput(bytes,0,prevoffset);
103 deflater.deflate(c1);
104 flushMuticast(rfb);
105 }
92 return; 106 return;
93 } 107 }
94 108
95 private void newMulticastPacket(TreeRFBProto rfb, FramebufferUpdateRectangle rect) { 109 private void newMulticastPacket(TreeRFBProto rfb, FramebufferUpdateRectangle rect) {
96 c1 = rfb.multicastqueue.allocate(deflate_size); 110 c1 = rfb.multicastqueue.allocate(deflate_size);
122 * +----+----------+ 136 * +----+----------+
123 * | | | phase 2 137 * | | | phase 2
124 * +----+ 138 * +----+
125 * 139 *
126 * Broadcast packet have to less than 64kbytes 140 * Broadcast packet have to less than 64kbytes
127 * A tile 8x8x3 192byte, a packet can contain 340 raw tiles, when these are 141 * A tile 64x64x3 11288byte, a packet can contain 5 raw tiles, when these are
128 * compressed 500 to 2000 tiles can be stored. It is impossible to predict the 142 * compressed 10 to 100 tiles can be stored. It is impossible to predict the
129 * compression rate. To check the compressed capacity, Deflate.needsInputs() can 143 * compression rate. To check the compressed capacity, Deflate.needsInputs() can
130 * be used. If needsInputs() is false on SYNC_FLUSH, smaller input is necessary. 144 * be used. If needsInputs() is false on SYNC_FLUSH, smaller input is necessary.
131 * 145 *
132 * We'll try 512 tiles before SYNC_FLUSH in a phase, if it fails try 256. 146 * We'll try 512 tiles before SYNC_FLUSH in a phase, if it fails try flush former 256 tiles.
133 * If it will failed again, flush the previous line and try again. 147 * If it will failed again, flush the previous line and do flush 512 tiles in new Packet.
134 * If 256 tiles are failed in new packet, discard it. 148 * If it failed again try former 256 tiles flushed, if this failes again dicard the former half.
149 * The last case cannot happen but former 256 tiles have to be flushed, because the next 256 lines
150 * may failed again and restart the from this point.
151 * The next packet start with later 256 tiles filled and unflushed.
135 * 152 *
136 * @param rfb 153 * @param rfb
137 * @param last 154 * @param last
138 * @param rect 155 * @param rect
139 * @param bytes 156 * @param bytes
143 */ 160 */
144 161
145 int MAX_ZTILE = 512; 162 int MAX_ZTILE = 512;
146 163
147 public void multicastPut(TreeRFBProto rfb, boolean last, FramebufferUpdateRectangle rect, byte[] bytes, int offset, int tileW, int tileH) { 164 public void multicastPut(TreeRFBProto rfb, boolean last, FramebufferUpdateRectangle rect, byte[] bytes, int offset, int tileW, int tileH) {
165 if (!blocking) return;
148 int span = offset - prevoffset; 166 int span = offset - prevoffset;
149 deflater.setInput(bytes,prevoffset,span); 167 deflater.setInput(bytes,prevoffset,span);
150 prevoffset = offset; 168 prevoffset = offset;
151 c1rect.width += tileW; width += tileW; 169 c1rect.width += tileW; width += tileW;
152 if (c1rect.x > rect.x) { // phase 0 170 if (c1rect.x > rect.x) { // phase 0
181 } 199 }
182 } 200 }
183 } 201 }
184 202
185 private void compressAndCheckFlush(TreeRFBProto rfb, FramebufferUpdateRectangle rect, byte[] bytes, int offset, boolean flush, boolean last) { 203 private void compressAndCheckFlush(TreeRFBProto rfb, FramebufferUpdateRectangle rect, byte[] bytes, int offset, boolean flush, boolean last) {
186 if (!flush && ztileInLine++ < MAX_ZTILE) { 204 ztileInLine++;
205 if (!flush && ztileInLine < MAX_ZTILE) {
187 if (ztileInLine == MAX_ZTILE/2) { 206 if (ztileInLine == MAX_ZTILE/2) {
188 hwidth = width; hc1width = c1rect.width; hoffset = offset; hc1offset = c1.position(); 207 hwidth = width; hc1width = c1rect.width; hoffset = offset; hc1offset = c1.position();
189 } 208 }
190 deflater.deflate(c1, Deflater.NO_FLUSH); 209 deflater.deflate(c1, Deflater.NO_FLUSH);
191 } else { 210 } else {
218 from = prevC1Offset; 237 from = prevC1Offset;
219 len = hoffset - prevLineOffset; 238 len = hoffset - prevLineOffset;
220 deflater.setInput(bytes, from, len); 239 deflater.setInput(bytes, from, len);
221 deflater.deflate(c1, Deflater.SYNC_FLUSH); 240 deflater.deflate(c1, Deflater.SYNC_FLUSH);
222 if (!deflater.needsInput()) { /* fatal error discard this line */ 241 if (!deflater.needsInput()) { /* fatal error discard this line */
242 discard++;
223 if (!last) { 243 if (!last) {
224 newMulticastPacket(rfb, rect); 244 newMulticastPacket(rfb, rect);
225 nextRectangle(rect); 245 nextRectangle(rect);
226 } 246 }
227 return; 247 return;
335 if (null == decodedBitmap) { 355 if (null == decodedBitmap) {
336 decodedBitmap = new int[MAX_TILE_SIZE * MAX_TILE_SIZE]; 356 decodedBitmap = new int[MAX_TILE_SIZE * MAX_TILE_SIZE];
337 } 357 }
338 358
339 if (rfbProto.multicastBlocking) { 359 if (rfbProto.multicastBlocking) {
340 tileloop.zrleeBlocking(rfbProto, header, rect); 360 tileloop.zrleeBlocking(rfbProto, header, rect,bytes);
341 } 361 }
342 for (int tileY = rect.y; tileY < maxY; tileY += MAX_TILE_SIZE) { 362 for (int tileY = rect.y; tileY < maxY; tileY += MAX_TILE_SIZE) {
343 int tileHeight = Math.min(maxY - tileY, MAX_TILE_SIZE); 363 int tileHeight = Math.min(maxY - tileY, MAX_TILE_SIZE);
344 364
345 for (int tileX = rect.x; tileX < maxX; tileX += MAX_TILE_SIZE) { 365 for (int tileX = rect.x; tileX < maxX; tileX += MAX_TILE_SIZE) {