mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
Merge branch 'mppc' of github.com:awakecoding/FreeRDP into mppc
This commit is contained in:
@@ -29,10 +29,8 @@ struct _MPPC_CONTEXT
|
||||
{
|
||||
wBitStream* bs;
|
||||
BOOL Compressor;
|
||||
UINT32 HistoryPtr;
|
||||
BYTE* pHistoryPtr;
|
||||
BYTE* HistoryPtr;
|
||||
UINT32 HistoryOffset;
|
||||
BYTE* pHistoryOffset;
|
||||
UINT32 HistoryBufferSize;
|
||||
BYTE HistoryBuffer[65536];
|
||||
UINT16 MatchBuffer[32768];
|
||||
@@ -45,6 +43,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
FREERDP_API UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32* pSize);
|
||||
FREERDP_API UINT32 mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE** ppDstData, UINT32* pSize, UINT32 flags);
|
||||
|
||||
FREERDP_API MPPC_CONTEXT* mppc_context_new(DWORD CompressionLevel, BOOL Compressor);
|
||||
FREERDP_API void mppc_context_free(MPPC_CONTEXT* mppc);
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/collections.h>
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
#include <freerdp/codec/mppc_enc.h>
|
||||
#include <freerdp/codec/mppc_dec.h>
|
||||
@@ -72,271 +72,675 @@ const UINT32 MPPC_MATCH_TABLE[256] =
|
||||
|
||||
//#define DEBUG_MPPC 1
|
||||
|
||||
UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32* pSize)
|
||||
UINT32 mppc_decompress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE** ppDstData, UINT32* pSize, UINT32 flags)
|
||||
{
|
||||
BYTE* pEnd;
|
||||
UINT32 Flags;
|
||||
BYTE* pMatch;
|
||||
UINT32 MatchIndex;
|
||||
BYTE Literal;
|
||||
BYTE* SrcPtr;
|
||||
UINT32 CopyOffset;
|
||||
UINT32 LengthOfMatch;
|
||||
UINT32 accumulator;
|
||||
BYTE* HistoryBuffer;
|
||||
BYTE* HistoryPtr;
|
||||
UINT32 HistoryOffset;
|
||||
UINT32 CompressionLevel;
|
||||
wBitStream* bs = mppc->bs;
|
||||
|
||||
Flags = mppc->CompressionLevel;
|
||||
HistoryBuffer = mppc->HistoryBuffer;
|
||||
CompressionLevel = mppc->CompressionLevel;
|
||||
|
||||
BitStream_Attach(mppc->bs, pDstData, *pSize);
|
||||
*ppDstData = HistoryBuffer;
|
||||
|
||||
if (((mppc->HistoryOffset + *pSize) < (mppc->HistoryBufferSize - 3)) /* && mppc->HistoryOffset */)
|
||||
BitStream_Attach(bs, pSrcData, *pSize);
|
||||
BitStream_Fetch(bs);
|
||||
|
||||
if (flags & PACKET_AT_FRONT)
|
||||
{
|
||||
/* SrcData fits into HistoryBuffer? (YES) */
|
||||
|
||||
CopyMemory(&(mppc->HistoryBuffer[mppc->HistoryOffset]), pSrcData, *pSize);
|
||||
|
||||
mppc->HistoryPtr = 0;
|
||||
mppc->pHistoryPtr = &(mppc->HistoryBuffer[mppc->HistoryPtr]);
|
||||
|
||||
mppc->HistoryOffset += *pSize;
|
||||
mppc->pHistoryOffset = &(mppc->HistoryBuffer[mppc->HistoryOffset]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* SrcData fits into HistoryBuffer? (NO) */
|
||||
|
||||
mppc->HistoryOffset = 0;
|
||||
mppc->pHistoryOffset = &(mppc->HistoryBuffer[mppc->HistoryOffset]);
|
||||
|
||||
Flags |= PACKET_AT_FRONT;
|
||||
mppc->HistoryPtr = &(HistoryBuffer[0]);
|
||||
}
|
||||
|
||||
if (mppc->HistoryPtr < mppc->HistoryOffset)
|
||||
if (flags & PACKET_FLUSHED)
|
||||
{
|
||||
/* HistoryPtr < HistoryOffset? (YES) */
|
||||
mppc->HistoryPtr = &(HistoryBuffer[0]);
|
||||
ZeroMemory(HistoryBuffer, mppc->HistoryBufferSize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for a match of at least 3 bytes from the start of the history buffer
|
||||
* to (HistoryPtr - 1) for the data that immediately follows HistoryPtr
|
||||
if (!(flags & PACKET_COMPRESSED))
|
||||
{
|
||||
CopyMemory(mppc->HistoryPtr, pSrcData, *pSize);
|
||||
mppc->HistoryPtr += *pSize;
|
||||
return 0;
|
||||
}
|
||||
|
||||
HistoryPtr = mppc->HistoryPtr;
|
||||
HistoryOffset = mppc->HistoryOffset;
|
||||
|
||||
while ((bs->length - bs->position) >= 8)
|
||||
{
|
||||
accumulator = bs->accumulator;
|
||||
|
||||
/**
|
||||
* Literal Encoding
|
||||
*/
|
||||
|
||||
mppc->HistoryPtr = 0;
|
||||
mppc->pHistoryPtr = &(mppc->HistoryBuffer[mppc->HistoryPtr]);
|
||||
|
||||
pEnd = &(mppc->HistoryBuffer[*pSize - 1]);
|
||||
|
||||
while (mppc->pHistoryPtr < (pEnd - 2))
|
||||
if ((accumulator & 0x80000000) == 0x00000000)
|
||||
{
|
||||
MatchIndex = MPPC_MATCH_INDEX(mppc->pHistoryPtr[0], mppc->pHistoryPtr[1], mppc->pHistoryPtr[2]);
|
||||
/**
|
||||
* Literal, less than 0x80
|
||||
* bit 0 followed by the lower 7 bits of the literal
|
||||
*/
|
||||
|
||||
pMatch = &(mppc->HistoryBuffer[mppc->MatchBuffer[MatchIndex]]);
|
||||
Literal = ((accumulator & 0x7F000000) >> 24);
|
||||
|
||||
mppc->MatchBuffer[MatchIndex] = (UINT16) mppc->HistoryPtr;
|
||||
*(HistoryPtr) = Literal;
|
||||
HistoryPtr++;
|
||||
|
||||
if ((mppc->pHistoryPtr[0] != pMatch[0]) || (mppc->pHistoryPtr[1] != pMatch[1]) ||
|
||||
(mppc->pHistoryPtr[2] != pMatch[2]) || (mppc->pHistoryPtr == pMatch))
|
||||
BitStream_Shift(bs, 8);
|
||||
|
||||
continue;
|
||||
}
|
||||
else if ((accumulator & 0xC0000000) == 0x80000000)
|
||||
{
|
||||
/**
|
||||
* Literal, greater than 0x7F
|
||||
* bits 10 followed by the lower 7 bits of the literal
|
||||
*/
|
||||
|
||||
Literal = ((accumulator & 0x3F800000) >> 23) + 0x80;
|
||||
|
||||
*(HistoryPtr) = Literal;
|
||||
HistoryPtr++;
|
||||
|
||||
BitStream_Shift(bs, 9);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/**
|
||||
* CopyOffset Encoding
|
||||
*/
|
||||
|
||||
CopyOffset = 0;
|
||||
|
||||
if (CompressionLevel) /* RDP5 */
|
||||
{
|
||||
if ((accumulator & 0xF8000000) == 0xF8000000)
|
||||
{
|
||||
accumulator = *(mppc->pHistoryPtr);
|
||||
/**
|
||||
* CopyOffset, range [0, 63]
|
||||
* bits 11111 + lower 6 bits of CopyOffset
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_MPPC
|
||||
printf("0x%02X", accumulator);
|
||||
#endif
|
||||
CopyOffset = ((accumulator >> 21) & 0x3F);
|
||||
BitStream_Shift(bs, 11);
|
||||
}
|
||||
else if ((accumulator & 0xF8000000) == 0xF0000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [64, 319]
|
||||
* bits 11110 + lower 8 bits of (CopyOffset - 64)
|
||||
*/
|
||||
|
||||
if (accumulator < 0x80)
|
||||
{
|
||||
/* 8 bits of literal are encoded as-is */
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* bits 10 followed by lower 7 bits of literal */
|
||||
accumulator = 0x100 | (accumulator & 0x7F);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 9);
|
||||
}
|
||||
CopyOffset = ((accumulator >> 19) & 0xFF) + 64;
|
||||
BitStream_Shift(bs, 13);
|
||||
}
|
||||
else if ((accumulator & 0xF0000000) == 0xE0000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [320, 2367]
|
||||
* bits 1110 + lower 11 bits of (CopyOffset - 320)
|
||||
*/
|
||||
|
||||
mppc->HistoryPtr++;
|
||||
mppc->pHistoryPtr = &(mppc->HistoryBuffer[mppc->HistoryPtr]);
|
||||
CopyOffset = ((accumulator >> 17) & 0x7FF) + 320;
|
||||
BitStream_Shift(bs, 15);
|
||||
}
|
||||
else if ((accumulator & 0xE0000000) == 0xC0000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [2368, ]
|
||||
* bits 110 + lower 16 bits of (CopyOffset - 2368)
|
||||
*/
|
||||
|
||||
CopyOffset = ((accumulator >> 13) & 0xFFFF) + 2368;
|
||||
BitStream_Shift(bs, 19);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD CopyOffset;
|
||||
DWORD LengthOfMatch = 1;
|
||||
/* Invalid CopyOffset Encoding */
|
||||
}
|
||||
}
|
||||
else /* RDP4 */
|
||||
{
|
||||
if ((accumulator & 0xF0000000) == 0xF0000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [0, 63]
|
||||
* bits 1111 + lower 6 bits of CopyOffset
|
||||
*/
|
||||
|
||||
CopyOffset = (DWORD) (mppc->pHistoryPtr - pMatch);
|
||||
CopyOffset = ((accumulator >> 22) & 0x3F);
|
||||
BitStream_Shift(bs, 10);
|
||||
}
|
||||
else if ((accumulator & 0xF0000000) == 0xE0000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [64, 319]
|
||||
* bits 1110 + lower 8 bits of (CopyOffset - 64)
|
||||
*/
|
||||
|
||||
while ((mppc->pHistoryPtr[LengthOfMatch] == pMatch[LengthOfMatch]) &&
|
||||
((mppc->HistoryPtr + LengthOfMatch) < (*pSize - 1)))
|
||||
{
|
||||
MatchIndex = MPPC_MATCH_INDEX(mppc->pHistoryPtr[LengthOfMatch],
|
||||
mppc->pHistoryPtr[LengthOfMatch + 1], mppc->pHistoryPtr[LengthOfMatch + 2]);
|
||||
CopyOffset = ((accumulator >> 20) & 0xFF) + 64;
|
||||
BitStream_Shift(bs, 12);
|
||||
}
|
||||
else if ((accumulator & 0xE0000000) == 0xC0000000)
|
||||
{
|
||||
/**
|
||||
* CopyOffset, range [320, 8191]
|
||||
* bits 110 + lower 13 bits of (CopyOffset - 320)
|
||||
*/
|
||||
|
||||
mppc->MatchBuffer[MatchIndex] = (UINT16) (mppc->HistoryPtr + LengthOfMatch);
|
||||
|
||||
LengthOfMatch++;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MPPC
|
||||
printf("<%d,%d>", (int) CopyOffset, (int) LengthOfMatch);
|
||||
#endif
|
||||
|
||||
/* Encode CopyOffset */
|
||||
|
||||
if (CopyOffset < 64)
|
||||
{
|
||||
/* 11111 + lower 6 bits of CopyOffset */
|
||||
accumulator = 0x07C0 | (CopyOffset & 0x003F);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 11);
|
||||
}
|
||||
else if ((CopyOffset >= 64) && (CopyOffset < 320))
|
||||
{
|
||||
/* 11110 + lower 8 bits of (CopyOffset - 64) */
|
||||
accumulator = 0x1E00 | ((CopyOffset - 64) & 0x00FF);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 13);
|
||||
}
|
||||
else if ((CopyOffset >= 320) && (CopyOffset < 2368))
|
||||
{
|
||||
/* 1110 + lower 11 bits of (CopyOffset - 320) */
|
||||
accumulator = 0x7000 | ((CopyOffset - 320) & 0x07FF);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 110 + lower 16 bits of (CopyOffset - 2368) */
|
||||
accumulator = 0x060000 | ((CopyOffset - 2368) & 0xFFFF);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 19);
|
||||
}
|
||||
|
||||
/* Encode LengthOfMatch */
|
||||
|
||||
if (LengthOfMatch == 3)
|
||||
{
|
||||
/* 0 + 0 lower bits of LengthOfMatch */
|
||||
BitStream_Write_Bits(mppc->bs, 0, 1);
|
||||
}
|
||||
else if ((LengthOfMatch >= 4) && (LengthOfMatch < 8))
|
||||
{
|
||||
/* 10 + 2 lower bits of LengthOfMatch */
|
||||
accumulator = 0x0008 | (LengthOfMatch & 0x0003);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 4);
|
||||
}
|
||||
else if ((LengthOfMatch >= 8) && (LengthOfMatch < 16))
|
||||
{
|
||||
/* 110 + 3 lower bits of LengthOfMatch */
|
||||
accumulator = 0x0030 | (LengthOfMatch & 0x0007);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 6);
|
||||
}
|
||||
else if ((LengthOfMatch >= 16) && (LengthOfMatch < 32))
|
||||
{
|
||||
/* 1110 + 4 lower bits of LengthOfMatch */
|
||||
accumulator = 0x00E0 | (LengthOfMatch & 0x000F);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 8);
|
||||
}
|
||||
else if ((LengthOfMatch >= 32) && (LengthOfMatch < 64))
|
||||
{
|
||||
/* 11110 + 5 lower bits of LengthOfMatch */
|
||||
accumulator = 0x03C0 | (LengthOfMatch & 0x001F);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 10);
|
||||
}
|
||||
else if ((LengthOfMatch >= 64) && (LengthOfMatch < 128))
|
||||
{
|
||||
/* 111110 + 6 lower bits of LengthOfMatch */
|
||||
accumulator = 0x0F80 | (LengthOfMatch & 0x003F);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 12);
|
||||
}
|
||||
else if ((LengthOfMatch >= 128) && (LengthOfMatch < 256))
|
||||
{
|
||||
/* 1111110 + 7 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3F00 | (LengthOfMatch & 0x007F);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 14);
|
||||
}
|
||||
else if ((LengthOfMatch >= 256) && (LengthOfMatch < 512))
|
||||
{
|
||||
/* 11111110 + 8 lower bits of LengthOfMatch */
|
||||
accumulator = 0xFE00 | (LengthOfMatch & 0x00FF);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 16);
|
||||
}
|
||||
else if ((LengthOfMatch >= 512) && (LengthOfMatch < 1024))
|
||||
{
|
||||
/* 111111110 + 9 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3FC00 | (LengthOfMatch & 0x01FF);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 18);
|
||||
}
|
||||
else if ((LengthOfMatch >= 1024) && (LengthOfMatch < 2048))
|
||||
{
|
||||
/* 1111111110 + 10 lower bits of LengthOfMatch */
|
||||
accumulator = 0xFF800 | (LengthOfMatch & 0x03FF);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 20);
|
||||
}
|
||||
else if ((LengthOfMatch >= 2048) && (LengthOfMatch < 4096))
|
||||
{
|
||||
/* 11111111110 + 11 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3FF000 | (LengthOfMatch & 0x07FF);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 22);
|
||||
}
|
||||
else if ((LengthOfMatch >= 4096) && (LengthOfMatch < 8192))
|
||||
{
|
||||
/* 111111111110 + 12 lower bits of LengthOfMatch */
|
||||
accumulator = 0xFFE000 | (LengthOfMatch & 0x0FFF);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 24);
|
||||
}
|
||||
else if ((LengthOfMatch >= 8192) && (LengthOfMatch < 16384))
|
||||
{
|
||||
/* 1111111111110 + 13 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3FFC000 | (LengthOfMatch & 0x1FFF);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 26);
|
||||
}
|
||||
else if ((LengthOfMatch >= 16384) && (LengthOfMatch < 32768))
|
||||
{
|
||||
/* 11111111111110 + 14 lower bits of LengthOfMatch */
|
||||
accumulator = 0xFFF8000 | (LengthOfMatch & 0x3FFF);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 28);
|
||||
}
|
||||
else if ((LengthOfMatch >= 32768) && (LengthOfMatch < 65536))
|
||||
{
|
||||
/* 111111111111110 + 15 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3FFF0000 | (LengthOfMatch & 0x7FFF);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 30);
|
||||
}
|
||||
|
||||
mppc->HistoryPtr += LengthOfMatch;
|
||||
mppc->pHistoryPtr += LengthOfMatch;
|
||||
CopyOffset = ((accumulator >> 16) & 0x1FFF) + 320;
|
||||
BitStream_Shift(bs, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid CopyOffset Encoding */
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode trailing symbols as literals */
|
||||
/**
|
||||
* LengthOfMatch Encoding
|
||||
*/
|
||||
|
||||
while (mppc->pHistoryPtr <= pEnd)
|
||||
LengthOfMatch = 0;
|
||||
accumulator = bs->accumulator;
|
||||
|
||||
if ((accumulator & 0x80000000) == 0x00000000)
|
||||
{
|
||||
MatchIndex = MPPC_MATCH_INDEX(mppc->pHistoryPtr[0], mppc->pHistoryPtr[1], mppc->pHistoryPtr[2]);
|
||||
/**
|
||||
* LengthOfMatch [3]
|
||||
* bit 0 + 0 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
pMatch = &(mppc->HistoryBuffer[mppc->MatchBuffer[MatchIndex]]);
|
||||
LengthOfMatch = 3;
|
||||
BitStream_Shift(bs, 1);
|
||||
}
|
||||
else if ((accumulator & 0xC0000000) == 0x80000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [4, 7]
|
||||
* bits 10 + 2 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
mppc->MatchBuffer[MatchIndex] = (UINT16) mppc->HistoryPtr;
|
||||
LengthOfMatch = ((accumulator >> 28) & 0x0003) + 0x0004;
|
||||
BitStream_Shift(bs, 4);
|
||||
}
|
||||
else if ((accumulator & 0xE0000000) == 0xC0000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [8, 15]
|
||||
* bits 110 + 3 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
accumulator = *(mppc->pHistoryPtr);
|
||||
LengthOfMatch = ((accumulator >> 26) & 0x0007) + 0x0008;
|
||||
BitStream_Shift(bs, 6);
|
||||
}
|
||||
else if ((accumulator & 0xF0000000) == 0xE0000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [16, 31]
|
||||
* bits 1110 + 4 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
LengthOfMatch = ((accumulator >> 24) & 0x000F) + 0x0010;
|
||||
BitStream_Shift(bs, 8);
|
||||
}
|
||||
else if ((accumulator & 0xF8000000) == 0xF0000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [32, 63]
|
||||
* bits 11110 + 5 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
LengthOfMatch = ((accumulator >> 22) & 0x001F) + 0x0020;
|
||||
BitStream_Shift(bs, 10);
|
||||
}
|
||||
else if ((accumulator & 0xFC000000) == 0xF8000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [64, 127]
|
||||
* bits 111110 + 6 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
LengthOfMatch = ((accumulator >> 20) & 0x003F) + 0x0040;
|
||||
BitStream_Shift(bs, 12);
|
||||
}
|
||||
else if ((accumulator & 0xFE000000) == 0xFC000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [128, 255]
|
||||
* bits 1111110 + 7 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
LengthOfMatch = ((accumulator >> 18) & 0x007F) + 0x0080;
|
||||
BitStream_Shift(bs, 14);
|
||||
}
|
||||
else if ((accumulator & 0xFF000000) == 0xFE000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [256, 511]
|
||||
* bits 11111110 + 8 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
LengthOfMatch = ((accumulator >> 16) & 0x00FF) + 0x0100;
|
||||
BitStream_Shift(bs, 16);
|
||||
}
|
||||
else if ((accumulator & 0xFF800000) == 0xFF000000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [512, 1023]
|
||||
* bits 111111110 + 9 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
LengthOfMatch = ((accumulator >> 14) & 0x01FF) + 0x0200;
|
||||
BitStream_Shift(bs, 18);
|
||||
}
|
||||
else if ((accumulator & 0xFFC00000) == 0xFF800000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [1024, 2047]
|
||||
* bits 1111111110 + 10 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
LengthOfMatch = ((accumulator >> 12) & 0x03FF) + 0x0400;
|
||||
BitStream_Shift(bs, 20);
|
||||
}
|
||||
else if ((accumulator & 0xFFE00000) == 0xFFC00000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [2048, 4095]
|
||||
* bits 11111111110 + 11 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
LengthOfMatch = ((accumulator >> 10) & 0x07FF) + 0x0800;
|
||||
BitStream_Shift(bs, 22);
|
||||
}
|
||||
else if ((accumulator & 0xFFF00000) == 0xFFE00000)
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [4096, 8191]
|
||||
* bits 111111111110 + 12 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
LengthOfMatch = ((accumulator >> 8) & 0x0FFF) + 0x1000;
|
||||
BitStream_Shift(bs, 24);
|
||||
}
|
||||
else if (((accumulator & 0xFFF80000) == 0xFFF00000) && CompressionLevel) /* RDP5 */
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [8192, 16383]
|
||||
* bits 1111111111110 + 13 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
LengthOfMatch = ((accumulator >> 6) & 0x1FFF) + 0x2000;
|
||||
BitStream_Shift(bs, 26);
|
||||
}
|
||||
else if (((accumulator & 0xFFFC0000) == 0xFFF80000) && CompressionLevel) /* RDP5 */
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [16384, 32767]
|
||||
* bits 11111111111110 + 14 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
LengthOfMatch = ((accumulator >> 4) & 0x3FFF) + 0x4000;
|
||||
BitStream_Shift(bs, 28);
|
||||
}
|
||||
else if (((accumulator & 0xFFFE0000) == 0xFFFC0000) && CompressionLevel) /* RDP5 */
|
||||
{
|
||||
/**
|
||||
* LengthOfMatch [32768, 65535]
|
||||
* bits 111111111111110 + 15 lower bits of LengthOfMatch
|
||||
*/
|
||||
|
||||
LengthOfMatch = ((accumulator >> 2) & 0x7FFF) + 0x8000;
|
||||
BitStream_Shift(bs, 30);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid LengthOfMatch Encoding */
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MPPC
|
||||
printf("%c", accumulator);
|
||||
printf("<%d,%d>\n", (int) CopyOffset, (int) LengthOfMatch);
|
||||
#endif
|
||||
|
||||
SrcPtr = HistoryPtr - CopyOffset;
|
||||
|
||||
while (LengthOfMatch > 0)
|
||||
{
|
||||
*(HistoryPtr) = *SrcPtr;
|
||||
|
||||
HistoryPtr++;
|
||||
SrcPtr++;
|
||||
|
||||
LengthOfMatch--;
|
||||
}
|
||||
}
|
||||
|
||||
*pSize = (UINT32) (HistoryPtr - mppc->HistoryPtr);
|
||||
|
||||
mppc->HistoryPtr = HistoryPtr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT32 mppc_compress(MPPC_CONTEXT* mppc, BYTE* pSrcData, BYTE* pDstData, UINT32* pSize)
|
||||
{
|
||||
UINT32 Flags;
|
||||
BYTE* pSrcEnd;
|
||||
BYTE* pDstEnd;
|
||||
BYTE* MatchPtr;
|
||||
UINT32 MatchIndex;
|
||||
UINT32 accumulator;
|
||||
DWORD CopyOffset;
|
||||
DWORD LengthOfMatch;
|
||||
BYTE* HistoryBuffer;
|
||||
BYTE* HistoryPtr;
|
||||
UINT32 HistoryOffset;
|
||||
UINT32 HistoryBufferSize;
|
||||
UINT32 CompressionLevel;
|
||||
wBitStream* bs = mppc->bs;
|
||||
|
||||
HistoryBuffer = mppc->HistoryBuffer;
|
||||
HistoryBufferSize = mppc->HistoryBufferSize;
|
||||
CompressionLevel = mppc->CompressionLevel;
|
||||
|
||||
HistoryPtr = mppc->HistoryPtr;
|
||||
HistoryOffset = mppc->HistoryOffset;
|
||||
|
||||
BitStream_Attach(bs, pDstData, *pSize);
|
||||
|
||||
CopyMemory(&(HistoryBuffer[HistoryOffset]), pSrcData, *pSize);
|
||||
|
||||
if (((HistoryOffset + *pSize) < (HistoryBufferSize - 3)) && HistoryOffset)
|
||||
{
|
||||
Flags = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
HistoryOffset = 0;
|
||||
Flags = PACKET_AT_FRONT;
|
||||
}
|
||||
|
||||
HistoryPtr = &(HistoryBuffer[HistoryOffset]);
|
||||
HistoryOffset += *pSize;
|
||||
|
||||
pSrcEnd = &(HistoryBuffer[*pSize - 1]);
|
||||
pDstEnd = &(pDstData[*pSize - 1]);
|
||||
|
||||
while (HistoryPtr < (pSrcEnd - 2))
|
||||
{
|
||||
MatchIndex = MPPC_MATCH_INDEX(HistoryPtr[0], HistoryPtr[1], HistoryPtr[2]);
|
||||
MatchPtr = &(HistoryBuffer[mppc->MatchBuffer[MatchIndex]]);
|
||||
|
||||
/* if (&MatchPtr[1] != HistoryPtr) */
|
||||
mppc->MatchBuffer[MatchIndex] = (UINT16) (HistoryPtr - HistoryBuffer);
|
||||
|
||||
if (mppc->HistoryPtr < HistoryPtr)
|
||||
mppc->HistoryPtr = HistoryPtr;
|
||||
|
||||
if ((HistoryPtr[0] != MatchPtr[0]) || (HistoryPtr[1] != MatchPtr[1]) ||
|
||||
(HistoryPtr[2] != MatchPtr[2]) || (&MatchPtr[2] > mppc->HistoryPtr) ||
|
||||
(MatchPtr == HistoryPtr) || (&MatchPtr[1] == HistoryPtr) ||
|
||||
(MatchPtr == HistoryBuffer))
|
||||
{
|
||||
accumulator = *(HistoryPtr);
|
||||
|
||||
#ifdef DEBUG_MPPC
|
||||
//printf("%c", accumulator);
|
||||
#endif
|
||||
|
||||
if (((bs->position / 8) + 2) > (*pSize - 1))
|
||||
{
|
||||
Flags = PACKET_FLUSHED;
|
||||
ZeroMemory(HistoryBuffer, HistoryBufferSize);
|
||||
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
|
||||
return Flags;
|
||||
}
|
||||
|
||||
if (accumulator < 0x80)
|
||||
{
|
||||
/* 8 bits of literal are encoded as-is */
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 8);
|
||||
BitStream_Write_Bits(bs, accumulator, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* bits 10 followed by lower 7 bits of literal */
|
||||
accumulator = 0x100 | (accumulator & 0x7F);
|
||||
BitStream_Write_Bits(mppc->bs, accumulator, 9);
|
||||
BitStream_Write_Bits(bs, accumulator, 9);
|
||||
}
|
||||
|
||||
mppc->HistoryPtr++;
|
||||
mppc->pHistoryPtr++;
|
||||
HistoryPtr++;
|
||||
}
|
||||
else
|
||||
{
|
||||
LengthOfMatch = 3;
|
||||
HistoryPtr += 3;
|
||||
MatchPtr += 3;
|
||||
|
||||
CopyOffset = (HistoryBufferSize - 1) & (HistoryPtr - MatchPtr);
|
||||
|
||||
while ((*HistoryPtr == *MatchPtr) && /* (MatchPtr <= mppc->HistoryPtr) && */
|
||||
((HistoryPtr - HistoryBuffer) < (*pSize - 1)))
|
||||
{
|
||||
LengthOfMatch++;
|
||||
HistoryPtr++;
|
||||
MatchPtr++;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_MPPC
|
||||
printf("<%d,%d>\n", (int) CopyOffset, (int) LengthOfMatch);
|
||||
#endif
|
||||
|
||||
/* Encode CopyOffset */
|
||||
|
||||
if (((bs->position / 8) + 7) > (*pSize - 1))
|
||||
{
|
||||
Flags = PACKET_FLUSHED;
|
||||
ZeroMemory(HistoryBuffer, HistoryBufferSize);
|
||||
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
|
||||
return Flags;
|
||||
}
|
||||
|
||||
if (CompressionLevel) /* RDP5 */
|
||||
{
|
||||
if (CopyOffset < 64)
|
||||
{
|
||||
/* bits 11111 + lower 6 bits of CopyOffset */
|
||||
accumulator = 0x07C0 | (CopyOffset & 0x003F);
|
||||
BitStream_Write_Bits(bs, accumulator, 11);
|
||||
}
|
||||
else if ((CopyOffset >= 64) && (CopyOffset < 320))
|
||||
{
|
||||
/* bits 11110 + lower 8 bits of (CopyOffset - 64) */
|
||||
accumulator = 0x1E00 | ((CopyOffset - 64) & 0x00FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 13);
|
||||
}
|
||||
else if ((CopyOffset >= 320) && (CopyOffset < 2368))
|
||||
{
|
||||
/* bits 1110 + lower 11 bits of (CopyOffset - 320) */
|
||||
accumulator = 0x7000 | ((CopyOffset - 320) & 0x07FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 15);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* bits 110 + lower 16 bits of (CopyOffset - 2368) */
|
||||
accumulator = 0x060000 | ((CopyOffset - 2368) & 0xFFFF);
|
||||
BitStream_Write_Bits(bs, accumulator, 19);
|
||||
}
|
||||
}
|
||||
else /* RDP4 */
|
||||
{
|
||||
if (CopyOffset < 64)
|
||||
{
|
||||
/* bits 1111 + lower 6 bits of CopyOffset */
|
||||
accumulator = 0x03C0 | (CopyOffset & 0x003F);
|
||||
BitStream_Write_Bits(bs, accumulator, 10);
|
||||
}
|
||||
else if ((CopyOffset >= 64) && (CopyOffset < 320))
|
||||
{
|
||||
/* bits 1110 + lower 8 bits of (CopyOffset - 64) */
|
||||
accumulator = 0x0E00 | ((CopyOffset - 64) & 0x00FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 12);
|
||||
}
|
||||
else if ((CopyOffset >= 320) && (CopyOffset < 8192))
|
||||
{
|
||||
/* bits 110 + lower 13 bits of (CopyOffset - 320) */
|
||||
accumulator = 0xC000 | ((CopyOffset - 320) & 0x1FFF);
|
||||
BitStream_Write_Bits(bs, accumulator, 16);
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode LengthOfMatch */
|
||||
|
||||
if (LengthOfMatch == 3)
|
||||
{
|
||||
/* 0 + 0 lower bits of LengthOfMatch */
|
||||
BitStream_Write_Bits(bs, 0, 1);
|
||||
}
|
||||
else if ((LengthOfMatch >= 4) && (LengthOfMatch < 8))
|
||||
{
|
||||
/* 10 + 2 lower bits of LengthOfMatch */
|
||||
accumulator = 0x0008 | (LengthOfMatch & 0x0003);
|
||||
BitStream_Write_Bits(bs, accumulator, 4);
|
||||
}
|
||||
else if ((LengthOfMatch >= 8) && (LengthOfMatch < 16))
|
||||
{
|
||||
/* 110 + 3 lower bits of LengthOfMatch */
|
||||
accumulator = 0x0030 | (LengthOfMatch & 0x0007);
|
||||
BitStream_Write_Bits(bs, accumulator, 6);
|
||||
}
|
||||
else if ((LengthOfMatch >= 16) && (LengthOfMatch < 32))
|
||||
{
|
||||
/* 1110 + 4 lower bits of LengthOfMatch */
|
||||
accumulator = 0x00E0 | (LengthOfMatch & 0x000F);
|
||||
BitStream_Write_Bits(bs, accumulator, 8);
|
||||
}
|
||||
else if ((LengthOfMatch >= 32) && (LengthOfMatch < 64))
|
||||
{
|
||||
/* 11110 + 5 lower bits of LengthOfMatch */
|
||||
accumulator = 0x03C0 | (LengthOfMatch & 0x001F);
|
||||
BitStream_Write_Bits(bs, accumulator, 10);
|
||||
}
|
||||
else if ((LengthOfMatch >= 64) && (LengthOfMatch < 128))
|
||||
{
|
||||
/* 111110 + 6 lower bits of LengthOfMatch */
|
||||
accumulator = 0x0F80 | (LengthOfMatch & 0x003F);
|
||||
BitStream_Write_Bits(bs, accumulator, 12);
|
||||
}
|
||||
else if ((LengthOfMatch >= 128) && (LengthOfMatch < 256))
|
||||
{
|
||||
/* 1111110 + 7 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3F00 | (LengthOfMatch & 0x007F);
|
||||
BitStream_Write_Bits(bs, accumulator, 14);
|
||||
}
|
||||
else if ((LengthOfMatch >= 256) && (LengthOfMatch < 512))
|
||||
{
|
||||
/* 11111110 + 8 lower bits of LengthOfMatch */
|
||||
accumulator = 0xFE00 | (LengthOfMatch & 0x00FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 16);
|
||||
}
|
||||
else if ((LengthOfMatch >= 512) && (LengthOfMatch < 1024))
|
||||
{
|
||||
/* 111111110 + 9 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3FC00 | (LengthOfMatch & 0x01FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 18);
|
||||
}
|
||||
else if ((LengthOfMatch >= 1024) && (LengthOfMatch < 2048))
|
||||
{
|
||||
/* 1111111110 + 10 lower bits of LengthOfMatch */
|
||||
accumulator = 0xFF800 | (LengthOfMatch & 0x03FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 20);
|
||||
}
|
||||
else if ((LengthOfMatch >= 2048) && (LengthOfMatch < 4096))
|
||||
{
|
||||
/* 11111111110 + 11 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3FF000 | (LengthOfMatch & 0x07FF);
|
||||
BitStream_Write_Bits(bs, accumulator, 22);
|
||||
}
|
||||
else if ((LengthOfMatch >= 4096) && (LengthOfMatch < 8192))
|
||||
{
|
||||
/* 111111111110 + 12 lower bits of LengthOfMatch */
|
||||
accumulator = 0xFFE000 | (LengthOfMatch & 0x0FFF);
|
||||
BitStream_Write_Bits(bs, accumulator, 24);
|
||||
}
|
||||
else if (((LengthOfMatch >= 8192) && (LengthOfMatch < 16384)) && CompressionLevel) /* RDP5 */
|
||||
{
|
||||
/* 1111111111110 + 13 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3FFC000 | (LengthOfMatch & 0x1FFF);
|
||||
BitStream_Write_Bits(bs, accumulator, 26);
|
||||
}
|
||||
else if (((LengthOfMatch >= 16384) && (LengthOfMatch < 32768)) && CompressionLevel) /* RDP5 */
|
||||
{
|
||||
/* 11111111111110 + 14 lower bits of LengthOfMatch */
|
||||
accumulator = 0xFFF8000 | (LengthOfMatch & 0x3FFF);
|
||||
BitStream_Write_Bits(bs, accumulator, 28);
|
||||
}
|
||||
else if (((LengthOfMatch >= 32768) && (LengthOfMatch < 65536)) && CompressionLevel) /* RDP5 */
|
||||
{
|
||||
/* 111111111111110 + 15 lower bits of LengthOfMatch */
|
||||
accumulator = 0x3FFF0000 | (LengthOfMatch & 0x7FFF);
|
||||
BitStream_Write_Bits(bs, accumulator, 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* HistoryPtr < HistoryOffset? (NO) */
|
||||
/* Encode trailing symbols as literals */
|
||||
|
||||
while (HistoryPtr <= pSrcEnd)
|
||||
{
|
||||
MatchIndex = MPPC_MATCH_INDEX(HistoryPtr[0], HistoryPtr[1], HistoryPtr[2]);
|
||||
MatchPtr = &(HistoryBuffer[mppc->MatchBuffer[MatchIndex]]);
|
||||
mppc->MatchBuffer[MatchIndex] = (UINT16) (HistoryPtr - HistoryBuffer);
|
||||
|
||||
accumulator = *(HistoryPtr);
|
||||
|
||||
#ifdef DEBUG_MPPC
|
||||
//printf("%c", accumulator);
|
||||
#endif
|
||||
|
||||
if (((bs->position / 8) + 2) > (*pSize - 1))
|
||||
{
|
||||
Flags = PACKET_FLUSHED;
|
||||
ZeroMemory(HistoryBuffer, HistoryBufferSize);
|
||||
ZeroMemory(mppc->MatchBuffer, sizeof(mppc->MatchBuffer));
|
||||
return Flags;
|
||||
}
|
||||
|
||||
if (accumulator < 0x80)
|
||||
{
|
||||
/* 8 bits of literal are encoded as-is */
|
||||
BitStream_Write_Bits(bs, accumulator, 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* bits 10 followed by lower 7 bits of literal */
|
||||
accumulator = 0x100 | (accumulator & 0x7F);
|
||||
BitStream_Write_Bits(bs, accumulator, 9);
|
||||
}
|
||||
|
||||
HistoryPtr++;
|
||||
}
|
||||
|
||||
BitStream_Flush(bs);
|
||||
|
||||
Flags |= PACKET_COMPRESSED;
|
||||
*pSize = ((bs->position + 7) / 8);
|
||||
|
||||
BitStream_Flush(mppc->bs);
|
||||
*pSize = (mppc->bs->position / 8);
|
||||
mppc->HistoryPtr = HistoryPtr;
|
||||
mppc->HistoryOffset = HistoryPtr - HistoryBuffer;
|
||||
|
||||
#ifdef DEBUG_MPPC
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
return Flags;
|
||||
}
|
||||
@@ -366,6 +770,9 @@ MPPC_CONTEXT* mppc_context_new(DWORD CompressionLevel, BOOL Compressor)
|
||||
ZeroMemory(&(mppc->MatchBuffer), sizeof(mppc->MatchBuffer));
|
||||
|
||||
mppc->bs = BitStream_New();
|
||||
|
||||
mppc->HistoryPtr = &(mppc->HistoryBuffer[0]);
|
||||
mppc->HistoryOffset = 0;
|
||||
}
|
||||
|
||||
return mppc;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
#include <freerdp/freerdp.h>
|
||||
#include <freerdp/codec/mppc.h>
|
||||
@@ -684,39 +685,375 @@ int test_mppc_old()
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char TEST_MPPC_BELL_TOLLS[] = "for.whom.the.bell.tolls,.the.bell.tolls.for.thee!";
|
||||
/**
|
||||
*
|
||||
* for.whom.the.bell.tolls,.the.bell.tolls.for.thee!
|
||||
*
|
||||
* for.whom.the.bell.tolls,<16,15>.<40,4><19,3>e! ([MS-RDPBCGR])
|
||||
*
|
||||
* <16,15> : ".the.bell.tolls"
|
||||
* <40,4> : "for."
|
||||
* <19,3> : "the"
|
||||
*
|
||||
* for.whom.the.bell.tolls,<16,15>.f<40,3><35,3>e! (Microsoft implementation)
|
||||
*
|
||||
* <16,15> : ".the.bell.tolls"
|
||||
* <40,3> : "or."
|
||||
* <19,3> " "the"
|
||||
*
|
||||
* RDP5:
|
||||
* 01100110 Literal 'f'
|
||||
* 01101111 Literal 'o'
|
||||
* 01110010 Literal 'r'
|
||||
* 00101110 Literal '.'
|
||||
* 01110111 Literal 'w'
|
||||
* 01101000 Literal 'h'
|
||||
* 01101111 Literal 'o'
|
||||
* 01101101 Literal 'm'
|
||||
* 00101110 Literal '.'
|
||||
* 01110100 Literal 't'
|
||||
* 01101000 Literal 'h'
|
||||
* 01100101 Literal 'e'
|
||||
* 00101110 Literal '.'
|
||||
* 01100010 Literal 'b'
|
||||
* 01100101 Literal 'e'
|
||||
* 01101100 Literal 'l'
|
||||
* 01101100 Literal 'l'
|
||||
* 00101110 Literal '.'
|
||||
* 01110100 Literal 't'
|
||||
* 01101111 Literal 'o'
|
||||
* 01101100 Literal 'l'
|
||||
* 01101100 Literal 'l'
|
||||
* 01110011 Literal 's'
|
||||
* 00101100 Literal ','
|
||||
* 11111+010000 CopyOffset 16
|
||||
* 110+111 LengthOfMatch 15
|
||||
* 00101110 Literal '.'
|
||||
* 01100110 Literal 'f'
|
||||
* 11111+101000 CopyOffset 40
|
||||
* 0 LengthOfMatch 3
|
||||
* 11111+100011 CopyOffset 35
|
||||
* 0 LengthOfMatch 3
|
||||
* 01100101 Literal 'e'
|
||||
* 00100001 Literal '!'
|
||||
* 0000000 Trailing Bits
|
||||
*
|
||||
* RDP4:
|
||||
* 01100110 Literal 'f'
|
||||
* 01101111 Literal 'o'
|
||||
* 01110010 Literal 'r'
|
||||
* 00101110 Literal '.'
|
||||
* 01110111 Literal 'w'
|
||||
* 01101000 Literal 'h'
|
||||
* 01101111 Literal 'o'
|
||||
* 01101101 Literal 'm'
|
||||
* 00101110 Literal '.'
|
||||
* 01110100 Literal 't'
|
||||
* 01101000 Literal 'h'
|
||||
* 01100101 Literal 'e'
|
||||
* 00101110 Literal '.'
|
||||
* 01100010 Literal 'b'
|
||||
* 01100101 Literal 'e'
|
||||
* 01101100 Literal 'l'
|
||||
* 01101100 Literal 'l'
|
||||
* 00101110 Literal '.'
|
||||
* 01110100 Literal 't'
|
||||
* 01101111 Literal 'o'
|
||||
* 01101100 Literal 'l'
|
||||
* 01101100 Literal 'l'
|
||||
* 01110011 Literal 's'
|
||||
* 00101100 Literal ','
|
||||
* 1111+010000 CopyOffset 16
|
||||
* 110+111 LengthOfMatch 15
|
||||
* 00101110 Literal '.'
|
||||
* 01100110 Literal 'f'
|
||||
* 1111+101000 CopyOffset 40
|
||||
* 0 LengthOfMatch 3
|
||||
* 1111+100011 CopyOffset 35
|
||||
* 0 LengthOfMatch 3
|
||||
* 01100101 Literal 'e'
|
||||
* 00100001 Literal '!'
|
||||
* 00 Trailing Bits
|
||||
*/
|
||||
|
||||
int TestFreeRDPCodecMppc(int argc, char* argv[])
|
||||
const BYTE TEST_MPPC_BELLS[] = "for.whom.the.bell.tolls,.the.bell.tolls.for.thee!";
|
||||
|
||||
/* Flags: 0x0060 Length: 33 */
|
||||
|
||||
const BYTE TEST_MPPC_BELLS_RDP4[] =
|
||||
"\x66\x6f\x72\x2e\x77\x68\x6f\x6d\x2e\x74\x68\x65\x2e\x62\x65\x6c"
|
||||
"\x6c\x2e\x74\x6f\x6c\x6c\x73\x2c\xf4\x37\x2e\x66\xfa\x1f\x19\x94"
|
||||
"\x84";
|
||||
|
||||
/* Flags: 0x0061 Length: 34 */
|
||||
|
||||
const BYTE TEST_MPPC_BELLS_RDP5[] =
|
||||
"\x66\x6f\x72\x2e\x77\x68\x6f\x6d\x2e\x74\x68\x65\x2e\x62\x65\x6c"
|
||||
"\x6c\x2e\x74\x6f\x6c\x6c\x73\x2c\xfa\x1b\x97\x33\x7e\x87\xe3\x32"
|
||||
"\x90\x80";
|
||||
|
||||
int test_MppcCompressBellsRdp5()
|
||||
{
|
||||
UINT32 size;
|
||||
UINT32 flags;
|
||||
BYTE* pSrcData;
|
||||
MPPC_CONTEXT* mppc;
|
||||
UINT32 expectedSize;
|
||||
BYTE OutputBuffer[65536];
|
||||
|
||||
mppc = mppc_context_new(1, TRUE);
|
||||
|
||||
#if 0
|
||||
size = sizeof(TEST_MPPC_BELL_TOLLS) - 1;
|
||||
pSrcData = (BYTE*) TEST_MPPC_BELL_TOLLS;
|
||||
|
||||
printf("%s\n", pSrcData);
|
||||
flags = mppc_compress(mppc, pSrcData, OutputBuffer, &size);
|
||||
printf("flags: 0x%04X size: %d\n", flags, size);
|
||||
#endif
|
||||
|
||||
size = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
|
||||
pSrcData = (BYTE*) TEST_RDP5_UNCOMPRESSED_DATA;
|
||||
size = sizeof(TEST_MPPC_BELLS) - 1;
|
||||
pSrcData = (BYTE*) TEST_MPPC_BELLS;
|
||||
expectedSize = sizeof(TEST_MPPC_BELLS_RDP5) - 1;
|
||||
|
||||
flags = mppc_compress(mppc, pSrcData, OutputBuffer, &size);
|
||||
|
||||
printf("flags: 0x%04X size: %d\n", flags, size);
|
||||
|
||||
winpr_HexDump(OutputBuffer, size);
|
||||
//winpr_HexDump(TEST_RDP5_COMPRESSED_DATA, sizeof(TEST_RDP5_COMPRESSED_DATA));
|
||||
if (size != expectedSize)
|
||||
{
|
||||
printf("MppcCompressBellsRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("sizeof(TEST_RDP5_COMPRESSED_DATA): %d\n", (int) sizeof(TEST_RDP5_COMPRESSED_DATA));
|
||||
if (memcmp(OutputBuffer, TEST_MPPC_BELLS_RDP5, size) != 0)
|
||||
{
|
||||
printf("MppcCompressBellsRdp5: output mismatch\n");
|
||||
|
||||
printf("Actual\n");
|
||||
BitDump(OutputBuffer, size * 8, 0);
|
||||
|
||||
printf("Expected\n");
|
||||
BitDump(TEST_MPPC_BELLS_RDP5, size * 8, 0);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
mppc_context_free(mppc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_MppcCompressBellsRdp4()
|
||||
{
|
||||
UINT32 size;
|
||||
UINT32 flags;
|
||||
BYTE* pSrcData;
|
||||
MPPC_CONTEXT* mppc;
|
||||
UINT32 expectedSize;
|
||||
BYTE OutputBuffer[65536];
|
||||
|
||||
mppc = mppc_context_new(0, TRUE);
|
||||
|
||||
size = sizeof(TEST_MPPC_BELLS) - 1;
|
||||
pSrcData = (BYTE*) TEST_MPPC_BELLS;
|
||||
expectedSize = sizeof(TEST_MPPC_BELLS_RDP4) - 1;
|
||||
|
||||
flags = mppc_compress(mppc, pSrcData, OutputBuffer, &size);
|
||||
|
||||
printf("flags: 0x%04X size: %d\n", flags, size);
|
||||
|
||||
if (size != expectedSize)
|
||||
{
|
||||
printf("MppcCompressBellsRdp4: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(OutputBuffer, TEST_MPPC_BELLS_RDP4, size) != 0)
|
||||
{
|
||||
printf("MppcCompressBellsRdp4: output mismatch\n");
|
||||
|
||||
printf("Actual\n");
|
||||
BitDump(OutputBuffer, size * 8, 0);
|
||||
|
||||
printf("Expected\n");
|
||||
BitDump(TEST_MPPC_BELLS_RDP4, size * 8, 0);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
mppc_context_free(mppc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_MppcDecompressBellsRdp5()
|
||||
{
|
||||
UINT32 size;
|
||||
UINT32 flags;
|
||||
BYTE* pSrcData;
|
||||
MPPC_CONTEXT* mppc;
|
||||
UINT32 expectedSize;
|
||||
BYTE* pDstData = NULL;
|
||||
|
||||
mppc = mppc_context_new(1, FALSE);
|
||||
|
||||
size = sizeof(TEST_MPPC_BELLS_RDP5) - 1;
|
||||
pSrcData = (BYTE*) TEST_MPPC_BELLS_RDP5;
|
||||
flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
|
||||
expectedSize = sizeof(TEST_MPPC_BELLS) - 1;
|
||||
|
||||
flags = mppc_decompress(mppc, pSrcData, &pDstData, &size, flags);
|
||||
printf("flags: 0x%04X size: %d\n", flags, size);
|
||||
|
||||
if (size != expectedSize)
|
||||
{
|
||||
printf("MppcDecompressBellsRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, TEST_MPPC_BELLS, size) != 0)
|
||||
{
|
||||
printf("MppcDecompressBellsRdp5: output mismatch\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mppc_context_free(mppc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_MppcDecompressBellsRdp4()
|
||||
{
|
||||
UINT32 size;
|
||||
UINT32 flags;
|
||||
BYTE* pSrcData;
|
||||
MPPC_CONTEXT* mppc;
|
||||
UINT32 expectedSize;
|
||||
BYTE* pDstData = NULL;
|
||||
|
||||
mppc = mppc_context_new(0, FALSE);
|
||||
|
||||
size = sizeof(TEST_MPPC_BELLS_RDP4) - 1;
|
||||
pSrcData = (BYTE*) TEST_MPPC_BELLS_RDP4;
|
||||
flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 0;
|
||||
expectedSize = sizeof(TEST_MPPC_BELLS) - 1;
|
||||
|
||||
flags = mppc_decompress(mppc, pSrcData, &pDstData, &size, flags);
|
||||
printf("flags: 0x%04X size: %d\n", flags, size);
|
||||
|
||||
if (size != expectedSize)
|
||||
{
|
||||
printf("MppcDecompressBellsRdp4: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, TEST_MPPC_BELLS, size) != 0)
|
||||
{
|
||||
printf("MppcDecompressBellsRdp4: output mismatch\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mppc_context_free(mppc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_MppcCompressBufferRdp5()
|
||||
{
|
||||
UINT32 size;
|
||||
UINT32 flags;
|
||||
BYTE* pSrcData;
|
||||
MPPC_CONTEXT* mppc;
|
||||
UINT32 expectedSize;
|
||||
BYTE OutputBuffer[65536];
|
||||
MPPC_CONTEXT* mppcRecv;
|
||||
BYTE* pDstData = NULL;
|
||||
|
||||
mppc = mppc_context_new(1, TRUE);
|
||||
|
||||
size = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
|
||||
pSrcData = (BYTE*) TEST_RDP5_UNCOMPRESSED_DATA;
|
||||
expectedSize = sizeof(TEST_RDP5_COMPRESSED_DATA);
|
||||
|
||||
flags = mppc_compress(mppc, pSrcData, OutputBuffer, &size);
|
||||
printf("flags: 0x%04X size: %d\n", flags, size);
|
||||
|
||||
mppcRecv = mppc_context_new(1, FALSE);
|
||||
|
||||
pSrcData = (BYTE*) OutputBuffer;
|
||||
flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
|
||||
expectedSize = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
|
||||
|
||||
flags = mppc_decompress(mppcRecv, pSrcData, &pDstData, &size, flags);
|
||||
printf("flags: 0x%04X size: %d\n", flags, size);
|
||||
|
||||
if (size != expectedSize)
|
||||
{
|
||||
printf("MppcCompressBufferRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, TEST_RDP5_UNCOMPRESSED_DATA, size) != 0)
|
||||
{
|
||||
printf("MppcCompressBufferRdp5: output mismatch: Decompress(Compress(X)) != X\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mppc_context_free(mppc);
|
||||
mppc_context_free(mppcRecv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_MppcDecompressBufferRdp5()
|
||||
{
|
||||
UINT32 size;
|
||||
UINT32 flags;
|
||||
BYTE* pSrcData;
|
||||
MPPC_CONTEXT* mppc;
|
||||
UINT32 expectedSize;
|
||||
BYTE* pDstData = NULL;
|
||||
|
||||
mppc = mppc_context_new(1, FALSE);
|
||||
|
||||
size = sizeof(TEST_RDP5_COMPRESSED_DATA);
|
||||
pSrcData = (BYTE*) TEST_RDP5_COMPRESSED_DATA;
|
||||
flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
|
||||
expectedSize = sizeof(TEST_RDP5_UNCOMPRESSED_DATA);
|
||||
|
||||
flags = mppc_decompress(mppc, pSrcData, &pDstData, &size, flags);
|
||||
printf("flags: 0x%04X size: %d\n", flags, size);
|
||||
|
||||
if (size != expectedSize)
|
||||
{
|
||||
printf("MppcDecompressBufferRdp5: output size mismatch: Actual: %d, Expected: %d\n", size, expectedSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (memcmp(pDstData, TEST_RDP5_UNCOMPRESSED_DATA, size) != 0)
|
||||
{
|
||||
printf("MppcDecompressBufferRdp5: output mismatch\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mppc_context_free(mppc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TestFreeRDPCodecMppc(int argc, char* argv[])
|
||||
{
|
||||
if (test_MppcCompressBellsRdp5() < 0)
|
||||
return -1;
|
||||
|
||||
if (test_MppcDecompressBellsRdp5() < 0)
|
||||
return -1;
|
||||
|
||||
if (test_MppcCompressBellsRdp4() < 0)
|
||||
return -1;
|
||||
|
||||
if (test_MppcDecompressBellsRdp4() < 0)
|
||||
return -1;
|
||||
|
||||
if (test_MppcCompressBufferRdp5() < 0)
|
||||
return -1;
|
||||
|
||||
if (test_MppcDecompressBufferRdp5() < 0)
|
||||
return -1;
|
||||
|
||||
//test_mppc_old();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
65
winpr/include/winpr/bitstream.h
Normal file
65
winpr/include/winpr/bitstream.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* WinPR: Windows Portable Runtime
|
||||
* BitStream Utils
|
||||
*
|
||||
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
*
|
||||
* 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 WINPR_UTILS_BITSTREAM_H
|
||||
#define WINPR_UTILS_BITSTREAM_H
|
||||
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
|
||||
struct _wBitStream
|
||||
{
|
||||
BYTE* buffer;
|
||||
BYTE* pointer;
|
||||
DWORD position;
|
||||
DWORD length;
|
||||
DWORD capacity;
|
||||
UINT32 mask;
|
||||
UINT32 offset;
|
||||
UINT32 prefetch;
|
||||
UINT32 accumulator;
|
||||
};
|
||||
typedef struct _wBitStream wBitStream;
|
||||
|
||||
#define BITDUMP_MSB_FIRST 0x00000001
|
||||
#define BITDUMP_STDERR 0x00000002
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WINPR_API void BitStream_Attach(wBitStream* bs, BYTE* buffer, UINT32 capacity);
|
||||
WINPR_API void BitStream_Write_Bits(wBitStream* bs, UINT32 bits, UINT32 nbits);
|
||||
WINPR_API void BitStream_Flush(wBitStream* bs);
|
||||
WINPR_API void BitStream_Prefetch(wBitStream* bs);
|
||||
WINPR_API void BitStream_Fetch(wBitStream* bs);
|
||||
WINPR_API void BitStream_Shift(wBitStream* bs, UINT32 nbits);
|
||||
|
||||
WINPR_API void BitDump(const BYTE* buffer, UINT32 length, UINT32 flags);
|
||||
|
||||
WINPR_API wBitStream* BitStream_New();
|
||||
WINPR_API void BitStream_Free(wBitStream* bs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_UTILS_BITSTREAM_H */
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <winpr/winpr.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/stream.h>
|
||||
|
||||
@@ -596,65 +597,8 @@ WINPR_API int PubSub_OnEvent(wPubSub* pubSub, const char* EventName, void* conte
|
||||
WINPR_API wPubSub* PubSub_New(BOOL synchronized);
|
||||
WINPR_API void PubSub_Free(wPubSub* pubSub);
|
||||
|
||||
/* BitStream */
|
||||
|
||||
struct _wBitStream
|
||||
{
|
||||
BYTE* buffer;
|
||||
BYTE* pointer;
|
||||
DWORD position;
|
||||
DWORD length;
|
||||
DWORD capacity;
|
||||
UINT32 offset;
|
||||
UINT32 accumulator;
|
||||
};
|
||||
typedef struct _wBitStream wBitStream;
|
||||
|
||||
#define BitStream_Attach(_bs, _buffer, _capacity) { \
|
||||
_bs->position = 0; \
|
||||
_bs->buffer = _buffer; \
|
||||
_bs->offset = 0; \
|
||||
_bs->accumulator = 0; \
|
||||
_bs->pointer = _bs->buffer; \
|
||||
_bs->capacity = _capacity; \
|
||||
_bs->length = _bs->capacity; \
|
||||
}
|
||||
|
||||
#define BitStream_Write_Bits(_bs, _bits, _nbits) { \
|
||||
_bs->accumulator |= (_bits << _bs->offset); \
|
||||
_bs->position += _nbits; \
|
||||
_bs->offset += _nbits; \
|
||||
if (_bs->offset >= 32) { \
|
||||
*(_bs->pointer + 0) = (_bs->accumulator >> 0); \
|
||||
*(_bs->pointer + 1) = (_bs->accumulator >> 8); \
|
||||
*(_bs->pointer + 2) = (_bs->accumulator >> 16); \
|
||||
*(_bs->pointer + 3) = (_bs->accumulator >> 24); \
|
||||
_bs->offset = _bs->offset - 32; \
|
||||
_bs->accumulator = _bits >> (_nbits - _bs->offset); \
|
||||
_bs->pointer += 4; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define BitStream_Flush(_bs) { \
|
||||
if ((_bs->pointer - _bs->buffer) > 0) \
|
||||
*(_bs->pointer + 0) = (_bs->accumulator >> 0); \
|
||||
if ((_bs->pointer - _bs->buffer) > 1) \
|
||||
*(_bs->pointer + 1) = (_bs->accumulator >> 8); \
|
||||
if ((_bs->pointer - _bs->buffer) > 2) \
|
||||
*(_bs->pointer + 2) = (_bs->accumulator >> 16); \
|
||||
if ((_bs->pointer - _bs->buffer) > 3) \
|
||||
*(_bs->pointer + 3) = (_bs->accumulator >> 24); \
|
||||
}
|
||||
|
||||
#define BITDUMP_MSB_FIRST 0x00000001
|
||||
#define BITDUMP_STDERR 0x00000002
|
||||
|
||||
WINPR_API void BitDump(BYTE* buffer, UINT32 length, UINT32 flags);
|
||||
|
||||
WINPR_API wBitStream* BitStream_New();
|
||||
WINPR_API void BitStream_Free(wBitStream* bs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_COLLECTIONS_H */
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/collections.h>
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
const char* BYTE_BIT_STRINGS_LSB[256] =
|
||||
{
|
||||
@@ -159,7 +159,7 @@ const char* BYTE_BIT_STRINGS_MSB[256] =
|
||||
"00111111", "10111111", "01111111", "11111111"
|
||||
};
|
||||
|
||||
void BitDump(BYTE* buffer, UINT32 length, UINT32 flags)
|
||||
void BitDump(const BYTE* buffer, UINT32 length, UINT32 flags)
|
||||
{
|
||||
DWORD i;
|
||||
int nbits;
|
||||
@@ -174,12 +174,126 @@ void BitDump(BYTE* buffer, UINT32 length, UINT32 flags)
|
||||
|
||||
nbits = (length - i) > 8 ? 8 : (length - i);
|
||||
|
||||
if ((i % 64) == 0)
|
||||
printf("\n");
|
||||
|
||||
printf("%.*s ", nbits, str);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void BitStream_Attach(wBitStream* bs, BYTE* buffer, UINT32 capacity)
|
||||
{
|
||||
bs->position = 0;
|
||||
bs->buffer = buffer;
|
||||
bs->offset = 0;
|
||||
bs->accumulator = 0;
|
||||
bs->pointer = bs->buffer;
|
||||
bs->capacity = capacity;
|
||||
bs->length = bs->capacity * 8;
|
||||
}
|
||||
|
||||
void BitStream_Flush(wBitStream* bs)
|
||||
{
|
||||
if ((bs->pointer - bs->buffer) < (bs->capacity + 0))
|
||||
*(bs->pointer + 0) = (bs->accumulator >> 24);
|
||||
if ((bs->pointer - bs->buffer) < (bs->capacity + 1))
|
||||
*(bs->pointer + 1) = (bs->accumulator >> 16);
|
||||
if ((bs->pointer - bs->buffer) < (bs->capacity + 2))
|
||||
*(bs->pointer + 2) = (bs->accumulator >> 8);
|
||||
if ((bs->pointer - bs->buffer) < (bs->capacity + 3))
|
||||
*(bs->pointer + 3) = (bs->accumulator >> 0);
|
||||
}
|
||||
|
||||
void BitStream_Prefetch(wBitStream* bs)
|
||||
{
|
||||
(bs->prefetch) = 0;
|
||||
if ((bs->pointer - bs->buffer) < (bs->capacity + 4))
|
||||
(bs->prefetch) |= (*(bs->pointer + 4) << 24);
|
||||
if ((bs->pointer - bs->buffer) < (bs->capacity + 5))
|
||||
(bs->prefetch) |= (*(bs->pointer + 5) << 16);
|
||||
if ((bs->pointer - bs->buffer) < (bs->capacity + 6))
|
||||
(bs->prefetch) |= (*(bs->pointer + 6) << 8);
|
||||
if ((bs->pointer - bs->buffer) < (bs->capacity + 7))
|
||||
(bs->prefetch) |= (*(bs->pointer + 7) << 0);
|
||||
}
|
||||
|
||||
void BitStream_Fetch(wBitStream* bs)
|
||||
{
|
||||
(bs->accumulator) = 0;
|
||||
|
||||
if ((bs->pointer - bs->buffer) < (bs->capacity + 0))
|
||||
(bs->accumulator) |= (*(bs->pointer + 0) << 24);
|
||||
if ((bs->pointer - bs->buffer) < (bs->capacity + 1))
|
||||
(bs->accumulator) |= (*(bs->pointer + 1) << 16);
|
||||
if ((bs->pointer - bs->buffer) < (bs->capacity + 2))
|
||||
(bs->accumulator) |= (*(bs->pointer + 2) << 8);
|
||||
if ((bs->pointer - bs->buffer) < (bs->capacity + 3))
|
||||
(bs->accumulator) |= (*(bs->pointer + 3) << 0);
|
||||
|
||||
BitStream_Prefetch(bs);
|
||||
}
|
||||
|
||||
void BitStream_Write_Bits(wBitStream* bs, UINT32 bits, UINT32 nbits)
|
||||
{
|
||||
bs->position += nbits;
|
||||
bs->offset += nbits;
|
||||
|
||||
if (bs->offset < 32)
|
||||
{
|
||||
bs->accumulator |= (bits << (32 - bs->offset));
|
||||
}
|
||||
else
|
||||
{
|
||||
bs->offset -= 32;
|
||||
bs->mask = ((1 << (nbits - bs->offset)) - 1);
|
||||
bs->accumulator |= ((bits >> bs->offset) & bs->mask);
|
||||
|
||||
BitStream_Flush(bs);
|
||||
bs->accumulator = 0;
|
||||
bs->pointer += 4;
|
||||
|
||||
if (bs->offset)
|
||||
{
|
||||
bs->mask = ((1 << bs->offset) - 1);
|
||||
bs->accumulator |= ((bits & bs->mask) << (32 - bs->offset));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BitStream_Shift(wBitStream* bs, UINT32 nbits)
|
||||
{
|
||||
bs->accumulator <<= nbits;
|
||||
bs->position += nbits;
|
||||
bs->offset += nbits;
|
||||
|
||||
if (bs->offset < 32)
|
||||
{
|
||||
bs->mask = ((1 << nbits) - 1);
|
||||
bs->accumulator |= ((bs->prefetch >> (32 - nbits)) & bs->mask);
|
||||
bs->prefetch <<= nbits;
|
||||
}
|
||||
else
|
||||
{
|
||||
bs->mask = ((1 << nbits) - 1);
|
||||
bs->accumulator |= ((bs->prefetch >> (32 - nbits)) & bs->mask);
|
||||
bs->prefetch <<= nbits;
|
||||
|
||||
bs->offset -= 32;
|
||||
bs->pointer += 4;
|
||||
|
||||
BitStream_Prefetch(bs);
|
||||
|
||||
if (bs->offset)
|
||||
{
|
||||
bs->mask = ((1 << bs->offset) - 1);
|
||||
bs->accumulator |= ((bs->prefetch >> (32 - bs->offset)) & bs->mask);
|
||||
bs->prefetch <<= bs->offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wBitStream* BitStream_New()
|
||||
{
|
||||
wBitStream* bs = NULL;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/stream.h>
|
||||
#include <winpr/collections.h>
|
||||
#include <winpr/bitstream.h>
|
||||
|
||||
void BitStrGen()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user