libfreerdp-codec: start working on clearcodec decompressor
This commit is contained in:
parent
eeb7cd2cb2
commit
0e27f5abe4
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user