Mercurial > hg > Applications > TreeVNC
comparison src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java @ 611:9a2bef3f3020
blocking fix
broadcast mode
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 21 Feb 2020 11:52:14 +0900 |
parents | e986dad88692 |
children | 994a710100fd |
comparison
equal
deleted
inserted
replaced
610:705fd8d79378 | 611:9a2bef3f3020 |
---|---|
36 import java.util.LinkedList; | 36 import java.util.LinkedList; |
37 import java.util.zip.Deflater; | 37 import java.util.zip.Deflater; |
38 | 38 |
39 public class ZRLEDecoder extends ZlibDecoder { | 39 public class ZRLEDecoder extends ZlibDecoder { |
40 private static final int MAX_TILE_SIZE = 64; | 40 private static final int MAX_TILE_SIZE = 64; |
41 private static final int RECT_HEADER_SIZE = 16; | |
41 private int[] decodedBitmap; | 42 private int[] decodedBitmap; |
42 private int[] palette; | 43 private int[] palette; |
44 private boolean WifiMulticast; | |
43 | 45 |
44 class TileLoop { | 46 class TileLoop { |
45 private final boolean blocking; | 47 private final boolean blocking; |
46 final int MARGIN = 18000; | 48 final int MARGIN = 25000; |
47 final int deflate_size = 60000-MARGIN; | 49 final int deflate_size = 62000-MARGIN; |
48 private ByteBuffer c1; | 50 private ByteBuffer c1; |
49 private int width; // phase2 length | 51 private int width; // phase2 length |
50 private FramebufferUpdateRectangle c0rect,c1rect,rect; | 52 private FramebufferUpdateRectangle c0rect,c1rect,rect; |
51 private int prevLineOffset; | 53 private int prevLineOffset; |
52 private int prevC1Offset; | 54 private int prevC1Offset; |
77 */ | 79 */ |
78 | 80 |
79 public TileLoop(TreeRFBProto rfb, int offset) { | 81 public TileLoop(TreeRFBProto rfb, int offset) { |
80 prevoffset = prevLineOffset = flushOffset = offset; | 82 prevoffset = prevLineOffset = flushOffset = offset; |
81 prevC1Offset = 0; | 83 prevC1Offset = 0; |
82 if (rfb == null || offset < deflate_size + spanGap) { | 84 if (rfb == null || offset < deflate_size + MARGIN) { |
83 // packet size fit in broadcast send it all at once | 85 // packet size fit in broadcast send it all at once |
84 blocking = false; | 86 blocking = false; |
85 } else | 87 } else |
86 blocking = true; | 88 blocking = true; |
87 } | 89 } |
118 prevC1LineOffset = prevC1Offset; | 120 prevC1LineOffset = prevC1Offset; |
119 c1rect.width = c1rect.height = 0; | 121 c1rect.width = c1rect.height = 0; |
120 c0rect = null; | 122 c0rect = null; |
121 } | 123 } |
122 | 124 |
123 int spanGap = 128; | |
124 /** | 125 /** |
125 * Series of tiles compose at most three rectangles. SYNC_FLUSH is necessary on | 126 * Series of tiles compose at most three rectangles. SYNC_FLUSH is necessary on |
126 * rectangle boundaries. | 127 * rectangle boundaries. |
127 * | 128 * |
128 * +----+ | 129 * +----+ |
208 flushRectangle(c1rect,c1.position()); | 209 flushRectangle(c1rect,c1.position()); |
209 if (end) { | 210 if (end) { |
210 flushMuticast(rfb,bytes); | 211 flushMuticast(rfb,bytes); |
211 return; | 212 return; |
212 } | 213 } |
213 c1.position(c1.position()+16); // header space | 214 c1.position(c1.position()+ RECT_HEADER_SIZE); // header space |
214 prevC1Offset = c1.position(); | 215 prevC1Offset = c1.position(); |
215 c1rect = new FramebufferUpdateRectangle(rect.x,c1rect.y+tileH,0,0); | 216 c1rect = new FramebufferUpdateRectangle(rect.x,c1rect.y+tileH,0,0); |
216 } | 217 } |
217 } else { // phase 1 | 218 } else { // phase 1 |
218 if (width >= rect.width) { // next line | 219 if (width >= rect.width) { // next line |
222 if (c0rect!=null) { // extend phase 1 | 223 if (c0rect!=null) { // extend phase 1 |
223 c0rect.height += tileH; | 224 c0rect.height += tileH; |
224 } else { // first phase 1 case | 225 } else { // first phase 1 case |
225 c0rect = c1rect; | 226 c0rect = c1rect; |
226 } | 227 } |
228 c1rect = new FramebufferUpdateRectangle(rect.x, c0rect.y+c0rect.height, 0, 0); | |
227 if (end) { | 229 if (end) { |
230 c0rect = null; // next will be first phase 1 case | |
228 flushMuticast(rfb,bytes); | 231 flushMuticast(rfb,bytes); |
229 return; | 232 return; |
230 } | 233 } |
231 c1rect = new FramebufferUpdateRectangle(rect.x, c0rect.y+c0rect.height, 0, 0); | |
232 prevLineOffset = offset; | 234 prevLineOffset = offset; |
233 } | 235 } |
234 } | 236 } |
235 } | 237 } |
236 | 238 |
237 public void makeHeaderSpace() { | 239 public void makeHeaderSpace() { |
238 // previous rectangle is finished, make next header space and copy already compressed part | 240 // previous rectangle is finished, make next header space and copy already compressed part |
239 System.arraycopy(c1.array(),prevC1LineOffset,c1.array(),prevC1LineOffset+16,c1.position()-prevC1LineOffset); | 241 System.arraycopy(c1.array(),prevC1LineOffset,c1.array(),prevC1LineOffset+ RECT_HEADER_SIZE,c1.position()-prevC1LineOffset); |
240 c1.position(c1.position()+16); | 242 c1.position(c1.position()+ RECT_HEADER_SIZE); |
241 prevC1Offset = prevC1LineOffset+16; | 243 prevC1Offset = prevC1LineOffset+ RECT_HEADER_SIZE; |
242 } | 244 } |
243 | 245 |
246 /** | |
247 * | |
248 * @param extend use MARGIN | |
249 * @param what reason of flush (debug purpose) | |
250 * @return packet full | |
251 * @throws TransportException | |
252 */ | |
244 private boolean flushDeflator(boolean extend,String what) throws TransportException { | 253 private boolean flushDeflator(boolean extend,String what) throws TransportException { |
245 // System.out.println("flusing "+what+c1); | 254 // System.out.println("flusing "+what+c1); |
246 if (extend) c1.limit(c1.capacity()-16); | 255 if (extend) c1.limit(c1.capacity()- RECT_HEADER_SIZE); |
247 deflater.deflate(c1, Deflater.FULL_FLUSH); | 256 deflater.deflate(c1, Deflater.FULL_FLUSH); |
248 if (c1.remaining()==0) { | 257 if (c1.remaining()==0) { |
249 if (!extend) { | 258 if (!extend) { |
250 c1.limit(c1.capacity()-16); | 259 c1.limit(c1.capacity()- RECT_HEADER_SIZE); |
251 deflater.deflate(c1, Deflater.FULL_FLUSH); | 260 deflater.deflate(c1, Deflater.FULL_FLUSH); |
252 } | 261 } |
253 if (c1.remaining() == 0) | 262 if (c1.remaining() == 0) { |
254 throw new TransportException("Multicast packet overrun", null); | 263 ByteBuffer tmp = ByteBuffer.allocate(65536); |
264 deflater.deflate(tmp,Deflater.FULL_FLUSH); | |
265 throw new TransportException("Multicast packet overrun "+(c1.limit()+tmp.position())+" bytes required", null); | |
266 } | |
255 return true; | 267 return true; |
256 } | 268 } |
257 return false; | 269 return false; |
258 } | 270 } |
259 | 271 |
280 deflater.reset(); | 292 deflater.reset(); |
281 LinkedList<ByteBuffer> bufs = new LinkedList<ByteBuffer>(); | 293 LinkedList<ByteBuffer> bufs = new LinkedList<ByteBuffer>(); |
282 bufs.add(c1); | 294 bufs.add(c1); |
283 // rfb.getContext().checkFrameBufferRectanble(c1, bytes, flushOffset, prevoffset); | 295 // rfb.getContext().checkFrameBufferRectanble(c1, bytes, flushOffset, prevoffset); |
284 flushOffset = prevoffset; | 296 flushOffset = prevoffset; |
285 if (rfb.isTreeManager() && rfb.connectionPresenter.isUseMulticast()) { | 297 if (WifiMulticast) { |
286 for (ByteBuffer buf : bufs) | 298 for (ByteBuffer buf : bufs) |
287 rfb.getViewer().getRfbBroadcastListener().multicastUpdateRectangle(buf); | 299 rfb.getViewer().getRfbBroadcastListener().multicastUpdateRectangle(buf); |
288 } else { | 300 } else if (rfb.multicastBlocking) { |
289 rfb.multicastqueue.put(bufs); | 301 rfb.multicastqueue.put(bufs); // debug purpose |
290 } | 302 } |
291 } | 303 } |
292 } | 304 } |
293 | 305 |
294 @Override | 306 @Override |
302 } | 314 } |
303 | 315 |
304 | 316 |
305 public void multicastDecode(Reader reader, Renderer renderer, | 317 public void multicastDecode(Reader reader, Renderer renderer, |
306 FramebufferUpdateRectangle rect, TreeRFBProto rfb) throws TransportException { | 318 FramebufferUpdateRectangle rect, TreeRFBProto rfb) throws TransportException { |
307 ByteBuffer header = ByteBuffer.allocate(16); | 319 ByteBuffer header = ByteBuffer.allocate(16); // FBU header |
308 reader.read(header.array()); | 320 reader.read(header.array()); |
309 int zippedLength = (int) reader.readUInt32(); | 321 int zippedLength = (int) reader.readUInt32(); |
310 if (0 == zippedLength) return; | 322 if (0 == zippedLength) return; |
311 int length = rect.width * rect.height * renderer.getBytesPerPixel(); | 323 int length = rect.width * rect.height * renderer.getBytesPerPixel(); |
312 ByteBuffer buf = unzip(reader, zippedLength, length, rect.getEncodingType()); | 324 ByteBuffer buf = unzip(reader, zippedLength, length, rect.getEncodingType()); |
318 public void decode1(Renderer renderer, ByteBuffer header, FramebufferUpdateRectangle rect, ByteBuffer buf, int zippedLength, TreeRFBProto rfbProto) throws TransportException { | 330 public void decode1(Renderer renderer, ByteBuffer header, FramebufferUpdateRectangle rect, ByteBuffer buf, int zippedLength, TreeRFBProto rfbProto) throws TransportException { |
319 int offset = zippedLength; | 331 int offset = zippedLength; |
320 int maxX = rect.x + rect.width; | 332 int maxX = rect.x + rect.width; |
321 int maxY = rect.y + rect.height; | 333 int maxY = rect.y + rect.height; |
322 byte[] bytes = buf.array(); | 334 byte[] bytes = buf.array(); |
323 boolean WifiMulticast = rfbProto !=null && (rfbProto.multicastBlocking || rfbProto.getViewer().getUseMulticast()); | 335 WifiMulticast = rfbProto !=null && (rfbProto.multicastBlocking ||(rfbProto.isTreeManager()&&rfbProto.getViewer().getUseMulticast())); |
324 | 336 |
325 TileLoop tileloop = new TileLoop(rfbProto, zippedLength); | 337 TileLoop tileloop = new TileLoop(rfbProto, zippedLength); |
326 //System.out.println("decode1: "+rect.toString()); | 338 //System.out.println("decode1: "+rect.toString()); |
327 if (null == palette) { | 339 if (null == palette) { |
328 palette = new int[128]; | 340 palette = new int[128]; |