libfreerdp-codec: refactor NSCodec

This commit is contained in:
Marc-André Moreau 2014-09-23 20:00:26 -04:00
parent af858e8f2a
commit 8123a1d9b8
5 changed files with 94 additions and 83 deletions

View File

@ -31,17 +31,6 @@
extern "C" {
#endif
/* NSCODEC_BITMAP_STREAM */
struct _NSC_STREAM
{
UINT32 PlaneByteCount[4];
BYTE ColorLossLevel;
BYTE ChromaSubSamplingLevel;
UINT16 Reserved;
BYTE* Planes;
};
typedef struct _NSC_STREAM NSC_STREAM;
struct _NSC_MESSAGE
{
int x;
@ -54,7 +43,13 @@ struct _NSC_MESSAGE
UINT32 MaxPlaneSize;
BYTE* PlaneBuffers[5];
UINT32 OrgByteCount[4];
UINT32 PlaneByteCount[4];
UINT32 LumaPlaneByteCount;
UINT32 OrangeChromaPlaneByteCount;
UINT32 GreenChromaPlaneByteCount;
UINT32 AlphaPlaneByteCount;
UINT32 ColorLossLevel;
UINT32 ChromaSubsamplingLevel;
};
typedef struct _NSC_MESSAGE NSC_MESSAGE;
@ -64,15 +59,20 @@ typedef struct _NSC_CONTEXT NSC_CONTEXT;
struct _NSC_CONTEXT
{
UINT32 OrgByteCount[4]; /* original byte length of luma, chroma orange, chroma green, alpha variable in order */
NSC_STREAM nsc_stream;
UINT32 OrgByteCount[4];
UINT16 bpp;
UINT16 width;
UINT16 height;
BYTE* BitmapData; /* final argb values in little endian order */
UINT32 BitmapDataLength; /* the maximum length of the buffer that bmpdata points to */
BYTE* BitmapData;
UINT32 BitmapDataLength;
RDP_PIXEL_FORMAT pixel_format;
BYTE* Planes;
UINT32 PlaneByteCount[4];
UINT32 ColorLossLevel;
UINT32 ChromaSubsamplingLevel;
BOOL DynamicColorFidelity;
/* color palette allocated by the application */
const BYTE* palette;

View File

@ -63,14 +63,14 @@ static void nsc_decode(NSC_CONTEXT* context)
bmpdata = context->BitmapData;
rw = ROUND_UP_TO(context->width, 8);
shift = context->nsc_stream.ColorLossLevel - 1; /* colorloss recovery + YCoCg shift */
shift = context->ColorLossLevel - 1; /* colorloss recovery + YCoCg shift */
WLog_Print(context->priv->log, WLOG_DEBUG, "NscDecode: width: %d height: %d ChromaSubSamplingLevel: %d",
context->width, context->height, context->nsc_stream.ChromaSubSamplingLevel);
WLog_Print(context->priv->log, WLOG_DEBUG, "NscDecode: width: %d height: %d ChromaSubsamplingLevel: %d",
context->width, context->height, context->ChromaSubsamplingLevel);
for (y = 0; y < context->height; y++)
{
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
if (context->ChromaSubsamplingLevel)
{
yplane = context->priv->PlaneBuffers[0] + y * rw; /* Y */
coplane = context->priv->PlaneBuffers[1] + (y >> 1) * (rw >> 1); /* Co, supersampled */
@ -98,8 +98,8 @@ static void nsc_decode(NSC_CONTEXT* context)
*bmpdata++ = MINMAX(r_val, 0, 0xFF);
*bmpdata++ = *aplane;
yplane++;
coplane += (context->nsc_stream.ChromaSubSamplingLevel > 0 ? x % 2 : 1);
cgplane += (context->nsc_stream.ChromaSubSamplingLevel > 0 ? x % 2 : 1);
coplane += (context->ChromaSubsamplingLevel ? x % 2 : 1);
cgplane += (context->ChromaSubsamplingLevel ? x % 2 : 1);
aplane++;
}
}
@ -159,12 +159,12 @@ static void nsc_rle_decompress_data(NSC_CONTEXT* context)
UINT32 planeSize;
UINT32 originalSize;
rle = context->nsc_stream.Planes;
rle = context->Planes;
for (i = 0; i < 4; i++)
{
originalSize = context->OrgByteCount[i];
planeSize = context->nsc_stream.PlaneByteCount[i];
planeSize = context->PlaneByteCount[i];
if (planeSize == 0)
FillMemory(context->priv->PlaneBuffers[i], originalSize, 0xFF);
@ -182,13 +182,13 @@ static void nsc_stream_initialize(NSC_CONTEXT* context, wStream* s)
int i;
for (i = 0; i < 4; i++)
Stream_Read_UINT32(s, context->nsc_stream.PlaneByteCount[i]);
Stream_Read_UINT32(s, context->PlaneByteCount[i]);
Stream_Read_UINT8(s, context->nsc_stream.ColorLossLevel);
Stream_Read_UINT8(s, context->nsc_stream.ChromaSubSamplingLevel);
Stream_Seek(s, 2);
Stream_Read_UINT8(s, context->ColorLossLevel); /* ColorLossLevel (1 byte) */
Stream_Read_UINT8(s, context->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
Stream_Seek(s, 2); /* Reserved (2 bytes) */
context->nsc_stream.Planes = Stream_Pointer(s);
context->Planes = Stream_Pointer(s);
}
static void nsc_context_initialize(NSC_CONTEXT* context, wStream* s)
@ -232,7 +232,7 @@ static void nsc_context_initialize(NSC_CONTEXT* context, wStream* s)
context->OrgByteCount[i] = context->width * context->height;
}
if (context->nsc_stream.ChromaSubSamplingLevel > 0) /* [MS-RDPNSC] 2.2 */
if (context->ChromaSubsamplingLevel)
{
context->OrgByteCount[0] = tempWidth * context->height;
context->OrgByteCount[1] = (tempWidth >> 1) * (tempHeight >> 1);
@ -288,8 +288,8 @@ NSC_CONTEXT* nsc_context_new(void)
PROFILER_CREATE(context->priv->prof_nsc_encode, "nsc_encode");
/* Default encoding parameters */
context->nsc_stream.ColorLossLevel = 3;
context->nsc_stream.ChromaSubSamplingLevel = 1;
context->ColorLossLevel = 3;
context->ChromaSubsamplingLevel = 1;
/* init optimized methods */
NSC_INIT_SIMD(context);

View File

@ -57,7 +57,7 @@ static void nsc_context_initialize_encode(NSC_CONTEXT* context)
context->priv->PlaneBuffersLength = length;
}
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
if (context->ChromaSubsamplingLevel)
{
context->OrgByteCount[0] = tempWidth * context->height;
context->OrgByteCount[1] = tempWidth * tempHeight / 4;
@ -93,8 +93,8 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* data, int scan
tempWidth = ROUND_UP_TO(context->width, 8);
tempHeight = ROUND_UP_TO(context->height, 2);
rw = (context->nsc_stream.ChromaSubSamplingLevel > 0 ? tempWidth : context->width);
ccl = context->nsc_stream.ColorLossLevel;
rw = (context->ChromaSubsamplingLevel ? tempWidth : context->width);
ccl = context->ColorLossLevel;
yplane = context->priv->PlaneBuffers[0];
coplane = context->priv->PlaneBuffers[1];
cgplane = context->priv->PlaneBuffers[2];
@ -201,7 +201,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* data, int scan
*aplane++ = a_val;
}
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (x % 2) == 1)
if (context->ChromaSubsamplingLevel && (x % 2) == 1)
{
*yplane = *(yplane - 1);
*coplane = *(coplane - 1);
@ -209,7 +209,7 @@ static void nsc_encode_argb_to_aycocg(NSC_CONTEXT* context, BYTE* data, int scan
}
}
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (y % 2) == 1)
if (context->ChromaSubsamplingLevel && (y % 2) == 1)
{
CopyMemory(yplane + rw, yplane, rw);
CopyMemory(coplane + rw, coplane, rw);
@ -260,7 +260,7 @@ void nsc_encode(NSC_CONTEXT* context, BYTE* bmpdata, int rowstride)
{
nsc_encode_argb_to_aycocg(context, bmpdata, rowstride);
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
if (context->ChromaSubsamplingLevel)
{
nsc_encode_subsampling(context);
}
@ -344,7 +344,7 @@ static void nsc_rle_compress_data(NSC_CONTEXT* context)
planeSize = originalSize;
}
context->nsc_stream.PlaneByteCount[i] = planeSize;
context->PlaneByteCount[i] = planeSize;
}
}
@ -359,7 +359,7 @@ UINT32 nsc_compute_byte_count(NSC_CONTEXT* context, UINT32* ByteCount, UINT32 wi
maxPlaneSize = tempWidth * tempHeight + 16;
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
if (context->ChromaSubsamplingLevel)
{
ByteCount[0] = tempWidth * height;
ByteCount[1] = tempWidth * tempHeight / 4;
@ -469,10 +469,12 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
nsc_rle_compress_data(context);
PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data);
messages[i].PlaneByteCount[0] = context->nsc_stream.PlaneByteCount[0];
messages[i].PlaneByteCount[1] = context->nsc_stream.PlaneByteCount[1];
messages[i].PlaneByteCount[2] = context->nsc_stream.PlaneByteCount[2];
messages[i].PlaneByteCount[3] = context->nsc_stream.PlaneByteCount[3];
messages[i].LumaPlaneByteCount = context->PlaneByteCount[0];
messages[i].OrangeChromaPlaneByteCount = context->PlaneByteCount[1];
messages[i].GreenChromaPlaneByteCount = context->PlaneByteCount[2];
messages[i].AlphaPlaneByteCount = context->PlaneByteCount[3];
messages[i].ColorLossLevel = context->ColorLossLevel;
messages[i].ChromaSubsamplingLevel = context->ChromaSubsamplingLevel;
}
context->priv->PlaneBuffers[0] = NULL;
@ -486,25 +488,31 @@ NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, int x, int y,
int nsc_write_message(NSC_CONTEXT* context, wStream* s, NSC_MESSAGE* message)
{
int i;
UINT32 totalPlaneByteCount;
Stream_EnsureRemainingCapacity(s, 20);
Stream_Write_UINT32(s, message->PlaneByteCount[0]); /* LumaPlaneByteCount (4 bytes) */
Stream_Write_UINT32(s, message->PlaneByteCount[1]); /* OrangeChromaPlaneByteCount (4 bytes) */
Stream_Write_UINT32(s, message->PlaneByteCount[2]); /* GreenChromaPlaneByteCount (4 bytes) */
Stream_Write_UINT32(s, message->PlaneByteCount[3]); /* AlphaPlaneByteCount (4 bytes) */
Stream_Write_UINT8(s, context->nsc_stream.ColorLossLevel); /* ColorLossLevel (1 byte) */
Stream_Write_UINT8(s, context->nsc_stream.ChromaSubSamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
totalPlaneByteCount = message->LumaPlaneByteCount + message->OrangeChromaPlaneByteCount +
message->GreenChromaPlaneByteCount + message->AlphaPlaneByteCount;
Stream_EnsureRemainingCapacity(s, 20 + totalPlaneByteCount);
Stream_Write_UINT32(s, message->LumaPlaneByteCount); /* LumaPlaneByteCount (4 bytes) */
Stream_Write_UINT32(s, message->OrangeChromaPlaneByteCount); /* OrangeChromaPlaneByteCount (4 bytes) */
Stream_Write_UINT32(s, message->GreenChromaPlaneByteCount); /* GreenChromaPlaneByteCount (4 bytes) */
Stream_Write_UINT32(s, message->AlphaPlaneByteCount); /* AlphaPlaneByteCount (4 bytes) */
Stream_Write_UINT8(s, message->ColorLossLevel); /* ColorLossLevel (1 byte) */
Stream_Write_UINT8(s, message->ChromaSubsamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
for (i = 0; i < 4; i++)
{
if (message->PlaneByteCount[i] > 0)
{
Stream_EnsureRemainingCapacity(s, (int) message->PlaneByteCount[i]);
Stream_Write(s, message->PlaneBuffers[i], message->PlaneByteCount[i]);
}
}
if (message->LumaPlaneByteCount)
Stream_Write(s, message->PlaneBuffers[0], message->LumaPlaneByteCount); /* LumaPlane */
if (message->OrangeChromaPlaneByteCount)
Stream_Write(s, message->PlaneBuffers[1], message->OrangeChromaPlaneByteCount); /* OrangeChromaPlane */
if (message->GreenChromaPlaneByteCount)
Stream_Write(s, message->PlaneBuffers[2], message->GreenChromaPlaneByteCount); /* GreenChromaPlane */
if (message->AlphaPlaneByteCount)
Stream_Write(s, message->PlaneBuffers[3], message->AlphaPlaneByteCount); /* AlphaPlane */
return 0;
}
@ -517,7 +525,8 @@ int nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message)
void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* data, int width, int height, int scanline)
{
int i;
NSC_MESSAGE s_message = { 0 };
NSC_MESSAGE* message = &s_message;
context->width = width;
context->height = height;
@ -533,22 +542,17 @@ void nsc_compose_message(NSC_CONTEXT* context, wStream* s, BYTE* data, int width
nsc_rle_compress_data(context);
PROFILER_EXIT(context->priv->prof_nsc_rle_compress_data);
/* Assemble the NSCodec message into stream */
Stream_EnsureRemainingCapacity(s, 20);
Stream_Write_UINT32(s, context->nsc_stream.PlaneByteCount[0]); /* LumaPlaneByteCount (4 bytes) */
Stream_Write_UINT32(s, context->nsc_stream.PlaneByteCount[1]); /* OrangeChromaPlaneByteCount (4 bytes) */
Stream_Write_UINT32(s, context->nsc_stream.PlaneByteCount[2]); /* GreenChromaPlaneByteCount (4 bytes) */
Stream_Write_UINT32(s, context->nsc_stream.PlaneByteCount[3]); /* AlphaPlaneByteCount (4 bytes) */
Stream_Write_UINT8(s, context->nsc_stream.ColorLossLevel); /* ColorLossLevel (1 byte) */
Stream_Write_UINT8(s, context->nsc_stream.ChromaSubSamplingLevel); /* ChromaSubsamplingLevel (1 byte) */
Stream_Write_UINT16(s, 0); /* Reserved (2 bytes) */
message->PlaneBuffers[0] = context->priv->PlaneBuffers[0];
message->PlaneBuffers[1] = context->priv->PlaneBuffers[1];
message->PlaneBuffers[2] = context->priv->PlaneBuffers[2];
message->PlaneBuffers[3] = context->priv->PlaneBuffers[3];
for (i = 0; i < 4; i++)
{
if (context->nsc_stream.PlaneByteCount[i] > 0)
{
Stream_EnsureRemainingCapacity(s, (int) context->nsc_stream.PlaneByteCount[i]);
Stream_Write(s, context->priv->PlaneBuffers[i], context->nsc_stream.PlaneByteCount[i]);
}
}
message->LumaPlaneByteCount = context->PlaneByteCount[0];
message->OrangeChromaPlaneByteCount = context->PlaneByteCount[1];
message->GreenChromaPlaneByteCount = context->PlaneByteCount[2];
message->AlphaPlaneByteCount = context->PlaneByteCount[3];
message->ColorLossLevel = context->ColorLossLevel;
message->ChromaSubsamplingLevel = context->ChromaSubsamplingLevel;
nsc_write_message(context, s, message);
}

View File

@ -56,8 +56,8 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* data, int
tempWidth = ROUND_UP_TO(context->width, 8);
tempHeight = ROUND_UP_TO(context->height, 2);
rw = (context->nsc_stream.ChromaSubSamplingLevel > 0 ? tempWidth : context->width);
ccl = context->nsc_stream.ColorLossLevel;
rw = (context->ChromaSubsamplingLevel > 0 ? tempWidth : context->width);
ccl = context->ColorLossLevel;
yplane = context->priv->PlaneBuffers[0];
coplane = context->priv->PlaneBuffers[1];
cgplane = context->priv->PlaneBuffers[2];
@ -278,7 +278,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* data, int
aplane += 8;
}
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (context->width % 2) == 1)
if (context->ChromaSubsamplingLevel > 0 && (context->width % 2) == 1)
{
context->priv->PlaneBuffers[0][y * rw + context->width] = context->priv->PlaneBuffers[0][y * rw + context->width - 1];
context->priv->PlaneBuffers[1][y * rw + context->width] = context->priv->PlaneBuffers[1][y * rw + context->width - 1];
@ -286,7 +286,7 @@ static void nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context, BYTE* data, int
}
}
if (context->nsc_stream.ChromaSubSamplingLevel > 0 && (y % 2) == 1)
if (context->ChromaSubsamplingLevel > 0 && (y % 2) == 1)
{
CopyMemory(yplane + rw, yplane, rw);
CopyMemory(coplane + rw, coplane, rw);
@ -351,7 +351,7 @@ static void nsc_encode_sse2(NSC_CONTEXT* context, BYTE* data, int scanline)
{
nsc_encode_argb_to_aycocg_sse2(context, data, scanline);
if (context->nsc_stream.ChromaSubSamplingLevel > 0)
if (context->ChromaSubsamplingLevel > 0)
{
nsc_encode_subsampling_sse2(context);
}

View File

@ -142,6 +142,9 @@ int shadow_encoder_init_rfx(rdpShadowEncoder* encoder)
int shadow_encoder_init_nsc(rdpShadowEncoder* encoder)
{
rdpContext* context = (rdpContext*) encoder->client;
rdpSettings* settings = context->settings;
if (!encoder->nsc)
encoder->nsc = nsc_context_new();
@ -159,6 +162,10 @@ int shadow_encoder_init_nsc(rdpShadowEncoder* encoder)
encoder->frameList = ListDictionary_New(TRUE);
}
encoder->nsc->ColorLossLevel = settings->NSCodecColorLossLevel;
encoder->nsc->ChromaSubsamplingLevel = settings->NSCodecAllowSubsampling ? 1 : 0;
encoder->nsc->DynamicColorFidelity = settings->NSCodecAllowDynamicColorFidelity;
encoder->codecs |= FREERDP_CODEC_NSCODEC;
return 1;