From 77790874c8a40051e9443d684a36978829f554d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 4 May 2014 19:46:40 -0400 Subject: [PATCH 1/4] libfreerdp-codec: stub XCrush data compression --- include/freerdp/codec/bulk.h | 40 +++++++++++ include/freerdp/codec/mppc.h | 4 +- include/freerdp/codec/xcrush.h | 69 +++++++++++++++++++ libfreerdp/codec/CMakeLists.txt | 1 + libfreerdp/codec/test/CMakeLists.txt | 1 + .../codec/test/TestFreeRDPCodecXCrush.c | 10 +++ libfreerdp/codec/xcrush.c | 68 ++++++++++++++++++ 7 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 include/freerdp/codec/bulk.h create mode 100644 include/freerdp/codec/xcrush.h create mode 100644 libfreerdp/codec/test/TestFreeRDPCodecXCrush.c create mode 100644 libfreerdp/codec/xcrush.c diff --git a/include/freerdp/codec/bulk.h b/include/freerdp/codec/bulk.h new file mode 100644 index 000000000..ccc6a4d85 --- /dev/null +++ b/include/freerdp/codec/bulk.h @@ -0,0 +1,40 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Bulk Data Compression + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CODEC_BULK_H +#define FREERDP_CODEC_BULK_H + +#include +#include + +/* Level-2 Compression Flags */ + +#define PACKET_COMPRESSED 0x20 +#define PACKET_AT_FRONT 0x40 +#define PACKET_FLUSHED 0x80 + +/* Level-1 Compression Flags */ + +#define L1_PACKET_AT_FRONT 0x04 +#define L1_NO_COMPRESSION 0x02 +#define L1_COMPRESSED 0x01 +#define L1_INNER_COMPRESSION 0x10 + +#endif /* FREERDP_CODEC_BULK_H */ + diff --git a/include/freerdp/codec/mppc.h b/include/freerdp/codec/mppc.h index 6577e6261..fabf63726 100644 --- a/include/freerdp/codec/mppc.h +++ b/include/freerdp/codec/mppc.h @@ -25,9 +25,7 @@ #include -#define PACKET_COMPRESSED 0x20 -#define PACKET_AT_FRONT 0x40 -#define PACKET_FLUSHED 0x80 +#include struct _MPPC_CONTEXT { diff --git a/include/freerdp/codec/xcrush.h b/include/freerdp/codec/xcrush.h new file mode 100644 index 000000000..4be6e2d9e --- /dev/null +++ b/include/freerdp/codec/xcrush.h @@ -0,0 +1,69 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * XCrush (RDP6.1) Bulk Data Compression + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CODEC_XCRUSH_H +#define FREERDP_CODEC_XCRUSH_H + +#include +#include + +#include + +struct _RDP61_MATCH_DETAILS +{ + UINT16 MatchLength; + UINT16 MatchOutputOffset; + UINT32 MatchHistoryOffset; +}; +typedef struct _RDP61_MATCH_DETAILS RDP61_MATCH_DETAILS; + +struct _RDP61_COMPRESSED_DATA +{ + BYTE Level1ComprFlags; + BYTE Level2ComprFlags; + UINT16 MatchCount; + RDP61_MATCH_DETAILS* MatchDetails; + BYTE* Literals; +}; +typedef struct _RDP61_COMPRESSED_DATA RDP61_COMPRESSED_DATA; + +struct _XCRUSH_CONTEXT +{ + BOOL Compressor; +}; +typedef struct _XCRUSH_CONTEXT XCRUSH_CONTEXT; + +#ifdef __cplusplus +extern "C" { +#endif + +FREERDP_API int xcrush_compress(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags); +FREERDP_API int xcrush_decompress(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags); + +FREERDP_API void xcrush_context_reset(XCRUSH_CONTEXT* xcrush); + +FREERDP_API XCRUSH_CONTEXT* xcrush_context_new(BOOL Compressor); +FREERDP_API void xcrush_context_free(XCRUSH_CONTEXT* xcrush); + +#ifdef __cplusplus +} +#endif + +#endif /* FREERDP_CODEC_XCRUSH_H */ + diff --git a/libfreerdp/codec/CMakeLists.txt b/libfreerdp/codec/CMakeLists.txt index 873726542..f6e392f82 100644 --- a/libfreerdp/codec/CMakeLists.txt +++ b/libfreerdp/codec/CMakeLists.txt @@ -48,6 +48,7 @@ set(${MODULE_PREFIX}_SRCS nsc_encode.h nsc_types.h ncrush.c + xcrush.c mppc.c jpeg.c) diff --git a/libfreerdp/codec/test/CMakeLists.txt b/libfreerdp/codec/test/CMakeLists.txt index 0eeb205a0..b63feac4c 100644 --- a/libfreerdp/codec/test/CMakeLists.txt +++ b/libfreerdp/codec/test/CMakeLists.txt @@ -8,6 +8,7 @@ set(${MODULE_PREFIX}_TESTS TestFreeRDPRegion.c TestFreeRDPCodecMppc.c TestFreeRDPCodecNCrush.c + TestFreeRDPCodecXCrush.c TestFreeRDPCodecPlanar.c TestFreeRDPCodecRemoteFX.c) diff --git a/libfreerdp/codec/test/TestFreeRDPCodecXCrush.c b/libfreerdp/codec/test/TestFreeRDPCodecXCrush.c new file mode 100644 index 000000000..84b77b455 --- /dev/null +++ b/libfreerdp/codec/test/TestFreeRDPCodecXCrush.c @@ -0,0 +1,10 @@ +#include +#include + +#include + +int TestFreeRDPCodecXCrush(int argc, char* argv[]) +{ + return 0; +} + diff --git a/libfreerdp/codec/xcrush.c b/libfreerdp/codec/xcrush.c new file mode 100644 index 000000000..cda1d5083 --- /dev/null +++ b/libfreerdp/codec/xcrush.c @@ -0,0 +1,68 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * XCrush (RDP6.1) Bulk Data Compression + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include + +int xcrush_decompress(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) +{ + return 1; +} + +int xcrush_compress(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags) +{ + return 1; +} + +void xcrush_context_reset(XCRUSH_CONTEXT* xcrush) +{ + +} + +XCRUSH_CONTEXT* xcrush_context_new(BOOL Compressor) +{ + XCRUSH_CONTEXT* xcrush; + + xcrush = (XCRUSH_CONTEXT*) calloc(1, sizeof(XCRUSH_CONTEXT)); + + if (xcrush) + { + xcrush->Compressor = Compressor; + + xcrush_context_reset(xcrush); + } + + return xcrush; +} + +void xcrush_context_free(XCRUSH_CONTEXT* xcrush) +{ + if (xcrush) + { + free(xcrush); + } +} + From 9162fcc7d871ed059ec844e1e5ed92460f56b67e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 4 May 2014 21:50:17 -0400 Subject: [PATCH 2/4] libfreerdp-codec: start working on XCrush decompressor --- include/freerdp/codec/xcrush.h | 5 ++ libfreerdp/codec/xcrush.c | 111 ++++++++++++++++++++++++++++++++- libfreerdp/core/bulk.c | 14 ++++- libfreerdp/core/bulk.h | 3 + 4 files changed, 130 insertions(+), 3 deletions(-) diff --git a/include/freerdp/codec/xcrush.h b/include/freerdp/codec/xcrush.h index 4be6e2d9e..cbe1a898e 100644 --- a/include/freerdp/codec/xcrush.h +++ b/include/freerdp/codec/xcrush.h @@ -46,6 +46,11 @@ typedef struct _RDP61_COMPRESSED_DATA RDP61_COMPRESSED_DATA; struct _XCRUSH_CONTEXT { BOOL Compressor; + MPPC_CONTEXT* mppc; + BYTE* HistoryPtr; + UINT32 HistoryOffset; + UINT32 HistoryBufferSize; + BYTE HistoryBuffer[2000000]; }; typedef struct _XCRUSH_CONTEXT XCRUSH_CONTEXT; diff --git a/libfreerdp/codec/xcrush.c b/libfreerdp/codec/xcrush.c index cda1d5083..fd9fabc96 100644 --- a/libfreerdp/codec/xcrush.c +++ b/libfreerdp/codec/xcrush.c @@ -27,9 +27,113 @@ #include +int xcrush_decompress_l1(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) +{ + BYTE* pSrcEnd = NULL; + BYTE* Literals = NULL; + UINT16 MatchCount = 0; + UINT16 MatchIndex = 0; + UINT16 MatchLength = 0; + UINT32 OutputOffset = 0; + BYTE* HistoryPtr = NULL; + BYTE* HistoryBuffer = NULL; + BYTE* HistoryBufferEnd = NULL; + RDP61_MATCH_DETAILS* MatchDetails = NULL; + + if (SrcSize < 1) + return -1; + + if (flags & L1_PACKET_AT_FRONT) + xcrush->HistoryOffset = 0; + + pSrcEnd = &pSrcData[SrcSize]; + HistoryBuffer = xcrush->HistoryBuffer; + HistoryBufferEnd = &(HistoryBuffer[xcrush->HistoryBufferSize]); + xcrush->HistoryPtr = HistoryPtr = &(HistoryBuffer[xcrush->HistoryOffset]); + + if (flags & L1_NO_COMPRESSION) + { + Literals = pSrcData; + } + else + { + if (!(flags & L1_COMPRESSED)) + { + return -1; + } + + if ((pSrcData + 2) > pSrcEnd) + { + return -1; + } + + MatchCount = *((UINT16*) pSrcData); + MatchDetails = (RDP61_MATCH_DETAILS*) &pSrcData[2]; + Literals = (BYTE*) &MatchDetails[MatchCount]; + OutputOffset = 0; + + for (MatchIndex = 0; MatchIndex < MatchCount; MatchIndex++) + { + MatchLength = MatchDetails->MatchLength; + + printf("Match[%d]: Length: %d OutputOffset: %d HistoryOffset: %d\n", + (int) MatchIndex, (int) MatchDetails->MatchLength, + (int) MatchDetails->MatchOutputOffset, (int) MatchDetails->MatchHistoryOffset); + } + } + + if (Literals >= pSrcEnd) + { + xcrush->HistoryOffset = HistoryPtr - HistoryBuffer; + *pDstSize = HistoryPtr - xcrush->HistoryPtr; + *ppDstData = xcrush->HistoryPtr; + return 1; + } + + return 1; +} + int xcrush_decompress(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) { - return 1; + int status = 0; + UINT32 DstSize = 0; + BYTE* pDstData = NULL; + BYTE Level1ComprFlags; + BYTE Level2ComprFlags; + + if (SrcSize < 2) + return -1; + + Level1ComprFlags = pSrcData[0]; + Level2ComprFlags = pSrcData[1]; + + pSrcData += 2; + SrcSize -= 2; + + printf("Compression Flags: L1: 0x%04X L2: 0x%04X\n", Level1ComprFlags, Level2ComprFlags); + + if (Level2ComprFlags & PACKET_COMPRESSED) + { + printf("Level-2 PACKET_COMPRESSED\n"); + + status = mppc_decompress(xcrush->mppc, pSrcData, SrcSize, &pDstData, &DstSize, Level2ComprFlags); + + if (status < 0) + return status; + } + else + { + printf("Level-2 PACKET_UNCOMPRESSED\n"); + + pDstData = pSrcData; + DstSize = SrcSize; + } + + /* Level-1 Decompression */ + + status = xcrush_decompress_l1(xcrush, pDstData, DstSize, ppDstData, pDstSize, Level1ComprFlags); + + return status; } int xcrush_compress(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags) @@ -51,6 +155,10 @@ XCRUSH_CONTEXT* xcrush_context_new(BOOL Compressor) if (xcrush) { xcrush->Compressor = Compressor; + xcrush->mppc = mppc_context_new(1, Compressor); + + xcrush->HistoryOffset = 0; + xcrush->HistoryBufferSize = 2000000; xcrush_context_reset(xcrush); } @@ -62,6 +170,7 @@ void xcrush_context_free(XCRUSH_CONTEXT* xcrush) { if (xcrush) { + mppc_context_free(xcrush->mppc); free(xcrush); } } diff --git a/libfreerdp/core/bulk.c b/libfreerdp/core/bulk.c index f1d7eca1f..c97b43d68 100644 --- a/libfreerdp/core/bulk.c +++ b/libfreerdp/core/bulk.c @@ -23,7 +23,7 @@ #include "bulk.h" -//#define WITH_BULK_DEBUG 1 +#define WITH_BULK_DEBUG 1 const char* bulk_get_compression_flags_string(UINT32 flags) { @@ -137,7 +137,7 @@ int bulk_decompress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstD break; case PACKET_COMPR_TYPE_RDP61: - status = -1; + status = xcrush_decompress(bulk->xcrushRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags); break; case PACKET_COMPR_TYPE_RDP8: @@ -251,8 +251,12 @@ void bulk_reset(rdpBulk* bulk) { mppc_context_reset(bulk->mppcSend); mppc_context_reset(bulk->mppcRecv); + ncrush_context_reset(bulk->ncrushRecv); ncrush_context_reset(bulk->ncrushSend); + + xcrush_context_reset(bulk->xcrushRecv); + xcrush_context_reset(bulk->xcrushSend); } rdpBulk* bulk_new(rdpContext* context) @@ -271,6 +275,9 @@ rdpBulk* bulk_new(rdpContext* context) bulk->ncrushRecv = ncrush_context_new(FALSE); bulk->ncrushSend = ncrush_context_new(TRUE); + bulk->xcrushRecv = xcrush_context_new(FALSE); + bulk->xcrushSend = xcrush_context_new(TRUE); + bulk->CompressionLevel = context->settings->CompressionLevel; bulk->TotalCompressedBytes = 0; @@ -291,5 +298,8 @@ void bulk_free(rdpBulk* bulk) ncrush_context_free(bulk->ncrushRecv); ncrush_context_free(bulk->ncrushSend); + xcrush_context_free(bulk->xcrushRecv); + xcrush_context_free(bulk->xcrushSend); + free(bulk); } diff --git a/libfreerdp/core/bulk.h b/libfreerdp/core/bulk.h index 7b976f8f9..72916edb2 100644 --- a/libfreerdp/core/bulk.h +++ b/libfreerdp/core/bulk.h @@ -26,6 +26,7 @@ typedef struct rdp_bulk rdpBulk; #include #include +#include struct rdp_bulk { @@ -36,6 +37,8 @@ struct rdp_bulk MPPC_CONTEXT* mppcRecv; NCRUSH_CONTEXT* ncrushRecv; NCRUSH_CONTEXT* ncrushSend; + XCRUSH_CONTEXT* xcrushRecv; + XCRUSH_CONTEXT* xcrushSend; BYTE OutputBuffer[65536]; UINT64 TotalCompressedBytes; UINT64 TotalUncompressedBytes; From db328a1e93031072371b9809acf9e1a098b4929f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 5 May 2014 16:26:31 -0400 Subject: [PATCH 3/4] libfreerdp-codec: initial RDP6.1 XCrush bulk data decompression support --- libfreerdp/codec/xcrush.c | 106 ++++++++++++++++++++++++++++---------- libfreerdp/core/bulk.c | 2 +- 2 files changed, 81 insertions(+), 27 deletions(-) diff --git a/libfreerdp/codec/xcrush.c b/libfreerdp/codec/xcrush.c index fd9fabc96..9b7f66d62 100644 --- a/libfreerdp/codec/xcrush.c +++ b/libfreerdp/codec/xcrush.c @@ -27,28 +27,46 @@ #include +int xcrush_copy_bytes(BYTE* dst, BYTE* src, int num) +{ + int index; + + for (index = 0; index < num; index++) + { + dst[index] = src[index]; + } + + return num; +} + int xcrush_decompress_l1(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags) { BYTE* pSrcEnd = NULL; BYTE* Literals = NULL; UINT16 MatchCount = 0; UINT16 MatchIndex = 0; - UINT16 MatchLength = 0; + BYTE* OutputPtr = NULL; + int OutputLength = 0; UINT32 OutputOffset = 0; BYTE* HistoryPtr = NULL; BYTE* HistoryBuffer = NULL; BYTE* HistoryBufferEnd = NULL; + UINT32 HistoryBufferSize = 0; + UINT16 MatchLength = 0; + UINT16 MatchOutputOffset = 0; + UINT32 MatchHistoryOffset = 0; RDP61_MATCH_DETAILS* MatchDetails = NULL; if (SrcSize < 1) - return -1; + return -1001; if (flags & L1_PACKET_AT_FRONT) xcrush->HistoryOffset = 0; pSrcEnd = &pSrcData[SrcSize]; HistoryBuffer = xcrush->HistoryBuffer; - HistoryBufferEnd = &(HistoryBuffer[xcrush->HistoryBufferSize]); + HistoryBufferSize = xcrush->HistoryBufferSize; + HistoryBufferEnd = &(HistoryBuffer[HistoryBufferSize]); xcrush->HistoryPtr = HistoryPtr = &(HistoryBuffer[xcrush->HistoryOffset]); if (flags & L1_NO_COMPRESSION) @@ -58,38 +76,82 @@ int xcrush_decompress_l1(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, else { if (!(flags & L1_COMPRESSED)) - { - return -1; - } + return -1002; if ((pSrcData + 2) > pSrcEnd) - { - return -1; - } + return -1003; MatchCount = *((UINT16*) pSrcData); + MatchDetails = (RDP61_MATCH_DETAILS*) &pSrcData[2]; Literals = (BYTE*) &MatchDetails[MatchCount]; OutputOffset = 0; + if (Literals > pSrcEnd) + return -1004; + for (MatchIndex = 0; MatchIndex < MatchCount; MatchIndex++) { - MatchLength = MatchDetails->MatchLength; + MatchLength = MatchDetails[MatchIndex].MatchLength; + MatchOutputOffset = MatchDetails[MatchIndex].MatchOutputOffset; + MatchHistoryOffset = MatchDetails[MatchIndex].MatchHistoryOffset; - printf("Match[%d]: Length: %d OutputOffset: %d HistoryOffset: %d\n", - (int) MatchIndex, (int) MatchDetails->MatchLength, - (int) MatchDetails->MatchOutputOffset, (int) MatchDetails->MatchHistoryOffset); + if (MatchOutputOffset < OutputOffset) + return -1005; + + if (MatchLength > HistoryBufferSize) + return -1006; + + if (MatchHistoryOffset > HistoryBufferSize) + return -1007; + + OutputLength = MatchOutputOffset - OutputOffset; + + if ((MatchOutputOffset - OutputOffset) > HistoryBufferSize) + return -1008; + + if (OutputLength > 0) + { + if ((&HistoryPtr[OutputLength] >= HistoryBufferEnd) || (Literals >= pSrcEnd) || (&Literals[OutputLength] > pSrcEnd)) + return -1009; + + xcrush_copy_bytes(HistoryPtr, Literals, OutputLength); + + HistoryPtr += OutputLength; + Literals += OutputLength; + OutputOffset += OutputLength; + + if (Literals > pSrcEnd) + return -1010; + } + + OutputPtr = &xcrush->HistoryBuffer[MatchHistoryOffset]; + + if ((&HistoryPtr[MatchLength] >= HistoryBufferEnd) || (&OutputPtr[MatchLength] >= HistoryBufferEnd)) + return -1011; + + xcrush_copy_bytes(HistoryPtr, OutputPtr, MatchLength); + + OutputOffset += MatchLength; + HistoryPtr += MatchLength; } } - if (Literals >= pSrcEnd) + if (Literals < pSrcEnd) { - xcrush->HistoryOffset = HistoryPtr - HistoryBuffer; - *pDstSize = HistoryPtr - xcrush->HistoryPtr; - *ppDstData = xcrush->HistoryPtr; - return 1; + OutputLength = pSrcEnd - Literals; + + if ((&HistoryPtr[OutputLength] >= HistoryBufferEnd) || (&Literals[OutputLength] > pSrcEnd)) + return -1012; + + xcrush_copy_bytes(HistoryPtr, Literals, OutputLength); + HistoryPtr += OutputLength; } + xcrush->HistoryOffset = HistoryPtr - HistoryBuffer; + *pDstSize = HistoryPtr - xcrush->HistoryPtr; + *ppDstData = xcrush->HistoryPtr; + return 1; } @@ -110,12 +172,8 @@ int xcrush_decompress(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BY pSrcData += 2; SrcSize -= 2; - printf("Compression Flags: L1: 0x%04X L2: 0x%04X\n", Level1ComprFlags, Level2ComprFlags); - if (Level2ComprFlags & PACKET_COMPRESSED) { - printf("Level-2 PACKET_COMPRESSED\n"); - status = mppc_decompress(xcrush->mppc, pSrcData, SrcSize, &pDstData, &DstSize, Level2ComprFlags); if (status < 0) @@ -123,14 +181,10 @@ int xcrush_decompress(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BY } else { - printf("Level-2 PACKET_UNCOMPRESSED\n"); - pDstData = pSrcData; DstSize = SrcSize; } - /* Level-1 Decompression */ - status = xcrush_decompress_l1(xcrush, pDstData, DstSize, ppDstData, pDstSize, Level1ComprFlags); return status; diff --git a/libfreerdp/core/bulk.c b/libfreerdp/core/bulk.c index c97b43d68..12486a733 100644 --- a/libfreerdp/core/bulk.c +++ b/libfreerdp/core/bulk.c @@ -23,7 +23,7 @@ #include "bulk.h" -#define WITH_BULK_DEBUG 1 +//#define WITH_BULK_DEBUG 1 const char* bulk_get_compression_flags_string(UINT32 flags) { From 88bee1fa6d7b057ef5d2e494643c8fd219c6e132 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 5 May 2014 20:47:30 -0400 Subject: [PATCH 4/4] libfreerdp-codec: start working on xcrush compressor --- include/freerdp/codec/xcrush.h | 1 + libfreerdp/codec/xcrush.c | 122 +++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) diff --git a/include/freerdp/codec/xcrush.h b/include/freerdp/codec/xcrush.h index cbe1a898e..180b35aea 100644 --- a/include/freerdp/codec/xcrush.h +++ b/include/freerdp/codec/xcrush.h @@ -51,6 +51,7 @@ struct _XCRUSH_CONTEXT UINT32 HistoryOffset; UINT32 HistoryBufferSize; BYTE HistoryBuffer[2000000]; + BYTE BlockBuffer[16384]; }; typedef struct _XCRUSH_CONTEXT XCRUSH_CONTEXT; diff --git a/libfreerdp/codec/xcrush.c b/libfreerdp/codec/xcrush.c index 9b7f66d62..e36b01f01 100644 --- a/libfreerdp/codec/xcrush.c +++ b/libfreerdp/codec/xcrush.c @@ -190,8 +190,130 @@ int xcrush_decompress(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BY return status; } +int xcrush_compress_l1(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags) +{ + UINT32 Flags = 0; + UINT32 HistoryOffset = 0; + BYTE* HistoryPtr = NULL; + BYTE* HistoryBuffer = NULL; + + HistoryOffset = xcrush->HistoryOffset; + HistoryBuffer = xcrush->HistoryBuffer; + HistoryPtr = &HistoryBuffer[HistoryOffset]; + + CopyMemory(HistoryPtr, pSrcData, SrcSize); + xcrush->HistoryOffset += SrcSize; + + if (SrcSize <= 50) + { + Flags |= L1_NO_COMPRESSION; + } + else + { + + } + + *pFlags = Flags; + + return 1; +} + int xcrush_compress(XCRUSH_CONTEXT* xcrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags) { + int status = 0; + UINT32 DstSize = 0; + BYTE* pDstData = NULL; + BYTE* CompressedData = NULL; + UINT32 CompressedDataSize = 0; + BYTE* OriginalData = NULL; + UINT32 OriginalDataSize = 0; + UINT32 Level1ComprFlags = 0; + UINT32 Level2ComprFlags = 0; + UINT32 CompressionLevel = 3; + + if (SrcSize > 16384) + return -1; + + if ((SrcSize + 2) > *pDstSize) + return -1; + + OriginalData = pDstData; + OriginalDataSize = *pDstSize; + + pDstData = xcrush->BlockBuffer; + DstSize = sizeof(xcrush->BlockBuffer); + + status = xcrush_compress_l1(xcrush, pSrcData, SrcSize, &pDstData, &DstSize, &Level1ComprFlags); + + if (status < 0) + return status; + + if (Level1ComprFlags & L1_COMPRESSED) + { + CompressedData = pDstData; + CompressedDataSize = DstSize; + + if (CompressedDataSize > SrcSize) + return -1; + } + else + { + CompressedData = pSrcData; + CompressedDataSize = DstSize; + + if (CompressedDataSize != SrcSize) + return -1; + } + + status = 1; + + pDstData = OriginalData + 2; + DstSize = OriginalDataSize - 2; + + if (DstSize > 50) + { + status = mppc_compress(xcrush->mppc, CompressedData, CompressedDataSize, &pDstData, &DstSize, &Level2ComprFlags); + } + + if (status < 0) + return status; + + if (!(Level2ComprFlags & PACKET_COMPRESSED) || (Level2ComprFlags & PACKET_FLUSHED)) + { + if (CompressedDataSize > DstSize) + return -1; + + DstSize = CompressedDataSize; + CopyMemory(pDstData, CompressedData, CompressedDataSize); + } + + if (Level2ComprFlags & PACKET_COMPRESSED) + { + + } + else + { + if (Level2ComprFlags & PACKET_FLUSHED) + { + + } + else + { + + } + } + + Level1ComprFlags |= L1_INNER_COMPRESSION; + + OriginalData[0] = (BYTE) Level1ComprFlags; + OriginalData[1] = (BYTE) Level2ComprFlags; + + if (*pDstSize < (DstSize + 2)) + return -1; + + *pDstSize = DstSize + 2; + *pFlags = PACKET_COMPRESSED | CompressionLevel; + return 1; }