libfreerdp-codec: refactor NSCodec code

This commit is contained in:
Marc-André Moreau 2013-08-14 20:57:16 -04:00
parent 08dce6e090
commit e35dae462b
2 changed files with 85 additions and 48 deletions

View File

@ -79,7 +79,9 @@ static void nsc_decode(NSC_CONTEXT* context)
coplane = context->priv->plane_buf[1] + y * context->width; /* Co */ coplane = context->priv->plane_buf[1] + y * context->width; /* Co */
cgplane = context->priv->plane_buf[2] + y * context->width; /* Cg */ cgplane = context->priv->plane_buf[2] + y * context->width; /* Cg */
} }
aplane = context->priv->plane_buf[3] + y * context->width; /* A */ aplane = context->priv->plane_buf[3] + y * context->width; /* A */
for (x = 0; x < context->width; x++) for (x = 0; x < context->width; x++)
{ {
y_val = (INT16) *yplane; y_val = (INT16) *yplane;
@ -100,13 +102,14 @@ static void nsc_decode(NSC_CONTEXT* context)
} }
} }
static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 origsz) static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 originalSize)
{ {
UINT32 len; UINT32 len;
UINT32 left; UINT32 left;
BYTE value; BYTE value;
left = origsz; left = originalSize;
while (left > 4) while (left > 4)
{ {
value = *in++; value = *in++;
@ -119,6 +122,7 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 origsz)
else if (value == *in) else if (value == *in)
{ {
in++; in++;
if (*in < 0xFF) if (*in < 0xFF)
{ {
len = (UINT32) *in++; len = (UINT32) *in++;
@ -130,7 +134,8 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 origsz)
len = *((UINT32*) in); len = *((UINT32*) in);
in += 4; in += 4;
} }
memset(out, value, len);
FillMemory(out, len, value);
out += len; out += len;
left -= len; left -= len;
} }
@ -148,24 +153,24 @@ static void nsc_rle_decompress_data(NSC_CONTEXT* context)
{ {
UINT16 i; UINT16 i;
BYTE* rle; BYTE* rle;
UINT32 origsize; UINT32 planeSize;
UINT32 planesize; UINT32 originalSize;
rle = context->nsc_stream.Planes; rle = context->nsc_stream.Planes;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
origsize = context->OrgByteCount[i]; originalSize = context->OrgByteCount[i];
planesize = context->nsc_stream.PlaneByteCount[i]; planeSize = context->nsc_stream.PlaneByteCount[i];
if (planesize == 0) if (planeSize == 0)
memset(context->priv->plane_buf[i], 0xff, origsize); FillMemory(context->priv->plane_buf[i], originalSize, 0xFF);
else if (planesize < origsize) else if (planeSize < originalSize)
nsc_rle_decode(rle, context->priv->plane_buf[i], origsize); nsc_rle_decode(rle, context->priv->plane_buf[i], originalSize);
else else
memcpy(context->priv->plane_buf[i], rle, origsize); CopyMemory(context->priv->plane_buf[i], rle, originalSize);
rle += planesize; rle += planeSize;
} }
} }
@ -192,7 +197,8 @@ static void nsc_context_initialize(NSC_CONTEXT* context, wStream* s)
nsc_stream_initialize(context, s); nsc_stream_initialize(context, s);
length = context->width * context->height * 4; length = context->width * context->height * 4;
if (context->bmpdata == NULL)
if (!context->bmpdata)
{ {
context->bmpdata = malloc(length + 16); context->bmpdata = malloc(length + 16);
ZeroMemory(context->bmpdata, length + 16); ZeroMemory(context->bmpdata, length + 16);
@ -206,12 +212,15 @@ static void nsc_context_initialize(NSC_CONTEXT* context, wStream* s)
tempWidth = ROUND_UP_TO(context->width, 8); tempWidth = ROUND_UP_TO(context->width, 8);
tempHeight = ROUND_UP_TO(context->height, 2); tempHeight = ROUND_UP_TO(context->height, 2);
/* The maximum length a decoded plane can reach in all cases */ /* The maximum length a decoded plane can reach in all cases */
length = tempWidth * tempHeight; length = tempWidth * tempHeight;
if (length > context->priv->plane_buf_length) if (length > context->priv->plane_buf_length)
{ {
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
context->priv->plane_buf[i] = (BYTE*) realloc(context->priv->plane_buf[i], length); context->priv->plane_buf[i] = (BYTE*) realloc(context->priv->plane_buf[i], length);
context->priv->plane_buf_length = length; context->priv->plane_buf_length = length;
} }
@ -250,6 +259,7 @@ void nsc_context_free(NSC_CONTEXT* context)
context->priv->plane_buf[i] = NULL; context->priv->plane_buf[i] = NULL;
} }
} }
if (context->bmpdata) if (context->bmpdata)
free(context->bmpdata); free(context->bmpdata);
@ -266,15 +276,17 @@ void nsc_context_free(NSC_CONTEXT* context)
NSC_CONTEXT* nsc_context_new(void) NSC_CONTEXT* nsc_context_new(void)
{ {
NSC_CONTEXT* nsc_context;
UINT8 i; UINT8 i;
NSC_CONTEXT* nsc_context;
nsc_context = (NSC_CONTEXT*) calloc(1, sizeof(NSC_CONTEXT)); nsc_context = (NSC_CONTEXT*) calloc(1, sizeof(NSC_CONTEXT));
nsc_context->priv = (NSC_CONTEXT_PRIV*) calloc(1, sizeof(NSC_CONTEXT_PRIV)); nsc_context->priv = (NSC_CONTEXT_PRIV*) calloc(1, sizeof(NSC_CONTEXT_PRIV));
for (i=0; i < 5; ++i)
for (i = 0; i < 5; ++i)
{ {
nsc_context->priv->plane_buf[i] = NULL; nsc_context->priv->plane_buf[i] = NULL;
} }
nsc_context->bmpdata = NULL; nsc_context->bmpdata = NULL;
nsc_context->decode = nsc_decode; nsc_context->decode = nsc_decode;
@ -298,34 +310,39 @@ NSC_CONTEXT* nsc_context_new(void)
void nsc_context_set_pixel_format(NSC_CONTEXT* context, RDP_PIXEL_FORMAT pixel_format) void nsc_context_set_pixel_format(NSC_CONTEXT* context, RDP_PIXEL_FORMAT pixel_format)
{ {
context->pixel_format = pixel_format; context->pixel_format = pixel_format;
switch (pixel_format) switch (pixel_format)
{ {
case RDP_PIXEL_FORMAT_B8G8R8A8: case RDP_PIXEL_FORMAT_B8G8R8A8:
case RDP_PIXEL_FORMAT_R8G8B8A8: case RDP_PIXEL_FORMAT_R8G8B8A8:
context->bpp = 32; context->bpp = 32;
break; break;
case RDP_PIXEL_FORMAT_B8G8R8: case RDP_PIXEL_FORMAT_B8G8R8:
case RDP_PIXEL_FORMAT_R8G8B8: case RDP_PIXEL_FORMAT_R8G8B8:
context->bpp = 24; context->bpp = 24;
break; break;
case RDP_PIXEL_FORMAT_B5G6R5_LE: case RDP_PIXEL_FORMAT_B5G6R5_LE:
case RDP_PIXEL_FORMAT_R5G6B5_LE: case RDP_PIXEL_FORMAT_R5G6B5_LE:
context->bpp = 16; context->bpp = 16;
break; break;
case RDP_PIXEL_FORMAT_P4_PLANER: case RDP_PIXEL_FORMAT_P4_PLANER:
context->bpp = 4; context->bpp = 4;
break; break;
case RDP_PIXEL_FORMAT_P8: case RDP_PIXEL_FORMAT_P8:
context->bpp = 8; context->bpp = 8;
break; break;
default: default:
context->bpp = 0; context->bpp = 0;
break; break;
} }
} }
void nsc_process_message(NSC_CONTEXT* context, UINT16 bpp, void nsc_process_message(NSC_CONTEXT* context, UINT16 bpp, UINT16 width, UINT16 height, BYTE* data, UINT32 length)
UINT16 width, UINT16 height, BYTE* data, UINT32 length)
{ {
wStream* s; wStream* s;

View File

@ -28,6 +28,8 @@
#include <stdint.h> #include <stdint.h>
#endif #endif
#include <winpr/crt.h>
#include <freerdp/codec/nsc.h> #include <freerdp/codec/nsc.h>
#include "nsc_types.h" #include "nsc_types.h"
@ -42,12 +44,15 @@ static void nsc_context_initialize_encode(NSC_CONTEXT* context)
tempWidth = ROUND_UP_TO(context->width, 8); tempWidth = ROUND_UP_TO(context->width, 8);
tempHeight = ROUND_UP_TO(context->height, 2); tempHeight = ROUND_UP_TO(context->height, 2);
/* The maximum length a decoded plane can reach in all cases */ /* The maximum length a decoded plane can reach in all cases */
length = tempWidth * tempHeight + 16; length = tempWidth * tempHeight + 16;
if (length > context->priv->plane_buf_length) if (length > context->priv->plane_buf_length)
{ {
for (i = 0; i < 5; i++) for (i = 0; i < 5; i++)
context->priv->plane_buf[i] = (BYTE*) realloc(context->priv->plane_buf[i], length); context->priv->plane_buf[i] = (BYTE*) realloc(context->priv->plane_buf[i], length);
context->priv->plane_buf_length = length; context->priv->plane_buf_length = length;
} }
@ -101,6 +106,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
coplane = context->priv->plane_buf[1] + y * rw; coplane = context->priv->plane_buf[1] + y * rw;
cgplane = context->priv->plane_buf[2] + y * rw; cgplane = context->priv->plane_buf[2] + y * rw;
aplane = context->priv->plane_buf[3] + y * context->width; aplane = context->priv->plane_buf[3] + y * context->width;
for (x = 0; x < context->width; x++) for (x = 0; x < context->width; x++)
{ {
switch (context->pixel_format) switch (context->pixel_format)
@ -111,24 +117,28 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
r_val = *src++; r_val = *src++;
a_val = *src++; a_val = *src++;
break; break;
case RDP_PIXEL_FORMAT_R8G8B8A8: case RDP_PIXEL_FORMAT_R8G8B8A8:
r_val = *src++; r_val = *src++;
g_val = *src++; g_val = *src++;
b_val = *src++; b_val = *src++;
a_val = *src++; a_val = *src++;
break; break;
case RDP_PIXEL_FORMAT_B8G8R8: case RDP_PIXEL_FORMAT_B8G8R8:
b_val = *src++; b_val = *src++;
g_val = *src++; g_val = *src++;
r_val = *src++; r_val = *src++;
a_val = 0xFF; a_val = 0xFF;
break; break;
case RDP_PIXEL_FORMAT_R8G8B8: case RDP_PIXEL_FORMAT_R8G8B8:
r_val = *src++; r_val = *src++;
g_val = *src++; g_val = *src++;
b_val = *src++; b_val = *src++;
a_val = 0xFF; a_val = 0xFF;
break; break;
case RDP_PIXEL_FORMAT_B5G6R5_LE: case RDP_PIXEL_FORMAT_B5G6R5_LE:
b_val = (INT16) (((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); b_val = (INT16) (((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5));
g_val = (INT16) ((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); g_val = (INT16) ((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3));
@ -136,6 +146,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
a_val = 0xFF; a_val = 0xFF;
src += 2; src += 2;
break; break;
case RDP_PIXEL_FORMAT_R5G6B5_LE: case RDP_PIXEL_FORMAT_R5G6B5_LE:
r_val = (INT16) (((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5)); r_val = (INT16) (((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5));
g_val = (INT16) ((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3)); g_val = (INT16) ((((*(src + 1)) & 0x07) << 5) | (((*src) & 0xE0) >> 3));
@ -143,6 +154,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
a_val = 0xFF; a_val = 0xFF;
src += 2; src += 2;
break; break;
case RDP_PIXEL_FORMAT_P4_PLANER: case RDP_PIXEL_FORMAT_P4_PLANER:
{ {
int shift; int shift;
@ -162,6 +174,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
} }
a_val = 0xFF; a_val = 0xFF;
break; break;
case RDP_PIXEL_FORMAT_P8: case RDP_PIXEL_FORMAT_P8:
{ {
int idx = (*src) * 3; int idx = (*src) * 3;
@ -173,16 +186,20 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
} }
a_val = 0xFF; a_val = 0xFF;
break; break;
default: default:
r_val = g_val = b_val = a_val = 0; r_val = g_val = b_val = a_val = 0;
break; break;
} }
*yplane++ = (BYTE) ((r_val >> 2) + (g_val >> 1) + (b_val >> 2)); *yplane++ = (BYTE) ((r_val >> 2) + (g_val >> 1) + (b_val >> 2));
/* Perform color loss reduction here */ /* Perform color loss reduction here */
*coplane++ = (BYTE) ((r_val - b_val) >> ccl); *coplane++ = (BYTE) ((r_val - b_val) >> ccl);
*cgplane++ = (BYTE) ((-(r_val >> 1) + g_val - (b_val >> 1)) >> ccl); *cgplane++ = (BYTE) ((-(r_val >> 1) + g_val - (b_val >> 1)) >> ccl);
*aplane++ = a_val; *aplane++ = a_val;
} }
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (x % 2) == 1) if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (x % 2) == 1)
{ {
*yplane = *(yplane - 1); *yplane = *(yplane - 1);
@ -190,11 +207,12 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
*cgplane = *(cgplane - 1); *cgplane = *(cgplane - 1);
} }
} }
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (y % 2) == 1) if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (y % 2) == 1)
{ {
memcpy(yplane + rw, yplane, rw); CopyMemory(yplane + rw, yplane, rw);
memcpy(coplane + rw, coplane, rw); CopyMemory(coplane + rw, coplane, rw);
memcpy(cgplane + rw, cgplane, rw); CopyMemory(cgplane + rw, cgplane, rw);
} }
} }
@ -222,6 +240,7 @@ static void nsc_encode_subsampling(NSC_CONTEXT* context)
co_src1 = co_src0 + tempWidth; co_src1 = co_src0 + tempWidth;
cg_src0 = (INT8*) context->priv->plane_buf[2] + (y << 1) * tempWidth; cg_src0 = (INT8*) context->priv->plane_buf[2] + (y << 1) * tempWidth;
cg_src1 = cg_src0 + tempWidth; cg_src1 = cg_src0 + tempWidth;
for (x = 0; x < tempWidth >> 1; x++) for (x = 0; x < tempWidth >> 1; x++)
{ {
*co_dst++ = (BYTE) (((INT16) *co_src0 + (INT16) *(co_src0 + 1) + *co_dst++ = (BYTE) (((INT16) *co_src0 + (INT16) *(co_src0 + 1) +
@ -239,24 +258,25 @@ static void nsc_encode_subsampling(NSC_CONTEXT* context)
void nsc_encode(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride) void nsc_encode(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride)
{ {
nsc_encode_argb_to_aycocg(context, bmpdata, rowstride); nsc_encode_argb_to_aycocg(context, bmpdata, rowstride);
if (context->nsc_stream.ChromaSubSamplingLevel > 0) if (context->nsc_stream.ChromaSubSamplingLevel > 0)
{ {
nsc_encode_subsampling(context); nsc_encode_subsampling(context);
} }
} }
static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz) static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 originalSize)
{ {
UINT32 left; UINT32 left;
UINT32 runlength = 1; UINT32 runlength = 1;
UINT32 planesize = 0; UINT32 planeSize = 0;
left = origsz; left = originalSize;
/** /**
* We quit the loop if the running compressed size is larger than the original. * We quit the loop if the running compressed size is larger than the original.
* In such cases data will be sent uncompressed. * In such cases data will be sent uncompressed.
*/ */
while (left > 4 && planesize < origsz - 4) while (left > 4 && planeSize < originalSize - 4)
{ {
if (left > 5 && *in == *(in + 1)) if (left > 5 && *in == *(in + 1))
{ {
@ -265,7 +285,7 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz)
else if (runlength == 1) else if (runlength == 1)
{ {
*out++ = *in; *out++ = *in;
planesize++; planeSize++;
} }
else if (runlength < 256) else if (runlength < 256)
{ {
@ -273,7 +293,7 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz)
*out++ = *in; *out++ = *in;
*out++ = runlength - 2; *out++ = runlength - 2;
runlength = 1; runlength = 1;
planesize += 3; planeSize += 3;
} }
else else
{ {
@ -285,52 +305,52 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz)
*out++ = (runlength & 0x00FF0000) >> 16; *out++ = (runlength & 0x00FF0000) >> 16;
*out++ = (runlength & 0xFF000000) >> 24; *out++ = (runlength & 0xFF000000) >> 24;
runlength = 1; runlength = 1;
planesize += 7; planeSize += 7;
} }
in++; in++;
left--; left--;
} }
if (planesize < origsz - 4)
{
memcpy(out, in, 4);
}
planesize += 4;
return planesize; if (planeSize < originalSize - 4)
CopyMemory(out, in, 4);
planeSize += 4;
return planeSize;
} }
static void nsc_rle_compress_data(NSC_CONTEXT* context) static void nsc_rle_compress_data(NSC_CONTEXT* context)
{ {
UINT16 i; UINT16 i;
BYTE* rle; BYTE* rle;
UINT32 origsize; UINT32 planeSize;
UINT32 planesize; UINT32 originalSize;
rle = context->nsc_stream.Planes; rle = context->nsc_stream.Planes;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
{ {
origsize = context->OrgByteCount[i]; originalSize = context->OrgByteCount[i];
if (origsize == 0)
if (originalSize == 0)
{ {
planesize = 0; planeSize = 0;
} }
else else
{ {
planesize = nsc_rle_encode(context->priv->plane_buf[i], planeSize = nsc_rle_encode(context->priv->plane_buf[i], context->priv->plane_buf[4], originalSize);
context->priv->plane_buf[4], origsize);
if (planesize < origsize) if (planeSize < originalSize)
memcpy(context->priv->plane_buf[i], context->priv->plane_buf[4], planesize); CopyMemory(context->priv->plane_buf[i], context->priv->plane_buf[4], planeSize);
else else
planesize = origsize; planeSize = originalSize;
} }
context->nsc_stream.PlaneByteCount[i] = planesize; context->nsc_stream.PlaneByteCount[i] = planeSize;
} }
} }
void nsc_compose_message(NSC_CONTEXT* context, wStream* s, void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* bmpdata, int width, int height, int scanline)
BYTE* bmpdata, int width, int height, int rowstride)
{ {
int i; int i;
@ -340,7 +360,7 @@ void nsc_compose_message(NSC_CONTEXT* context, wStream* s,
/* ARGB to AYCoCg conversion, chroma subsampling and colorloss reduction */ /* ARGB to AYCoCg conversion, chroma subsampling and colorloss reduction */
PROFILER_ENTER(context->priv->prof_nsc_encode); PROFILER_ENTER(context->priv->prof_nsc_encode);
context->encode(context, bmpdata, rowstride); context->encode(context, bmpdata, scanline);
PROFILER_EXIT(context->priv->prof_nsc_encode); PROFILER_EXIT(context->priv->prof_nsc_encode);
/* RLE encode */ /* RLE encode */