From 2b3cd390265a001f21d8064690698882423694eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 29 Jul 2014 12:38:29 -0400 Subject: [PATCH 01/12] libfreerdp-codec: more parsing of progressive data blocks --- include/freerdp/codec/progressive.h | 81 ++++++-- libfreerdp/codec/progressive.c | 295 ++++++++++++++++++++++++---- 2 files changed, 324 insertions(+), 52 deletions(-) diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index be063aadd..603d1efe4 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -32,10 +32,41 @@ #define PROGRESSIVE_WBT_CONTEXT 0xCCC3 #define PROGRESSIVE_WBT_REGION 0xCCC4 #define PROGRESSIVE_WBT_TILE_SIMPLE 0xCCC5 -#define PROGRESSIVE_WBT_TILE_PROGRESSIVE_FIRST 0xCCC6 -#define PROGRESSIVE_WBT_TILE_PROGRESSIVE_UPGRADE 0xCCC7 +#define PROGRESSIVE_WBT_TILE_FIRST 0xCCC6 +#define PROGRESSIVE_WBT_TILE_UPGRADE 0xCCC7 -struct _PROGRESSIVE_SYNC +struct _RFX_PROGRESSIVE_CODEC_QUANT +{ + BYTE quality; + BYTE yQuantValues[5]; + BYTE cbQuantValues[5]; + BYTE crQuantValues[5]; +}; +typedef struct _RFX_PROGRESSIVE_CODEC_QUANT RFX_PROGRESSIVE_CODEC_QUANT; + +struct _RFX_COMPONENT_CODEC_QUANT +{ + BYTE LL3; + BYTE HL3; + BYTE LH3; + BYTE HH3; + BYTE HL2; + BYTE LH2; + BYTE HH2; + BYTE HL1; + BYTE LH1; + BYTE HH1; +}; +typedef struct _RFX_COMPONENT_CODEC_QUANT RFX_COMPONENT_CODEC_QUANT; + +struct _PROGRESSIVE_BLOCK +{ + UINT16 blockType; + UINT32 blockLen; +}; +typedef struct _PROGRESSIVE_BLOCK PROGRESSIVE_BLOCK; + +struct _PROGRESSIVE_BLOCK_SYNC { UINT16 blockType; UINT32 blockLen; @@ -43,9 +74,20 @@ struct _PROGRESSIVE_SYNC UINT32 magic; UINT16 version; }; -typedef struct _PROGRESSIVE_SYNC PROGRESSIVE_SYNC; +typedef struct _PROGRESSIVE_BLOCK_SYNC PROGRESSIVE_BLOCK_SYNC; -struct _PROGRESSIVE_REGION +struct _PROGRESSIVE_BLOCK_CONTEXT +{ + UINT16 blockType; + UINT32 blockLen; + + BYTE ctxId; + UINT16 tileSize; + BYTE flags; +}; +typedef struct _PROGRESSIVE_BLOCK_CONTEXT PROGRESSIVE_BLOCK_CONTEXT; + +struct _PROGRESSIVE_BLOCK_REGION { UINT16 blockType; UINT32 blockLen; @@ -58,30 +100,31 @@ struct _PROGRESSIVE_REGION UINT16 numTiles; UINT32 tileDataSize; RFX_RECT* rects; - UINT32* quantVals; - UINT32* quantProgVals; + RFX_COMPONENT_CODEC_QUANT* quantVals; + RFX_PROGRESSIVE_CODEC_QUANT* quantProgVals; + PROGRESSIVE_BLOCK** tiles; }; -typedef struct _PROGRESSIVE_REGION PROGRESSIVE_REGION; +typedef struct _PROGRESSIVE_BLOCK_REGION PROGRESSIVE_BLOCK_REGION; -struct _PROGRESSIVE_FRAME_BEGIN +struct _PROGRESSIVE_BLOCK_FRAME_BEGIN { UINT16 blockType; UINT32 blockLen; UINT32 frameIndex; UINT16 regionCount; - PROGRESSIVE_REGION* regions; + PROGRESSIVE_BLOCK_REGION* regions; }; -typedef struct _PROGRESSIVE_FRAME_BEGIN PROGRESSIVE_FRAME_BEGIN; +typedef struct _PROGRESSIVE_BLOCK_FRAME_BEGIN PROGRESSIVE_BLOCK_FRAME_BEGIN; -struct _PROGRESSIVE_FRAME_END +struct _PROGRESSIVE_BLOCK_FRAME_END { UINT16 blockType; UINT32 blockLen; }; -typedef struct _PROGRESSIVE_FRAME_END PROGRESSIVE_FRAME_END; +typedef struct _PROGRESSIVE_BLOCK_FRAME_END PROGRESSIVE_BLOCK_FRAME_END; -struct _PROGRESSIVE_TILE_SIMPLE +struct _PROGRESSIVE_BLOCK_TILE_SIMPLE { UINT16 blockType; UINT32 blockLen; @@ -101,9 +144,9 @@ struct _PROGRESSIVE_TILE_SIMPLE BYTE* crData; BYTE* tailData; }; -typedef struct _PROGRESSIVE_TILE_SIMPLE PROGRESSIVE_TILE_SIMPLE; +typedef struct _PROGRESSIVE_BLOCK_TILE_SIMPLE PROGRESSIVE_BLOCK_TILE_SIMPLE; -struct _PROGRESSIVE_TILE_FIRST +struct _PROGRESSIVE_BLOCK_TILE_FIRST { UINT16 blockType; UINT32 blockLen; @@ -124,9 +167,9 @@ struct _PROGRESSIVE_TILE_FIRST BYTE* crData; BYTE* tailData; }; -typedef struct _PROGRESSIVE_TILE_FIRST PROGRESSIVE_TILE_FIRST; +typedef struct _PROGRESSIVE_BLOCK_TILE_FIRST PROGRESSIVE_BLOCK_TILE_FIRST; -struct _PROGRESSIVE_TILE_UPGRADE +struct _PROGRESSIVE_BLOCK_TILE_UPGRADE { UINT16 blockType; UINT32 blockLen; @@ -150,7 +193,7 @@ struct _PROGRESSIVE_TILE_UPGRADE BYTE* crSrlData; BYTE* crRawData; }; -typedef struct _PROGRESSIVE_TILE_UPGRADE PROGRESSIVE_TILE_UPGRADE; +typedef struct _PROGRESSIVE_BLOCK_TILE_UPGRADE PROGRESSIVE_BLOCK_TILE_UPGRADE; struct _PROGRESSIVE_CONTEXT { diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 2dfee8460..1cd1ce76d 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -28,83 +28,171 @@ #include #include +const char* progressive_get_block_type_string(UINT16 blockType) +{ + switch (blockType) + { + case PROGRESSIVE_WBT_SYNC: + return "PROGRESSIVE_WBT_SYNC"; + break; + + case PROGRESSIVE_WBT_FRAME_BEGIN: + return "PROGRESSIVE_WBT_FRAME_BEGIN"; + break; + + case PROGRESSIVE_WBT_FRAME_END: + return "PROGRESSIVE_WBT_FRAME_END"; + break; + + case PROGRESSIVE_WBT_CONTEXT: + return "PROGRESSIVE_WBT_CONTEXT"; + break; + + case PROGRESSIVE_WBT_REGION: + return "PROGRESSIVE_WBT_REGION"; + break; + + case PROGRESSIVE_WBT_TILE_SIMPLE: + return "PROGRESSIVE_WBT_TILE_SIMPLE"; + break; + + case PROGRESSIVE_WBT_TILE_FIRST: + return "PROGRESSIVE_WBT_TILE_FIRST"; + break; + + case PROGRESSIVE_WBT_TILE_UPGRADE: + return "PROGRESSIVE_WBT_TILE_UPGRADE"; + break; + + default: + return "PROGRESSIVE_WBT_UNKNOWN"; + break; + } + + return "PROGRESSIVE_WBT_UNKNOWN"; +} + int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) { BYTE* block; + UINT16 index; UINT32 boffset; - UINT32 ctxId; - UINT32 flags; - UINT32 tileSize; - UINT32 magic; - UINT32 version; UINT16 blockType; UINT32 blockLen; + RFX_RECT* rect; UINT32 offset = 0; - UINT32 frameIndex; - UINT32 regionCount; - PROGRESSIVE_REGION region; - PROGRESSIVE_TILE_SIMPLE simple; - PROGRESSIVE_TILE_FIRST first; - PROGRESSIVE_TILE_UPGRADE upgrade; + PROGRESSIVE_BLOCK_SYNC sync; + PROGRESSIVE_BLOCK_REGION region; + PROGRESSIVE_BLOCK_CONTEXT context; + PROGRESSIVE_BLOCK_FRAME_BEGIN frameBegin; + PROGRESSIVE_BLOCK_FRAME_END frameEnd; + PROGRESSIVE_BLOCK_TILE_SIMPLE simple; + PROGRESSIVE_BLOCK_TILE_FIRST first; + PROGRESSIVE_BLOCK_TILE_UPGRADE upgrade; + RFX_COMPONENT_CODEC_QUANT* quantVal; + RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; printf("ProgressiveDecompress\n"); - while ((SrcSize - offset) > 6) + if (SrcSize < 6) + return -1001; + + while ((SrcSize - offset) >= 6) { boffset = 0; block = &pSrcData[offset]; - blockType = *((UINT16*) &block[boffset]); /* blockType (2 bytes) */ + blockType = *((UINT16*) &block[boffset + 0]); /* blockType (2 bytes) */ blockLen = *((UINT32*) &block[boffset + 2]); /* blockLen (4 bytes) */ boffset += 6; + if ((SrcSize - offset) < blockLen) + return -1002; + switch (blockType) { case PROGRESSIVE_WBT_SYNC: - if (blockLen != 12) - return -1; + sync.blockType = blockType; + sync.blockLen = blockLen; - magic = (UINT32) *((UINT32*) &block[boffset]); /* magic (4 bytes) */ - version = (UINT32) *((UINT16*) &block[boffset + 4]); /* version (2 bytes) */ + if (blockLen != 12) + return -1003; + + sync.magic = (UINT32) *((UINT32*) &block[boffset + 0]); /* magic (4 bytes) */ + sync.version = (UINT32) *((UINT16*) &block[boffset + 4]); /* version (2 bytes) */ boffset += 6; + /* magic SHOULD be set to 0xCACCACCA, but the decoder SHOULD ignore it */ + /* version SHOULD be set to 0x0100, but the decoder SHOULD ignore it */ + break; case PROGRESSIVE_WBT_FRAME_BEGIN: - frameIndex = (UINT32) *((UINT32*) &block[boffset]); /* frameIndex (4 bytes) */ - regionCount = (UINT32) *((UINT16*) &block[boffset + 4]); /* regionCount (2 bytes) */ + frameBegin.blockType = blockType; + frameBegin.blockLen = blockLen; + + if ((blockLen - boffset) < 6) + return -1004; + + frameBegin.frameIndex = (UINT32) *((UINT32*) &block[boffset + 0]); /* frameIndex (4 bytes) */ + frameBegin.regionCount = (UINT32) *((UINT16*) &block[boffset + 4]); /* regionCount (2 bytes) */ boffset += 6; + /** + * If the number of elements specified by the regionCount field is + * larger than the actual number of elements in the regions field, + * the decoder SHOULD ignore this inconsistency. + */ + + if ((blockLen - boffset) > 6) + { + fprintf(stderr, "warning: regions present in frame begin block are ignored\n"); + } + + boffset = blockLen; + break; case PROGRESSIVE_WBT_FRAME_END: + frameEnd.blockType = blockType; + frameEnd.blockLen = blockLen; + if (blockLen != 6) - return -1; + return -1005; break; case PROGRESSIVE_WBT_CONTEXT: - if (blockLen != 10) - return -1; + context.blockType = blockType; + context.blockLen = blockLen; - ctxId = (UINT32) block[boffset]; /* ctxId (1 byte) */ - tileSize = (UINT32) *((UINT16*) &block[boffset + 1]); /* tileSize (2 bytes) */ - flags = (UINT32) block[boffset + 3]; /* flags (1 byte) */ + if (blockLen != 10) + return -1006; + + context.ctxId = block[boffset + 0]; /* ctxId (1 byte) */ + context.tileSize = *((UINT16*) &block[boffset + 1]); /* tileSize (2 bytes) */ + context.flags = block[boffset + 3]; /* flags (1 byte) */ boffset += 4; - if (tileSize != 64) - return -1; + if (context.tileSize != 64) + return -1007; break; case PROGRESSIVE_WBT_REGION: - region.tileSize = block[boffset]; /* tileSize (1 byte) */ + region.blockType = blockType; + region.blockLen = blockLen; + + if ((blockLen - boffset) < 12) + return -1008; + + region.tileSize = block[boffset + 0]; /* tileSize (1 byte) */ region.numRects = *((UINT16*) &block[boffset + 1]); /* numRects (2 bytes) */ region.numQuant = block[boffset + 3]; /* numQuant (1 byte) */ region.numProgQuant = block[boffset + 4]; /* numProgQuant (1 byte) */ @@ -113,11 +201,97 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN region.tileDataSize = *((UINT32*) &block[boffset + 8]); /* tileDataSize (4 bytes) */ boffset += 12; + if (region.tileSize != 64) + return -1; + + if (region.numRects < 1) + return -1; + + if (region.numQuant > 7) + return -1; + + if ((blockLen - boffset) < (region.numRects * 8)) + return -1; + + region.rects = (RFX_RECT*) malloc(region.numRects * sizeof(RFX_RECT)); + + if (!region.rects) + return -1; + + for (index = 0; index < region.numRects; index++) + { + rect = &(region.rects[index]); + rect->x = *((UINT16*) &block[boffset + 0]); + rect->y = *((UINT16*) &block[boffset + 2]); + rect->width = *((UINT16*) &block[boffset + 4]); + rect->height = *((UINT16*) &block[boffset + 6]); + boffset += 8; + } + + if (region.numQuant > 0) + { + if ((blockLen - boffset) < (region.numQuant * 5)) + return -1; + + region.quantVals = (RFX_COMPONENT_CODEC_QUANT*) malloc(region.numQuant * sizeof(RFX_COMPONENT_CODEC_QUANT)); + + if (!region.quantVals) + return -1; + + for (index = 0; index < region.numQuant; index++) + { + quantVal = &(region.quantVals[index]); + quantVal->LL3 = block[boffset + 0] & 0x0F; + quantVal->HL3 = block[boffset + 0] >> 4; + quantVal->LH3 = block[boffset + 1] & 0x0F; + quantVal->HH3 = block[boffset + 1] >> 4; + quantVal->HL2 = block[boffset + 2] & 0x0F; + quantVal->LH2 = block[boffset + 2] >> 4; + quantVal->HH2 = block[boffset + 3] & 0x0F; + quantVal->HL1 = block[boffset + 3] >> 4; + quantVal->LH1 = block[boffset + 4] & 0x0F; + quantVal->HH1 = block[boffset + 4] >> 4; + boffset += 5; + } + } + + if (region.numProgQuant > 0) + { + if ((blockLen - boffset) < (region.numProgQuant * 16)) + return -1; + + region.quantProgVals = (RFX_PROGRESSIVE_CODEC_QUANT*) malloc(region.numProgQuant * sizeof(RFX_PROGRESSIVE_CODEC_QUANT)); + + if (!region.quantVals) + return -1; + + for (index = 0; index < region.numProgQuant; index++) + { + quantProgVal = &(region.quantProgVals[index]); + quantProgVal->quality = block[boffset + 0]; + CopyMemory(quantProgVal->yQuantValues, &block[boffset + 1], 5); + CopyMemory(quantProgVal->cbQuantValues, &block[boffset + 6], 5); + CopyMemory(quantProgVal->crQuantValues, &block[boffset + 11], 5); + boffset += 16; + } + } + + printf("numTiles: %d tileDataSize: %d numQuant: %d numProgQuant: %d\n", + region.numTiles, region.tileDataSize, region.numQuant, region.numProgQuant); + + boffset += region.tileDataSize; /* skip for now */ + break; case PROGRESSIVE_WBT_TILE_SIMPLE: - simple.quantIdxY = block[boffset]; /* quantIdxY (1 byte) */ + simple.blockType = blockType; + simple.blockLen = blockLen; + + if ((blockLen - boffset) < 16) + return -1009; + + simple.quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ simple.quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ simple.quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */ simple.xIdx = *((UINT16*) &block[boffset + 3]); /* xIdx (2 bytes) */ @@ -143,9 +317,15 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN break; - case PROGRESSIVE_WBT_TILE_PROGRESSIVE_FIRST: + case PROGRESSIVE_WBT_TILE_FIRST: - first.quantIdxY = block[boffset]; /* quantIdxY (1 byte) */ + first.blockType = blockType; + first.blockLen = blockLen; + + if ((blockLen - boffset) < 17) + return -1010; + + first.quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ first.quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ first.quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */ first.xIdx = *((UINT16*) &block[boffset + 3]); /* xIdx (2 bytes) */ @@ -158,23 +338,41 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN first.tailLen = *((UINT16*) &block[boffset + 15]); /* tailLen (2 bytes) */ boffset += 17; + if ((blockLen - boffset) < first.yLen) + return -1011; + first.yData = &block[boffset]; boffset += first.yLen; + if ((blockLen - boffset) < first.cbLen) + return -1012; + first.cbData = &block[boffset]; boffset += first.cbLen; + if ((blockLen - boffset) < first.crLen) + return -1013; + first.crData = &block[boffset]; boffset += first.crLen; + if ((blockLen - boffset) < first.tailLen) + return -1014; + first.tailData = &block[boffset]; boffset += first.tailLen; break; - case PROGRESSIVE_WBT_TILE_PROGRESSIVE_UPGRADE: + case PROGRESSIVE_WBT_TILE_UPGRADE: - upgrade.quantIdxY = block[boffset]; /* quantIdxY (1 byte) */ + upgrade.blockType = blockType; + upgrade.blockLen = blockLen; + + if ((blockLen - boffset) < 18) + return -1015; + + upgrade.quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ upgrade.quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ upgrade.quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */ upgrade.xIdx = *((UINT16*) &block[boffset + 3]); /* xIdx (2 bytes) */ @@ -188,30 +386,61 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN upgrade.crRawLen = *((UINT16*) &block[boffset + 18]); /* crRawLen (2 bytes) */ boffset += 18; + if ((blockLen - boffset) < upgrade.ySrlLen) + return -1016; + upgrade.ySrlData = &block[boffset]; boffset += upgrade.ySrlLen; + if ((blockLen - boffset) < upgrade.yRawLen) + return -1017; + upgrade.yRawData = &block[boffset]; boffset += upgrade.yRawLen; + if ((blockLen - boffset) < upgrade.cbSrlLen) + return -1018; + upgrade.cbSrlData = &block[boffset]; boffset += upgrade.cbSrlLen; + if ((blockLen - boffset) < upgrade.cbRawLen) + return -1019; + upgrade.cbRawData = &block[boffset]; boffset += upgrade.cbRawLen; + if ((blockLen - boffset) < upgrade.crSrlLen) + return -1020; + upgrade.crSrlData = &block[boffset]; boffset += upgrade.crSrlLen; + if ((blockLen - boffset) < upgrade.crRawLen) + return -1021; + upgrade.crRawData = &block[boffset]; boffset += upgrade.crRawLen; break; + + default: + return -1022; + break; + } + + if (boffset != blockLen) + { + printf("failure %s\n", progressive_get_block_type_string(blockType)); + return -1023; } offset += blockLen; } + if (offset != SrcSize) + return -1024; + return 1; } From 800be2f680dec9ba6d867fe6fab891256843e35b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 29 Jul 2014 17:37:46 -0400 Subject: [PATCH 02/12] libfreerdp-codec: complete parsing of progressive codec block arrays --- client/common/cmdline.c | 1 + include/freerdp/codec/progressive.h | 19 ++ libfreerdp/codec/progressive.c | 298 ++++++++++++++++++---------- 3 files changed, 217 insertions(+), 101 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 480f9f21b..b05864db8 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1640,6 +1640,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, CommandLineSwitchCase(arg, "gfx-progressive") { settings->GfxProgressive = arg->Value ? TRUE : FALSE; + settings->GfxThinClient = settings->GfxProgressive ? FALSE : TRUE; settings->SupportGraphicsPipeline = TRUE; } CommandLineSwitchCase(arg, "gfx-h264") diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index 603d1efe4..8c6327f5d 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -26,6 +26,12 @@ #include #include +#define RFX_SUBBAND_DIFFING 0x01 + +#define RFX_TILE_DIFFERENCE 0x01 + +#define RFX_DWT_REDUCE_EXTRAPOLATE 0x01 + #define PROGRESSIVE_WBT_SYNC 0xCCC0 #define PROGRESSIVE_WBT_FRAME_BEGIN 0xCCC1 #define PROGRESSIVE_WBT_FRAME_END 0xCCC2 @@ -35,6 +41,10 @@ #define PROGRESSIVE_WBT_TILE_FIRST 0xCCC6 #define PROGRESSIVE_WBT_TILE_UPGRADE 0xCCC7 +#define PROGRESSIVE_BLOCKS_ALL 0x0001 +#define PROGRESSIVE_BLOCKS_REGION 0x0002 +#define PROGRESSIVE_BLOCKS_TILE 0x0004 + struct _RFX_PROGRESSIVE_CODEC_QUANT { BYTE quality; @@ -198,6 +208,15 @@ typedef struct _PROGRESSIVE_BLOCK_TILE_UPGRADE PROGRESSIVE_BLOCK_TILE_UPGRADE; struct _PROGRESSIVE_CONTEXT { BOOL Compressor; + + UINT32 cRects; + RFX_RECT* rects; + + UINT32 cQuant; + RFX_COMPONENT_CODEC_QUANT* quantVals; + + UINT32 cProgQuant; + RFX_PROGRESSIVE_CODEC_QUANT* quantProgVals; }; typedef struct _PROGRESSIVE_CONTEXT PROGRESSIVE_CONTEXT; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 1cd1ce76d..a30e85b01 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -72,16 +72,17 @@ const char* progressive_get_block_type_string(UINT16 blockType) return "PROGRESSIVE_WBT_UNKNOWN"; } -int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UINT32 SrcSize, - BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) +int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UINT32 blocksLen, UINT32 blockCount, UINT32 flags) { + int status; BYTE* block; UINT16 index; UINT32 boffset; UINT16 blockType; UINT32 blockLen; - RFX_RECT* rect; + UINT32 count = 0; UINT32 offset = 0; + RFX_RECT* rect = NULL; PROGRESSIVE_BLOCK_SYNC sync; PROGRESSIVE_BLOCK_REGION region; PROGRESSIVE_BLOCK_CONTEXT context; @@ -93,22 +94,40 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN RFX_COMPONENT_CODEC_QUANT* quantVal; RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; - printf("ProgressiveDecompress\n"); - - if (SrcSize < 6) - return -1001; - - while ((SrcSize - offset) >= 6) + while ((blocksLen - offset) >= 6) { boffset = 0; - block = &pSrcData[offset]; + block = &blocks[offset]; blockType = *((UINT16*) &block[boffset + 0]); /* blockType (2 bytes) */ blockLen = *((UINT32*) &block[boffset + 2]); /* blockLen (4 bytes) */ boffset += 6; - if ((SrcSize - offset) < blockLen) - return -1002; + if (flags & PROGRESSIVE_BLOCKS_REGION) + { + if ((count + 1) > blockCount) + break; + + if (blockType != PROGRESSIVE_WBT_REGION) + return -1001; + } + else if (flags & PROGRESSIVE_BLOCKS_TILE) + { + if ((count + 1) > blockCount) + break; + + if ((blockType != PROGRESSIVE_WBT_TILE_SIMPLE) && + (blockType != PROGRESSIVE_WBT_TILE_FIRST) && + (blockType != PROGRESSIVE_WBT_TILE_UPGRADE)) + { + return -1002; + } + } + + printf("%s\n", progressive_get_block_type_string(blockType)); + + if ((blocksLen - offset) < blockLen) + return -1003; switch (blockType) { @@ -117,15 +136,18 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN sync.blockType = blockType; sync.blockLen = blockLen; - if (blockLen != 12) - return -1003; + if ((blockLen - boffset) != 6) + return -1004; sync.magic = (UINT32) *((UINT32*) &block[boffset + 0]); /* magic (4 bytes) */ sync.version = (UINT32) *((UINT16*) &block[boffset + 4]); /* version (2 bytes) */ boffset += 6; - /* magic SHOULD be set to 0xCACCACCA, but the decoder SHOULD ignore it */ - /* version SHOULD be set to 0x0100, but the decoder SHOULD ignore it */ + if (sync.magic != 0xCACCACCA) + return -1005; + + if (sync.version != 0x0100) + return -1006; break; @@ -135,7 +157,7 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN frameBegin.blockLen = blockLen; if ((blockLen - boffset) < 6) - return -1004; + return -1007; frameBegin.frameIndex = (UINT32) *((UINT32*) &block[boffset + 0]); /* frameIndex (4 bytes) */ frameBegin.regionCount = (UINT32) *((UINT16*) &block[boffset + 4]); /* regionCount (2 bytes) */ @@ -147,12 +169,16 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN * the decoder SHOULD ignore this inconsistency. */ - if ((blockLen - boffset) > 6) + if ((blockLen - boffset) > 0) { - fprintf(stderr, "warning: regions present in frame begin block are ignored\n"); - } + status = progressive_process_blocks(progressive, &block[boffset], + blockLen - boffset, frameBegin.regionCount, PROGRESSIVE_BLOCKS_REGION); - boffset = blockLen; + if (status < 0) + return status; + + boffset += status; + } break; @@ -161,8 +187,8 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN frameEnd.blockType = blockType; frameEnd.blockLen = blockLen; - if (blockLen != 6) - return -1005; + if ((blockLen - boffset) != 0) + return -1008; break; @@ -171,8 +197,8 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN context.blockType = blockType; context.blockLen = blockLen; - if (blockLen != 10) - return -1006; + if ((blockLen - boffset) != 4) + return -1009; context.ctxId = block[boffset + 0]; /* ctxId (1 byte) */ context.tileSize = *((UINT16*) &block[boffset + 1]); /* tileSize (2 bytes) */ @@ -180,7 +206,7 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN boffset += 4; if (context.tileSize != 64) - return -1007; + return -1010; break; @@ -190,7 +216,7 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN region.blockLen = blockLen; if ((blockLen - boffset) < 12) - return -1008; + return -1011; region.tileSize = block[boffset + 0]; /* tileSize (1 byte) */ region.numRects = *((UINT16*) &block[boffset + 1]); /* numRects (2 bytes) */ @@ -202,21 +228,27 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN boffset += 12; if (region.tileSize != 64) - return -1; + return -1012; if (region.numRects < 1) - return -1; + return -1013; if (region.numQuant > 7) - return -1; + return -1014; if ((blockLen - boffset) < (region.numRects * 8)) - return -1; + return -1015; - region.rects = (RFX_RECT*) malloc(region.numRects * sizeof(RFX_RECT)); + if (region.numRects > progressive->cRects) + { + progressive->rects = (RFX_RECT*) realloc(progressive->rects, region.numRects * sizeof(RFX_RECT)); + progressive->cRects = region.numRects; + } + + region.rects = progressive->rects; if (!region.rects) - return -1; + return -1016; for (index = 0; index < region.numRects; index++) { @@ -228,58 +260,75 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN boffset += 8; } - if (region.numQuant > 0) + if ((blockLen - boffset) < (region.numQuant * 5)) + return -1017; + + if (region.numQuant > progressive->cQuant) { - if ((blockLen - boffset) < (region.numQuant * 5)) - return -1; - - region.quantVals = (RFX_COMPONENT_CODEC_QUANT*) malloc(region.numQuant * sizeof(RFX_COMPONENT_CODEC_QUANT)); - - if (!region.quantVals) - return -1; - - for (index = 0; index < region.numQuant; index++) - { - quantVal = &(region.quantVals[index]); - quantVal->LL3 = block[boffset + 0] & 0x0F; - quantVal->HL3 = block[boffset + 0] >> 4; - quantVal->LH3 = block[boffset + 1] & 0x0F; - quantVal->HH3 = block[boffset + 1] >> 4; - quantVal->HL2 = block[boffset + 2] & 0x0F; - quantVal->LH2 = block[boffset + 2] >> 4; - quantVal->HH2 = block[boffset + 3] & 0x0F; - quantVal->HL1 = block[boffset + 3] >> 4; - quantVal->LH1 = block[boffset + 4] & 0x0F; - quantVal->HH1 = block[boffset + 4] >> 4; - boffset += 5; - } + progressive->quantVals = (RFX_COMPONENT_CODEC_QUANT*) realloc(progressive->quantVals, + region.numQuant * sizeof(RFX_COMPONENT_CODEC_QUANT)); + progressive->cQuant = region.numQuant; } - if (region.numProgQuant > 0) + region.quantVals = progressive->quantVals; + + if (!region.quantVals) + return -1018; + + for (index = 0; index < region.numQuant; index++) { - if ((blockLen - boffset) < (region.numProgQuant * 16)) - return -1; - - region.quantProgVals = (RFX_PROGRESSIVE_CODEC_QUANT*) malloc(region.numProgQuant * sizeof(RFX_PROGRESSIVE_CODEC_QUANT)); - - if (!region.quantVals) - return -1; - - for (index = 0; index < region.numProgQuant; index++) - { - quantProgVal = &(region.quantProgVals[index]); - quantProgVal->quality = block[boffset + 0]; - CopyMemory(quantProgVal->yQuantValues, &block[boffset + 1], 5); - CopyMemory(quantProgVal->cbQuantValues, &block[boffset + 6], 5); - CopyMemory(quantProgVal->crQuantValues, &block[boffset + 11], 5); - boffset += 16; - } + quantVal = &(region.quantVals[index]); + quantVal->LL3 = block[boffset + 0] & 0x0F; + quantVal->HL3 = block[boffset + 0] >> 4; + quantVal->LH3 = block[boffset + 1] & 0x0F; + quantVal->HH3 = block[boffset + 1] >> 4; + quantVal->HL2 = block[boffset + 2] & 0x0F; + quantVal->LH2 = block[boffset + 2] >> 4; + quantVal->HH2 = block[boffset + 3] & 0x0F; + quantVal->HL1 = block[boffset + 3] >> 4; + quantVal->LH1 = block[boffset + 4] & 0x0F; + quantVal->HH1 = block[boffset + 4] >> 4; + boffset += 5; } - printf("numTiles: %d tileDataSize: %d numQuant: %d numProgQuant: %d\n", - region.numTiles, region.tileDataSize, region.numQuant, region.numProgQuant); + if ((blockLen - boffset) < (region.numProgQuant * 16)) + return -1019; - boffset += region.tileDataSize; /* skip for now */ + if (region.numProgQuant > progressive->cProgQuant) + { + progressive->quantProgVals = (RFX_PROGRESSIVE_CODEC_QUANT*) realloc(progressive->quantProgVals, + region.numProgQuant * sizeof(RFX_PROGRESSIVE_CODEC_QUANT)); + progressive->cProgQuant = region.numProgQuant; + } + + region.quantProgVals = progressive->quantProgVals; + + if (!region.quantProgVals) + return -1020; + + for (index = 0; index < region.numProgQuant; index++) + { + quantProgVal = &(region.quantProgVals[index]); + quantProgVal->quality = block[boffset + 0]; + CopyMemory(quantProgVal->yQuantValues, &block[boffset + 1], 5); + CopyMemory(quantProgVal->cbQuantValues, &block[boffset + 6], 5); + CopyMemory(quantProgVal->crQuantValues, &block[boffset + 11], 5); + boffset += 16; + } + + if ((blockLen - boffset) < region.tileDataSize) + return -1021; + + printf("numRects: %d numTiles: %d numQuant: %d numProgQuant: %d\n", + region.numRects, region.numTiles, region.numQuant, region.numProgQuant); + + status = progressive_process_blocks(progressive, &block[boffset], + region.tileDataSize, region.numTiles, PROGRESSIVE_BLOCKS_TILE); + + if (status < 0) + return status; + + boffset += (UINT32) status; break; @@ -289,7 +338,7 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN simple.blockLen = blockLen; if ((blockLen - boffset) < 16) - return -1009; + return -1022; simple.quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ simple.quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ @@ -303,15 +352,27 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN simple.tailLen = *((UINT16*) &block[boffset + 14]); /* tailLen (2 bytes) */ boffset += 16; + if ((blockLen - boffset) < simple.yLen) + return -1023; + simple.yData = &block[boffset]; boffset += simple.yLen; + if ((blockLen - boffset) < simple.cbLen) + return -1024; + simple.cbData = &block[boffset]; boffset += simple.cbLen; + if ((blockLen - boffset) < simple.crLen) + return -1025; + simple.crData = &block[boffset]; boffset += simple.crLen; + if ((blockLen - boffset) < simple.tailLen) + return -1026; + simple.tailData = &block[boffset]; boffset += simple.tailLen; @@ -323,7 +384,7 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN first.blockLen = blockLen; if ((blockLen - boffset) < 17) - return -1010; + return -1027; first.quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ first.quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ @@ -339,25 +400,25 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN boffset += 17; if ((blockLen - boffset) < first.yLen) - return -1011; + return -1028; first.yData = &block[boffset]; boffset += first.yLen; if ((blockLen - boffset) < first.cbLen) - return -1012; + return -1029; first.cbData = &block[boffset]; boffset += first.cbLen; if ((blockLen - boffset) < first.crLen) - return -1013; + return -1030; first.crData = &block[boffset]; boffset += first.crLen; if ((blockLen - boffset) < first.tailLen) - return -1014; + return -1031; first.tailData = &block[boffset]; boffset += first.tailLen; @@ -369,8 +430,8 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN upgrade.blockType = blockType; upgrade.blockLen = blockLen; - if ((blockLen - boffset) < 18) - return -1015; + if ((blockLen - boffset) < 20) + return -1032; upgrade.quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ upgrade.quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ @@ -384,40 +445,40 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN upgrade.cbRawLen = *((UINT16*) &block[boffset + 14]); /* cbRawLen (2 bytes) */ upgrade.crSrlLen = *((UINT16*) &block[boffset + 16]); /* crSrlLen (2 bytes) */ upgrade.crRawLen = *((UINT16*) &block[boffset + 18]); /* crRawLen (2 bytes) */ - boffset += 18; + boffset += 20; if ((blockLen - boffset) < upgrade.ySrlLen) - return -1016; + return -1033; upgrade.ySrlData = &block[boffset]; boffset += upgrade.ySrlLen; if ((blockLen - boffset) < upgrade.yRawLen) - return -1017; + return -1034; upgrade.yRawData = &block[boffset]; boffset += upgrade.yRawLen; if ((blockLen - boffset) < upgrade.cbSrlLen) - return -1018; + return -1035; upgrade.cbSrlData = &block[boffset]; boffset += upgrade.cbSrlLen; if ((blockLen - boffset) < upgrade.cbRawLen) - return -1019; + return -1036; upgrade.cbRawData = &block[boffset]; boffset += upgrade.cbRawLen; if ((blockLen - boffset) < upgrade.crSrlLen) - return -1020; + return -1037; upgrade.crSrlData = &block[boffset]; boffset += upgrade.crSrlLen; if ((blockLen - boffset) < upgrade.crRawLen) - return -1021; + return -1038; upgrade.crRawData = &block[boffset]; boffset += upgrade.crRawLen; @@ -425,23 +486,34 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN break; default: - return -1022; + return -1039; break; } if (boffset != blockLen) - { - printf("failure %s\n", progressive_get_block_type_string(blockType)); - return -1023; - } + return -1040; offset += blockLen; + count++; } - if (offset != SrcSize) - return -1024; + if (offset != blocksLen) + return -1041; - return 1; + return (int) offset; +} + +int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UINT32 SrcSize, + BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) +{ + int status; + + status = progressive_process_blocks(progressive, pSrcData, SrcSize, 0, PROGRESSIVE_BLOCKS_ALL); + + if (status >= 0) + status = 1; + + return status; } int progressive_compress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize) @@ -463,6 +535,26 @@ PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor) if (progressive) { progressive->Compressor = Compressor; + + progressive->cRects = 64; + progressive->rects = (RFX_RECT*) malloc(progressive->cRects * sizeof(RFX_RECT)); + + if (!progressive->rects) + return NULL; + + progressive->cQuant = 8; + progressive->quantVals = (RFX_COMPONENT_CODEC_QUANT*) malloc(progressive->cQuant * sizeof(RFX_COMPONENT_CODEC_QUANT)); + + if (!progressive->quantVals) + return NULL; + + progressive->cProgQuant = 8; + progressive->quantProgVals = (RFX_PROGRESSIVE_CODEC_QUANT*) malloc(progressive->cProgQuant * sizeof(RFX_PROGRESSIVE_CODEC_QUANT)); + + if (!progressive->quantProgVals) + return NULL; + + progressive_context_reset(progressive); } return progressive; @@ -473,6 +565,10 @@ void progressive_context_free(PROGRESSIVE_CONTEXT* progressive) if (!progressive) return; + free(progressive->rects); + free(progressive->quantVals); + free(progressive->quantProgVals); + free(progressive); } From 574c1789b735ff29b885314032108e94f7915f21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 31 Jul 2014 15:08:54 -0400 Subject: [PATCH 03/12] libfreerdp-codec: start processing progressive tiles --- include/freerdp/codec/progressive.h | 3 + libfreerdp/codec/progressive.c | 213 ++++++++++++++++++++++------ 2 files changed, 176 insertions(+), 40 deletions(-) diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index 8c6327f5d..ef454fb06 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -217,6 +217,9 @@ struct _PROGRESSIVE_CONTEXT UINT32 cProgQuant; RFX_PROGRESSIVE_CODEC_QUANT* quantProgVals; + + PROGRESSIVE_BLOCK_REGION region; + RFX_PROGRESSIVE_CODEC_QUANT quantProgValFull; }; typedef struct _PROGRESSIVE_CONTEXT PROGRESSIVE_CONTEXT; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index a30e85b01..c810c8ebe 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -72,6 +72,125 @@ const char* progressive_get_block_type_string(UINT16 blockType) return "PROGRESSIVE_WBT_UNKNOWN"; } +int progressive_decompress_tile_simple(PROGRESSIVE_CONTEXT* progressive, PROGRESSIVE_BLOCK_TILE_SIMPLE* tile) +{ + PROGRESSIVE_BLOCK_REGION* region; + RFX_COMPONENT_CODEC_QUANT* quantY; + RFX_COMPONENT_CODEC_QUANT* quantCb; + RFX_COMPONENT_CODEC_QUANT* quantCr; + RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; + + printf("ProgressiveTileSimple: quantIdx Y: %d Cb: %d Cr: %d xIdx: %d yIdx: %d flags: %d yLen: %d cbLen: %d crLen: %d tailLen: %d\n", + tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, tile->xIdx, tile->yIdx, tile->flags, tile->yLen, tile->cbLen, tile->crLen, tile->tailLen); + + region = &(progressive->region); + + if (tile->quantIdxY >= region->numQuant) + return -1; + + quantY = &(region->quantVals[tile->quantIdxY]); + + if (tile->quantIdxCb >= region->numQuant) + return -1; + + quantCb = &(region->quantVals[tile->quantIdxCb]); + + if (tile->quantIdxCr >= region->numQuant) + return -1; + + quantCr = &(region->quantVals[tile->quantIdxCr]); + + quantProgVal = &(progressive->quantProgValFull); + + return 1; +} + +int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, PROGRESSIVE_BLOCK_TILE_FIRST* tile) +{ + PROGRESSIVE_BLOCK_REGION* region; + RFX_COMPONENT_CODEC_QUANT* quantY; + RFX_COMPONENT_CODEC_QUANT* quantCb; + RFX_COMPONENT_CODEC_QUANT* quantCr; + RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; + + printf("ProgressiveTileFirst: quantIdx Y: %d Cb: %d Cr: %d xIdx: %d yIdx: %d flags: %d quality: %d yLen: %d cbLen: %d crLen: %d tailLen: %d\n", + tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, tile->xIdx, tile->yIdx, tile->flags, tile->quality, tile->yLen, tile->cbLen, tile->crLen, tile->tailLen); + + region = &(progressive->region); + + if (tile->quantIdxY >= region->numQuant) + return -1; + + quantY = &(region->quantVals[tile->quantIdxY]); + + if (tile->quantIdxCb >= region->numQuant) + return -1; + + quantCb = &(region->quantVals[tile->quantIdxCb]); + + if (tile->quantIdxCr >= region->numQuant) + return -1; + + quantCr = &(region->quantVals[tile->quantIdxCr]); + + if (tile->quality == 0xFF) + { + quantProgVal = &(progressive->quantProgValFull); + } + else + { + if (tile->quality >= region->numProgQuant) + return -1; + + quantProgVal = &(region->quantProgVals[tile->quality]); + } + + return 1; +} + +int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, PROGRESSIVE_BLOCK_TILE_UPGRADE* tile) +{ + PROGRESSIVE_BLOCK_REGION* region; + RFX_COMPONENT_CODEC_QUANT* quantY; + RFX_COMPONENT_CODEC_QUANT* quantCb; + RFX_COMPONENT_CODEC_QUANT* quantCr; + RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; + + printf("ProgressiveTileUpgrade: quantIdx Y: %d Cb: %d Cr: %d xIdx: %d yIdx: %d quality: %d ySrlLen: %d yRawLen: %d cbSrlLen: %d cbRawLen: %d crSrlLen: %d crRawLen: %d\n", + tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, tile->xIdx, tile->yIdx, tile->quality, tile->ySrlLen, tile->yRawLen, tile->cbSrlLen, tile->cbRawLen, tile->crSrlLen, tile->crRawLen); + + region = &(progressive->region); + + if (tile->quantIdxY >= region->numQuant) + return -1; + + quantY = &(region->quantVals[tile->quantIdxY]); + + if (tile->quantIdxCb >= region->numQuant) + return -1; + + quantCb = &(region->quantVals[tile->quantIdxCb]); + + if (tile->quantIdxCr >= region->numQuant) + return -1; + + quantCr = &(region->quantVals[tile->quantIdxCr]); + + if (tile->quality == 0xFF) + { + quantProgVal = &(progressive->quantProgValFull); + } + else + { + if (tile->quality >= region->numProgQuant) + return -1; + + quantProgVal = &(region->quantProgVals[tile->quality]); + } + + return 1; +} + int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UINT32 blocksLen, UINT32 blockCount, UINT32 flags) { int status; @@ -84,7 +203,7 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U UINT32 offset = 0; RFX_RECT* rect = NULL; PROGRESSIVE_BLOCK_SYNC sync; - PROGRESSIVE_BLOCK_REGION region; + PROGRESSIVE_BLOCK_REGION* region; PROGRESSIVE_BLOCK_CONTEXT context; PROGRESSIVE_BLOCK_FRAME_BEGIN frameBegin; PROGRESSIVE_BLOCK_FRAME_END frameEnd; @@ -94,6 +213,8 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U RFX_COMPONENT_CODEC_QUANT* quantVal; RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; + region = &(progressive->region); + while ((blocksLen - offset) >= 6) { boffset = 0; @@ -212,47 +333,47 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U case PROGRESSIVE_WBT_REGION: - region.blockType = blockType; - region.blockLen = blockLen; + region->blockType = blockType; + region->blockLen = blockLen; if ((blockLen - boffset) < 12) return -1011; - region.tileSize = block[boffset + 0]; /* tileSize (1 byte) */ - region.numRects = *((UINT16*) &block[boffset + 1]); /* numRects (2 bytes) */ - region.numQuant = block[boffset + 3]; /* numQuant (1 byte) */ - region.numProgQuant = block[boffset + 4]; /* numProgQuant (1 byte) */ - region.flags = block[boffset + 5]; /* flags (1 byte) */ - region.numTiles = *((UINT16*) &block[boffset + 6]); /* numTiles (2 bytes) */ - region.tileDataSize = *((UINT32*) &block[boffset + 8]); /* tileDataSize (4 bytes) */ + region->tileSize = block[boffset + 0]; /* tileSize (1 byte) */ + region->numRects = *((UINT16*) &block[boffset + 1]); /* numRects (2 bytes) */ + region->numQuant = block[boffset + 3]; /* numQuant (1 byte) */ + region->numProgQuant = block[boffset + 4]; /* numProgQuant (1 byte) */ + region->flags = block[boffset + 5]; /* flags (1 byte) */ + region->numTiles = *((UINT16*) &block[boffset + 6]); /* numTiles (2 bytes) */ + region->tileDataSize = *((UINT32*) &block[boffset + 8]); /* tileDataSize (4 bytes) */ boffset += 12; - if (region.tileSize != 64) + if (region->tileSize != 64) return -1012; - if (region.numRects < 1) + if (region->numRects < 1) return -1013; - if (region.numQuant > 7) + if (region->numQuant > 7) return -1014; - if ((blockLen - boffset) < (region.numRects * 8)) + if ((blockLen - boffset) < (region->numRects * 8)) return -1015; - if (region.numRects > progressive->cRects) + if (region->numRects > progressive->cRects) { - progressive->rects = (RFX_RECT*) realloc(progressive->rects, region.numRects * sizeof(RFX_RECT)); - progressive->cRects = region.numRects; + progressive->rects = (RFX_RECT*) realloc(progressive->rects, region->numRects * sizeof(RFX_RECT)); + progressive->cRects = region->numRects; } - region.rects = progressive->rects; + region->rects = progressive->rects; - if (!region.rects) + if (!region->rects) return -1016; - for (index = 0; index < region.numRects; index++) + for (index = 0; index < region->numRects; index++) { - rect = &(region.rects[index]); + rect = &(region->rects[index]); rect->x = *((UINT16*) &block[boffset + 0]); rect->y = *((UINT16*) &block[boffset + 2]); rect->width = *((UINT16*) &block[boffset + 4]); @@ -260,24 +381,24 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U boffset += 8; } - if ((blockLen - boffset) < (region.numQuant * 5)) + if ((blockLen - boffset) < (region->numQuant * 5)) return -1017; - if (region.numQuant > progressive->cQuant) + if (region->numQuant > progressive->cQuant) { progressive->quantVals = (RFX_COMPONENT_CODEC_QUANT*) realloc(progressive->quantVals, - region.numQuant * sizeof(RFX_COMPONENT_CODEC_QUANT)); - progressive->cQuant = region.numQuant; + region->numQuant * sizeof(RFX_COMPONENT_CODEC_QUANT)); + progressive->cQuant = region->numQuant; } - region.quantVals = progressive->quantVals; + region->quantVals = progressive->quantVals; - if (!region.quantVals) + if (!region->quantVals) return -1018; - for (index = 0; index < region.numQuant; index++) + for (index = 0; index < region->numQuant; index++) { - quantVal = &(region.quantVals[index]); + quantVal = &(region->quantVals[index]); quantVal->LL3 = block[boffset + 0] & 0x0F; quantVal->HL3 = block[boffset + 0] >> 4; quantVal->LH3 = block[boffset + 1] & 0x0F; @@ -291,24 +412,24 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U boffset += 5; } - if ((blockLen - boffset) < (region.numProgQuant * 16)) + if ((blockLen - boffset) < (region->numProgQuant * 16)) return -1019; - if (region.numProgQuant > progressive->cProgQuant) + if (region->numProgQuant > progressive->cProgQuant) { progressive->quantProgVals = (RFX_PROGRESSIVE_CODEC_QUANT*) realloc(progressive->quantProgVals, - region.numProgQuant * sizeof(RFX_PROGRESSIVE_CODEC_QUANT)); - progressive->cProgQuant = region.numProgQuant; + region->numProgQuant * sizeof(RFX_PROGRESSIVE_CODEC_QUANT)); + progressive->cProgQuant = region->numProgQuant; } - region.quantProgVals = progressive->quantProgVals; + region->quantProgVals = progressive->quantProgVals; - if (!region.quantProgVals) + if (!region->quantProgVals) return -1020; - for (index = 0; index < region.numProgQuant; index++) + for (index = 0; index < region->numProgQuant; index++) { - quantProgVal = &(region.quantProgVals[index]); + quantProgVal = &(region->quantProgVals[index]); quantProgVal->quality = block[boffset + 0]; CopyMemory(quantProgVal->yQuantValues, &block[boffset + 1], 5); CopyMemory(quantProgVal->cbQuantValues, &block[boffset + 6], 5); @@ -316,14 +437,14 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U boffset += 16; } - if ((blockLen - boffset) < region.tileDataSize) + if ((blockLen - boffset) < region->tileDataSize) return -1021; printf("numRects: %d numTiles: %d numQuant: %d numProgQuant: %d\n", - region.numRects, region.numTiles, region.numQuant, region.numProgQuant); + region->numRects, region->numTiles, region->numQuant, region->numProgQuant); status = progressive_process_blocks(progressive, &block[boffset], - region.tileDataSize, region.numTiles, PROGRESSIVE_BLOCKS_TILE); + region->tileDataSize, region->numTiles, PROGRESSIVE_BLOCKS_TILE); if (status < 0) return status; @@ -376,6 +497,8 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U simple.tailData = &block[boffset]; boffset += simple.tailLen; + status = progressive_decompress_tile_simple(progressive, &simple); + break; case PROGRESSIVE_WBT_TILE_FIRST: @@ -423,6 +546,11 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U first.tailData = &block[boffset]; boffset += first.tailLen; + status = progressive_decompress_tile_first(progressive, &first); + + if (status < 0) + return -1; + break; case PROGRESSIVE_WBT_TILE_UPGRADE: @@ -483,6 +611,8 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U upgrade.crRawData = &block[boffset]; boffset += upgrade.crRawLen; + status = progressive_decompress_tile_upgrade(progressive, &upgrade); + break; default: @@ -554,6 +684,9 @@ PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor) if (!progressive->quantProgVals) return NULL; + ZeroMemory(&(progressive->quantProgValFull), sizeof(RFX_PROGRESSIVE_CODEC_QUANT)); + progressive->quantProgValFull.quality = 100; + progressive_context_reset(progressive); } From 14a3ff94ebb8109ea0d246b386a9de3324c3f1b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 1 Aug 2014 09:44:00 -0400 Subject: [PATCH 04/12] libfreerdp-codec: simplify block reading logic --- include/freerdp/codec/progressive.h | 115 ++++--- libfreerdp/codec/progressive.c | 493 ++++++++++++++-------------- 2 files changed, 322 insertions(+), 286 deletions(-) diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index ef454fb06..a86ebdd4c 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -97,43 +97,6 @@ struct _PROGRESSIVE_BLOCK_CONTEXT }; typedef struct _PROGRESSIVE_BLOCK_CONTEXT PROGRESSIVE_BLOCK_CONTEXT; -struct _PROGRESSIVE_BLOCK_REGION -{ - UINT16 blockType; - UINT32 blockLen; - - BYTE tileSize; - UINT16 numRects; - BYTE numQuant; - BYTE numProgQuant; - BYTE flags; - UINT16 numTiles; - UINT32 tileDataSize; - RFX_RECT* rects; - RFX_COMPONENT_CODEC_QUANT* quantVals; - RFX_PROGRESSIVE_CODEC_QUANT* quantProgVals; - PROGRESSIVE_BLOCK** tiles; -}; -typedef struct _PROGRESSIVE_BLOCK_REGION PROGRESSIVE_BLOCK_REGION; - -struct _PROGRESSIVE_BLOCK_FRAME_BEGIN -{ - UINT16 blockType; - UINT32 blockLen; - - UINT32 frameIndex; - UINT16 regionCount; - PROGRESSIVE_BLOCK_REGION* regions; -}; -typedef struct _PROGRESSIVE_BLOCK_FRAME_BEGIN PROGRESSIVE_BLOCK_FRAME_BEGIN; - -struct _PROGRESSIVE_BLOCK_FRAME_END -{ - UINT16 blockType; - UINT32 blockLen; -}; -typedef struct _PROGRESSIVE_BLOCK_FRAME_END PROGRESSIVE_BLOCK_FRAME_END; - struct _PROGRESSIVE_BLOCK_TILE_SIMPLE { UINT16 blockType; @@ -205,6 +168,81 @@ struct _PROGRESSIVE_BLOCK_TILE_UPGRADE }; typedef struct _PROGRESSIVE_BLOCK_TILE_UPGRADE PROGRESSIVE_BLOCK_TILE_UPGRADE; +struct _RFX_PROGRESSIVE_TILE +{ + UINT16 blockType; + UINT32 blockLen; + + BYTE quantIdxY; + BYTE quantIdxCb; + BYTE quantIdxCr; + UINT16 xIdx; + UINT16 yIdx; + + BYTE flags; + BYTE quality; + + UINT16 yLen; + UINT16 cbLen; + UINT16 crLen; + UINT16 tailLen; + BYTE* yData; + BYTE* cbData; + BYTE* crData; + BYTE* tailData; + + UINT16 ySrlLen; + UINT16 yRawLen; + UINT16 cbSrlLen; + UINT16 cbRawLen; + UINT16 crSrlLen; + UINT16 crRawLen; + BYTE* ySrlData; + BYTE* yRawData; + BYTE* cbSrlData; + BYTE* cbRawData; + BYTE* crSrlData; + BYTE* crRawData; +}; +typedef struct _RFX_PROGRESSIVE_TILE RFX_PROGRESSIVE_TILE; + +struct _PROGRESSIVE_BLOCK_REGION +{ + UINT16 blockType; + UINT32 blockLen; + + BYTE tileSize; + UINT16 numRects; + BYTE numQuant; + BYTE numProgQuant; + BYTE flags; + UINT16 numTiles; + UINT32 tileDataSize; + RFX_RECT* rects; + RFX_COMPONENT_CODEC_QUANT* quantVals; + RFX_PROGRESSIVE_CODEC_QUANT* quantProgVals; + RFX_PROGRESSIVE_TILE* tiles; +}; +typedef struct _PROGRESSIVE_BLOCK_REGION PROGRESSIVE_BLOCK_REGION; + +struct _PROGRESSIVE_BLOCK_FRAME_BEGIN +{ + UINT16 blockType; + UINT32 blockLen; + + UINT32 frameIndex; + UINT16 regionCount; + PROGRESSIVE_BLOCK_REGION* regions; +}; +typedef struct _PROGRESSIVE_BLOCK_FRAME_BEGIN PROGRESSIVE_BLOCK_FRAME_BEGIN; + +struct _PROGRESSIVE_BLOCK_FRAME_END +{ + UINT16 blockType; + UINT32 blockLen; +}; +typedef struct _PROGRESSIVE_BLOCK_FRAME_END PROGRESSIVE_BLOCK_FRAME_END; + struct _PROGRESSIVE_CONTEXT { BOOL Compressor; @@ -212,6 +250,9 @@ struct _PROGRESSIVE_CONTEXT UINT32 cRects; RFX_RECT* rects; + UINT32 cTiles; + RFX_PROGRESSIVE_TILE* tiles; + UINT32 cQuant; RFX_COMPONENT_CODEC_QUANT* quantVals; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index c810c8ebe..558eaeef3 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -72,40 +72,7 @@ const char* progressive_get_block_type_string(UINT16 blockType) return "PROGRESSIVE_WBT_UNKNOWN"; } -int progressive_decompress_tile_simple(PROGRESSIVE_CONTEXT* progressive, PROGRESSIVE_BLOCK_TILE_SIMPLE* tile) -{ - PROGRESSIVE_BLOCK_REGION* region; - RFX_COMPONENT_CODEC_QUANT* quantY; - RFX_COMPONENT_CODEC_QUANT* quantCb; - RFX_COMPONENT_CODEC_QUANT* quantCr; - RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; - - printf("ProgressiveTileSimple: quantIdx Y: %d Cb: %d Cr: %d xIdx: %d yIdx: %d flags: %d yLen: %d cbLen: %d crLen: %d tailLen: %d\n", - tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, tile->xIdx, tile->yIdx, tile->flags, tile->yLen, tile->cbLen, tile->crLen, tile->tailLen); - - region = &(progressive->region); - - if (tile->quantIdxY >= region->numQuant) - return -1; - - quantY = &(region->quantVals[tile->quantIdxY]); - - if (tile->quantIdxCb >= region->numQuant) - return -1; - - quantCb = &(region->quantVals[tile->quantIdxCb]); - - if (tile->quantIdxCr >= region->numQuant) - return -1; - - quantCr = &(region->quantVals[tile->quantIdxCr]); - - quantProgVal = &(progressive->quantProgValFull); - - return 1; -} - -int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, PROGRESSIVE_BLOCK_TILE_FIRST* tile) +int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) { PROGRESSIVE_BLOCK_REGION* region; RFX_COMPONENT_CODEC_QUANT* quantY; @@ -148,7 +115,7 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, PROGRESS return 1; } -int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, PROGRESSIVE_BLOCK_TILE_UPGRADE* tile) +int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) { PROGRESSIVE_BLOCK_REGION* region; RFX_COMPONENT_CODEC_QUANT* quantY; @@ -191,14 +158,231 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, PROGRE return 1; } -int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UINT32 blocksLen, UINT32 blockCount, UINT32 flags) +int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UINT32 blocksLen) +{ + BYTE* block; + UINT16 index; + UINT32 boffset; + UINT32 count = 0; + UINT32 offset = 0; + RFX_PROGRESSIVE_TILE* tile; + RFX_PROGRESSIVE_TILE* tiles; + PROGRESSIVE_BLOCK_REGION* region; + + region = &(progressive->region); + + tiles = region->tiles; + + while ((blocksLen - offset) >= 6) + { + boffset = 0; + block = &blocks[offset]; + + tile = &tiles[count]; + + tile->blockType = *((UINT16*) &block[boffset + 0]); /* blockType (2 bytes) */ + tile->blockLen = *((UINT32*) &block[boffset + 2]); /* blockLen (4 bytes) */ + boffset += 6; + + printf("%s\n", progressive_get_block_type_string(tile->blockType)); + + if ((blocksLen - offset) < tile->blockLen) + return -1003; + + switch (tile->blockType) + { + case PROGRESSIVE_WBT_TILE_SIMPLE: + + if ((tile->blockLen - boffset) < 16) + return -1022; + + tile->quality = 0xFF; /* simple tiles use no progressive techniques */ + + tile->quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ + tile->quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ + tile->quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */ + tile->xIdx = *((UINT16*) &block[boffset + 3]); /* xIdx (2 bytes) */ + tile->yIdx = *((UINT16*) &block[boffset + 5]); /* yIdx (2 bytes) */ + tile->flags = block[boffset + 7]; /* flags (1 byte) */ + tile->yLen = *((UINT16*) &block[boffset + 8]); /* yLen (2 bytes) */ + tile->cbLen = *((UINT16*) &block[boffset + 10]); /* cbLen (2 bytes) */ + tile->crLen = *((UINT16*) &block[boffset + 12]); /* crLen (2 bytes) */ + tile->tailLen = *((UINT16*) &block[boffset + 14]); /* tailLen (2 bytes) */ + boffset += 16; + + if ((tile->blockLen - boffset) < tile->yLen) + return -1023; + + tile->yData = &block[boffset]; + boffset += tile->yLen; + + if ((tile->blockLen - boffset) < tile->cbLen) + return -1024; + + tile->cbData = &block[boffset]; + boffset += tile->cbLen; + + if ((tile->blockLen - boffset) < tile->crLen) + return -1025; + + tile->crData = &block[boffset]; + boffset += tile->crLen; + + if ((tile->blockLen - boffset) < tile->tailLen) + return -1026; + + tile->tailData = &block[boffset]; + boffset += tile->tailLen; + + break; + + case PROGRESSIVE_WBT_TILE_FIRST: + + if ((tile->blockLen - boffset) < 17) + return -1027; + + tile->quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ + tile->quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ + tile->quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */ + tile->xIdx = *((UINT16*) &block[boffset + 3]); /* xIdx (2 bytes) */ + tile->yIdx = *((UINT16*) &block[boffset + 5]); /* yIdx (2 bytes) */ + tile->flags = block[boffset + 7]; /* flags (1 byte) */ + tile->quality = block[boffset + 8]; /* quality (1 byte) */ + tile->yLen = *((UINT16*) &block[boffset + 9]); /* yLen (2 bytes) */ + tile->cbLen = *((UINT16*) &block[boffset + 11]); /* cbLen (2 bytes) */ + tile->crLen = *((UINT16*) &block[boffset + 13]); /* crLen (2 bytes) */ + tile->tailLen = *((UINT16*) &block[boffset + 15]); /* tailLen (2 bytes) */ + boffset += 17; + + if ((tile->blockLen - boffset) < tile->yLen) + return -1028; + + tile->yData = &block[boffset]; + boffset += tile->yLen; + + if ((tile->blockLen - boffset) < tile->cbLen) + return -1029; + + tile->cbData = &block[boffset]; + boffset += tile->cbLen; + + if ((tile->blockLen - boffset) < tile->crLen) + return -1030; + + tile->crData = &block[boffset]; + boffset += tile->crLen; + + if ((tile->blockLen - boffset) < tile->tailLen) + return -1031; + + tile->tailData = &block[boffset]; + boffset += tile->tailLen; + + break; + + case PROGRESSIVE_WBT_TILE_UPGRADE: + + if ((tile->blockLen - boffset) < 20) + return -1032; + + tile->quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ + tile->quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ + tile->quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */ + tile->xIdx = *((UINT16*) &block[boffset + 3]); /* xIdx (2 bytes) */ + tile->yIdx = *((UINT16*) &block[boffset + 5]); /* yIdx (2 bytes) */ + tile->quality = block[boffset + 7]; /* quality (1 byte) */ + tile->ySrlLen = *((UINT16*) &block[boffset + 8]); /* ySrlLen (2 bytes) */ + tile->yRawLen = *((UINT16*) &block[boffset + 10]); /* yRawLen (2 bytes) */ + tile->cbSrlLen = *((UINT16*) &block[boffset + 12]); /* cbSrlLen (2 bytes) */ + tile->cbRawLen = *((UINT16*) &block[boffset + 14]); /* cbRawLen (2 bytes) */ + tile->crSrlLen = *((UINT16*) &block[boffset + 16]); /* crSrlLen (2 bytes) */ + tile->crRawLen = *((UINT16*) &block[boffset + 18]); /* crRawLen (2 bytes) */ + boffset += 20; + + if ((tile->blockLen - boffset) < tile->ySrlLen) + return -1033; + + tile->ySrlData = &block[boffset]; + boffset += tile->ySrlLen; + + if ((tile->blockLen - boffset) < tile->yRawLen) + return -1034; + + tile->yRawData = &block[boffset]; + boffset += tile->yRawLen; + + if ((tile->blockLen - boffset) < tile->cbSrlLen) + return -1035; + + tile->cbSrlData = &block[boffset]; + boffset += tile->cbSrlLen; + + if ((tile->blockLen - boffset) < tile->cbRawLen) + return -1036; + + tile->cbRawData = &block[boffset]; + boffset += tile->cbRawLen; + + if ((tile->blockLen - boffset) < tile->crSrlLen) + return -1037; + + tile->crSrlData = &block[boffset]; + boffset += tile->crSrlLen; + + if ((tile->blockLen - boffset) < tile->crRawLen) + return -1038; + + tile->crRawData = &block[boffset]; + boffset += tile->crRawLen; + + break; + + default: + return -1039; + break; + } + + if (boffset != tile->blockLen) + return -1040; + + offset += tile->blockLen; + count++; + } + + if (offset != blocksLen) + return -1041; + + for (index = 0; index < region->numTiles; index++) + { + tile = &tiles[index]; + + switch (tile->blockType) + { + case PROGRESSIVE_WBT_TILE_SIMPLE: + case PROGRESSIVE_WBT_TILE_FIRST: + progressive_decompress_tile_first(progressive, tile); + break; + + case PROGRESSIVE_WBT_TILE_UPGRADE: + progressive_decompress_tile_upgrade(progressive, tile); + break; + } + } + + return (int) offset; +} + +int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UINT32 SrcSize, + BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) { int status; BYTE* block; + BYTE* blocks; UINT16 index; UINT32 boffset; UINT16 blockType; UINT32 blockLen; + UINT32 blocksLen; UINT32 count = 0; UINT32 offset = 0; RFX_RECT* rect = NULL; @@ -207,12 +391,12 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U PROGRESSIVE_BLOCK_CONTEXT context; PROGRESSIVE_BLOCK_FRAME_BEGIN frameBegin; PROGRESSIVE_BLOCK_FRAME_END frameEnd; - PROGRESSIVE_BLOCK_TILE_SIMPLE simple; - PROGRESSIVE_BLOCK_TILE_FIRST first; - PROGRESSIVE_BLOCK_TILE_UPGRADE upgrade; RFX_COMPONENT_CODEC_QUANT* quantVal; RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; + blocks = pSrcData; + blocksLen = SrcSize; + region = &(progressive->region); while ((blocksLen - offset) >= 6) @@ -224,27 +408,6 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U blockLen = *((UINT32*) &block[boffset + 2]); /* blockLen (4 bytes) */ boffset += 6; - if (flags & PROGRESSIVE_BLOCKS_REGION) - { - if ((count + 1) > blockCount) - break; - - if (blockType != PROGRESSIVE_WBT_REGION) - return -1001; - } - else if (flags & PROGRESSIVE_BLOCKS_TILE) - { - if ((count + 1) > blockCount) - break; - - if ((blockType != PROGRESSIVE_WBT_TILE_SIMPLE) && - (blockType != PROGRESSIVE_WBT_TILE_FIRST) && - (blockType != PROGRESSIVE_WBT_TILE_UPGRADE)) - { - return -1002; - } - } - printf("%s\n", progressive_get_block_type_string(blockType)); if ((blocksLen - offset) < blockLen) @@ -290,17 +453,6 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U * the decoder SHOULD ignore this inconsistency. */ - if ((blockLen - boffset) > 0) - { - status = progressive_process_blocks(progressive, &block[boffset], - blockLen - boffset, frameBegin.regionCount, PROGRESSIVE_BLOCKS_REGION); - - if (status < 0) - return status; - - boffset += status; - } - break; case PROGRESSIVE_WBT_FRAME_END: @@ -440,11 +592,22 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U if ((blockLen - boffset) < region->tileDataSize) return -1021; + if (region->numTiles > progressive->cTiles) + { + progressive->tiles = (RFX_PROGRESSIVE_TILE*) realloc(progressive->tiles, + region->numTiles * sizeof(RFX_PROGRESSIVE_TILE)); + progressive->cTiles = region->numTiles; + } + + region->tiles = progressive->tiles; + + if (!region->tiles) + return -1; + printf("numRects: %d numTiles: %d numQuant: %d numProgQuant: %d\n", region->numRects, region->numTiles, region->numQuant, region->numProgQuant); - status = progressive_process_blocks(progressive, &block[boffset], - region->tileDataSize, region->numTiles, PROGRESSIVE_BLOCKS_TILE); + status = progressive_process_tiles(progressive, &block[boffset], region->tileDataSize); if (status < 0) return status; @@ -453,168 +616,6 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U break; - case PROGRESSIVE_WBT_TILE_SIMPLE: - - simple.blockType = blockType; - simple.blockLen = blockLen; - - if ((blockLen - boffset) < 16) - return -1022; - - simple.quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ - simple.quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ - simple.quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */ - simple.xIdx = *((UINT16*) &block[boffset + 3]); /* xIdx (2 bytes) */ - simple.yIdx = *((UINT16*) &block[boffset + 5]); /* yIdx (2 bytes) */ - simple.flags = block[boffset + 7]; /* flags (1 byte) */ - simple.yLen = *((UINT16*) &block[boffset + 8]); /* yLen (2 bytes) */ - simple.cbLen = *((UINT16*) &block[boffset + 10]); /* cbLen (2 bytes) */ - simple.crLen = *((UINT16*) &block[boffset + 12]); /* crLen (2 bytes) */ - simple.tailLen = *((UINT16*) &block[boffset + 14]); /* tailLen (2 bytes) */ - boffset += 16; - - if ((blockLen - boffset) < simple.yLen) - return -1023; - - simple.yData = &block[boffset]; - boffset += simple.yLen; - - if ((blockLen - boffset) < simple.cbLen) - return -1024; - - simple.cbData = &block[boffset]; - boffset += simple.cbLen; - - if ((blockLen - boffset) < simple.crLen) - return -1025; - - simple.crData = &block[boffset]; - boffset += simple.crLen; - - if ((blockLen - boffset) < simple.tailLen) - return -1026; - - simple.tailData = &block[boffset]; - boffset += simple.tailLen; - - status = progressive_decompress_tile_simple(progressive, &simple); - - break; - - case PROGRESSIVE_WBT_TILE_FIRST: - - first.blockType = blockType; - first.blockLen = blockLen; - - if ((blockLen - boffset) < 17) - return -1027; - - first.quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ - first.quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ - first.quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */ - first.xIdx = *((UINT16*) &block[boffset + 3]); /* xIdx (2 bytes) */ - first.yIdx = *((UINT16*) &block[boffset + 5]); /* yIdx (2 bytes) */ - first.flags = block[boffset + 7]; /* flags (1 byte) */ - first.quality = block[boffset + 8]; /* quality (1 byte) */ - first.yLen = *((UINT16*) &block[boffset + 9]); /* yLen (2 bytes) */ - first.cbLen = *((UINT16*) &block[boffset + 11]); /* cbLen (2 bytes) */ - first.crLen = *((UINT16*) &block[boffset + 13]); /* crLen (2 bytes) */ - first.tailLen = *((UINT16*) &block[boffset + 15]); /* tailLen (2 bytes) */ - boffset += 17; - - if ((blockLen - boffset) < first.yLen) - return -1028; - - first.yData = &block[boffset]; - boffset += first.yLen; - - if ((blockLen - boffset) < first.cbLen) - return -1029; - - first.cbData = &block[boffset]; - boffset += first.cbLen; - - if ((blockLen - boffset) < first.crLen) - return -1030; - - first.crData = &block[boffset]; - boffset += first.crLen; - - if ((blockLen - boffset) < first.tailLen) - return -1031; - - first.tailData = &block[boffset]; - boffset += first.tailLen; - - status = progressive_decompress_tile_first(progressive, &first); - - if (status < 0) - return -1; - - break; - - case PROGRESSIVE_WBT_TILE_UPGRADE: - - upgrade.blockType = blockType; - upgrade.blockLen = blockLen; - - if ((blockLen - boffset) < 20) - return -1032; - - upgrade.quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ - upgrade.quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ - upgrade.quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */ - upgrade.xIdx = *((UINT16*) &block[boffset + 3]); /* xIdx (2 bytes) */ - upgrade.yIdx = *((UINT16*) &block[boffset + 5]); /* yIdx (2 bytes) */ - upgrade.quality = block[boffset + 7]; /* quality (1 byte) */ - upgrade.ySrlLen = *((UINT16*) &block[boffset + 8]); /* ySrlLen (2 bytes) */ - upgrade.yRawLen = *((UINT16*) &block[boffset + 10]); /* yRawLen (2 bytes) */ - upgrade.cbSrlLen = *((UINT16*) &block[boffset + 12]); /* cbSrlLen (2 bytes) */ - upgrade.cbRawLen = *((UINT16*) &block[boffset + 14]); /* cbRawLen (2 bytes) */ - upgrade.crSrlLen = *((UINT16*) &block[boffset + 16]); /* crSrlLen (2 bytes) */ - upgrade.crRawLen = *((UINT16*) &block[boffset + 18]); /* crRawLen (2 bytes) */ - boffset += 20; - - if ((blockLen - boffset) < upgrade.ySrlLen) - return -1033; - - upgrade.ySrlData = &block[boffset]; - boffset += upgrade.ySrlLen; - - if ((blockLen - boffset) < upgrade.yRawLen) - return -1034; - - upgrade.yRawData = &block[boffset]; - boffset += upgrade.yRawLen; - - if ((blockLen - boffset) < upgrade.cbSrlLen) - return -1035; - - upgrade.cbSrlData = &block[boffset]; - boffset += upgrade.cbSrlLen; - - if ((blockLen - boffset) < upgrade.cbRawLen) - return -1036; - - upgrade.cbRawData = &block[boffset]; - boffset += upgrade.cbRawLen; - - if ((blockLen - boffset) < upgrade.crSrlLen) - return -1037; - - upgrade.crSrlData = &block[boffset]; - boffset += upgrade.crSrlLen; - - if ((blockLen - boffset) < upgrade.crRawLen) - return -1038; - - upgrade.crRawData = &block[boffset]; - boffset += upgrade.crRawLen; - - status = progressive_decompress_tile_upgrade(progressive, &upgrade); - - break; - default: return -1039; break; @@ -630,20 +631,7 @@ int progressive_process_blocks(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, U if (offset != blocksLen) return -1041; - return (int) offset; -} - -int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UINT32 SrcSize, - BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) -{ - int status; - - status = progressive_process_blocks(progressive, pSrcData, SrcSize, 0, PROGRESSIVE_BLOCKS_ALL); - - if (status >= 0) - status = 1; - - return status; + return 1; } int progressive_compress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize) @@ -672,6 +660,12 @@ PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor) if (!progressive->rects) return NULL; + progressive->cTiles = 64; + progressive->tiles = (RFX_PROGRESSIVE_TILE*) malloc(progressive->cTiles * sizeof(RFX_PROGRESSIVE_TILE)); + + if (!progressive->tiles) + return NULL; + progressive->cQuant = 8; progressive->quantVals = (RFX_COMPONENT_CODEC_QUANT*) malloc(progressive->cQuant * sizeof(RFX_COMPONENT_CODEC_QUANT)); @@ -699,6 +693,7 @@ void progressive_context_free(PROGRESSIVE_CONTEXT* progressive) return; free(progressive->rects); + free(progressive->tiles); free(progressive->quantVals); free(progressive->quantProgVals); From 85026bff761a31c92de9b74f0cd11ea3bd6fc44a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 2 Aug 2014 11:24:47 -0400 Subject: [PATCH 05/12] libfreerdp-codec: initial RLGR1 progressive implementation --- libfreerdp/codec/progressive.c | 274 +++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 558eaeef3..ac3acdc5a 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -72,6 +72,280 @@ const char* progressive_get_block_type_string(UINT16 blockType) return "PROGRESSIVE_WBT_UNKNOWN"; } +/* Constants used within the RLGR1/RLGR3 algorithm */ +#define KPMAX (80) /* max value for kp or krp */ +#define LSGR (3) /* shift count to convert kp to k */ +#define UP_GR (4) /* increase in kp after a zero run in RL mode */ +#define DN_GR (6) /* decrease in kp after a nonzero symbol in RL mode */ +#define UQ_GR (3) /* increase in kp after nonzero symbol in GR mode */ +#define DQ_GR (3) /* decrease in kp after zero symbol in GR mode */ + +/** + * __lzcnt16, __lzcnt, __lzcnt64: + * http://msdn.microsoft.com/en-us/library/bb384809/ + */ + +#ifndef _WIN32 + +INLINE UINT16 __lzcnt16(UINT16 value) +{ + return (UINT16) (__builtin_clz((UINT32) value) - 16); +} + +INLINE UINT32 __lzcnt(UINT32 value) +{ + return __builtin_clz(value); +} + +INLINE UINT64 __lzcnt64(UINT64 value) +{ + return __builtin_clzll(value); +} + +#endif + +int progressive_rfx_rlgr_decode(PROGRESSIVE_CONTEXT* progressive, BYTE* data, UINT16 length) +{ + int vk; + int run; + INT16 mag; + int k, kp; + int kr, krp; + UINT16 code; + UINT32 sign; + wBitStream* bs; + UINT32 accumulator; + + k = 1; + kp = k << LSGR; + + kr = 1; + krp = kr << LSGR; + + bs = BitStream_New(); + + BitStream_Attach(bs, data, length); + BitStream_Fetch(bs); + + while ((bs->length - bs->position) > 0) + { + accumulator = bs->accumulator; + + if (k) + { + /* Run-Length (RL) Mode */ + + run = 0; + + /* count number of leading 0s */ + + vk = __lzcnt(bs->accumulator); + + while (vk && (vk % 32 == 0)) + { + BitStream_Shift(bs, vk); + vk += __lzcnt(bs->accumulator); + } + + BitStream_Shift(bs, ((vk % 32) + 1)); + + while (vk--) + { + run += (1 << k); /* add (1 << k) to run length */ + + /* update k, kp params */ + + kp += UP_GR; + + if (kp > KPMAX) + kp = KPMAX; + else if (kp < 0) + kp = 0; + + k = kp >> LSGR; + } + + /* next k bits contain run length remainder */ + + run += (bs->accumulator >> (32 - k)); + BitStream_Shift(bs, k); + + /* read sign bit */ + + sign = (bs->accumulator & 0x80000000) ? 1 : 0; + BitStream_Shift(bs, 1); + + /* count number of leading 1s */ + + vk = __lzcnt(~(bs->accumulator)); + + while (vk && (vk % 32 == 0)) + { + BitStream_Shift(bs, vk); + vk += __lzcnt(~(bs->accumulator)); + } + + BitStream_Shift(bs, ((vk % 32) + 1)); + + /* add (vk << kr) to code */ + + code = (vk << kr); + + /* next kr bits contain code remainder */ + + code += (bs->accumulator >> (32 - kr)); + BitStream_Shift(bs, kr); + + if (!vk) + { + /* update kr, krp params */ + + krp += -2; + + if (krp > KPMAX) + krp = KPMAX; + else if (krp < 0) + krp = 0; + + kr = krp >> LSGR; + } + else if (vk != 1) + { + /* update kr, krp params */ + + krp += vk; + + if (krp > KPMAX) + krp = KPMAX; + else if (krp < 0) + krp = 0; + + kr = krp >> LSGR; + } + + /* update k, kp params */ + + kp += -DN_GR; + + if (kp > KPMAX) + kp = KPMAX; + else if (kp < 0) + kp = 0; + + k = kp >> LSGR; + + /* compute magnitude from code */ + + if (sign) + mag = ((INT16) (code + 1)) * -1; + else + mag = (INT16) (code + 1); + + /* write to output stream */ + + // WriteZeroes(run); + // WriteValue(mag); + } + else + { + /* Golomb-Rice (GR) Mode */ + + /* count number of leading 1s */ + + vk = __lzcnt(~(bs->accumulator)); + + while (vk && (vk % 32 == 0)) + { + BitStream_Shift(bs, vk); + vk += __lzcnt(~(bs->accumulator)); + } + + BitStream_Shift(bs, ((vk % 32) + 1)); + + /* add (vk << kr) to code */ + + code = (vk << kr); + + /* next kr bits contain code remainder */ + + code += (bs->accumulator >> (32 - kr)); + BitStream_Shift(bs, kr); + + if (!vk) + { + /* update kr, krp params */ + + krp += -2; + + if (krp > KPMAX) + krp = KPMAX; + else if (krp < 0) + krp = 0; + + kr = krp >> LSGR; + } + else if (vk != 1) + { + /* update kr, krp params */ + + krp += vk; + + if (krp > KPMAX) + krp = KPMAX; + else if (krp < 0) + krp = 0; + + kr = krp >> LSGR; + } + + if (!code) + { + /* update k, kp params */ + + kp += UQ_GR; + + if (kp > KPMAX) + kp = KPMAX; + else if (kp < 0) + kp = 0; + + k = kp >> LSGR; + + // WriteValue(0); + } + else + { + /* update k, kp params */ + + kp += -DQ_GR; + + if (kp > KPMAX) + kp = KPMAX; + else if (kp < 0) + kp = 0; + + k = kp >> LSGR; + + /* + * code = 2 * mag - sign + * sign + code = 2 * mag + */ + + if (code & 1) + mag = ((INT16) ((code + 1) >> 1)) * -1; + else + mag = (INT16) (mag >> 1); + + // WriteValue(mag); + } + } + } + + BitStream_Free(bs); + + return 1; +} + int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) { PROGRESSIVE_BLOCK_REGION* region; From 51f6ffd2ba760122b6cf03c0e7eef74d1967e350 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sat, 2 Aug 2014 22:26:05 -0400 Subject: [PATCH 06/12] libfreerdp-codec: improve rfx progressive RLGR1 implementation --- libfreerdp/codec/progressive.c | 187 +++++++++++++++++------ winpr/include/winpr/bitstream.h | 55 ++++--- winpr/include/winpr/crt.h | 49 ++++++ winpr/libwinpr/crt/test/CMakeLists.txt | 1 + winpr/libwinpr/crt/test/TestIntrinsics.c | 109 +++++++++++++ 5 files changed, 330 insertions(+), 71 deletions(-) create mode 100644 winpr/libwinpr/crt/test/TestIntrinsics.c diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index ac3acdc5a..6c703a3c7 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -80,41 +80,21 @@ const char* progressive_get_block_type_string(UINT16 blockType) #define UQ_GR (3) /* increase in kp after nonzero symbol in GR mode */ #define DQ_GR (3) /* decrease in kp after zero symbol in GR mode */ -/** - * __lzcnt16, __lzcnt, __lzcnt64: - * http://msdn.microsoft.com/en-us/library/bb384809/ - */ - -#ifndef _WIN32 - -INLINE UINT16 __lzcnt16(UINT16 value) -{ - return (UINT16) (__builtin_clz((UINT32) value) - 16); -} - -INLINE UINT32 __lzcnt(UINT32 value) -{ - return __builtin_clz(value); -} - -INLINE UINT64 __lzcnt64(UINT64 value) -{ - return __builtin_clzll(value); -} - -#endif - -int progressive_rfx_rlgr_decode(PROGRESSIVE_CONTEXT* progressive, BYTE* data, UINT16 length) +int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 DstSize) { int vk; int run; + int cnt; + int size; + int nbits; + int offset; INT16 mag; int k, kp; int kr, krp; UINT16 code; UINT32 sign; + INT16* pOutput; wBitStream* bs; - UINT32 accumulator; k = 1; kp = k << LSGR; @@ -122,15 +102,24 @@ int progressive_rfx_rlgr_decode(PROGRESSIVE_CONTEXT* progressive, BYTE* data, UI kr = 1; krp = kr << LSGR; + if (!pSrcData) + return -2001; + + if (SrcSize < 1) + return -2002; + + pOutput = pDstData; + bs = BitStream_New(); - BitStream_Attach(bs, data, length); + if (!bs) + return -2003; + + BitStream_Attach(bs, pSrcData, SrcSize); BitStream_Fetch(bs); - while ((bs->length - bs->position) > 0) + while ((BitStream_GetRemainingLength(bs) > 0) && ((pOutput - pDstData) < DstSize)) { - accumulator = bs->accumulator; - if (k) { /* Run-Length (RL) Mode */ @@ -139,15 +128,38 @@ int progressive_rfx_rlgr_decode(PROGRESSIVE_CONTEXT* progressive, BYTE* data, UI /* count number of leading 0s */ - vk = __lzcnt(bs->accumulator); + cnt = __lzcnt(bs->accumulator); - while (vk && (vk % 32 == 0)) + nbits = BitStream_GetRemainingLength(bs); + + if (cnt > nbits) + cnt = nbits; + + vk = cnt; + + while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0)) { - BitStream_Shift(bs, vk); - vk += __lzcnt(bs->accumulator); + printf("__lzcnt loop: cnt: %d length: %d position: %d\n", + cnt, bs->length, bs->position); + + BitStream_Shift32(bs); + + cnt = __lzcnt(bs->accumulator); + + nbits = BitStream_GetRemainingLength(bs); + + if (cnt > nbits) + cnt = nbits; + + vk += cnt; } - BitStream_Shift(bs, ((vk % 32) + 1)); + BitStream_Shift(bs, (vk % 32)); + + if (BitStream_GetRemainingLength(bs) < 1) + break; + + BitStream_Shift(bs, 1); while (vk--) { @@ -167,25 +179,51 @@ int progressive_rfx_rlgr_decode(PROGRESSIVE_CONTEXT* progressive, BYTE* data, UI /* next k bits contain run length remainder */ + if (BitStream_GetRemainingLength(bs) < k) + break; + run += (bs->accumulator >> (32 - k)); BitStream_Shift(bs, k); /* read sign bit */ + if (BitStream_GetRemainingLength(bs) < 1) + break; + sign = (bs->accumulator & 0x80000000) ? 1 : 0; BitStream_Shift(bs, 1); /* count number of leading 1s */ - vk = __lzcnt(~(bs->accumulator)); + cnt = __lzcnt(~(bs->accumulator)); - while (vk && (vk % 32 == 0)) + nbits = BitStream_GetRemainingLength(bs); + + if (cnt > nbits) + cnt = nbits; + + vk = cnt; + + while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0)) { - BitStream_Shift(bs, vk); - vk += __lzcnt(~(bs->accumulator)); + BitStream_Shift32(bs); + + cnt = __lzcnt(~(bs->accumulator)); + + nbits = BitStream_GetRemainingLength(bs); + + if (cnt > nbits) + cnt = nbits; + + vk += cnt; } - BitStream_Shift(bs, ((vk % 32) + 1)); + BitStream_Shift(bs, (vk % 32)); + + if (BitStream_GetRemainingLength(bs) < 1) + break; + + BitStream_Shift(bs, 1); /* add (vk << kr) to code */ @@ -193,6 +231,9 @@ int progressive_rfx_rlgr_decode(PROGRESSIVE_CONTEXT* progressive, BYTE* data, UI /* next kr bits contain code remainder */ + if (BitStream_GetRemainingLength(bs) < kr) + break; + code += (bs->accumulator >> (32 - kr)); BitStream_Shift(bs, kr); @@ -243,8 +284,25 @@ int progressive_rfx_rlgr_decode(PROGRESSIVE_CONTEXT* progressive, BYTE* data, UI /* write to output stream */ - // WriteZeroes(run); - // WriteValue(mag); + offset = (int) (pOutput - pDstData); + size = run; + + if ((offset + size) > DstSize) + size = DstSize - offset; + + if (size) + { + ZeroMemory(pOutput, size * sizeof(INT16)); + pOutput += size; + } + + offset = (int) (pOutput - pDstData); + + if ((offset + 1) <= DstSize) + { + *pOutput = mag; + pOutput++; + } } else { @@ -252,15 +310,35 @@ int progressive_rfx_rlgr_decode(PROGRESSIVE_CONTEXT* progressive, BYTE* data, UI /* count number of leading 1s */ - vk = __lzcnt(~(bs->accumulator)); + cnt = __lzcnt(~(bs->accumulator)); - while (vk && (vk % 32 == 0)) + nbits = BitStream_GetRemainingLength(bs); + + if (cnt > nbits) + cnt = nbits; + + vk = cnt; + + while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0)) { - BitStream_Shift(bs, vk); - vk += __lzcnt(~(bs->accumulator)); + BitStream_Shift32(bs); + + cnt = __lzcnt(~(bs->accumulator)); + + nbits = BitStream_GetRemainingLength(bs); + + if (cnt > nbits) + cnt = nbits; + + vk += cnt; } - BitStream_Shift(bs, ((vk % 32) + 1)); + BitStream_Shift(bs, (vk % 32)); + + if (BitStream_GetRemainingLength(bs) < 1) + break; + + BitStream_Shift(bs, 1); /* add (vk << kr) to code */ @@ -268,6 +346,9 @@ int progressive_rfx_rlgr_decode(PROGRESSIVE_CONTEXT* progressive, BYTE* data, UI /* next kr bits contain code remainder */ + if (BitStream_GetRemainingLength(bs) < kr) + break; + code += (bs->accumulator >> (32 - kr)); BitStream_Shift(bs, kr); @@ -311,7 +392,7 @@ int progressive_rfx_rlgr_decode(PROGRESSIVE_CONTEXT* progressive, BYTE* data, UI k = kp >> LSGR; - // WriteValue(0); + mag = 0; } else { @@ -335,15 +416,21 @@ int progressive_rfx_rlgr_decode(PROGRESSIVE_CONTEXT* progressive, BYTE* data, UI mag = ((INT16) ((code + 1) >> 1)) * -1; else mag = (INT16) (mag >> 1); + } - // WriteValue(mag); + offset = (int) (pOutput - pDstData); + + if ((offset + 1) <= DstSize) + { + *pOutput = mag; + pOutput++; } } } BitStream_Free(bs); - return 1; + return (int) (pOutput - pDstData); } int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) diff --git a/winpr/include/winpr/bitstream.h b/winpr/include/winpr/bitstream.h index b77a1dc97..092917322 100644 --- a/winpr/include/winpr/bitstream.h +++ b/winpr/include/winpr/bitstream.h @@ -29,9 +29,9 @@ struct _wBitStream { BYTE* buffer; BYTE* pointer; - DWORD position; - DWORD length; - DWORD capacity; + int position; + int length; + int capacity; UINT32 mask; UINT32 offset; UINT32 prefetch; @@ -83,28 +83,38 @@ extern "C" { } while(0) #define BitStream_Shift(_bs, _nbits) do { \ - _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; \ + if (_nbits == 0) { \ + } else if ((_nbits > 0) && (_nbits < 32)) { \ + _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; \ + } \ } \ + } else { \ + fprintf(stderr, "warning: BitStream_Shift(%d)\n", _nbits); \ } \ } while(0) +#define BitStream_Shift32(_bs) do { \ + BitStream_Shift(_bs, 16); \ + BitStream_Shift(_bs, 16); \ +} while(0) + #define BitStream_Write_Bits(_bs, _bits, _nbits) do { \ _bs->position += _nbits; \ _bs->offset += _nbits; \ @@ -124,6 +134,9 @@ extern "C" { } \ } while(0) +#define BitStream_GetRemainingLength(_bs) \ + (_bs->length - _bs->position) + WINPR_API void BitDump(const BYTE* buffer, UINT32 length, UINT32 flags); WINPR_API UINT32 ReverseBits32(UINT32 bits, UINT32 nbits); diff --git a/winpr/include/winpr/crt.h b/winpr/include/winpr/crt.h index 6da3f4b16..ed136a2a0 100644 --- a/winpr/include/winpr/crt.h +++ b/winpr/include/winpr/crt.h @@ -82,6 +82,55 @@ static INLINE UINT64 _rotr64(UINT64 value, int shift) { #endif +/** + * __lzcnt16, __lzcnt, __lzcnt64: + * http://msdn.microsoft.com/en-us/library/bb384809/ + */ + +#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) + +/** + * __lzcnt16, __lzcnt, __lzcnt64: + * http://msdn.microsoft.com/en-us/library/bb384809/ + * + * Beware: the result of __builtin_clz(0) is undefined + */ + +static INLINE UINT32 __lzcnt(UINT32 _val32) { + return _val32 ? ((UINT32) __builtin_clz(_val32)) : 32; +} + +static INLINE UINT16 __lzcnt16(UINT16 _val16) { + return _val16 ? ((UINT16) (__builtin_clz((UINT32) _val16) - 16)) : 16; +} + +static INLINE UINT64 __lzcnt64(UINT64 _val64) { + return _val64 ? ((UINT64) __builtin_clzll(_val64)) : 64; +} + +#else + +static INLINE UINT32 __lzcnt(UINT32 x) { + unsigned y; + int n = 32; + y = x >> 16; if (y != 0) { n = n - 16; x = y; } + y = x >> 8; if (y != 0) { n = n - 8; x = y; } + y = x >> 4; if (y != 0) { n = n - 4; x = y; } + y = x >> 2; if (y != 0) { n = n - 2; x = y; } + y = x >> 1; if (y != 0) return n - 2; + return n - x; +} + +static INLINE UINT16 __lzcnt16(UINT16 x) { + return ((UINT16) __lzcnt((UINT32) x)); +} + +static INLINE UINT64 __lzcnt64(UINT64 x) { + return 0; /* TODO */ +} + +#endif + #endif #ifndef _WIN32 diff --git a/winpr/libwinpr/crt/test/CMakeLists.txt b/winpr/libwinpr/crt/test/CMakeLists.txt index 4f1f9d3fd..4bccde151 100644 --- a/winpr/libwinpr/crt/test/CMakeLists.txt +++ b/winpr/libwinpr/crt/test/CMakeLists.txt @@ -8,6 +8,7 @@ set(${MODULE_PREFIX}_TESTS TestTypes.c TestAlignment.c TestString.c + TestIntrinsics.c TestUnicodeConversion.c) create_test_sourcelist(${MODULE_PREFIX}_SRCS diff --git a/winpr/libwinpr/crt/test/TestIntrinsics.c b/winpr/libwinpr/crt/test/TestIntrinsics.c new file mode 100644 index 000000000..bb1f07b05 --- /dev/null +++ b/winpr/libwinpr/crt/test/TestIntrinsics.c @@ -0,0 +1,109 @@ + +#include +#include +#include + +int test_lzcnt() +{ + if (__lzcnt(0x0) != 32) { + fprintf(stderr, "__lzcnt(0x0) != 32\n"); + return -1; + } + + if (__lzcnt(0x1) != 31) { + fprintf(stderr, "__lzcnt(0x1) != 31\n"); + return -1; + } + + if (__lzcnt(0xFF) != 24) { + fprintf(stderr, "__lzcnt(0xFF) != 24\n"); + return -1; + } + + if (__lzcnt(0xFFFF) != 16) { + fprintf(stderr, "__lzcnt(0xFFFF) != 16\n"); + return -1; + } + + if (__lzcnt(0xFFFFFF) != 8) { + fprintf(stderr, "__lzcnt(0xFFFFFF) != 8\n"); + return -1; + } + + if (__lzcnt(0xFFFFFFFF) != 0) { + fprintf(stderr, "__lzcnt(0xFFFFFFFF) != 0\n"); + return -1; + } + + return 1; +} + +int test_lzcnt16() +{ + if (__lzcnt16(0x0) != 16) { + fprintf(stderr, "__lzcnt16(0x0) != 16\n"); + return -1; + } + + if (__lzcnt16(0x1) != 15) { + fprintf(stderr, "__lzcnt16(0x1) != 15\n"); + return -1; + } + + if (__lzcnt16(0xFF) != 8) { + fprintf(stderr, "__lzcnt16(0xFF) != 8\n"); + return -1; + } + + if (__lzcnt16(0xFFFF) != 0) { + fprintf(stderr, "__lzcnt16(0xFFFF) != 0\n"); + return -1; + } + + return 1; +} + +int test_lzcnt64() +{ + if (__lzcnt64(0x0) != 64) { + fprintf(stderr, "__lzcnt64(0x0) != 64\n"); + return -1; + } + + if (__lzcnt64(0x1) != 63) { + fprintf(stderr, "__lzcnt64(0x1) != 63\n"); + return -1; + } + + if (__lzcnt64(0xFF) != 56) { + fprintf(stderr, "__lzcnt64(0xFF) != 56\n"); + return -1; + } + + if (__lzcnt64(0xFFFF) != 48) { + fprintf(stderr, "__lzcnt64(0xFFFF) != 48\n"); + return -1; + } + + if (__lzcnt64(0xFFFFFF) != 40) { + fprintf(stderr, "__lzcnt64(0xFFFFFF) != 40\n"); + return -1; + } + + if (__lzcnt64(0xFFFFFFFF) != 32) { + fprintf(stderr, "__lzcnt64(0xFFFFFFFF) != 32\n"); + return -1; + } + + return 1; +} + +int TestIntrinsics(int argc, char* argv[]) +{ + test_lzcnt(); + test_lzcnt16(); + test_lzcnt64(); + + return 0; +} + From 88e5bacda7fd12b610e22e31af006507cfba01d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 3 Aug 2014 00:08:22 -0400 Subject: [PATCH 07/12] libfreerdp-codec: improve progressive rfx rlgr1 --- libfreerdp/codec/progressive.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 6c703a3c7..5eee980db 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -139,9 +139,6 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0)) { - printf("__lzcnt loop: cnt: %d length: %d position: %d\n", - cnt, bs->length, bs->position); - BitStream_Shift32(bs); cnt = __lzcnt(bs->accumulator); @@ -182,7 +179,8 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst if (BitStream_GetRemainingLength(bs) < k) break; - run += (bs->accumulator >> (32 - k)); + bs->mask = ((1 << k) - 1); + run += ((bs->accumulator >> (32 - k)) & bs->mask); BitStream_Shift(bs, k); /* read sign bit */ @@ -225,18 +223,19 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst BitStream_Shift(bs, 1); - /* add (vk << kr) to code */ - - code = (vk << kr); - /* next kr bits contain code remainder */ if (BitStream_GetRemainingLength(bs) < kr) break; - code += (bs->accumulator >> (32 - kr)); + bs->mask = ((1 << kr) - 1); + code = (UINT16) ((bs->accumulator >> (32 - kr)) & bs->mask); BitStream_Shift(bs, kr); + /* add (vk << kr) to code */ + + code |= (vk << kr); + if (!vk) { /* update kr, krp params */ @@ -340,18 +339,19 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst BitStream_Shift(bs, 1); - /* add (vk << kr) to code */ - - code = (vk << kr); - /* next kr bits contain code remainder */ if (BitStream_GetRemainingLength(bs) < kr) break; - code += (bs->accumulator >> (32 - kr)); + bs->mask = ((1 << kr) - 1); + code = (UINT16) ((bs->accumulator >> (32 - kr)) & bs->mask); BitStream_Shift(bs, kr); + /* add (vk << kr) to code */ + + code |= (vk << kr); + if (!vk) { /* update kr, krp params */ @@ -415,7 +415,7 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst if (code & 1) mag = ((INT16) ((code + 1) >> 1)) * -1; else - mag = (INT16) (mag >> 1); + mag = (INT16) (code >> 1); } offset = (int) (pOutput - pDstData); From e6dbbfb305e31c77ace7013aac400cc2dd665e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 5 Aug 2014 17:07:06 -0400 Subject: [PATCH 08/12] libfreerdp-codec: fix progressive RLGR1 decode --- libfreerdp/codec/progressive.c | 35 +++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 5eee980db..fb7a502a8 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -95,6 +95,7 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst UINT32 sign; INT16* pOutput; wBitStream* bs; + wBitStream s_bs; k = 1; kp = k << LSGR; @@ -102,23 +103,20 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst kr = 1; krp = kr << LSGR; - if (!pSrcData) - return -2001; + if (!pSrcData || !SrcSize) + return -1; - if (SrcSize < 1) - return -2002; + if (!pDstData || !DstSize) + return -1; pOutput = pDstData; - bs = BitStream_New(); - - if (!bs) - return -2003; + bs = &s_bs; BitStream_Attach(bs, pSrcData, SrcSize); BitStream_Fetch(bs); - while ((BitStream_GetRemainingLength(bs) > 0) && ((pOutput - pDstData) < DstSize)) + while ((BitStream_GetRemainingLength(bs) > 1) && ((pOutput - pDstData) < DstSize)) { if (k) { @@ -428,9 +426,24 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst } } - BitStream_Free(bs); + offset = (int) (pOutput - pDstData); - return (int) (pOutput - pDstData); + if (offset < DstSize) + { + size = DstSize - offset; + ZeroMemory(pOutput, size * 2); + pOutput += size; + } + + offset = (int) (pOutput - pDstData); + + if (offset != DstSize) + return -1; + + if (((bs->position + 7) / 8) != SrcSize) + return -1; + + return 1; } int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) From db5b94785257f9af059362456935ccf70c7c50bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 5 Aug 2014 17:22:20 -0400 Subject: [PATCH 09/12] libfreerdp-codec: optimize RLGR1 --- libfreerdp/codec/progressive.c | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index fb7a502a8..71bbb65d1 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -166,8 +166,6 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst if (kp > KPMAX) kp = KPMAX; - else if (kp < 0) - kp = 0; k = kp >> LSGR; } @@ -238,11 +236,9 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst { /* update kr, krp params */ - krp += -2; + krp -= 2; - if (krp > KPMAX) - krp = KPMAX; - else if (krp < 0) + if (krp < 0) krp = 0; kr = krp >> LSGR; @@ -255,19 +251,15 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst if (krp > KPMAX) krp = KPMAX; - else if (krp < 0) - krp = 0; kr = krp >> LSGR; } /* update k, kp params */ - kp += -DN_GR; + kp -= DN_GR; - if (kp > KPMAX) - kp = KPMAX; - else if (kp < 0) + if (kp < 0) kp = 0; k = kp >> LSGR; @@ -354,11 +346,9 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst { /* update kr, krp params */ - krp += -2; + krp -= 2; - if (krp > KPMAX) - krp = KPMAX; - else if (krp < 0) + if (krp < 0) krp = 0; kr = krp >> LSGR; @@ -371,8 +361,6 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst if (krp > KPMAX) krp = KPMAX; - else if (krp < 0) - krp = 0; kr = krp >> LSGR; } @@ -385,8 +373,6 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst if (kp > KPMAX) kp = KPMAX; - else if (kp < 0) - kp = 0; k = kp >> LSGR; @@ -396,11 +382,9 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst { /* update k, kp params */ - kp += -DQ_GR; + kp -= DQ_GR; - if (kp > KPMAX) - kp = KPMAX; - else if (kp < 0) + if (kp < 0) kp = 0; k = kp >> LSGR; From b7ca13f19d6c18b5a803c1d77a9488d02a7048f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 5 Aug 2014 21:26:47 -0400 Subject: [PATCH 10/12] libfreerdp-codec: add RLGR3 support in new RLGR function --- libfreerdp/codec/progressive.c | 162 +++++++++++++++++++++++---------- 1 file changed, 114 insertions(+), 48 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 71bbb65d1..f207a53e3 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -72,15 +72,15 @@ const char* progressive_get_block_type_string(UINT16 blockType) return "PROGRESSIVE_WBT_UNKNOWN"; } -/* Constants used within the RLGR1/RLGR3 algorithm */ -#define KPMAX (80) /* max value for kp or krp */ -#define LSGR (3) /* shift count to convert kp to k */ -#define UP_GR (4) /* increase in kp after a zero run in RL mode */ -#define DN_GR (6) /* decrease in kp after a nonzero symbol in RL mode */ -#define UQ_GR (3) /* increase in kp after nonzero symbol in GR mode */ -#define DQ_GR (3) /* decrease in kp after zero symbol in GR mode */ +/* Constants used in RLGR1/RLGR3 algorithm */ +#define KPMAX (80) /* max value for kp or krp */ +#define LSGR (3) /* shift count to convert kp to k */ +#define UP_GR (4) /* increase in kp after a zero run in RL mode */ +#define DN_GR (6) /* decrease in kp after a nonzero symbol in RL mode */ +#define UQ_GR (3) /* increase in kp after nonzero symbol in GR mode */ +#define DQ_GR (3) /* decrease in kp after zero symbol in GR mode */ -int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 DstSize) +int rfx_rlgrx_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 DstSize, int mode) { int vk; int run; @@ -93,6 +93,9 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst int kr, krp; UINT16 code; UINT32 sign; + UINT32 nIdx; + UINT32 val1; + UINT32 val2; INT16* pOutput; wBitStream* bs; wBitStream s_bs; @@ -103,6 +106,9 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst kr = 1; krp = kr << LSGR; + if ((mode != 1) && (mode != 3)) + mode = 1; + if (!pSrcData || !SrcSize) return -1; @@ -116,7 +122,7 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst BitStream_Attach(bs, pSrcData, SrcSize); BitStream_Fetch(bs); - while ((BitStream_GetRemainingLength(bs) > 1) && ((pOutput - pDstData) < DstSize)) + while ((BitStream_GetRemainingLength(bs) > 0) && ((pOutput - pDstData) < DstSize)) { if (k) { @@ -285,9 +291,7 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst pOutput += size; } - offset = (int) (pOutput - pDstData); - - if ((offset + 1) <= DstSize) + if ((pOutput - pDstData) < DstSize) { *pOutput = mag; pOutput++; @@ -365,47 +369,112 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst kr = krp >> LSGR; } - if (!code) + if (mode == 1) /* RLGR1 */ { - /* update k, kp params */ + if (!code) + { + /* update k, kp params */ - kp += UQ_GR; + kp += UQ_GR; - if (kp > KPMAX) - kp = KPMAX; + if (kp > KPMAX) + kp = KPMAX; - k = kp >> LSGR; + k = kp >> LSGR; - mag = 0; - } - else - { - /* update k, kp params */ - - kp -= DQ_GR; - - if (kp < 0) - kp = 0; - - k = kp >> LSGR; - - /* - * code = 2 * mag - sign - * sign + code = 2 * mag - */ - - if (code & 1) - mag = ((INT16) ((code + 1) >> 1)) * -1; + mag = 0; + } else - mag = (INT16) (code >> 1); + { + /* update k, kp params */ + + kp -= DQ_GR; + + if (kp < 0) + kp = 0; + + k = kp >> LSGR; + + /* + * code = 2 * mag - sign + * sign + code = 2 * mag + */ + + if (code & 1) + mag = ((INT16) ((code + 1) >> 1)) * -1; + else + mag = (INT16) (code >> 1); + } + + if ((pOutput - pDstData) < DstSize) + { + *pOutput = mag; + pOutput++; + } } - - offset = (int) (pOutput - pDstData); - - if ((offset + 1) <= DstSize) + else if (mode == 3) /* RLGR3 */ { - *pOutput = mag; - pOutput++; + nIdx = 0; + + if (code) + { + mag = (UINT32) code; + nIdx = 32 - __lzcnt(mag); + } + + if (BitStream_GetRemainingLength(bs) < nIdx) + break; + + bs->mask = ((1 << nIdx) - 1); + val1 = ((bs->accumulator >> (32 - nIdx)) & bs->mask); + BitStream_Shift(bs, nIdx); + + val2 = code - val1; + + if (val1 && val2) + { + /* update k, kp params */ + + kp -= (2 * DQ_GR); + + if (kp < 0) + kp = 0; + + k = kp >> LSGR; + } + else if (!val1 && !val2) + { + /* update k, kp params */ + + kp += (2 * UQ_GR); + + if (kp > KPMAX) + kp = KPMAX; + + k = kp >> LSGR; + } + + if (val1 & 1) + mag = ((INT16) ((val1 + 1) >> 1)) * -1; + else + mag = (INT16) (val1 >> 1); + + if ((pOutput - pDstData) < DstSize) + { + *pOutput = mag; + pOutput++; + } + + if (val2 & 1) + mag = ((INT16) ((val2 + 1) >> 1)) * -1; + else + mag = (INT16) (val2 >> 1); + + if ((pOutput - pDstData) < DstSize) + { + *pOutput = mag; + pOutput++; + } } } } @@ -424,9 +493,6 @@ int rfx_rlgr1_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 Dst if (offset != DstSize) return -1; - if (((bs->position + 7) / 8) != SrcSize) - return -1; - return 1; } From 22d3b6c74b54e139642324f45e9ea81050a006ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 5 Aug 2014 21:41:58 -0400 Subject: [PATCH 11/12] libfreerdp-codec: remove old RemoteFX RLGR implementation in favour of faster one --- include/freerdp/codec/rfx.h | 4 +- libfreerdp/codec/progressive.c | 424 ---------------- libfreerdp/codec/rfx.c | 2 - libfreerdp/codec/rfx_decode.c | 2 +- libfreerdp/codec/rfx_encode.c | 2 +- libfreerdp/codec/rfx_rlgr.c | 505 ++++++++++++++----- libfreerdp/codec/rfx_rlgr.h | 1 - winpr/include/winpr/bitstream.h | 4 +- winpr/libwinpr/utils/collections/BitStream.c | 4 +- 9 files changed, 384 insertions(+), 564 deletions(-) diff --git a/include/freerdp/codec/rfx.h b/include/freerdp/codec/rfx.h index 60ada8b79..08480bec2 100644 --- a/include/freerdp/codec/rfx.h +++ b/include/freerdp/codec/rfx.h @@ -146,8 +146,6 @@ struct _RFX_CONTEXT void (*quantization_encode)(INT16* buffer, const UINT32* quantization_values); void (*dwt_2d_decode)(INT16* buffer, INT16* dwt_buffer); void (*dwt_2d_encode)(INT16* buffer, INT16* dwt_buffer); - int (*rlgr_decode)(RLGR_MODE mode, const BYTE* data, int data_size, INT16* buffer, int buffer_size); - int (*rlgr_encode)(RLGR_MODE mode, const INT16* data, int data_size, BYTE* buffer, int buffer_size); /* private definitions */ RFX_CONTEXT_PRIV* priv; @@ -159,6 +157,8 @@ FREERDP_API void rfx_context_free(RFX_CONTEXT* context); FREERDP_API void rfx_context_set_pixel_format(RFX_CONTEXT* context, RDP_PIXEL_FORMAT pixel_format); FREERDP_API void rfx_context_reset(RFX_CONTEXT* context); +FREERDP_API int rfx_rlgr_decode(const BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 DstSize, int mode); + FREERDP_API RFX_MESSAGE* rfx_process_message(RFX_CONTEXT* context, BYTE* data, UINT32 length); FREERDP_API UINT16 rfx_message_get_tile_count(RFX_MESSAGE* message); FREERDP_API RFX_TILE* rfx_message_get_tile(RFX_MESSAGE* message, int index); diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index f207a53e3..558eaeef3 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -72,430 +72,6 @@ const char* progressive_get_block_type_string(UINT16 blockType) return "PROGRESSIVE_WBT_UNKNOWN"; } -/* Constants used in RLGR1/RLGR3 algorithm */ -#define KPMAX (80) /* max value for kp or krp */ -#define LSGR (3) /* shift count to convert kp to k */ -#define UP_GR (4) /* increase in kp after a zero run in RL mode */ -#define DN_GR (6) /* decrease in kp after a nonzero symbol in RL mode */ -#define UQ_GR (3) /* increase in kp after nonzero symbol in GR mode */ -#define DQ_GR (3) /* decrease in kp after zero symbol in GR mode */ - -int rfx_rlgrx_decode(BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 DstSize, int mode) -{ - int vk; - int run; - int cnt; - int size; - int nbits; - int offset; - INT16 mag; - int k, kp; - int kr, krp; - UINT16 code; - UINT32 sign; - UINT32 nIdx; - UINT32 val1; - UINT32 val2; - INT16* pOutput; - wBitStream* bs; - wBitStream s_bs; - - k = 1; - kp = k << LSGR; - - kr = 1; - krp = kr << LSGR; - - if ((mode != 1) && (mode != 3)) - mode = 1; - - if (!pSrcData || !SrcSize) - return -1; - - if (!pDstData || !DstSize) - return -1; - - pOutput = pDstData; - - bs = &s_bs; - - BitStream_Attach(bs, pSrcData, SrcSize); - BitStream_Fetch(bs); - - while ((BitStream_GetRemainingLength(bs) > 0) && ((pOutput - pDstData) < DstSize)) - { - if (k) - { - /* Run-Length (RL) Mode */ - - run = 0; - - /* count number of leading 0s */ - - cnt = __lzcnt(bs->accumulator); - - nbits = BitStream_GetRemainingLength(bs); - - if (cnt > nbits) - cnt = nbits; - - vk = cnt; - - while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0)) - { - BitStream_Shift32(bs); - - cnt = __lzcnt(bs->accumulator); - - nbits = BitStream_GetRemainingLength(bs); - - if (cnt > nbits) - cnt = nbits; - - vk += cnt; - } - - BitStream_Shift(bs, (vk % 32)); - - if (BitStream_GetRemainingLength(bs) < 1) - break; - - BitStream_Shift(bs, 1); - - while (vk--) - { - run += (1 << k); /* add (1 << k) to run length */ - - /* update k, kp params */ - - kp += UP_GR; - - if (kp > KPMAX) - kp = KPMAX; - - k = kp >> LSGR; - } - - /* next k bits contain run length remainder */ - - if (BitStream_GetRemainingLength(bs) < k) - break; - - bs->mask = ((1 << k) - 1); - run += ((bs->accumulator >> (32 - k)) & bs->mask); - BitStream_Shift(bs, k); - - /* read sign bit */ - - if (BitStream_GetRemainingLength(bs) < 1) - break; - - sign = (bs->accumulator & 0x80000000) ? 1 : 0; - BitStream_Shift(bs, 1); - - /* count number of leading 1s */ - - cnt = __lzcnt(~(bs->accumulator)); - - nbits = BitStream_GetRemainingLength(bs); - - if (cnt > nbits) - cnt = nbits; - - vk = cnt; - - while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0)) - { - BitStream_Shift32(bs); - - cnt = __lzcnt(~(bs->accumulator)); - - nbits = BitStream_GetRemainingLength(bs); - - if (cnt > nbits) - cnt = nbits; - - vk += cnt; - } - - BitStream_Shift(bs, (vk % 32)); - - if (BitStream_GetRemainingLength(bs) < 1) - break; - - BitStream_Shift(bs, 1); - - /* next kr bits contain code remainder */ - - if (BitStream_GetRemainingLength(bs) < kr) - break; - - bs->mask = ((1 << kr) - 1); - code = (UINT16) ((bs->accumulator >> (32 - kr)) & bs->mask); - BitStream_Shift(bs, kr); - - /* add (vk << kr) to code */ - - code |= (vk << kr); - - if (!vk) - { - /* update kr, krp params */ - - krp -= 2; - - if (krp < 0) - krp = 0; - - kr = krp >> LSGR; - } - else if (vk != 1) - { - /* update kr, krp params */ - - krp += vk; - - if (krp > KPMAX) - krp = KPMAX; - - kr = krp >> LSGR; - } - - /* update k, kp params */ - - kp -= DN_GR; - - if (kp < 0) - kp = 0; - - k = kp >> LSGR; - - /* compute magnitude from code */ - - if (sign) - mag = ((INT16) (code + 1)) * -1; - else - mag = (INT16) (code + 1); - - /* write to output stream */ - - offset = (int) (pOutput - pDstData); - size = run; - - if ((offset + size) > DstSize) - size = DstSize - offset; - - if (size) - { - ZeroMemory(pOutput, size * sizeof(INT16)); - pOutput += size; - } - - if ((pOutput - pDstData) < DstSize) - { - *pOutput = mag; - pOutput++; - } - } - else - { - /* Golomb-Rice (GR) Mode */ - - /* count number of leading 1s */ - - cnt = __lzcnt(~(bs->accumulator)); - - nbits = BitStream_GetRemainingLength(bs); - - if (cnt > nbits) - cnt = nbits; - - vk = cnt; - - while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0)) - { - BitStream_Shift32(bs); - - cnt = __lzcnt(~(bs->accumulator)); - - nbits = BitStream_GetRemainingLength(bs); - - if (cnt > nbits) - cnt = nbits; - - vk += cnt; - } - - BitStream_Shift(bs, (vk % 32)); - - if (BitStream_GetRemainingLength(bs) < 1) - break; - - BitStream_Shift(bs, 1); - - /* next kr bits contain code remainder */ - - if (BitStream_GetRemainingLength(bs) < kr) - break; - - bs->mask = ((1 << kr) - 1); - code = (UINT16) ((bs->accumulator >> (32 - kr)) & bs->mask); - BitStream_Shift(bs, kr); - - /* add (vk << kr) to code */ - - code |= (vk << kr); - - if (!vk) - { - /* update kr, krp params */ - - krp -= 2; - - if (krp < 0) - krp = 0; - - kr = krp >> LSGR; - } - else if (vk != 1) - { - /* update kr, krp params */ - - krp += vk; - - if (krp > KPMAX) - krp = KPMAX; - - kr = krp >> LSGR; - } - - if (mode == 1) /* RLGR1 */ - { - if (!code) - { - /* update k, kp params */ - - kp += UQ_GR; - - if (kp > KPMAX) - kp = KPMAX; - - k = kp >> LSGR; - - mag = 0; - } - else - { - /* update k, kp params */ - - kp -= DQ_GR; - - if (kp < 0) - kp = 0; - - k = kp >> LSGR; - - /* - * code = 2 * mag - sign - * sign + code = 2 * mag - */ - - if (code & 1) - mag = ((INT16) ((code + 1) >> 1)) * -1; - else - mag = (INT16) (code >> 1); - } - - if ((pOutput - pDstData) < DstSize) - { - *pOutput = mag; - pOutput++; - } - } - else if (mode == 3) /* RLGR3 */ - { - nIdx = 0; - - if (code) - { - mag = (UINT32) code; - nIdx = 32 - __lzcnt(mag); - } - - if (BitStream_GetRemainingLength(bs) < nIdx) - break; - - bs->mask = ((1 << nIdx) - 1); - val1 = ((bs->accumulator >> (32 - nIdx)) & bs->mask); - BitStream_Shift(bs, nIdx); - - val2 = code - val1; - - if (val1 && val2) - { - /* update k, kp params */ - - kp -= (2 * DQ_GR); - - if (kp < 0) - kp = 0; - - k = kp >> LSGR; - } - else if (!val1 && !val2) - { - /* update k, kp params */ - - kp += (2 * UQ_GR); - - if (kp > KPMAX) - kp = KPMAX; - - k = kp >> LSGR; - } - - if (val1 & 1) - mag = ((INT16) ((val1 + 1) >> 1)) * -1; - else - mag = (INT16) (val1 >> 1); - - if ((pOutput - pDstData) < DstSize) - { - *pOutput = mag; - pOutput++; - } - - if (val2 & 1) - mag = ((INT16) ((val2 + 1) >> 1)) * -1; - else - mag = (INT16) (val2 >> 1); - - if ((pOutput - pDstData) < DstSize) - { - *pOutput = mag; - pOutput++; - } - } - } - } - - offset = (int) (pOutput - pDstData); - - if (offset < DstSize) - { - size = DstSize - offset; - ZeroMemory(pOutput, size * 2); - pOutput += size; - } - - offset = (int) (pOutput - pDstData); - - if (offset != DstSize) - return -1; - - return 1; -} - int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) { PROGRESSIVE_BLOCK_REGION* region; diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c index 9d8403510..1fa7c0034 100644 --- a/libfreerdp/codec/rfx.c +++ b/libfreerdp/codec/rfx.c @@ -330,8 +330,6 @@ RFX_CONTEXT* rfx_context_new(BOOL encoder) context->quantization_encode = rfx_quantization_encode; context->dwt_2d_decode = rfx_dwt_2d_decode; context->dwt_2d_encode = rfx_dwt_2d_encode; - context->rlgr_decode = rfx_rlgr_decode; - context->rlgr_encode = rfx_rlgr_encode; RFX_INIT_SIMD(context); diff --git a/libfreerdp/codec/rfx_decode.c b/libfreerdp/codec/rfx_decode.c index 3d027a393..d3baf5462 100644 --- a/libfreerdp/codec/rfx_decode.c +++ b/libfreerdp/codec/rfx_decode.c @@ -103,7 +103,7 @@ static void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantizatio PROFILER_ENTER(context->priv->prof_rfx_decode_component); PROFILER_ENTER(context->priv->prof_rfx_rlgr_decode); - context->rlgr_decode(context->mode, data, size, buffer, 4096); + rfx_rlgr_decode(data, size, buffer, 4096, (context->mode == RLGR1) ? 1 : 3); PROFILER_EXIT(context->priv->prof_rfx_rlgr_decode); PROFILER_ENTER(context->priv->prof_rfx_differential_decode); diff --git a/libfreerdp/codec/rfx_encode.c b/libfreerdp/codec/rfx_encode.c index 5dd10e29f..f929846cf 100644 --- a/libfreerdp/codec/rfx_encode.c +++ b/libfreerdp/codec/rfx_encode.c @@ -209,7 +209,7 @@ static void rfx_encode_component(RFX_CONTEXT* context, const UINT32* quantizatio PROFILER_EXIT(context->priv->prof_rfx_differential_encode); PROFILER_ENTER(context->priv->prof_rfx_rlgr_encode); - *size = context->rlgr_encode(context->mode, data, 4096, buffer, buffer_size); + *size = rfx_rlgr_encode(context->mode, data, 4096, buffer, buffer_size); PROFILER_EXIT(context->priv->prof_rfx_rlgr_encode); PROFILER_EXIT(context->priv->prof_rfx_encode_component); diff --git a/libfreerdp/codec/rfx_rlgr.c b/libfreerdp/codec/rfx_rlgr.c index e6a1c2e1a..1571dec20 100644 --- a/libfreerdp/codec/rfx_rlgr.c +++ b/libfreerdp/codec/rfx_rlgr.c @@ -31,43 +31,20 @@ #include #include +#include +#include #include "rfx_bitstream.h" #include "rfx_rlgr.h" -/* Constants used within the RLGR1/RLGR3 algorithm */ -#define KPMAX (80) /* max value for kp or krp */ -#define LSGR (3) /* shift count to convert kp to k */ -#define UP_GR (4) /* increase in kp after a zero run in RL mode */ -#define DN_GR (6) /* decrease in kp after a nonzero symbol in RL mode */ -#define UQ_GR (3) /* increase in kp after nonzero symbol in GR mode */ -#define DQ_GR (3) /* decrease in kp after zero symbol in GR mode */ - -/* Gets (returns) the next nBits from the bitstream */ -#define GetBits(nBits, r) rfx_bitstream_get_bits(bs, nBits, r) - -/* From current output pointer, write "value", check and update buffer_size */ -#define WriteValue(value) \ -{ \ - if (buffer_size > 0) \ - *dst++ = (value); \ - buffer_size--; \ -} - -/* From current output pointer, write next nZeroes terms with value 0, check and update buffer_size */ -#define WriteZeroes(nZeroes) \ -{ \ - int nZeroesWritten = (nZeroes); \ - if (nZeroesWritten > buffer_size) \ - nZeroesWritten = buffer_size; \ - if (nZeroesWritten > 0) \ - { \ - memset(dst, 0, nZeroesWritten * sizeof(INT16)); \ - dst += nZeroesWritten; \ - } \ - buffer_size -= (nZeroes); \ -} +/* Constants used in RLGR1/RLGR3 algorithm */ +#define KPMAX (80) /* max value for kp or krp */ +#define LSGR (3) /* shift count to convert kp to k */ +#define UP_GR (4) /* increase in kp after a zero run in RL mode */ +#define DN_GR (6) /* decrease in kp after a nonzero symbol in RL mode */ +#define UQ_GR (3) /* increase in kp after nonzero symbol in GR mode */ +#define DQ_GR (3) /* decrease in kp after zero symbol in GR mode */ /* Returns the least number of bits required to represent a given value */ #define GetMinBits(_val, _nbits) \ @@ -81,9 +58,6 @@ } \ } -/* Converts from (2 * magnitude - sign) to integer */ -#define GetIntFrom2MagSign(twoMs) (((twoMs) & 1) ? -1 * (INT16)(((twoMs) + 1) >> 1) : (INT16)((twoMs) >> 1)) - /* * Update the passed parameter and clamp it to the range [0, KPMAX] * Return the value of parameter right-shifted by LSGR @@ -98,147 +72,420 @@ _k = (_param >> LSGR); \ } -/* Outputs the Golomb/Rice encoding of a non-negative integer */ -#define GetGRCode(krp, kr, vk, _mag) \ - vk = 0; \ - _mag = 0; \ - /* chew up/count leading 1s and escape 0 */ \ - do { \ - GetBits(1, r); \ - if (r == 1) \ - vk++; \ - else \ - break; \ - } while (1); \ - /* get next *kr bits, and combine with leading 1s */ \ - GetBits(*kr, _mag); \ - _mag |= (vk << *kr); \ - /* adjust krp and kr based on vk */ \ - if (!vk) { \ - UpdateParam(*krp, -2, *kr); \ - } \ - else if (vk != 1) { \ - UpdateParam(*krp, vk, *kr); /* at 1, no change! */ \ - } - -int rfx_rlgr_decode(RLGR_MODE mode, const BYTE* data, int data_size, INT16* buffer, int buffer_size) +int rfx_rlgr_decode(const BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 DstSize, int mode) { - int k; - int kp; - int kr; - int krp; - UINT16 r; - INT16* dst; - RFX_BITSTREAM* bs; - int vk; - UINT16 mag16; + int run; + int cnt; + int size; + int nbits; + int offset; + INT16 mag; + int k, kp; + int kr, krp; + UINT16 code; + UINT32 sign; + UINT32 nIdx; + UINT32 val1; + UINT32 val2; + INT16* pOutput; + wBitStream* bs; + wBitStream s_bs; - bs = (RFX_BITSTREAM*) malloc(sizeof(RFX_BITSTREAM)); - ZeroMemory(bs, sizeof(RFX_BITSTREAM)); - - rfx_bitstream_attach(bs, data, data_size); - dst = buffer; - - /* initialize the parameters */ k = 1; kp = k << LSGR; + kr = 1; krp = kr << LSGR; - while (!rfx_bitstream_eos(bs) && buffer_size > 0) + if ((mode != 1) && (mode != 3)) + mode = 1; + + if (!pSrcData || !SrcSize) + return -1; + + if (!pDstData || !DstSize) + return -1; + + pOutput = pDstData; + + bs = &s_bs; + + BitStream_Attach(bs, pSrcData, SrcSize); + BitStream_Fetch(bs); + + while ((BitStream_GetRemainingLength(bs) > 0) && ((pOutput - pDstData) < DstSize)) { - int run; if (k) { - int mag; - UINT32 sign; + /* Run-Length (RL) Mode */ - /* RL MODE */ - while (!rfx_bitstream_eos(bs)) + run = 0; + + /* count number of leading 0s */ + + cnt = __lzcnt(bs->accumulator); + + nbits = BitStream_GetRemainingLength(bs); + + if (cnt > nbits) + cnt = nbits; + + vk = cnt; + + while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0)) { - GetBits(1, r); - if (r) - break; - /* we have an RL escape "0", which translates to a run (1<accumulator); + + nbits = BitStream_GetRemainingLength(bs); + + if (cnt > nbits) + cnt = nbits; + + vk += cnt; } - /* next k bits will contain remaining run or zeros */ - GetBits(k, run); - WriteZeroes(run); + BitStream_Shift(bs, (vk % 32)); - /* get nonzero value, starting with sign bit and then GRCode for magnitude -1 */ - GetBits(1, sign); + if (BitStream_GetRemainingLength(bs) < 1) + break; - /* magnitude - 1 was coded (because it was nonzero) */ - GetGRCode(&krp, &kr, vk, mag16) - mag = (int) (mag16 + 1); + BitStream_Shift(bs, 1); - WriteValue(sign ? -mag : mag); - UpdateParam(kp, -DN_GR, k); /* lower k and kp because of nonzero term */ + while (vk--) + { + run += (1 << k); /* add (1 << k) to run length */ + + /* update k, kp params */ + + kp += UP_GR; + + if (kp > KPMAX) + kp = KPMAX; + + k = kp >> LSGR; + } + + /* next k bits contain run length remainder */ + + if (BitStream_GetRemainingLength(bs) < k) + break; + + bs->mask = ((1 << k) - 1); + run += ((bs->accumulator >> (32 - k)) & bs->mask); + BitStream_Shift(bs, k); + + /* read sign bit */ + + if (BitStream_GetRemainingLength(bs) < 1) + break; + + sign = (bs->accumulator & 0x80000000) ? 1 : 0; + BitStream_Shift(bs, 1); + + /* count number of leading 1s */ + + cnt = __lzcnt(~(bs->accumulator)); + + nbits = BitStream_GetRemainingLength(bs); + + if (cnt > nbits) + cnt = nbits; + + vk = cnt; + + while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0)) + { + BitStream_Shift32(bs); + + cnt = __lzcnt(~(bs->accumulator)); + + nbits = BitStream_GetRemainingLength(bs); + + if (cnt > nbits) + cnt = nbits; + + vk += cnt; + } + + BitStream_Shift(bs, (vk % 32)); + + if (BitStream_GetRemainingLength(bs) < 1) + break; + + BitStream_Shift(bs, 1); + + /* next kr bits contain code remainder */ + + if (BitStream_GetRemainingLength(bs) < kr) + break; + + bs->mask = ((1 << kr) - 1); + code = (UINT16) ((bs->accumulator >> (32 - kr)) & bs->mask); + BitStream_Shift(bs, kr); + + /* add (vk << kr) to code */ + + code |= (vk << kr); + + if (!vk) + { + /* update kr, krp params */ + + krp -= 2; + + if (krp < 0) + krp = 0; + + kr = krp >> LSGR; + } + else if (vk != 1) + { + /* update kr, krp params */ + + krp += vk; + + if (krp > KPMAX) + krp = KPMAX; + + kr = krp >> LSGR; + } + + /* update k, kp params */ + + kp -= DN_GR; + + if (kp < 0) + kp = 0; + + k = kp >> LSGR; + + /* compute magnitude from code */ + + if (sign) + mag = ((INT16) (code + 1)) * -1; + else + mag = (INT16) (code + 1); + + /* write to output stream */ + + offset = (int) (pOutput - pDstData); + size = run; + + if ((offset + size) > DstSize) + size = DstSize - offset; + + if (size) + { + ZeroMemory(pOutput, size * sizeof(INT16)); + pOutput += size; + } + + if ((pOutput - pDstData) < DstSize) + { + *pOutput = mag; + pOutput++; + } } else { - UINT32 mag; - UINT32 nIdx; - UINT32 val1; - UINT32 val2; + /* Golomb-Rice (GR) Mode */ - /* GR (GOLOMB-RICE) MODE */ - GetGRCode(&krp, &kr, vk, mag16) /* values coded are 2 * magnitude - sign */ - mag = (UINT32) mag16; + /* count number of leading 1s */ - if (mode == RLGR1) + cnt = __lzcnt(~(bs->accumulator)); + + nbits = BitStream_GetRemainingLength(bs); + + if (cnt > nbits) + cnt = nbits; + + vk = cnt; + + while ((cnt == 32) && (BitStream_GetRemainingLength(bs) > 0)) { - if (!mag) + BitStream_Shift32(bs); + + cnt = __lzcnt(~(bs->accumulator)); + + nbits = BitStream_GetRemainingLength(bs); + + if (cnt > nbits) + cnt = nbits; + + vk += cnt; + } + + BitStream_Shift(bs, (vk % 32)); + + if (BitStream_GetRemainingLength(bs) < 1) + break; + + BitStream_Shift(bs, 1); + + /* next kr bits contain code remainder */ + + if (BitStream_GetRemainingLength(bs) < kr) + break; + + bs->mask = ((1 << kr) - 1); + code = (UINT16) ((bs->accumulator >> (32 - kr)) & bs->mask); + BitStream_Shift(bs, kr); + + /* add (vk << kr) to code */ + + code |= (vk << kr); + + if (!vk) + { + /* update kr, krp params */ + + krp -= 2; + + if (krp < 0) + krp = 0; + + kr = krp >> LSGR; + } + else if (vk != 1) + { + /* update kr, krp params */ + + krp += vk; + + if (krp > KPMAX) + krp = KPMAX; + + kr = krp >> LSGR; + } + + if (mode == 1) /* RLGR1 */ + { + if (!code) { - WriteValue(0); - UpdateParam(kp, UQ_GR, k); /* raise k and kp due to zero */ + /* update k, kp params */ + + kp += UQ_GR; + + if (kp > KPMAX) + kp = KPMAX; + + k = kp >> LSGR; + + mag = 0; } else { - WriteValue(GetIntFrom2MagSign(mag)); - UpdateParam(kp, -DQ_GR, k); /* lower k and kp due to nonzero */ + /* update k, kp params */ + + kp -= DQ_GR; + + if (kp < 0) + kp = 0; + + k = kp >> LSGR; + + /* + * code = 2 * mag - sign + * sign + code = 2 * mag + */ + + if (code & 1) + mag = ((INT16) ((code + 1) >> 1)) * -1; + else + mag = (INT16) (code >> 1); + } + + if ((pOutput - pDstData) < DstSize) + { + *pOutput = mag; + pOutput++; } } - else /* mode == RLGR3 */ + else if (mode == 3) /* RLGR3 */ { - /* - * In GR mode FOR RLGR3, we have encoded the - * sum of two (2 * mag - sign) values - */ + nIdx = 0; - /* maximum possible bits for first term */ - GetMinBits(mag, nIdx); + if (code) + { + mag = (UINT32) code; + nIdx = 32 - __lzcnt(mag); + } - /* decode val1 is first term's (2 * mag - sign) value */ - GetBits(nIdx, val1); + if (BitStream_GetRemainingLength(bs) < nIdx) + break; - /* val2 is second term's (2 * mag - sign) value */ - val2 = mag - val1; + bs->mask = ((1 << nIdx) - 1); + val1 = ((bs->accumulator >> (32 - nIdx)) & bs->mask); + BitStream_Shift(bs, nIdx); + + val2 = code - val1; if (val1 && val2) { - /* raise k and kp if both terms nonzero */ - UpdateParam(kp, -2 * DQ_GR, k); + /* update k, kp params */ + + kp -= (2 * DQ_GR); + + if (kp < 0) + kp = 0; + + k = kp >> LSGR; } else if (!val1 && !val2) { - /* lower k and kp if both terms zero */ - UpdateParam(kp, 2 * UQ_GR, k); + /* update k, kp params */ + + kp += (2 * UQ_GR); + + if (kp > KPMAX) + kp = KPMAX; + + k = kp >> LSGR; } - WriteValue(GetIntFrom2MagSign(val1)); - WriteValue(GetIntFrom2MagSign(val2)); + if (val1 & 1) + mag = ((INT16) ((val1 + 1) >> 1)) * -1; + else + mag = (INT16) (val1 >> 1); + + if ((pOutput - pDstData) < DstSize) + { + *pOutput = mag; + pOutput++; + } + + if (val2 & 1) + mag = ((INT16) ((val2 + 1) >> 1)) * -1; + else + mag = (INT16) (val2 >> 1); + + if ((pOutput - pDstData) < DstSize) + { + *pOutput = mag; + pOutput++; + } } } } - free(bs); + offset = (int) (pOutput - pDstData); - return (dst - buffer); + if (offset < DstSize) + { + size = DstSize - offset; + ZeroMemory(pOutput, size * 2); + pOutput += size; + } + + offset = (int) (pOutput - pDstData); + + if (offset != DstSize) + return -1; + + return 1; } /* Returns the next coefficient (a signed int) to encode, from the input stream */ diff --git a/libfreerdp/codec/rfx_rlgr.h b/libfreerdp/codec/rfx_rlgr.h index 07fa895f6..25b16cf43 100644 --- a/libfreerdp/codec/rfx_rlgr.h +++ b/libfreerdp/codec/rfx_rlgr.h @@ -22,7 +22,6 @@ #include -int rfx_rlgr_decode(RLGR_MODE mode, const BYTE* data, int data_size, INT16* buffer, int buffer_size); int rfx_rlgr_encode(RLGR_MODE mode, const INT16* data, int data_size, BYTE* buffer, int buffer_size); #endif /* __RFX_RLGR_H */ diff --git a/winpr/include/winpr/bitstream.h b/winpr/include/winpr/bitstream.h index 092917322..c67d58e38 100644 --- a/winpr/include/winpr/bitstream.h +++ b/winpr/include/winpr/bitstream.h @@ -27,7 +27,7 @@ struct _wBitStream { - BYTE* buffer; + const BYTE* buffer; BYTE* pointer; int position; int length; @@ -140,7 +140,7 @@ extern "C" { WINPR_API void BitDump(const BYTE* buffer, UINT32 length, UINT32 flags); WINPR_API UINT32 ReverseBits32(UINT32 bits, UINT32 nbits); -WINPR_API void BitStream_Attach(wBitStream* bs, BYTE* buffer, UINT32 capacity); +WINPR_API void BitStream_Attach(wBitStream* bs, const BYTE* buffer, UINT32 capacity); WINPR_API wBitStream* BitStream_New(); WINPR_API void BitStream_Free(wBitStream* bs); diff --git a/winpr/libwinpr/utils/collections/BitStream.c b/winpr/libwinpr/utils/collections/BitStream.c index 5604a5e20..ebe47f282 100644 --- a/winpr/libwinpr/utils/collections/BitStream.c +++ b/winpr/libwinpr/utils/collections/BitStream.c @@ -316,13 +316,13 @@ void BitStream_Write_Bits(wBitStream* bs, UINT32 bits, UINT32 nbits) #endif -void BitStream_Attach(wBitStream* bs, BYTE* buffer, UINT32 capacity) +void BitStream_Attach(wBitStream* bs, const BYTE* buffer, UINT32 capacity) { bs->position = 0; bs->buffer = buffer; bs->offset = 0; bs->accumulator = 0; - bs->pointer = bs->buffer; + bs->pointer = (BYTE*) bs->buffer; bs->capacity = capacity; bs->length = bs->capacity * 8; } From 2653c5420f2524971f644c30038ea327b75a7f26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 6 Aug 2014 10:23:14 -0400 Subject: [PATCH 12/12] libfreerdp-codec: start processing tiles in progressive rfx --- include/freerdp/codec/progressive.h | 4 ++++ libfreerdp/codec/progressive.c | 30 +++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index a86ebdd4c..e22ab10fc 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -23,6 +23,8 @@ #include #include +#include + #include #include @@ -247,6 +249,8 @@ struct _PROGRESSIVE_CONTEXT { BOOL Compressor; + wBufferPool* bufferPool; + UINT32 cRects; RFX_RECT* rects; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 558eaeef3..24d9493eb 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -72,8 +72,23 @@ const char* progressive_get_block_type_string(UINT16 blockType) return "PROGRESSIVE_WBT_UNKNOWN"; } +int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, + RFX_COMPONENT_CODEC_QUANT* quant, const BYTE* data, int length, INT16* buffer) +{ + int status; + + status = rfx_rlgr_decode(data, length, buffer, 4096, 1); + + if (status < 0) + return status; + + return 1; +} + int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) { + BYTE* pBuffer; + INT16* pSrcDst[3]; PROGRESSIVE_BLOCK_REGION* region; RFX_COMPONENT_CODEC_QUANT* quantY; RFX_COMPONENT_CODEC_QUANT* quantCb; @@ -112,6 +127,17 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG quantProgVal = &(region->quantProgVals[tile->quality]); } + pBuffer = (BYTE*) BufferPool_Take(progressive->bufferPool, -1); + pSrcDst[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ + pSrcDst[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ + pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */ + + progressive_rfx_decode_component(progressive, quantY, tile->yData, tile->yLen, pSrcDst[0]); /* Y */ + progressive_rfx_decode_component(progressive, quantCb, tile->cbData, tile->cbLen, pSrcDst[1]); /* Cb */ + progressive_rfx_decode_component(progressive, quantCr, tile->crData, tile->crLen, pSrcDst[2]); /* Cr */ + + BufferPool_Return(progressive->bufferPool, pBuffer); + return 1; } @@ -654,6 +680,8 @@ PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor) { progressive->Compressor = Compressor; + progressive->bufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16); + progressive->cRects = 64; progressive->rects = (RFX_RECT*) malloc(progressive->cRects * sizeof(RFX_RECT)); @@ -692,6 +720,8 @@ void progressive_context_free(PROGRESSIVE_CONTEXT* progressive) if (!progressive) return; + BufferPool_Free(progressive->bufferPool); + free(progressive->rects); free(progressive->tiles); free(progressive->quantVals);