libfreerdp-codec: start hooking new NCrush decompressor

This commit is contained in:
Marc-André Moreau 2014-03-16 20:54:07 -04:00
parent 20019f10b2
commit 698cae2052
4 changed files with 100 additions and 53 deletions

View File

@ -32,8 +32,9 @@ struct _NCRUSH_CONTEXT
BOOL Compressor;
BYTE* HistoryPtr;
UINT32 HistoryOffset;
UINT32 HistoryBufferSize;
UINT32 HistoryEndOffset;
BYTE HistoryBuffer[65536];
UINT32 HistoryBufferFence;
UINT32 OffsetCache[4];
};
typedef struct _NCRUSH_CONTEXT NCRUSH_CONTEXT;
@ -45,6 +46,8 @@ extern "C" {
FREERDP_API int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE* pDstData, UINT32* pDstSize, UINT32* pFlags);
FREERDP_API int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags);
FREERDP_API void ncrush_context_reset(NCRUSH_CONTEXT* ncrush);
FREERDP_API NCRUSH_CONTEXT* ncrush_context_new(BOOL Compressor);
FREERDP_API void ncrush_context_free(NCRUSH_CONTEXT* ncrush);

View File

@ -1115,6 +1115,7 @@ UINT32 LOMBaseLUT[30] =
int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)
{
UINT32 index;
UINT32 bits;
UINT32 nbits;
BYTE* SrcPtr;
@ -1125,6 +1126,7 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
UINT32 BitLength;
UINT32 MaskedBits;
UINT32 CopyOffset;
UINT32 CopyLength;
UINT32 OldCopyOffset;
UINT32 LengthOfMatch;
UINT32 CopyOffsetIndex;
@ -1132,30 +1134,36 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
BYTE* HistoryPtr;
BYTE* HistoryBuffer;
BYTE* HistoryBufferEnd;
UINT32 HistoryBufferSize;
UINT32 CopyOffsetBits = 0;
UINT32 CopyOffsetBase = 0;
UINT32 LengthOfMatchBits = 0;
UINT32 LengthOfMatchBase = 0;
BYTE* CopyOffsetPtr = NULL;
if (ncrush->HistoryEndOffset != 65535)
return -1;
HistoryBuffer = ncrush->HistoryBuffer;
HistoryBufferSize = ncrush->HistoryBufferSize;
HistoryBufferEnd = &HistoryBuffer[HistoryBufferSize - 1];
HistoryBufferEnd = &HistoryBuffer[ncrush->HistoryEndOffset];
if (flags & PACKET_AT_FRONT)
{
printf("PACKET_AT_FRONT\n");
if ((ncrush->HistoryPtr - 32768) <= HistoryBuffer)
return -1;
CopyMemory(HistoryBuffer, (ncrush->HistoryPtr - 32768), 32768);
MoveMemory(HistoryBuffer, (ncrush->HistoryPtr - 32768), 32768);
ncrush->HistoryPtr = &(HistoryBuffer[32768]);
ZeroMemory(&HistoryBuffer[32768], 32768);
}
if (flags & PACKET_FLUSHED)
{
printf("PACKET_FLUSHED\n");
ncrush->HistoryPtr = HistoryBuffer;
ZeroMemory(HistoryBuffer, ncrush->HistoryBufferSize);
ZeroMemory(HistoryBuffer, sizeof(ncrush->HistoryBuffer));
ZeroMemory(&(ncrush->OffsetCache), sizeof(ncrush->OffsetCache));
}
@ -1163,6 +1171,8 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
if (!(flags & PACKET_COMPRESSED))
{
printf("PACKET_UNCOMPRESSED\n");
CopyMemory(HistoryPtr, pSrcData, SrcSize);
HistoryPtr += SrcSize;
ncrush->HistoryPtr = HistoryPtr;
@ -1203,10 +1213,8 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
*HistoryPtr++ = Literal;
}
if (IndexLEC <= 256)
{
if (IndexLEC == 256)
break; /* EOS */
}
CopyOffsetIndex = IndexLEC - 257;
@ -1238,11 +1246,11 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
Mask = *((UINT16*) &HuffTableMask[(2 * LengthOfMatchBits) + 3]);
MaskedBits = bits & Mask;
LengthOfMatchBase += MaskedBits;
bits >>= LengthOfMatchBits;
nbits -= LengthOfMatchBits;
LengthOfMatchBase += MaskedBits;
NCrushFetchBits();
}
@ -1288,11 +1296,11 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
Mask = *((UINT16*) &HuffTableMask[(2 * LengthOfMatchBits) + 3]);
MaskedBits = bits & Mask;
LengthOfMatchBase += MaskedBits;
bits >>= LengthOfMatchBits;
nbits -= LengthOfMatchBits;
LengthOfMatchBase += MaskedBits;
NCrushFetchBits();
}
@ -1305,45 +1313,70 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BY
CopyOffsetPtr = HistoryPtr - CopyOffset;
LengthOfMatch = LengthOfMatchBase;
if ((HistoryPtr >= &HistoryBufferEnd[-LengthOfMatch]) ||
(CopyOffsetPtr >= &HistoryBufferEnd[-LengthOfMatch]))
{
if (HistoryPtr >= &HistoryBufferEnd[-LengthOfMatch])
return -1;
}
if (LengthOfMatch < 2)
{
return -1;
}
else if (LengthOfMatch == 2)
index = 0;
CopyLength = (LengthOfMatch > CopyOffset) ? CopyOffset : LengthOfMatch;
if (CopyOffsetPtr >= HistoryBuffer)
{
HistoryPtr[0] = CopyOffsetPtr[0];
HistoryPtr[1] = CopyOffsetPtr[1];
HistoryPtr += 2;
continue;
}
else
{
while (LengthOfMatch > 0)
while (CopyLength > 0)
{
*HistoryPtr++ = *CopyOffsetPtr++;
CopyLength--;
}
while (LengthOfMatch > CopyOffset)
{
index = ((index >= CopyOffset)) ? 0 : index;
*HistoryPtr++ = *(CopyOffsetPtr + index++);
LengthOfMatch--;
}
}
else
{
CopyOffsetPtr = HistoryBufferEnd - (CopyOffset - (HistoryPtr - HistoryBuffer));
CopyOffsetPtr++;
while (CopyLength && (CopyOffsetPtr <= HistoryBufferEnd))
{
*HistoryPtr++ = *CopyOffsetPtr++;
CopyLength--;
}
CopyOffsetPtr = HistoryBuffer;
while (LengthOfMatch > CopyOffset)
{
index = ((index >= CopyOffset)) ? 0 : index;
*HistoryPtr++ = *(CopyOffsetPtr + index++);
LengthOfMatch--;
}
}
LengthOfMatch = LengthOfMatchBase;
if (LengthOfMatch == 2)
continue;
}
if (IndexLEC == 256)
{
*pDstSize = HistoryPtr - ncrush->HistoryPtr;
*ppDstData = ncrush->HistoryPtr;
ncrush->HistoryPtr = HistoryPtr;
return 1;
}
else
if (IndexLEC != 256)
return -1;
if (ncrush->HistoryBufferFence != 0xABABABAB)
{
printf("NCrushDecompress: history buffer fence was overwritten, potential buffer overflow detected\n");
return -1;
}
*pDstSize = HistoryPtr - ncrush->HistoryPtr;
*ppDstData = ncrush->HistoryPtr;
ncrush->HistoryPtr = HistoryPtr;
return 1;
}
@ -1352,6 +1385,15 @@ int ncrush_compress(NCRUSH_CONTEXT* ncrush, BYTE* pSrcData, UINT32 SrcSize, BYTE
return 1;
}
void ncrush_context_reset(NCRUSH_CONTEXT* ncrush)
{
ZeroMemory(&(ncrush->HistoryBuffer), sizeof(ncrush->HistoryBuffer));
ZeroMemory(&(ncrush->OffsetCache), sizeof(ncrush->OffsetCache));
ncrush->HistoryOffset = 0;
ncrush->HistoryPtr = &(ncrush->HistoryBuffer[ncrush->HistoryOffset]);
}
NCRUSH_CONTEXT* ncrush_context_new(BOOL Compressor)
{
NCRUSH_CONTEXT* ncrush;
@ -1362,10 +1404,12 @@ NCRUSH_CONTEXT* ncrush_context_new(BOOL Compressor)
{
ncrush->Compressor = Compressor;
ncrush->HistoryBufferSize = 65536;
ZeroMemory(&(ncrush->HistoryBuffer), sizeof(ncrush->HistoryBuffer));
ZeroMemory(&(ncrush->OffsetCache), sizeof(ncrush->OffsetCache));
ncrush->HistoryEndOffset = 65535;
ZeroMemory(&(ncrush->HistoryBuffer), sizeof(ncrush->HistoryBuffer));
ncrush->HistoryBufferFence = 0xABABABAB;
ncrush->HistoryOffset = 0;
ncrush->HistoryPtr = &(ncrush->HistoryBuffer[ncrush->HistoryOffset]);
}

View File

@ -23,7 +23,7 @@
#include "bulk.h"
//#define WITH_BULK_DEBUG 1
#define WITH_BULK_DEBUG 1
UINT32 bulk_compression_level(rdpBulk* bulk)
{
@ -42,8 +42,6 @@ UINT32 bulk_compression_max_size(rdpBulk* bulk)
int bulk_decompress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)
{
int status = -1;
UINT32 roff = 0;
UINT32 rlen = 0;
UINT32 CompressedBytes;
UINT32 UncompressedBytes;
UINT32 type = flags & 0x0F;
@ -61,9 +59,7 @@ int bulk_decompress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstD
break;
case PACKET_COMPR_TYPE_RDP6:
status = decompress_rdp_6(bulk->mppc_dec, pSrcData, SrcSize, flags, &roff, &rlen);
*ppDstData = (bulk->mppc_dec->history_buf + roff);
*pDstSize = rlen;
status = ncrush_decompress(bulk->ncrushRecv, pSrcData, SrcSize, ppDstData, pDstSize, flags);
break;
case PACKET_COMPR_TYPE_RDP61:
@ -91,10 +87,17 @@ int bulk_decompress(rdpBulk* bulk, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstD
CompressionRatio = ((double) CompressedBytes) / ((double) UncompressedBytes);
TotalCompressionRatio = ((double) bulk->TotalCompressedBytes) / ((double) bulk->TotalUncompressedBytes);
printf("Compression Ratio: %f Total: %f\n", CompressionRatio, TotalCompressionRatio);
printf("Type: %d Compression Ratio: %f Total: %f %d / %d\n",
type, CompressionRatio, TotalCompressionRatio, CompressedBytes, UncompressedBytes);
}
#endif
}
else
{
#ifdef WITH_BULK_DEBUG
printf("Decompression failure!\n");
#endif
}
return status;
}
@ -140,9 +143,7 @@ void bulk_reset(rdpBulk* bulk)
{
mppc_context_reset(bulk->mppcSend);
mppc_context_reset(bulk->mppcRecv);
mppc_dec_free(bulk->mppc_dec);
bulk->mppc_dec = mppc_dec_new();
ncrush_context_reset(bulk->ncrushRecv);
}
rdpBulk* bulk_new(rdpContext* context)
@ -158,7 +159,7 @@ rdpBulk* bulk_new(rdpContext* context)
bulk->mppcSend = mppc_context_new(1, TRUE);
bulk->mppcRecv = mppc_context_new(1, FALSE);
bulk->mppc_dec = mppc_dec_new();
bulk->ncrushRecv = ncrush_context_new(FALSE);
bulk->CompressionLevel = context->settings->CompressionLevel;
@ -176,7 +177,7 @@ void bulk_free(rdpBulk* bulk)
mppc_context_free(bulk->mppcSend);
mppc_context_free(bulk->mppcRecv);
mppc_dec_free(bulk->mppc_dec);
ncrush_context_free(bulk->ncrushRecv);
free(bulk);
}

View File

@ -25,8 +25,7 @@ typedef struct rdp_bulk rdpBulk;
#include "rdp.h"
#include <freerdp/codec/mppc.h>
#include <freerdp/codec/mppc_enc.h>
#include <freerdp/codec/mppc_dec.h>
#include <freerdp/codec/ncrush.h>
struct rdp_bulk
{
@ -35,8 +34,8 @@ struct rdp_bulk
UINT32 CompressionMaxSize;
MPPC_CONTEXT* mppcSend;
MPPC_CONTEXT* mppcRecv;
NCRUSH_CONTEXT* ncrushRecv;
BYTE OutputBuffer[65536];
struct rdp_mppc_dec* mppc_dec;
UINT64 TotalCompressedBytes;
UINT64 TotalUncompressedBytes;