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;
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
if (((rgb[i] >> 8) & 0x1) == 0x1)
180
val = ~((uint8) rgb[i]) + 0x1;
182
val = (uint8) rgb[i];
184
stream_write_uint8(context->org_buf[i], val);
191
for (i = 0; i < 3; i++)
192
context->org_buf[i]->p = context->org_buf[i]->data;
195
void nsc_colorloss_recover(NSC_CONTEXT* context)
199
cllvl = context->nsc_stream->colorLossLevel;
201
for (i = 1; i < 3; i++)
202
nsc_cl_expand(context->org_buf[i], cllvl, context->OrgByteCount[i]);
205
void nsc_rle_decode(STREAM* in, STREAM* out, uint32 origsz)
213
stream_read_uint8(in, value);
217
stream_write_uint8(out,value);
220
else if (value == *(in->p))
227
stream_read_uint8(in, len);
228
stream_set_byte(out, value, len+2);
235
stream_read_uint32(in, len);
236
stream_set_byte(out, value, len);
242
stream_write_uint8(out, value);
247
stream_copy(out, in, 4);
250
void nsc_rle_decompress_data(NSC_CONTEXT* context)
255
rles = stream_new(0);
256
rles->p = rles->data = context->nsc_stream->pdata->p;
257
rles->size = context->nsc_stream->pdata->size;
259
for (i = 0; i < 4; i++)
261
origsize = context->OrgByteCount[i];
263
if (i == 3 && context->nsc_stream->PlaneByteCount[i] == 0)
264
stream_set_byte(context->org_buf[i], 0xff, origsize);
265
else if (context->nsc_stream->PlaneByteCount[i] < origsize)
266
nsc_rle_decode(rles, context->org_buf[i], origsize);
268
stream_copy(context->org_buf[i], rles, origsize);
270
context->org_buf[i]->p = context->org_buf[i]->data;
274
void nsc_combine_argb(NSC_CONTEXT* context)
278
bmp = context->bmpdata;
280
for (i = 0; i < (context->width * context->height); i++)
282
stream_read_uint8(context->org_buf[2], *bmp++);
283
stream_read_uint8(context->org_buf[1], *bmp++);
284
stream_read_uint8(context->org_buf[0], *bmp++);
285
stream_read_uint8(context->org_buf[3], *bmp++);
289
void nsc_stream_initialize(NSC_CONTEXT* context, STREAM* s)
293
for (i = 0; i < 4; i++)
294
stream_read_uint32(s, context->nsc_stream->PlaneByteCount[i]);
296
stream_read_uint8(s, context->nsc_stream->colorLossLevel);
297
stream_read_uint8(s, context->nsc_stream->ChromaSubSamplingLevel);
300
context->nsc_stream->pdata = stream_new(0);
301
stream_attach(context->nsc_stream->pdata, s->p, BYTESUM(context->nsc_stream->PlaneByteCount));
304
void nsc_context_initialize(NSC_CONTEXT* context, STREAM* s)
308
nsc_stream_initialize(context, s);
309
context->bmpdata = xzalloc(context->width * context->height * 4);
311
for (i = 0; i < 4; i++)
312
context->OrgByteCount[i]=context->width * context->height;
314
if (context->nsc_stream->ChromaSubSamplingLevel > 0) /* [MS-RDPNSC] 2.2 */
316
uint32 tempWidth,tempHeight;
317
tempWidth = ROUND_UP_TO(context->width, 8);
318
context->OrgByteCount[0] = tempWidth * context->height;
319
tempWidth = tempWidth >> 1 ;
320
tempHeight = ROUND_UP_TO(context->height, 2);
321
tempHeight = tempHeight >> 1;
322
context->OrgByteCount[1] = tempWidth * tempHeight;
323
context->OrgByteCount[2] = tempWidth * tempHeight;
325
for (i = 0; i < 4; i++)
327
tempsz = context->OrgByteCount[i];
329
if (i == 1 || i == 2)
330
tempsz += (tempsz & 0x7) ? (tempsz >> 3) + 0x1 : (tempsz >> 3); /* extra bytes/8 bytes for bitstream to store the 9th bit after colorloss recover */
332
context->org_buf[i] = stream_new(tempsz);
336
void nsc_context_destroy(NSC_CONTEXT* context)
340
for (i = 0;i < 4; i++)
341
stream_free(context->org_buf[i]);
343
stream_detach(context->nsc_stream->pdata);
344
xfree(context->bmpdata);
347
NSC_CONTEXT* nsc_context_new(void)
349
NSC_CONTEXT* nsc_context;
350
nsc_context = xnew(NSC_CONTEXT);
351
nsc_context->nsc_stream = xnew(NSC_STREAM);
355
void nsc_process_message(NSC_CONTEXT* context, uint8* data, uint32 length)
359
stream_attach(s, data, length);
360
nsc_context_initialize(context, s);
363
nsc_rle_decompress_data(context);
365
/* colorloss recover */
366
nsc_colorloss_recover(context);
368
/* Chroma supersample */
369
if (context->nsc_stream->ChromaSubSamplingLevel > 0)
370
nsc_chroma_supersample(context);
372
/* YCoCg to RGB Convert */
373
nsc_ycocg_rgb(context);
375
/* Combine ARGB planes */
376
nsc_combine_argb(context);