diff --git a/include/freerdp/codec/nsc.h b/include/freerdp/codec/nsc.h index 951a46f94..2ba5623af 100644 --- a/include/freerdp/codec/nsc.h +++ b/include/freerdp/codec/nsc.h @@ -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; diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c index c412302d9..ed8b4caa0 100644 --- a/libfreerdp/codec/nsc.c +++ b/libfreerdp/codec/nsc.c @@ -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); diff --git a/libfreerdp/codec/nsc_encode.c b/libfreerdp/codec/nsc_encode.c index 007ee2e52..724a6d843 100644 --- a/libfreerdp/codec/nsc_encode.c +++ b/libfreerdp/codec/nsc_encode.c @@ -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); } diff --git a/libfreerdp/codec/nsc_sse2.c b/libfreerdp/codec/nsc_sse2.c index f4f1eb1bf..1a9be3633 100644 --- a/libfreerdp/codec/nsc_sse2.c +++ b/libfreerdp/codec/nsc_sse2.c @@ -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); } diff --git a/server/shadow/shadow_encoder.c b/server/shadow/shadow_encoder.c index cfa118b38..7ab48baaf 100644 --- a/server/shadow/shadow_encoder.c +++ b/server/shadow/shadow_encoder.c @@ -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;