Mercurial > hg > Members > riono > TreeVNC_ja_comment
comparison src/main/java/com/glavsoft/rfb/encoding/decoder/ZRLEDecoder.java @ 528:2956c4a7bfbd
define TileLoop class
author | anatofuz |
---|---|
date | Fri, 03 May 2019 18:16:58 +0900 |
parents | 96e15614a31f |
children | 9de5137e1598 |
comparison
equal
deleted
inserted
replaced
527:96e15614a31f | 528:2956c4a7bfbd |
---|---|
33 | 33 |
34 import java.io.ByteArrayInputStream; | 34 import java.io.ByteArrayInputStream; |
35 import java.io.InputStream; | 35 import java.io.InputStream; |
36 import java.io.UnsupportedEncodingException; | 36 import java.io.UnsupportedEncodingException; |
37 import java.nio.ByteBuffer; | 37 import java.nio.ByteBuffer; |
38 import java.util.LinkedList; | |
38 import java.util.zip.DataFormatException; | 39 import java.util.zip.DataFormatException; |
39 import java.util.zip.Deflater; | 40 import java.util.zip.Deflater; |
40 | 41 |
41 public class ZRLEDecoder extends ZlibDecoder { | 42 public class ZRLEDecoder extends ZlibDecoder { |
42 private static final int MAX_TILE_SIZE = 64; | 43 private static final int MAX_TILE_SIZE = 64; |
43 private int[] decodedBitmap; | 44 private int[] decodedBitmap; |
44 private int[] palette; | 45 private int[] palette; |
45 | 46 |
46 private int deflate_size = 65507; | 47 class TileLoop { |
47 private ByteBuffer c1; | 48 private int deflate_size = 65507; |
48 private FramebufferUpdateRectangle c1rect; | 49 private ByteBuffer c1; |
49 private int c1headerPos; | 50 private FramebufferUpdateRectangle c1rect; |
50 private int prevLineOffset; | 51 private int c1headerPos; |
51 private int prevC1Offset; | 52 private int prevLineOffset; |
53 private int prevC1Offset; | |
54 private int prevoffset; | |
55 private Deflater deflater; | |
56 | |
57 /** | |
58 * Multicast framebufferUpdate to children. | |
59 * read FrameBuffferUpdate. If it is ZLE, make it ZLEE which is self contained compressed packet. | |
60 * put the packet to the multicastqueue. Then normal rendering engine read the same stream using is.reset(). | |
61 * | |
62 * Haeder | |
63 * messageID ( FrameBuffer Update | |
64 * 1 byte padding | |
65 * 2 byte numberofrectangle | |
66 * 2 - U16 - x-position | |
67 * 2 - U16 - y-position | |
68 * 2 - U16 - width | |
69 * 2 - U16 - height | |
70 * 4 - S32 - encoding-type | |
71 * 4 byte datalengths | |
72 * datalengths databyte | |
73 * | |
74 * @throws TransportException | |
75 * @throws UnsupportedEncodingException | |
76 */ | |
77 | |
78 | |
79 private void zrleeBlocking(TreeRFBProto rfb, ByteBuffer header, byte[] bytes, FramebufferUpdateRectangle rect) throws TransportException, DataFormatException { | |
80 // dump32(inputs); | |
81 deflater = rfb.deflater; | |
82 c1 = rfb.multicastqueue.allocate(deflate_size); | |
83 if (rfb.addSerialNum) | |
84 c1.putLong(rfb.counter++); | |
85 if (rfb.checkDelay) | |
86 CheckDelay.checkDelay(c1, rect.x, rect.y, rect.width, rect.height, System.currentTimeMillis(), EncodingType.CHECK_DELAY); | |
87 c1headerPos = c1.position(); | |
88 c1.put(header); | |
89 header.flip(); | |
90 c1.putInt(0); | |
91 c1rect = new FramebufferUpdateRectangle(rect.x, rect.y, 0, 0); | |
92 return; | |
93 } | |
94 int spanGap = 128; | |
95 | |
96 /** | |
97 * | |
98 * @param rfb | |
99 * @param last | |
100 * @param header | |
101 * @param rect | |
102 * @param bytes | |
103 * @param offset | |
104 * @param tileX | |
105 * @param tileY | |
106 * @param tileW | |
107 * @param tileH | |
108 */ | |
109 public void multicastPut(TreeRFBProto rfb, boolean last, ByteBuffer header, FramebufferUpdateRectangle rect, byte[] bytes, int offset, int tileX, int tileY, int tileW, int tileH) { | |
110 int span = offset - prevoffset; | |
111 deflater.setInput(bytes,prevoffset,span); | |
112 prevoffset = offset; | |
113 c1rect.height += tileH; | |
114 c1rect.width += tileW; | |
115 if (c1rect.x > rect.x) { // phase0 | |
116 if (c1.remaining() > span + spanGap && c1rect.width < rect.width) { | |
117 deflater.deflate(c1, Deflater.SYNC_FLUSH); | |
118 return; | |
119 } | |
120 flushRectangle(rfb, header, rect, false); | |
121 return; | |
122 } | |
123 if (!last) { // phase1 | |
124 if (c1.remaining() > span + spanGap) { | |
125 if (c1rect.width >= rect.width) { | |
126 prevLineOffset = offset; | |
127 prevC1Offset = c1.position(); | |
128 } | |
129 deflater.deflate(c1, Deflater.SYNC_FLUSH); | |
130 } else { // phase2 | |
131 c1.position(prevC1Offset); | |
132 flushRectangle(rfb, header, rect, false); | |
133 deflater.setInput(bytes, prevLineOffset, span); | |
134 deflater.deflate(c1, Deflater.SYNC_FLUSH); | |
135 flushRectangle(rfb, header,rect, false); | |
136 } | |
137 return; | |
138 } | |
139 flushRectangle(rfb, header, rect, true); | |
140 } | |
141 | |
142 /** | |
143 * fix rectangle header | |
144 * create next rectangle header | |
145 * update position paramater | |
146 * send muticast pacate if nessesally | |
147 * @param rfb | |
148 * @param header | |
149 * @param rect | |
150 | |
151 * @param b | |
152 */ | |
153 private void flushRectangle(TreeRFBProto rfb, ByteBuffer header, FramebufferUpdateRectangle rect, boolean b) { | |
154 flushMuticast(rfb, header, rect); | |
155 } | |
156 | |
157 private void flushMuticast(TreeRFBProto rfb, ByteBuffer header, FramebufferUpdateRectangle rect) { | |
158 deflater.deflate(c1, Deflater.FULL_FLUSH); | |
159 deflater.finish(); | |
160 c1.flip(); | |
161 //System.out.println("multicastPut: " + c1rect + " length: " + (c1.remaining()-c1headerPos-header.limit())); | |
162 try { | |
163 writeUpdateRectangleWithHeader(c1, c1headerPos, c1.remaining()-c1headerPos-header.limit()-4, c1rect.x, c1rect.y, c1rect.width + tileW, c1rect.height + tileY); | |
164 } catch (InterruptedException e) { | |
165 e.printStackTrace(); | |
166 } | |
167 c1rect.x += c1rect.width; | |
168 if (c1rect.x >= rect.x + rect.width) { | |
169 c1rect.x = rect.x; | |
170 c1rect.y += tileH; | |
171 } | |
172 c1rect.width = 0; | |
173 c1 = rfb.multicastqueue.allocate(deflate_size); | |
174 if (rfb.addSerialNum) | |
175 c1.putLong(rfb.counter++); | |
176 c1headerPos = c1.position(); | |
177 c1.put(header); | |
178 header.flip(); | |
179 c1.putInt(0); | |
180 } | |
181 | |
182 /** | |
183 * make and send frameBufferUpdateRectangle packet | |
184 * @param c1 | |
185 * @param headerPos | |
186 * @param len2 | |
187 * @param x | |
188 * @param y | |
189 * @param w | |
190 * @param h | |
191 * @throws InterruptedException | |
192 * | |
193 */ | |
194 public void writeUpdateRectangleWithHeader(ByteBuffer c1, int headerPos, int len2, int x, int y, int w, int h) throws InterruptedException { | |
195 deflater.reset(); | |
196 | |
197 c1.putInt(headerPos + 16, len2); | |
198 c1.putShort(headerPos + 4, (short) x); | |
199 c1.putShort(headerPos + 6, (short) y); | |
200 c1.putShort(headerPos + 8, (short) w); | |
201 c1.putShort(headerPos + 10, (short) h); | |
202 LinkedList<ByteBuffer> bufs = new LinkedList<ByteBuffer>(); | |
203 bufs.add(c1); | |
204 if (rfb.isTreeManager && rfb.connectionPresenter.isUseMulticast()) { | |
205 for (ByteBuffer buf : bufs) | |
206 rfb.viewer.getRfbBroadcastListener().multicastUpdateRectangle(buf); | |
207 } else { | |
208 rfb.multicastqueue.waitput(bufs); | |
209 } | |
210 } | |
211 } | |
52 | 212 |
53 @Override | 213 @Override |
54 public void decode(Reader reader, Renderer renderer, | 214 public void decode(Reader reader, Renderer renderer, |
55 FramebufferUpdateRectangle rect) throws TransportException { | 215 FramebufferUpdateRectangle rect) throws TransportException { |
56 int zippedLength = (int) reader.readUInt32(); | 216 int zippedLength = (int) reader.readUInt32(); |
62 | 222 |
63 public void decode1(Renderer renderer, ByteBuffer header, FramebufferUpdateRectangle rect, byte[] bytes, int zippedLength, TreeRFBProto rfbProto) throws TransportException { | 223 public void decode1(Renderer renderer, ByteBuffer header, FramebufferUpdateRectangle rect, byte[] bytes, int zippedLength, TreeRFBProto rfbProto) throws TransportException { |
64 int offset = zippedLength; | 224 int offset = zippedLength; |
65 int maxX = rect.x + rect.width; | 225 int maxX = rect.x + rect.width; |
66 int maxY = rect.y + rect.height; | 226 int maxY = rect.y + rect.height; |
67 int prevoffset = offset; | 227 |
228 TileLoop tileloop = new TileLoop(); | |
68 //System.out.println("decode1: "+rect); | 229 //System.out.println("decode1: "+rect); |
69 if (null == palette) { | 230 if (null == palette) { |
70 palette = new int [128]; | 231 palette = new int [128]; |
71 } | 232 } |
72 if (null == decodedBitmap) { | 233 if (null == decodedBitmap) { |
73 decodedBitmap = new int[MAX_TILE_SIZE * MAX_TILE_SIZE]; | 234 decodedBitmap = new int[MAX_TILE_SIZE * MAX_TILE_SIZE]; |
74 } | 235 } |
75 | 236 |
76 if (rfbProto.multicastBlocking) { | 237 if (rfbProto.multicastBlocking) { |
77 try { | 238 try { |
78 zrleeBlocking(rfbProto, header, bytes, rect); | 239 tileloop.zrleeBlocking(rfbProto, header, bytes, rect); |
79 } catch (DataFormatException e) { | 240 } catch (DataFormatException e) { |
80 e.printStackTrace(); | 241 e.printStackTrace(); |
81 } | 242 } |
82 } | 243 } |
83 for (int tileY = rect.y; tileY < maxY; tileY += MAX_TILE_SIZE) { | 244 for (int tileY = rect.y; tileY < maxY; tileY += MAX_TILE_SIZE) { |
107 // System.out.println("offset:"+offset); | 268 // System.out.println("offset:"+offset); |
108 } else { | 269 } else { |
109 offset += decodePacked(bytes, offset, renderer, paletteSize, tileX, tileY, tileWidth, tileHeight); | 270 offset += decodePacked(bytes, offset, renderer, paletteSize, tileX, tileY, tileWidth, tileHeight); |
110 } | 271 } |
111 } | 272 } |
112 if (rfbProto != null && rfbProto.multicastBlocking) multicastPut(rfbProto, false, header, rect, bytes, prevoffset, offset, tileX, tileY,tileWidth, tileHeight); | 273 if (rfbProto != null && rfbProto.multicastBlocking) tileloop.multicastPut(rfbProto, false, header, rect, bytes, offset, tileX, tileY,tileWidth, tileHeight); |
113 prevoffset = offset; | 274 } |
114 } | 275 } |
115 } | 276 if (rfbProto != null && rfbProto.multicastBlocking) tileloop.multicastPut(rfbProto, false, header, rect, bytes, offset, maxX, maxY, 0, 0); |
116 if (rfbProto != null && rfbProto.multicastBlocking) multicastPut(rfbProto, false, header, rect, bytes, prevoffset, offset, maxX, maxY, 0, 0); | |
117 } | 277 } |
118 | 278 |
119 private int decodePlainRle(byte[] bytes, int offset, Renderer renderer, | 279 private int decodePlainRle(byte[] bytes, int offset, Renderer renderer, |
120 int tileX, int tileY, int tileWidth, int tileHeight) { | 280 int tileX, int tileY, int tileWidth, int tileHeight) { |
121 int bytesPerCPixel = renderer.getBytesPerCPixel(); | 281 int bytesPerCPixel = renderer.getBytesPerCPixel(); |
198 } | 358 } |
199 return paletteSize * bytesPerCPixel; | 359 return paletteSize * bytesPerCPixel; |
200 } | 360 } |
201 | 361 |
202 | 362 |
203 /** | 363 |
204 * Multicast framebufferUpdate to children. | |
205 * read FrameBuffferUpdate. If it is ZLE, make it ZLEE which is self contained compressed packet. | |
206 * put the packet to the multicastqueue. Then normal rendering engine read the same stream using is.reset(). | |
207 * | |
208 * Haeder | |
209 * messageID ( FrameBuffer Update | |
210 * 1 byte padding | |
211 * 2 byte numberofrectangle | |
212 * 2 - U16 - x-position | |
213 * 2 - U16 - y-position | |
214 * 2 - U16 - width | |
215 * 2 - U16 - height | |
216 * 4 - S32 - encoding-type | |
217 * 4 byte datalengths | |
218 * datalengths databyte | |
219 * | |
220 * @throws TransportException | |
221 * @throws UnsupportedEncodingException | |
222 */ | |
223 | |
224 | |
225 private void zrleeBlocking(TreeRFBProto rfb, ByteBuffer header, byte[] bytes, FramebufferUpdateRectangle rect) throws TransportException, DataFormatException { | |
226 // dump32(inputs); | |
227 c1 = rfb.multicastqueue.allocate(deflate_size); | |
228 if (rfb.addSerialNum) | |
229 c1.putLong(rfb.counter++); | |
230 if (rfb.checkDelay) | |
231 CheckDelay.checkDelay(c1, rect.x, rect.y, rect.width, rect.height, System.currentTimeMillis(), EncodingType.CHECK_DELAY); | |
232 c1headerPos = c1.position(); | |
233 c1.put(header); | |
234 header.flip(); | |
235 c1.putInt(0); | |
236 c1rect = new FramebufferUpdateRectangle(rect.x, rect.y, 0, 0); | |
237 return; | |
238 } | |
239 int spanGap = 128; | |
240 | |
241 public void multicastPut(TreeRFBProto rfb, boolean last, ByteBuffer header, FramebufferUpdateRectangle rect, byte[] bytes, int prevoffset, int offset, int tileX, int tileY, int tileW, int tileH) { | |
242 int span = offset - prevoffset; | |
243 rfb.deflater.setInput(bytes,prevoffset,span); | |
244 c1rect.height = tileH; | |
245 if (c1rect.x > 0) { // phase0 | |
246 if (c1.remaining() > span + spanGap && c1rect.width + tileW < rect.width) { | |
247 rfb.deflater.deflate(c1, Deflater.SYNC_FLUSH); | |
248 return; | |
249 } | |
250 flushRectangle(rfb, header, offset, rect, tileX, tileY, tileW, tileH, false); | |
251 return; | |
252 } | |
253 if (!last) { // phase1 | |
254 if (c1.remaining() > span + spanGap) { | |
255 if (tileX == tileW) { | |
256 prevLineOffset = offset; | |
257 prevC1Offset = c1.position(); | |
258 } | |
259 rfb.deflater.deflate(c1, Deflater.SYNC_FLUSH); | |
260 return; | |
261 } | |
262 if (tileX < tileW) { // phase2 | |
263 c1.position(prevC1Offset); | |
264 flushRectangle(rfb, header, prevoffset, rect, 0, tileY-tileH, tileW, tileH, false); | |
265 rfb.deflater.setInput(bytes, prevLineOffset, span); | |
266 rfb.deflater.deflate(c1, Deflater.SYNC_FLUSH); | |
267 flushRectangle(rfb, header, prevoffset, rect, 0, tileY-tileH, tileW, tileH, false); | |
268 return; | |
269 } | |
270 return; | |
271 } | |
272 flushRectangle(rfb, header, prevoffset, rect, 0, tileY-tileH, tileW, tileH, true); | |
273 c1rect.width += tileW; | |
274 } | |
275 | |
276 /** | |
277 * fix rectangle header | |
278 * create next rectangle header | |
279 * update position paramater | |
280 * send muticast pacate if necessary | |
281 * @param rfb | |
282 * @param header | |
283 * @param prevoffset | |
284 * @param rect | |
285 * @param i | |
286 * @param i1 | |
287 * @param tileW | |
288 * @param tileH | |
289 * @param b | |
290 */ | |
291 private void flushRectangle(TreeRFBProto rfb, ByteBuffer header, int prevoffset, FramebufferUpdateRectangle rect, int i, int i1, int tileW, int tileH, boolean b) { | |
292 flushMuticast(rfb, header, rect, tileY, tileW, tileH); | |
293 } | |
294 | |
295 private void flushMuticast(TreeRFBProto rfb, ByteBuffer header, FramebufferUpdateRectangle rect, int tileY, int tileW, int tileH) { | |
296 rfb.deflater.deflate(c1, Deflater.FULL_FLUSH); | |
297 rfb.deflater.finish(); | |
298 c1.flip(); | |
299 //System.out.println("multicastPut: " + c1rect + " length: " + (c1.remaining()-c1headerPos-header.limit())); | |
300 try { | |
301 rfb.writeUpdateRectangleWithHeader(c1, c1headerPos, c1.remaining()-c1headerPos-header.limit()-4, c1rect.x, c1rect.y, c1rect.width + tileW, c1rect.height + tileY); | |
302 } catch (InterruptedException e) { | |
303 e.printStackTrace(); | |
304 } | |
305 c1rect.x += c1rect.width; | |
306 if (c1rect.x >= rect.x + rect.width) { | |
307 c1rect.x = rect.x; | |
308 c1rect.y += tileH; | |
309 } | |
310 c1rect.width = 0; | |
311 c1 = rfb.multicastqueue.allocate(deflate_size); | |
312 if (rfb.addSerialNum) | |
313 c1.putLong(rfb.counter++); | |
314 c1headerPos = c1.position(); | |
315 c1.put(header); | |
316 header.flip(); | |
317 c1.putInt(0); | |
318 } | |
319 } | 364 } |