libfreerdp-codec: fix ClearCodec decoding

This commit is contained in:
Marc-André Moreau 2014-06-13 17:30:13 -04:00
parent 0e27f5abe4
commit 61eb7f2f8e
6 changed files with 151 additions and 56 deletions

View File

@ -985,45 +985,54 @@ void xf_process_channel_event(rdpChannels *channels, freerdp *instance)
void xf_window_free(xfContext *xfc)
{
rdpContext *context = (rdpContext *) xfc;
rdpContext* context = (rdpContext*) xfc;
xf_keyboard_free(xfc);
if(xfc->gc)
if (xfc->gc)
{
XFreeGC(xfc->display, xfc->gc);
xfc->gc = 0;
}
if(xfc->gc_mono)
if (xfc->gc_mono)
{
XFreeGC(xfc->display, xfc->gc_mono);
xfc->gc_mono = 0;
}
if(xfc->window)
if (xfc->window)
{
xf_DestroyWindow(xfc, xfc->window);
xfc->window = NULL;
}
if(xfc->primary)
if (xfc->primary)
{
XFreePixmap(xfc->display, xfc->primary);
xfc->primary = 0;
}
if(xfc->bitmap_mono)
if (xfc->bitmap_mono)
{
XFreePixmap(xfc->display, xfc->bitmap_mono);
xfc->bitmap_mono = 0;
}
if(xfc->image)
if (xfc->image)
{
xfc->image->data = NULL;
XDestroyImage(xfc->image);
xfc->image = NULL;
}
if(context->cache)
if (context->cache)
{
cache_free(context->cache);
context->cache = NULL;
}
if(context->rail)
if (context->rail)
{
rail_free(context->rail);
context->rail = NULL;
@ -1040,26 +1049,38 @@ void xf_window_free(xfContext *xfc)
nsc_context_free(xfc->nsc);
xfc->nsc = NULL;
}
if(xfc->clrconv)
if (xfc->clear)
{
clear_context_free(xfc->clear);
xfc->clear = NULL;
}
if (xfc->clrconv)
{
freerdp_clrconv_free(xfc->clrconv);
xfc->clrconv = NULL;
}
if(xfc->hdc)
if (xfc->hdc)
{
gdi_DeleteDC(xfc->hdc);
if(xfc->xv_context)
}
if (xfc->xv_context)
{
xf_tsmf_uninit(xfc);
xfc->xv_context = NULL;
}
if(xfc->clipboard_context)
if (xfc->clipboard_context)
{
xf_cliprdr_uninit(xfc);
xfc->clipboard_context = NULL;
}
}
void *xf_update_thread(void *arg)
void* xf_update_thread(void *arg)
{
int status;
wMessage message;

View File

@ -54,6 +54,8 @@ int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* re
xfc->nsc->height = resetGraphics->height;
nsc_context_set_pixel_format(xfc->nsc, RDP_PIXEL_FORMAT_B8G8R8A8);
xfc->clear = clear_context_new(FALSE);
region16_init(&(xfc->invalidRegion));
xfc->graphicsReset = TRUE;
@ -256,6 +258,33 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP
int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int status;
UINT32 DstSize = 0;
BYTE* pDstData = NULL;
xfGfxSurface* surface;
RECTANGLE_16 invalidRect;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
if (!surface)
return -1;
status = clear_decompress(xfc->clear, cmd->data, cmd->length, &pDstData, &DstSize);
printf("xf_SurfaceCommand_ClearCodec: status: %d\n", status);
/* fill with pink for now to distinguish from the rest */
freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline,
cmd->left, cmd->top, cmd->width, cmd->height, 0xFF69B4);
invalidRect.left = cmd->left;
invalidRect.top = cmd->top;
invalidRect.right = cmd->right;
invalidRect.bottom = cmd->bottom;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
@ -286,7 +315,6 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
break;
case RDPGFX_CODECID_CLEARCODEC:
printf("xf_SurfaceCommand_ClearCodec\n");
status = xf_SurfaceCommand_ClearCodec(xfc, context, cmd);
break;
@ -482,8 +510,8 @@ int xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU*
surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToCache->surfaceId);
printf("xf_SurfaceToCache: cacheKey: 0x%016X cacheSlot: %ld\n",
surfaceToCache->cacheKey, surfaceToCache->cacheSlot);
//printf("xf_SurfaceToCache: cacheKey: 0x%016X cacheSlot: %ld\n",
// surfaceToCache->cacheKey, surfaceToCache->cacheSlot);
if (!surface)
return -1;
@ -524,8 +552,8 @@ int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU*
surface = (xfGfxSurface*) context->GetSurfaceData(context, cacheToSurface->surfaceId);
cacheEntry = (xfGfxCacheEntry*) context->GetCacheSlotData(context, cacheToSurface->cacheSlot);
printf("xf_CacheToSurface: cacheEntry: %d\n",
cacheToSurface->cacheSlot);
//printf("xf_CacheToSurface: cacheEntry: %d\n",
// cacheToSurface->cacheSlot);
if (!surface || !cacheEntry)
return -1;

View File

@ -31,7 +31,7 @@ typedef struct xf_context xfContext;
#include <freerdp/gdi/gdi.h>
#include <freerdp/codec/rfx.h>
#include <freerdp/codec/nsc.h>
#include <freerdp/constants.h>
#include <freerdp/codec/clear.h>
#include <freerdp/codec/color.h>
#include <freerdp/codec/bitmap.h>
#include <freerdp/codec/region.h>
@ -151,6 +151,7 @@ struct xf_context
BYTE* bmp_codec_nsc;
RFX_CONTEXT* rfx;
NSC_CONTEXT* nsc;
CLEAR_CONTEXT* clear;
void* xv_context;
void* clipboard_context;

View File

@ -30,6 +30,10 @@
struct _CLEAR_CONTEXT
{
BOOL Compressor;
UINT32 VBarStorageCursor;
void* VBarStorage[32768];
UINT32 ShortVBarStorageCursor;
void* ShortVBarStorage[16384];
};
typedef struct _CLEAR_CONTEXT CLEAR_CONTEXT;

View File

@ -29,6 +29,7 @@
int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize)
{
int index;
BYTE glyphFlags;
BYTE seqNumber;
UINT16 glyphIndex;
@ -38,7 +39,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
UINT32 subcodecByteCount;
if (SrcSize < 2)
return -1;
return -1001;
glyphFlags = pSrcData[0];
seqNumber = pSrcData[1];
@ -49,7 +50,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
if (glyphFlags & CLEARCODEC_FLAG_GLYPH_INDEX)
{
if (SrcSize < 4)
return -1;
return -1002;
glyphIndex = *((UINT16*) &pSrcData[2]);
offset += 2;
@ -68,7 +69,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
/* Read composition payload header parameters */
if ((SrcSize - offset) < 12)
return -1;
return -1003;
residualByteCount = *((UINT32*) &pSrcData[offset]);
bandsByteCount = *((UINT32*) &pSrcData[offset + 4]);
@ -91,7 +92,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
UINT32 runLengthFactor = 0;
if ((SrcSize - offset) < residualByteCount)
return -1;
return -1004;
suboffset = 0;
residualData = &pSrcData[offset];
@ -99,7 +100,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
while (suboffset < residualByteCount)
{
if ((residualByteCount - suboffset) < 4)
return -1;
return -1005;
blueValue = residualData[suboffset];
greenValue = residualData[suboffset + 1];
@ -113,7 +114,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
if (runLengthFactor1 >= 0xFF)
{
if ((residualByteCount - suboffset) < 2)
return -1;
return -1006;
runLengthFactor2 = *((UINT16*) &residualData[suboffset]);
runLengthFactor = runLengthFactor2;
@ -122,7 +123,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
if (runLengthFactor2 >= 0xFFFF)
{
if ((residualByteCount - suboffset) < 4)
return -1;
return -1007;
runLengthFactor3 = *((UINT32*) &residualData[suboffset]);
runLengthFactor = runLengthFactor3;
@ -141,7 +142,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
UINT32 suboffset;
if ((SrcSize - offset) < bandsByteCount)
return -1;
return -1008;
suboffset = 0;
bandsData = &pSrcData[offset];
@ -157,9 +158,14 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
BYTE redBkg;
BYTE* vBars;
UINT16 vBarHeader;
UINT16 vBarIndex;
UINT16 vBarYOn;
UINT16 vBarYOff;
int vBarCount;
int vBarPixelCount;
if ((bandsByteCount - suboffset) < 11)
return -1;
return -1009;
xStart = *((UINT16*) &bandsData[suboffset]);
xEnd = *((UINT16*) &bandsData[suboffset + 2]);
@ -170,31 +176,66 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
redBkg = bandsData[suboffset + 10];
suboffset += 11;
vBars = &bandsData[suboffset];
vBarCount = (xEnd - xStart) + 1;
vBarHeader = *((UINT16*) &vBars[0]);
printf("CLEARCODEC_BAND: xStart: %d xEnd: %d yStart: %d yEnd: %d vBarCount: %d blueBkg: 0x%02X greenBkg: 0x%02X redBkg: 0x%02X\n",
xStart, xEnd, yStart, yEnd, vBarCount, blueBkg, greenBkg, redBkg);
if ((vBarHeader & 0xC000) == 0x8000) /* VBAR_CACHE_HIT */
for (index = 0; index < vBarCount; index++)
{
printf("VBAR_CACHE_HIT\n");
vBars = &bandsData[suboffset];
if ((bandsByteCount - suboffset) < 2)
return -1010;
vBarHeader = *((UINT16*) &vBars[0]);
suboffset += 2;
}
else if ((vBarHeader & 0xC000) == 0xC000) /* SHORT_VBAR_CACHE_HIT */
{
printf("SHORT_VBAR_CACHE_HIT\n");
suboffset += 3;
}
else if ((vBarHeader & 0xC000) == 0) /* SHORT_VBAR_CACHE_MISS */
{
printf("SHORT_VBAR_CACHE_MISS\n");
suboffset += 2;
}
else
{
return -1; /* invalid vBarHeader */
}
/* shortVBarPixels: variable */
if ((vBarHeader & 0xC000) == 0x8000) /* VBAR_CACHE_HIT */
{
vBarIndex = (vBarHeader & 0x7FFF);
printf("VBAR_CACHE_HIT: vBarIndex: %d\n",
vBarIndex);
}
else if ((vBarHeader & 0xC000) == 0xC000) /* SHORT_VBAR_CACHE_HIT */
{
vBarIndex = (vBarHeader & 0x3FFF);
if ((bandsByteCount - suboffset) < 1)
return -1011;
vBarYOn = vBars[2];
suboffset += 1;
printf("SHORT_VBAR_CACHE_HIT: vBarIndex: %d vBarYOn: %d\n",
vBarIndex, vBarYOn);
}
else if ((vBarHeader & 0xC000) == 0x0000) /* SHORT_VBAR_CACHE_MISS */
{
vBarYOn = (vBarHeader & 0xFF);
vBarYOff = ((vBarHeader >> 8) & 0x3F);
if (vBarYOff < vBarYOn)
return -1012;
/* shortVBarPixels: variable */
vBarPixelCount = (3 * (vBarYOff - vBarYOn));
printf("SHORT_VBAR_CACHE_MISS: vBarYOn: %d vBarYOff: %d bytes: %d\n",
vBarYOn, vBarYOff, vBarPixelCount);
if ((bandsByteCount - suboffset) < vBarPixelCount)
return -1013;
suboffset += vBarPixelCount;
}
else
{
return -1014; /* invalid vBarHeader */
}
}
}
/* Decompress bands layer and write to output bitmap */
@ -214,7 +255,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
UINT32 suboffset;
if ((SrcSize - offset) < subcodecByteCount)
return -1;
return -1015;
suboffset = 0;
subcodecs = &pSrcData[offset];
@ -222,7 +263,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
while (suboffset < subcodecByteCount)
{
if ((subcodecByteCount - suboffset) < 13)
return -1;
return -1016;
xStart = *((UINT16*) &subcodecs[suboffset]);
yStart = *((UINT16*) &subcodecs[suboffset + 2]);
@ -232,11 +273,11 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE*
subcodecId = subcodecs[suboffset + 12];
suboffset += 13;
printf("bitmapDataByteCount: %d subcodecByteCount: %d suboffset: %d\n",
bitmapDataByteCount, subcodecByteCount, suboffset);
printf("bitmapDataByteCount: %d subcodecByteCount: %d suboffset: %d subCodecId: %d\n",
bitmapDataByteCount, subcodecByteCount, suboffset, subcodecId);
if ((subcodecByteCount - suboffset) < bitmapDataByteCount)
return -1;
return -1017;
bitmapData = &subcodecs[suboffset];

View File

@ -135,9 +135,9 @@ int TestFreeRDPCodecClear(int argc, char* argv[])
//test_ClearDecompressExample2();
test_ClearDecompressExample3();
//test_ClearDecompressExample3();
//test_ClearDecompressExample4();
test_ClearDecompressExample4();
return 0;
}