libfreerdp-codec: start working on clearcodec decompressor

This commit is contained in:
Marc-André Moreau 2014-06-13 12:17:16 -04:00
parent eeb7cd2cb2
commit 0e27f5abe4
3 changed files with 369 additions and 0 deletions

View File

@ -23,6 +23,10 @@
#include <freerdp/api.h>
#include <freerdp/types.h>
#define CLEARCODEC_FLAG_GLYPH_INDEX 0x01
#define CLEARCODEC_FLAG_GLYPH_HIT 0x02
#define CLEARCODEC_FLAG_CACHE_RESET 0x03
struct _CLEAR_CONTEXT
{
BOOL Compressor;

View File

@ -29,6 +29,237 @@
int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize)
{
BYTE glyphFlags;
BYTE seqNumber;
UINT16 glyphIndex;
UINT32 offset = 0;
UINT32 residualByteCount;
UINT32 bandsByteCount;
UINT32 subcodecByteCount;
if (SrcSize < 2)
return -1;
glyphFlags = pSrcData[0];
seqNumber = pSrcData[1];
offset += 2;
printf("glyphFlags: 0x%02X seqNumber: %d\n", glyphFlags, seqNumber);
if (glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX)
{
if (SrcSize < 4)
return -1;
glyphIndex = *((UINT16*) &pSrcData[2]);
offset += 2;
if (glyphFlags & CLEARCODEC_FLAG_GLYPH_HIT)
{
/**
* Copy pixels from the Decompressor Glyph Storage position
* specified by the glyphIndex field to the output bitmap
*/
return 1; /* Finish */
}
}
/* Read composition payload header parameters */
if ((SrcSize - offset) < 12)
return -1;
residualByteCount = *((UINT32*) &pSrcData[offset]);
bandsByteCount = *((UINT32*) &pSrcData[offset + 4]);
subcodecByteCount = *((UINT32*) &pSrcData[offset + 8]);
offset += 12;
printf("residualByteCount: %d bandsByteCount: %d subcodecByteCount: %d\n",
residualByteCount, bandsByteCount, subcodecByteCount);
if (residualByteCount > 0)
{
BYTE blueValue;
BYTE greenValue;
BYTE redValue;
UINT32 suboffset;
BYTE* residualData;
BYTE runLengthFactor1 = 0;
UINT16 runLengthFactor2 = 0;
UINT32 runLengthFactor3 = 0;
UINT32 runLengthFactor = 0;
if ((SrcSize - offset) < residualByteCount)
return -1;
suboffset = 0;
residualData = &pSrcData[offset];
while (suboffset < residualByteCount)
{
if ((residualByteCount - suboffset) < 4)
return -1;
blueValue = residualData[suboffset];
greenValue = residualData[suboffset + 1];
redValue = residualData[suboffset + 2];
suboffset += 3;
runLengthFactor1 = residualData[suboffset];
runLengthFactor = runLengthFactor1;
suboffset += 1;
if (runLengthFactor1 >= 0xFF)
{
if ((residualByteCount - suboffset) < 2)
return -1;
runLengthFactor2 = *((UINT16*) &residualData[suboffset]);
runLengthFactor = runLengthFactor2;
suboffset += 2;
if (runLengthFactor2 >= 0xFFFF)
{
if ((residualByteCount - suboffset) < 4)
return -1;
runLengthFactor3 = *((UINT32*) &residualData[suboffset]);
runLengthFactor = runLengthFactor3;
suboffset += 4;
}
}
}
/* Decompress residual layer and write to output bitmap */
offset += residualByteCount;
}
if (bandsByteCount > 0)
{
BYTE* bandsData;
UINT32 suboffset;
if ((SrcSize - offset) < bandsByteCount)
return -1;
suboffset = 0;
bandsData = &pSrcData[offset];
while (suboffset < bandsByteCount)
{
UINT16 xStart;
UINT16 xEnd;
UINT16 yStart;
UINT16 yEnd;
BYTE blueBkg;
BYTE greenBkg;
BYTE redBkg;
BYTE* vBars;
UINT16 vBarHeader;
if ((bandsByteCount - suboffset) < 11)
return -1;
xStart = *((UINT16*) &bandsData[suboffset]);
xEnd = *((UINT16*) &bandsData[suboffset + 2]);
yStart = *((UINT16*) &bandsData[suboffset + 4]);
yEnd = *((UINT16*) &bandsData[suboffset + 6]);
blueBkg = bandsData[suboffset + 8];
greenBkg = bandsData[suboffset + 9];
redBkg = bandsData[suboffset + 10];
suboffset += 11;
vBars = &bandsData[suboffset];
vBarHeader = *((UINT16*) &vBars[0]);
if ((vBarHeader & 0xC000) == 0x8000) /* VBAR_CACHE_HIT */
{
printf("VBAR_CACHE_HIT\n");
suboffset += 2;
}
else if ((vBarHeader & 0xC000) == 0xC000) /* SHORT_VBAR_CACHE_HIT */
{
printf("SHORT_VBAR_CACHE_HIT\n");
suboffset += 3;
}
else if ((vBarHeader & 0xC000) == 0) /* SHORT_VBAR_CACHE_MISS */
{
printf("SHORT_VBAR_CACHE_MISS\n");
suboffset += 2;
}
else
{
return -1; /* invalid vBarHeader */
}
/* shortVBarPixels: variable */
}
/* Decompress bands layer and write to output bitmap */
offset += bandsByteCount;
}
if (subcodecByteCount > 0)
{
UINT16 xStart;
UINT16 yStart;
UINT16 width;
UINT16 height;
BYTE* bitmapData;
UINT32 bitmapDataByteCount;
BYTE subcodecId;
BYTE* subcodecs;
UINT32 suboffset;
if ((SrcSize - offset) < subcodecByteCount)
return -1;
suboffset = 0;
subcodecs = &pSrcData[offset];
while (suboffset < subcodecByteCount)
{
if ((subcodecByteCount - suboffset) < 13)
return -1;
xStart = *((UINT16*) &subcodecs[suboffset]);
yStart = *((UINT16*) &subcodecs[suboffset + 2]);
width = *((UINT16*) &subcodecs[suboffset + 4]);
height = *((UINT16*) &subcodecs[suboffset + 6]);
bitmapDataByteCount = *((UINT32*) &subcodecs[suboffset + 8]);
subcodecId = subcodecs[suboffset + 12];
suboffset += 13;
printf("bitmapDataByteCount: %d subcodecByteCount: %d suboffset: %d\n",
bitmapDataByteCount, subcodecByteCount, suboffset);
if ((subcodecByteCount - suboffset) < bitmapDataByteCount)
return -1;
bitmapData = &subcodecs[suboffset];
suboffset += bitmapDataByteCount;
}
/* Decompress subcodec layer and write to output bitmap */
offset += subcodecByteCount;
}
if (glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX)
{
/**
* Copy decompressed bitmap to the Decompressor Glyph
* Storage position specified by the glyphIndex field
*/
}
if (offset != SrcSize)
{
printf("clear_decompress: incomplete processing of bytes: Actual: %d, Expected: %d\n", offset, SrcSize);
}
return 1;
}

View File

@ -3,8 +3,142 @@
#include <freerdp/codec/clear.h>
static BYTE TEST_CLEAR_EXAMPLE_1[] = "\x03\xc3\x11\x00";
static BYTE TEST_CLEAR_EXAMPLE_2[] =
"\x00\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x82\x00\x00\x00\x00\x00"
"\x00\x00\x4e\x00\x11\x00\x75\x00\x00\x00\x02\x0e\xff\xff\xff\x00"
"\x00\x00\xdb\xff\xff\x00\x3a\x90\xff\xb6\x66\x66\xb6\xff\xb6\x66"
"\x00\x90\xdb\xff\x00\x00\x3a\xdb\x90\x3a\x3a\x90\xdb\x66\x00\x00"
"\xff\xff\xb6\x64\x64\x64\x11\x04\x11\x4c\x11\x4c\x11\x4c\x11\x4c"
"\x11\x4c\x00\x47\x13\x00\x01\x01\x04\x00\x01\x00\x00\x47\x16\x00"
"\x11\x02\x00\x47\x29\x00\x11\x01\x00\x49\x0a\x00\x01\x00\x04\x00"
"\x01\x00\x00\x4a\x0a\x00\x09\x00\x01\x00\x00\x47\x05\x00\x01\x01"
"\x1c\x00\x01\x00\x11\x4c\x11\x4c\x11\x4c\x00\x47\x0d\x4d\x00\x4d";
static BYTE TEST_CLEAR_EXAMPLE_3[] =
"\x00\xdf\x0e\x00\x00\x00\x8b\x00\x00\x00\x00\x00\x00\x00\xfe\xfe"
"\xfe\xff\x80\x05\xff\xff\xff\x40\xfe\xfe\xfe\x40\x00\x00\x3f\x00"
"\x03\x00\x0b\x00\xfe\xfe\xfe\xc5\xd0\xc6\xd0\xc7\xd0\x68\xd4\x69"
"\xd4\x6a\xd4\x6b\xd4\x6c\xd4\x6d\xd4\x1a\xd4\x1a\xd4\xa6\xd0\x6e"
"\xd4\x6f\xd4\x70\xd4\x71\xd4\x72\xd4\x73\xd4\x74\xd4\x21\xd4\x22"
"\xd4\x23\xd4\x24\xd4\x25\xd4\xd9\xd0\xda\xd0\xdb\xd0\xc5\xd0\xc5"
"\xd0\xdc\xd0\xc2\xd0\x21\xd4\x22\xd4\x23\xd4\x24\xd4\x25\xd4\xc9"
"\xd0\xca\xd0\x5a\xd4\x2b\xd1\x28\xd1\x2c\xd1\x75\xd4\x27\xd4\x28"
"\xd4\x29\xd4\x2a\xd4\x1a\xd4\x1a\xd4\x1a\xd4\xb7\xd0\xb8\xd0\xb9"
"\xd0\xba\xd0\xbb\xd0\xbc\xd0\xbd\xd0\xbe\xd0\xbf\xd0\xc0\xd0\xc1"
"\xd0\xc2\xd0\xc3\xd0\xc4\xd0";
static BYTE TEST_CLEAR_EXAMPLE_4[] =
"\x01\x0b\x78\x00\x00\x00\x00\x00\x46\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x06\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x0f\xff\xff\xff"
"\xff\xff\xff\xff\xff\xff\xb6\xff\xff\xff\xff\xff\xff\xff\xff\xff"
"\xb6\x66\xff\xff\xff\xff\xff\xff\xff\xb6\x66\xdb\x90\x3a\xff\xff"
"\xb6\xff\xff\xff\xff\xff\xff\xff\xff\xff\x46\x91\x47\x91\x48\x91"
"\x49\x91\x4a\x91\x1b\x91";
int test_ClearDecompressExample1()
{
int status;
BYTE* pSrcData;
UINT32 SrcSize;
UINT32 DstSize;
BYTE* pDstData = NULL;
CLEAR_CONTEXT* clear;
clear = clear_context_new(FALSE);
SrcSize = sizeof(TEST_CLEAR_EXAMPLE_1) - 1;
pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_1;
status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize);
printf("clear_decompress example 1 status: %d\n", status);
clear_context_free(clear);
return 1;
}
int test_ClearDecompressExample2()
{
int status;
BYTE* pSrcData;
UINT32 SrcSize;
UINT32 DstSize;
BYTE* pDstData = NULL;
CLEAR_CONTEXT* clear;
clear = clear_context_new(FALSE);
SrcSize = sizeof(TEST_CLEAR_EXAMPLE_2) - 1;
pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_2;
status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize);
printf("clear_decompress example 2 status: %d\n", status);
clear_context_free(clear);
return 1;
}
int test_ClearDecompressExample3()
{
int status;
BYTE* pSrcData;
UINT32 SrcSize;
UINT32 DstSize;
BYTE* pDstData = NULL;
CLEAR_CONTEXT* clear;
clear = clear_context_new(FALSE);
SrcSize = sizeof(TEST_CLEAR_EXAMPLE_3) - 1;
pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_3;
status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize);
printf("clear_decompress example 3 status: %d\n", status);
clear_context_free(clear);
return 1;
}
int test_ClearDecompressExample4()
{
int status;
BYTE* pSrcData;
UINT32 SrcSize;
UINT32 DstSize;
BYTE* pDstData = NULL;
CLEAR_CONTEXT* clear;
clear = clear_context_new(FALSE);
SrcSize = sizeof(TEST_CLEAR_EXAMPLE_4) - 1;
pSrcData = (BYTE*) TEST_CLEAR_EXAMPLE_4;
status = clear_decompress(clear, pSrcData, SrcSize, &pDstData, &DstSize);
printf("clear_decompress example 4 status: %d\n", status);
clear_context_free(clear);
return 1;
}
int TestFreeRDPCodecClear(int argc, char* argv[])
{
//test_ClearDecompressExample1();
//test_ClearDecompressExample2();
test_ClearDecompressExample3();
//test_ClearDecompressExample4();
return 0;
}