2 * FreeRDP: A Remote Desktop Protocol client.
5 * Copyright 2011 Samsung, Author Jiten Pathy
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
24 #include <freerdp/codec/nsc.h>
25 #include <freerdp/utils/memory.h>
27 /* we store the 9th bits at the end of stream as bitstream */
28 void nsc_cl_expand(STREAM* stream, uint8 shiftcount, uint32 origsz)
34 sbitstream = stream->data + origsz;
38 sign = (*(stream->p) << (shiftcount - 1)) & 0x80;
39 bitno = stream->p - stream->data;
40 *(stream->p++) <<= shiftcount;
41 temptr = sbitstream + ((bitno) >> 3);
43 (*temptr) |= (sign >> bitoff);
45 while (((uint32)(stream->p - stream->data)) < origsz);
47 stream->p = stream->data;
50 void nsc_chroma_supersample(NSC_CONTEXT* context)
57 uint8 val, bitoff, sign;
59 uint32 alloclen, orglen, bytno;
65 alloclen = orglen = w * h;
66 pw = ROUND_UP_TO(context->width, 8);
69 for (i = 0; i < 3; i++)
72 alloclen = orglen + ((orglen & 0x7) ? (orglen >> 3) + 0x1 : (orglen >> 3));
74 new_s = stream_new(alloclen);
75 stream_attach(temp, context->org_buf[i]->data, context->org_buf[i]->size);
77 sbitstream = temp->data + context->OrgByteCount[i];
78 nbitstream = new_s->data + orglen;
84 while (((uint32)(temp->p - temp->data)) < context->OrgByteCount[i])
86 bytno = temp->p - temp->data;
88 stream_read_uint8(temp, val);
90 row = (temp->p - temp->data) % pw;
96 stream_seek(temp, pw-row);
100 tptr = sbitstream + ((bytno) >> 3);
101 sign = ((*tptr) << bitoff) & 0x80;
102 bytno = cur - new_s->data;
104 *(nbitstream + (bytno >> 3)) |= (sign >> bitoff);
106 if ((bytno+w) < orglen)
109 bitoff = (bytno + w) % 8;
110 *(nbitstream + ((bytno + w) >> 3)) |= (sign >> bitoff);
116 bitoff = (bytno + 1) % 8;
117 *(nbitstream + ((bytno + 1) >> 3)) |= (sign >> bitoff);
118 if ((bytno+w) < orglen)
121 bitoff = (bytno + w + 1) % 8;
122 *(nbitstream + ((bytno + w + 1) >> 3)) |= (sign >> bitoff);
127 bytno = cur - new_s->data;
129 if (((bytno/w) < h) && ((bytno) % w) < 2 )
138 stream_seek(temp, pw-row);
144 stream_attach(context->org_buf[i], new_s->data, new_s->size);
145 context->OrgByteCount[i] = orglen;
149 void nsc_ycocg_rgb(NSC_CONTEXT* context)
151 uint8* sbitstream[2];
152 uint8 bitoff, sign[2], i, val, tmp;
153 sint16 rgb[3], ycocg[3];
155 size = context->OrgByteCount[0];
157 for (i = 1; i < 3; i++)
158 sbitstream[i-1] = context->org_buf[i]->data + context->OrgByteCount[i];
162 for (i = 0; i < 3; i++)
163 ycocg[i] = *(context->org_buf[i]->p);
165 for (i = 1; i < 3; i++)
167 bytno = context->OrgByteCount[i] - size;
169 sign[i-1] = (*(sbitstream[i-1] + (bytno >> 3)) >> (7 - bitoff)) & 0x1;
170 ycocg[i] = (((sint16)(0 - sign[i-1])) << 8) | ycocg[i];
173 rgb[0] = ycocg[0] + (ycocg[1] >> 1) - (ycocg[2] >> 1);
174 rgb[1] = ycocg[0] + (ycocg[2] >> 1);
175 rgb[2] = ycocg[0] - (ycocg[1] >> 1) - (ycocg[2] >> 1);
177 for (i = 0; i < 3; i++)
179 tmp = (rgb[i] >> 8) & 0xff;
185 val = (uint8) rgb[i];
187 stream_write_uint8(context->org_buf[i], val);
194 for (i = 0; i < 3; i++)
195 context->org_buf[i]->p = context->org_buf[i]->data;
198 void nsc_colorloss_recover(NSC_CONTEXT* context)
202 cllvl = context->nsc_stream->colorLossLevel;
204 for (i = 1; i < 3; i++)
205 nsc_cl_expand(context->org_buf[i], cllvl, context->OrgByteCount[i]);
208 void nsc_rle_decode(STREAM* in, STREAM* out, uint32 origsz)
216 stream_read_uint8(in, value);
220 stream_write_uint8(out,value);
223 else if (value == *(in->p))
230 stream_read_uint8(in, len);
231 stream_set_byte(out, value, len+2);
238 stream_read_uint32(in, len);
239 stream_set_byte(out, value, len);
245 stream_write_uint8(out, value);
250 stream_copy(out, in, 4);
253 void nsc_rle_decompress_data(NSC_CONTEXT* context)
258 rles = stream_new(0);
259 rles->p = rles->data = context->nsc_stream->pdata->p;
260 rles->size = context->nsc_stream->pdata->size;
262 for (i = 0; i < 4; i++)
264 origsize = context->OrgByteCount[i];
266 if (i == 3 && context->nsc_stream->PlaneByteCount[i] == 0)
267 stream_set_byte(context->org_buf[i], 0xff, origsize);
268 else if (context->nsc_stream->PlaneByteCount[i] < origsize)
269 nsc_rle_decode(rles, context->org_buf[i], origsize);
271 stream_copy(context->org_buf[i], rles, origsize);
273 context->org_buf[i]->p = context->org_buf[i]->data;
277 void nsc_combine_argb(NSC_CONTEXT* context)
281 bmp = context->bmpdata;
283 for (i = 0; i < (context->width * context->height); i++)
285 stream_read_uint8(context->org_buf[2], *bmp++);
286 stream_read_uint8(context->org_buf[1], *bmp++);
287 stream_read_uint8(context->org_buf[0], *bmp++);
288 stream_read_uint8(context->org_buf[3], *bmp++);
292 void nsc_stream_initialize(NSC_CONTEXT* context, STREAM* s)
296 for (i = 0; i < 4; i++)
297 stream_read_uint32(s, context->nsc_stream->PlaneByteCount[i]);
299 stream_read_uint8(s, context->nsc_stream->colorLossLevel);
300 stream_read_uint8(s, context->nsc_stream->ChromaSubSamplingLevel);
303 context->nsc_stream->pdata = stream_new(0);
304 stream_attach(context->nsc_stream->pdata, s->p, BYTESUM(context->nsc_stream->PlaneByteCount));
307 void nsc_context_initialize(NSC_CONTEXT* context, STREAM* s)
311 nsc_stream_initialize(context, s);
312 context->bmpdata = xzalloc(context->width * context->height * 4);
314 for (i = 0; i < 4; i++)
315 context->OrgByteCount[i]=context->width * context->height;
317 if (context->nsc_stream->ChromaSubSamplingLevel > 0) /* [MS-RDPNSC] 2.2 */
319 uint32 tempWidth,tempHeight;
320 tempWidth = ROUND_UP_TO(context->width, 8);
321 context->OrgByteCount[0] = tempWidth * context->height;
322 tempWidth = tempWidth >> 1 ;
323 tempHeight = ROUND_UP_TO(context->height, 2);
324 tempHeight = tempHeight >> 1;
325 context->OrgByteCount[1] = tempWidth * tempHeight;
326 context->OrgByteCount[2] = tempWidth * tempHeight;
328 for (i = 0; i < 4; i++)
330 tempsz = context->OrgByteCount[i];
332 if (i == 1 || i == 2)
333 tempsz += (tempsz & 0x7) ? (tempsz >> 3) + 0x1 : (tempsz >> 3); /* extra bytes/8 bytes for bitstream to store the 9th bit after colorloss recover */
335 context->org_buf[i] = stream_new(tempsz);
339 void nsc_context_destroy(NSC_CONTEXT* context)
343 for (i = 0;i < 4; i++)
344 stream_free(context->org_buf[i]);
346 stream_detach(context->nsc_stream->pdata);
347 xfree(context->bmpdata);
350 NSC_CONTEXT* nsc_context_new(void)
352 NSC_CONTEXT* nsc_context;
353 nsc_context = xnew(NSC_CONTEXT);
354 nsc_context->nsc_stream = xnew(NSC_STREAM);
358 void nsc_process_message(NSC_CONTEXT* context, uint8* data, uint32 length)
362 stream_attach(s, data, length);
363 nsc_context_initialize(context, s);
366 nsc_rle_decompress_data(context);
368 /* colorloss recover */
369 nsc_colorloss_recover(context);
371 /* Chroma supersample */
372 if (context->nsc_stream->ChromaSubSamplingLevel > 0)
373 nsc_chroma_supersample(context);
375 /* YCoCg to RGB Convert */
376 nsc_ycocg_rgb(context);
378 /* Combine ARGB planes */
379 nsc_combine_argb(context);