libfreerdp-codec: simplify zgfx segment processing
This commit is contained in:
parent
6ad00125b4
commit
161e7b0026
@ -306,11 +306,16 @@ int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODIN
|
||||
|
||||
int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface)
|
||||
{
|
||||
printf("xf_CreateSurface: surfaceId: %d width: %d height: %d format: 0x%02X\n",
|
||||
createSurface->surfaceId, createSurface->width, createSurface->height, createSurface->pixelFormat);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface)
|
||||
{
|
||||
printf("xf_DeleteSurface: surfaceId: %d\n", deleteSurface->surfaceId);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -28,24 +28,6 @@
|
||||
#define ZGFX_SEGMENTED_SINGLE 0xE0
|
||||
#define ZGFX_SEGMENTED_MULTIPART 0xE1
|
||||
|
||||
#pragma pack(push,1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
BYTE descriptor;
|
||||
UINT16 segmentCount;
|
||||
UINT32 uncompressedSize;
|
||||
// RDP_DATA_SEGMENT first;
|
||||
} RDP_SEGMENTED_DATA;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UINT32 size;
|
||||
// BYTE data[size];
|
||||
} RDP_DATA_SEGMENT;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
struct _ZGFX_CONTEXT
|
||||
{
|
||||
BOOL Compressor;
|
||||
@ -62,6 +44,7 @@ struct _ZGFX_CONTEXT
|
||||
|
||||
BYTE HistoryBuffer[2500000];
|
||||
UINT32 HistoryIndex;
|
||||
UINT32 HistoryBufferSize;
|
||||
};
|
||||
typedef struct _ZGFX_CONTEXT ZGFX_CONTEXT;
|
||||
|
||||
|
@ -92,9 +92,7 @@ UINT32 zgfx_GetBits(ZGFX_CONTEXT* zgfx, UINT32 bitCount)
|
||||
zgfx->BitsCurrent <<= 8;
|
||||
|
||||
if (zgfx->pbInputCurrent < zgfx->pbInputEnd)
|
||||
{
|
||||
zgfx->BitsCurrent += *(zgfx->pbInputCurrent)++;
|
||||
}
|
||||
|
||||
zgfx->cBitsCurrent += 8;
|
||||
}
|
||||
@ -122,7 +120,7 @@ int zgfx_OutputFromNotCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbRaw, int cbRaw)
|
||||
|
||||
zgfx->HistoryBuffer[zgfx->HistoryIndex++] = c;
|
||||
|
||||
if (zgfx->HistoryIndex == sizeof(zgfx->HistoryBuffer))
|
||||
if (zgfx->HistoryIndex == zgfx->HistoryBufferSize)
|
||||
zgfx->HistoryIndex = 0;
|
||||
|
||||
zgfx->OutputBuffer[zgfx->OutputCount++] = c;
|
||||
@ -138,6 +136,7 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded
|
||||
int opIndex;
|
||||
int haveBits;
|
||||
int inPrefix;
|
||||
UINT32 bits;
|
||||
UINT32 count;
|
||||
UINT32 distance;
|
||||
UINT32 prevIndex;
|
||||
@ -160,7 +159,8 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded
|
||||
{
|
||||
while (haveBits < ZGFX_TOKEN_TABLE[opIndex].prefixLength)
|
||||
{
|
||||
inPrefix = (inPrefix << 1) + zgfx_GetBits(zgfx, 1);
|
||||
bits = zgfx_GetBits(zgfx, 1);
|
||||
inPrefix = (inPrefix << 1) + bits;
|
||||
haveBits++;
|
||||
}
|
||||
|
||||
@ -168,19 +168,21 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded
|
||||
{
|
||||
if (ZGFX_TOKEN_TABLE[opIndex].tokenType == 0)
|
||||
{
|
||||
c = (BYTE)(ZGFX_TOKEN_TABLE[opIndex].valueBase +
|
||||
zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits));
|
||||
bits = zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits);
|
||||
c = (BYTE) (ZGFX_TOKEN_TABLE[opIndex].valueBase + bits);
|
||||
|
||||
goto output_literal;
|
||||
}
|
||||
else
|
||||
{
|
||||
distance = ZGFX_TOKEN_TABLE[opIndex].valueBase +
|
||||
zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits);
|
||||
bits = zgfx_GetBits(zgfx, ZGFX_TOKEN_TABLE[opIndex].valueBits);
|
||||
distance = ZGFX_TOKEN_TABLE[opIndex].valueBase + bits;
|
||||
|
||||
if (distance != 0)
|
||||
{
|
||||
if (zgfx_GetBits(zgfx, 1) == 0)
|
||||
bits = zgfx_GetBits(zgfx, 1);
|
||||
|
||||
if (bits == 0)
|
||||
{
|
||||
count = 3;
|
||||
}
|
||||
@ -189,20 +191,26 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded
|
||||
count = 4;
|
||||
extra = 2;
|
||||
|
||||
while (zgfx_GetBits(zgfx, 1) == 1)
|
||||
bits = zgfx_GetBits(zgfx, 1);
|
||||
|
||||
while (bits == 1)
|
||||
{
|
||||
count *= 2;
|
||||
extra++;
|
||||
|
||||
bits = zgfx_GetBits(zgfx, 1);
|
||||
}
|
||||
|
||||
count += zgfx_GetBits(zgfx, extra);
|
||||
bits = zgfx_GetBits(zgfx, extra);
|
||||
count += bits;
|
||||
}
|
||||
|
||||
goto output_match;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = zgfx_GetBits(zgfx, 15);
|
||||
bits = zgfx_GetBits(zgfx, 15);
|
||||
count = bits;
|
||||
|
||||
zgfx->cBitsRemaining -= zgfx->cBitsCurrent;
|
||||
zgfx->cBitsCurrent = 0;
|
||||
@ -216,30 +224,28 @@ int zgfx_OutputFromCompressed(ZGFX_CONTEXT* zgfx, BYTE* pbEncoded, int cbEncoded
|
||||
break;
|
||||
|
||||
output_literal:
|
||||
|
||||
zgfx->HistoryBuffer[zgfx->HistoryIndex] = c;
|
||||
|
||||
if (++zgfx->HistoryIndex == sizeof(zgfx->HistoryBuffer))
|
||||
if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize)
|
||||
zgfx->HistoryIndex = 0;
|
||||
|
||||
zgfx->OutputBuffer[zgfx->OutputCount++] = c;
|
||||
continue;
|
||||
|
||||
output_match:
|
||||
|
||||
prevIndex = zgfx->HistoryIndex + sizeof(zgfx->HistoryBuffer) - distance;
|
||||
prevIndex = prevIndex % sizeof(zgfx->HistoryBuffer);
|
||||
prevIndex = zgfx->HistoryIndex + zgfx->HistoryBufferSize - distance;
|
||||
prevIndex = prevIndex % zgfx->HistoryBufferSize;
|
||||
|
||||
while (count--)
|
||||
{
|
||||
c = zgfx->HistoryBuffer[prevIndex];
|
||||
|
||||
if (++prevIndex == sizeof(zgfx->HistoryBuffer))
|
||||
if (++prevIndex == zgfx->HistoryBufferSize)
|
||||
prevIndex = 0;
|
||||
|
||||
zgfx->HistoryBuffer[zgfx->HistoryIndex] = c;
|
||||
|
||||
if (++zgfx->HistoryIndex == sizeof(zgfx->HistoryBuffer))
|
||||
if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize)
|
||||
zgfx->HistoryIndex = 0;
|
||||
|
||||
zgfx->OutputBuffer[zgfx->OutputCount] = c;
|
||||
@ -255,7 +261,7 @@ output_unencoded:
|
||||
|
||||
zgfx->HistoryBuffer[zgfx->HistoryIndex] = c;
|
||||
|
||||
if (++zgfx->HistoryIndex == sizeof(zgfx->HistoryBuffer))
|
||||
if (++zgfx->HistoryIndex == zgfx->HistoryBufferSize)
|
||||
zgfx->HistoryIndex = 0;
|
||||
|
||||
zgfx->OutputBuffer[zgfx->OutputCount] = c;
|
||||
@ -267,71 +273,83 @@ output_unencoded:
|
||||
return 1;
|
||||
}
|
||||
|
||||
int zgfx_OutputFromSegment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, int cbSegment)
|
||||
int zgfx_OutputFromSegment(ZGFX_CONTEXT* zgfx, BYTE* pbSegment, UINT32 cbSegment)
|
||||
{
|
||||
int status;
|
||||
BYTE header;
|
||||
|
||||
if (pbSegment[0] & PACKET_COMPRESSED)
|
||||
status = zgfx_OutputFromCompressed(zgfx, pbSegment + 1, cbSegment - 1);
|
||||
if (cbSegment < 1)
|
||||
return -1;
|
||||
|
||||
header = pbSegment[0];
|
||||
|
||||
if (header & PACKET_COMPRESSED)
|
||||
{
|
||||
status = zgfx_OutputFromCompressed(zgfx, &pbSegment[1], cbSegment - 1);
|
||||
}
|
||||
else
|
||||
status = zgfx_OutputFromNotCompressed(zgfx, pbSegment + 1, cbSegment - 1);
|
||||
{
|
||||
status = zgfx_OutputFromNotCompressed(zgfx, &pbSegment[1], cbSegment - 1);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int zgfx_Decompress_Internal(ZGFX_CONTEXT* zgfx, BYTE* pbInput, int cbInput, BYTE** ppbOutput, int* pcbOutput)
|
||||
{
|
||||
int status;
|
||||
|
||||
RDP_SEGMENTED_DATA* pSegmentedData = (RDP_SEGMENTED_DATA*) pbInput;
|
||||
|
||||
if (pSegmentedData->descriptor == ZGFX_SEGMENTED_SINGLE)
|
||||
{
|
||||
status = zgfx_OutputFromSegment(zgfx, pbInput + 1, cbInput - 1);
|
||||
|
||||
*ppbOutput = (BYTE*) malloc(zgfx->OutputCount);
|
||||
*pcbOutput = zgfx->OutputCount;
|
||||
CopyMemory(*ppbOutput, zgfx->OutputBuffer, zgfx->OutputCount);
|
||||
}
|
||||
else if (pSegmentedData->descriptor == ZGFX_SEGMENTED_MULTIPART)
|
||||
{
|
||||
UINT16 segmentNumber;
|
||||
UINT32 segmentOffset = sizeof(RDP_SEGMENTED_DATA);
|
||||
BYTE* pConcatenated = (BYTE*) malloc(pSegmentedData->uncompressedSize);
|
||||
|
||||
*ppbOutput = pConcatenated;
|
||||
*pcbOutput = pSegmentedData->uncompressedSize;
|
||||
|
||||
for (segmentNumber = 0; segmentNumber < pSegmentedData->segmentCount; segmentNumber++)
|
||||
{
|
||||
RDP_DATA_SEGMENT* pSegment = (RDP_DATA_SEGMENT*) (pbInput + segmentOffset);
|
||||
|
||||
status = zgfx_OutputFromSegment(zgfx, pbInput + segmentOffset + sizeof(RDP_DATA_SEGMENT), pSegment->size);
|
||||
|
||||
segmentOffset += sizeof(RDP_DATA_SEGMENT) + pSegment->size;
|
||||
CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount);
|
||||
pConcatenated += zgfx->OutputCount;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int zgfx_decompress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32 flags)
|
||||
{
|
||||
int status = 0;
|
||||
int cbOutput = 0;
|
||||
BYTE* pbOutput = NULL;
|
||||
int status;
|
||||
BYTE descriptor;
|
||||
|
||||
status = zgfx_Decompress_Internal(zgfx, pSrcData, SrcSize, &pbOutput, &cbOutput);
|
||||
if (SrcSize < 1)
|
||||
return -1;
|
||||
|
||||
if (status >= 0)
|
||||
descriptor = pSrcData[0]; /* descriptor (1 byte) */
|
||||
|
||||
if (descriptor == ZGFX_SEGMENTED_SINGLE)
|
||||
{
|
||||
*ppDstData = pbOutput;
|
||||
*pDstSize = (UINT32) cbOutput;
|
||||
status = zgfx_OutputFromSegment(zgfx, &pSrcData[1], SrcSize - 1);
|
||||
|
||||
*ppDstData = (BYTE*) malloc(zgfx->OutputCount);
|
||||
*pDstSize = zgfx->OutputCount;
|
||||
|
||||
CopyMemory(*ppDstData, zgfx->OutputBuffer, zgfx->OutputCount);
|
||||
}
|
||||
else if (descriptor == ZGFX_SEGMENTED_MULTIPART)
|
||||
{
|
||||
UINT32 segmentSize;
|
||||
UINT16 segmentNumber;
|
||||
UINT16 segmentCount;
|
||||
UINT32 segmentOffset;
|
||||
UINT32 uncompressedSize;
|
||||
BYTE* pConcatenated;
|
||||
|
||||
segmentOffset = 7;
|
||||
segmentCount = *((UINT16*) &pSrcData[1]); /* segmentCount (2 bytes) */
|
||||
uncompressedSize = *((UINT32*) &pSrcData[3]); /* uncompressedSize (4 bytes) */
|
||||
|
||||
pConcatenated = (BYTE*) malloc(uncompressedSize);
|
||||
|
||||
*ppDstData = pConcatenated;
|
||||
*pDstSize = uncompressedSize;
|
||||
|
||||
for (segmentNumber = 0; segmentNumber < segmentCount; segmentNumber++)
|
||||
{
|
||||
segmentSize = *((UINT32*) &pSrcData[segmentOffset]); /* segmentSize (4 bytes) */
|
||||
segmentOffset += 4;
|
||||
|
||||
status = zgfx_OutputFromSegment(zgfx, &pSrcData[segmentOffset], segmentSize);
|
||||
segmentOffset += segmentSize;
|
||||
|
||||
CopyMemory(pConcatenated, zgfx->OutputBuffer, zgfx->OutputCount);
|
||||
pConcatenated += zgfx->OutputCount;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return status;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int zgfx_compress(ZGFX_CONTEXT* zgfx, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize, UINT32* pFlags)
|
||||
@ -354,6 +372,8 @@ ZGFX_CONTEXT* zgfx_context_new(BOOL Compressor)
|
||||
{
|
||||
zgfx->Compressor = Compressor;
|
||||
|
||||
zgfx->HistoryBufferSize = sizeof(zgfx->HistoryBuffer);
|
||||
|
||||
zgfx_context_reset(zgfx, FALSE);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user