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 */
cgplane = context->priv->plane_buf[2] + y * context->width; /* Cg */
}
aplane = context->priv->plane_buf[3] + y * context->width; /* A */
for (x = 0; x < context->width; x++)
{
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 left;
BYTE value;
left = origsz;
left = originalSize;
while (left > 4)
{
value = *in++;
@ -119,6 +122,7 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 origsz)
else if (value == *in)
{
in++;
if (*in < 0xFF)
{
len = (UINT32) *in++;
@ -130,7 +134,8 @@ static void nsc_rle_decode(BYTE* in, BYTE* out, UINT32 origsz)
len = *((UINT32*) in);
in += 4;
}
memset(out, value, len);
FillMemory(out, len, value);
out += len;
left -= len;
}
@ -148,24 +153,24 @@ static void nsc_rle_decompress_data(NSC_CONTEXT* context)
{
UINT16 i;
BYTE* rle;
UINT32 origsize;
UINT32 planesize;
UINT32 planeSize;
UINT32 originalSize;
rle = context->nsc_stream.Planes;
for (i = 0; i < 4; i++)
{
origsize = context->OrgByteCount[i];
planesize = context->nsc_stream.PlaneByteCount[i];
originalSize = context->OrgByteCount[i];
planeSize = context->nsc_stream.PlaneByteCount[i];
if (planesize == 0)
memset(context->priv->plane_buf[i], 0xff, origsize);
else if (planesize < origsize)
nsc_rle_decode(rle, context->priv->plane_buf[i], origsize);
if (planeSize == 0)
FillMemory(context->priv->plane_buf[i], originalSize, 0xFF);
else if (planeSize < originalSize)
nsc_rle_decode(rle, context->priv->plane_buf[i], originalSize);
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);
length = context->width * context->height * 4;
if (context->bmpdata == NULL)
if (!context->bmpdata)
{
context->bmpdata = malloc(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);
tempHeight = ROUND_UP_TO(context->height, 2);
/* The maximum length a decoded plane can reach in all cases */
length = tempWidth * tempHeight;
if (length > context->priv->plane_buf_length)
{
for (i = 0; i < 4; i++)
context->priv->plane_buf[i] = (BYTE*) realloc(context->priv->plane_buf[i], length);
context->priv->plane_buf_length = length;
}
@ -250,6 +259,7 @@ void nsc_context_free(NSC_CONTEXT* context)
context->priv->plane_buf[i] = NULL;
}
}
if (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;
UINT8 i;
NSC_CONTEXT* nsc_context;
nsc_context = (NSC_CONTEXT*) calloc(1, sizeof(NSC_CONTEXT));
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->bmpdata = NULL;
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)
{
context->pixel_format = pixel_format;
switch (pixel_format)
{
case RDP_PIXEL_FORMAT_B8G8R8A8:
case RDP_PIXEL_FORMAT_R8G8B8A8:
context->bpp = 32;
break;
case RDP_PIXEL_FORMAT_B8G8R8:
case RDP_PIXEL_FORMAT_R8G8B8:
context->bpp = 24;
break;
case RDP_PIXEL_FORMAT_B5G6R5_LE:
case RDP_PIXEL_FORMAT_R5G6B5_LE:
context->bpp = 16;
break;
case RDP_PIXEL_FORMAT_P4_PLANER:
context->bpp = 4;
break;
case RDP_PIXEL_FORMAT_P8:
context->bpp = 8;
break;
default:
context->bpp = 0;
break;
}
}
void nsc_process_message(NSC_CONTEXT* context, UINT16 bpp,
UINT16 width, UINT16 height, BYTE* data, UINT32 length)
void nsc_process_message(NSC_CONTEXT* context, UINT16 bpp, UINT16 width, UINT16 height, BYTE* data, UINT32 length)
{
wStream* s;

View File

@ -28,6 +28,8 @@
#include <stdint.h>
#endif
#include <winpr/crt.h>
#include <freerdp/codec/nsc.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);
tempHeight = ROUND_UP_TO(context->height, 2);
/* The maximum length a decoded plane can reach in all cases */
length = tempWidth * tempHeight + 16;
if (length > context->priv->plane_buf_length)
{
for (i = 0; i < 5; i++)
context->priv->plane_buf[i] = (BYTE*) realloc(context->priv->plane_buf[i], 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;
cgplane = context->priv->plane_buf[2] + y * rw;
aplane = context->priv->plane_buf[3] + y * context->width;
for (x = 0; x < context->width; x++)
{
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++;
a_val = *src++;
break;
case RDP_PIXEL_FORMAT_R8G8B8A8:
r_val = *src++;
g_val = *src++;
b_val = *src++;
a_val = *src++;
break;
case RDP_PIXEL_FORMAT_B8G8R8:
b_val = *src++;
g_val = *src++;
r_val = *src++;
a_val = 0xFF;
break;
case RDP_PIXEL_FORMAT_R8G8B8:
r_val = *src++;
g_val = *src++;
b_val = *src++;
a_val = 0xFF;
break;
case RDP_PIXEL_FORMAT_B5G6R5_LE:
b_val = (INT16) (((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5));
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;
src += 2;
break;
case RDP_PIXEL_FORMAT_R5G6B5_LE:
r_val = (INT16) (((*(src + 1)) & 0xF8) | ((*(src + 1)) >> 5));
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;
src += 2;
break;
case RDP_PIXEL_FORMAT_P4_PLANER:
{
int shift;
@ -162,6 +174,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* bmpdata, int r
}
a_val = 0xFF;
break;
case RDP_PIXEL_FORMAT_P8:
{
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;
break;
default:
r_val = g_val = b_val = a_val = 0;
break;
}
*yplane++ = (BYTE) ((r_val >> 2) + (g_val >> 1) + (b_val >> 2));
/* Perform color loss reduction here */
*coplane++ = (BYTE) ((r_val - b_val) >> ccl);
*cgplane++ = (BYTE) ((-(r_val >> 1) + g_val - (b_val >> 1)) >> ccl);
*aplane++ = a_val;
}
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (x % 2) == 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);
}
}
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (y % 2) == 1)
{
memcpy(yplane + rw, yplane, rw);
memcpy(coplane + rw, coplane, rw);
memcpy(cgplane + rw, cgplane, rw);
CopyMemory(yplane + rw, yplane, rw);
CopyMemory(coplane + rw, coplane, rw);
CopyMemory(cgplane + rw, cgplane, rw);
}
}
@ -222,6 +240,7 @@ static void nsc_encode_subsampling(NSC_CONTEXT* context)
co_src1 = co_src0 + tempWidth;
cg_src0 = (INT8*) context->priv->plane_buf[2] + (y << 1) * tempWidth;
cg_src1 = cg_src0 + tempWidth;
for (x = 0; x < tempWidth >> 1; x++)
{
*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)
{
nsc_encode_argb_to_aycocg(context, bmpdata, rowstride);
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
{
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 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.
* 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))
{
@ -265,7 +285,7 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz)
else if (runlength == 1)
{
*out++ = *in;
planesize++;
planeSize++;
}
else if (runlength < 256)
{
@ -273,7 +293,7 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz)
*out++ = *in;
*out++ = runlength - 2;
runlength = 1;
planesize += 3;
planeSize += 3;
}
else
{
@ -285,52 +305,52 @@ static UINT32 nsc_rle_encode(BYTE* in, BYTE* out, UINT32 origsz)
*out++ = (runlength & 0x00FF0000) >> 16;
*out++ = (runlength & 0xFF000000) >> 24;
runlength = 1;
planesize += 7;
planeSize += 7;
}
in++;
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)
{
UINT16 i;
BYTE* rle;
UINT32 origsize;
UINT32 planesize;
UINT32 planeSize;
UINT32 originalSize;
rle = context->nsc_stream.Planes;
for (i = 0; i < 4; i++)
{
origsize = context->OrgByteCount[i];
if (origsize == 0)
originalSize = context->OrgByteCount[i];
if (originalSize == 0)
{
planesize = 0;
planeSize = 0;
}
else
{
planesize = nsc_rle_encode(context->priv->plane_buf[i],
context->priv->plane_buf[4], origsize);
if (planesize < origsize)
memcpy(context->priv->plane_buf[i], context->priv->plane_buf[4], planesize);
planeSize = nsc_rle_encode(context->priv->plane_buf[i], context->priv->plane_buf[4], originalSize);
if (planeSize < originalSize)
CopyMemory(context->priv->plane_buf[i], context->priv->plane_buf[4], planeSize);
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,
BYTE* bmpdata, int width, int height, int rowstride)
void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* bmpdata, int width, int height, int scanline)
{
int i;
@ -340,7 +360,7 @@ void nsc_compose_message(NSC_CONTEXT* context, wStream* s,
/* ARGB to AYCoCg conversion, chroma subsampling and colorloss reduction */
PROFILER_ENTER(context->priv->prof_nsc_encode);
context->encode(context, bmpdata, rowstride);
context->encode(context, bmpdata, scanline);
PROFILER_EXIT(context->priv->prof_nsc_encode);
/* RLE encode */