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 }