From 6744bbe7aee89595cb3e8ce64a07e3de075c5923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 18 Aug 2014 19:12:08 -0400 Subject: [PATCH 01/30] libfreerdp-codec: start working on progressive dequantization --- libfreerdp/codec/progressive.c | 39 +++++++++++++++++++++++++++++ libfreerdp/codec/rfx_quantization.c | 23 +++++++++++++++-- libfreerdp/codec/rfx_quantization.h | 2 ++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 24d9493eb..c9e3adf1d 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -25,9 +25,13 @@ #include #include +#include #include #include +#include "rfx_differential.h" +#include "rfx_quantization.h" + const char* progressive_get_block_type_string(UINT16 blockType) { switch (blockType) @@ -72,16 +76,51 @@ const char* progressive_get_block_type_string(UINT16 blockType) return "PROGRESSIVE_WBT_UNKNOWN"; } +/* + * Band Offset Dimensions Size + * + * HL1 0 31x33 1023 + * LH1 1023 33x31 1023 + * HH1 2046 31x31 961 + * + * HL2 3007 16x17 272 + * LH2 3279 17x16 272 + * HH2 3551 16x16 256 + * + * HL3 3807 8x9 72 + * LH3 3879 9x8 72 + * HH3 3951 8x8 64 + * + * LL3 4015 9x9 81 + */ + int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* quant, const BYTE* data, int length, INT16* buffer) { int status; + const primitives_t* prims = primitives_get(); status = rfx_rlgr_decode(data, length, buffer, 4096, 1); if (status < 0) return status; + rfx_differential_decode(&buffer[4015], 81); /* LL3 */ + + /* Scale the values so that they are represented as 11.5 fixed-point number */ + rfx_quantization_decode_block(prims, buffer, 4096, 5); + + rfx_quantization_decode_block(prims, &buffer[0], 1023, (quant->HL1 - 6)); /* HL1 */ + rfx_quantization_decode_block(prims, &buffer[1023], 1023, (quant->LH1 - 6)); /* LH1 */ + rfx_quantization_decode_block(prims, &buffer[2046], 961, (quant->HH1 - 6)); /* HH1 */ + rfx_quantization_decode_block(prims, &buffer[3007], 272, (quant->HL2 - 6)); /* HL2 */ + rfx_quantization_decode_block(prims, &buffer[3279], 272, (quant->LH2 - 6)); /* LH2 */ + rfx_quantization_decode_block(prims, &buffer[3551], 256, (quant->HH2 - 6)); /* HH2 */ + rfx_quantization_decode_block(prims, &buffer[3807], 72, (quant->HL3 - 6)); /* HL3 */ + rfx_quantization_decode_block(prims, &buffer[3879], 72, (quant->LH3 - 6)); /* LH3 */ + rfx_quantization_decode_block(prims, &buffer[3951], 64, (quant->HH3 - 6)); /* HH3 */ + rfx_quantization_decode_block(prims, &buffer[4015], 81, (quant->LL3 - 6)); /* LL3 */ + return 1; } diff --git a/libfreerdp/codec/rfx_quantization.c b/libfreerdp/codec/rfx_quantization.c index 2cedfd91d..b5c79e5f2 100644 --- a/libfreerdp/codec/rfx_quantization.c +++ b/libfreerdp/codec/rfx_quantization.c @@ -22,9 +22,28 @@ #endif #include + #include "rfx_quantization.h" -static void rfx_quantization_decode_block(const primitives_t *prims, INT16* buffer, int buffer_size, UINT32 factor) +/* + * Band Offset Size + * + * HL1 0 1024 + * LH1 1024 1024 + * HH1 2048 1024 + * + * HL2 3072 256 + * LH2 3328 256 + * HH2 3584 256 + * + * HL3 3840 64 + * LH3 3904 64 + * HH3 3968 64 + * + * LL3 4032 64 + */ + +void rfx_quantization_decode_block(const primitives_t *prims, INT16* buffer, int buffer_size, UINT32 factor) { if (factor == 0) return; @@ -34,7 +53,7 @@ static void rfx_quantization_decode_block(const primitives_t *prims, INT16* buff void rfx_quantization_decode(INT16* buffer, const UINT32* quantization_values) { - const primitives_t *prims = primitives_get(); + const primitives_t* prims = primitives_get(); /* Scale the values so that they are represented as 11.5 fixed-point number */ rfx_quantization_decode_block(prims, buffer, 4096, 5); diff --git a/libfreerdp/codec/rfx_quantization.h b/libfreerdp/codec/rfx_quantization.h index b10aa729f..e446a098a 100644 --- a/libfreerdp/codec/rfx_quantization.h +++ b/libfreerdp/codec/rfx_quantization.h @@ -25,4 +25,6 @@ void rfx_quantization_decode(INT16* buffer, const UINT32* quantization_values); void rfx_quantization_encode(INT16* buffer, const UINT32* quantization_values); +void rfx_quantization_decode_block(const primitives_t *prims, INT16* buffer, int buffer_size, UINT32 factor); + #endif /* __RFX_QUANTIZATION_H */ From 2e672d5bdbc09d6fa34005118ecf299cf39a9a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 18 Aug 2014 21:10:56 -0400 Subject: [PATCH 02/30] libfreerdp-codec: optimize RemoteFX dequantization and differentiation --- libfreerdp/codec/progressive.c | 23 ++++++-------- libfreerdp/codec/rfx_differential.c | 15 ++++----- libfreerdp/codec/rfx_differential.h | 4 +-- libfreerdp/codec/rfx_neon.c | 25 +++++++-------- libfreerdp/codec/rfx_quantization.c | 47 ++++++++++++++--------------- libfreerdp/codec/rfx_sse2.c | 24 +++++++-------- 6 files changed, 64 insertions(+), 74 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index c9e3adf1d..c36b29a8a 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -107,19 +107,16 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, rfx_differential_decode(&buffer[4015], 81); /* LL3 */ - /* Scale the values so that they are represented as 11.5 fixed-point number */ - rfx_quantization_decode_block(prims, buffer, 4096, 5); - - rfx_quantization_decode_block(prims, &buffer[0], 1023, (quant->HL1 - 6)); /* HL1 */ - rfx_quantization_decode_block(prims, &buffer[1023], 1023, (quant->LH1 - 6)); /* LH1 */ - rfx_quantization_decode_block(prims, &buffer[2046], 961, (quant->HH1 - 6)); /* HH1 */ - rfx_quantization_decode_block(prims, &buffer[3007], 272, (quant->HL2 - 6)); /* HL2 */ - rfx_quantization_decode_block(prims, &buffer[3279], 272, (quant->LH2 - 6)); /* LH2 */ - rfx_quantization_decode_block(prims, &buffer[3551], 256, (quant->HH2 - 6)); /* HH2 */ - rfx_quantization_decode_block(prims, &buffer[3807], 72, (quant->HL3 - 6)); /* HL3 */ - rfx_quantization_decode_block(prims, &buffer[3879], 72, (quant->LH3 - 6)); /* LH3 */ - rfx_quantization_decode_block(prims, &buffer[3951], 64, (quant->HH3 - 6)); /* HH3 */ - rfx_quantization_decode_block(prims, &buffer[4015], 81, (quant->LL3 - 6)); /* LL3 */ + rfx_quantization_decode_block(prims, &buffer[0], 1023, (quant->HL1 - 1)); /* HL1 */ + rfx_quantization_decode_block(prims, &buffer[1023], 1023, (quant->LH1 - 1)); /* LH1 */ + rfx_quantization_decode_block(prims, &buffer[2046], 961, (quant->HH1 - 1)); /* HH1 */ + rfx_quantization_decode_block(prims, &buffer[3007], 272, (quant->HL2 - 1)); /* HL2 */ + rfx_quantization_decode_block(prims, &buffer[3279], 272, (quant->LH2 - 1)); /* LH2 */ + rfx_quantization_decode_block(prims, &buffer[3551], 256, (quant->HH2 - 1)); /* HH2 */ + rfx_quantization_decode_block(prims, &buffer[3807], 72, (quant->HL3 - 1)); /* HL3 */ + rfx_quantization_decode_block(prims, &buffer[3879], 72, (quant->LH3 - 1)); /* LH3 */ + rfx_quantization_decode_block(prims, &buffer[3951], 64, (quant->HH3 - 1)); /* HH3 */ + rfx_quantization_decode_block(prims, &buffer[4015], 81, (quant->LL3 - 1)); /* LL3 */ return 1; } diff --git a/libfreerdp/codec/rfx_differential.c b/libfreerdp/codec/rfx_differential.c index e80aa98f3..4429fb8c0 100644 --- a/libfreerdp/codec/rfx_differential.c +++ b/libfreerdp/codec/rfx_differential.c @@ -27,23 +27,24 @@ #include "rfx_differential.h" -void rfx_differential_decode(INT16* buffer, int buffer_size) +void rfx_differential_decode(INT16* buffer, int size) { - INT16* src; - INT16* dst; + INT16* ptr = buffer; + INT16* end = &buffer[size - 1]; - for (src = buffer, dst = buffer + 1; buffer_size > 1; src++, dst++, buffer_size--) + while (ptr != end) { - *dst += *src; + ptr[1] += ptr[0]; + ptr++; } } -void rfx_differential_encode(INT16* buffer, int buffer_size) +void rfx_differential_encode(INT16* buffer, int size) { INT16 n1, n2; INT16* dst; - for (n1 = *buffer, dst = buffer + 1; buffer_size > 1; dst++, buffer_size--) + for (n1 = *buffer, dst = buffer + 1; size > 1; dst++, size--) { n2 = *dst; *dst -= n1; diff --git a/libfreerdp/codec/rfx_differential.h b/libfreerdp/codec/rfx_differential.h index 3f6dbf623..47e1a4241 100644 --- a/libfreerdp/codec/rfx_differential.h +++ b/libfreerdp/codec/rfx_differential.h @@ -22,7 +22,7 @@ #include -void rfx_differential_decode(INT16* buffer, int buffer_size); -void rfx_differential_encode(INT16* buffer, int buffer_size); +void rfx_differential_decode(INT16* buffer, int size); +void rfx_differential_encode(INT16* buffer, int size); #endif /* __RFX_DIFFERENTIAL_H */ diff --git a/libfreerdp/codec/rfx_neon.c b/libfreerdp/codec/rfx_neon.c index 6fe8ec83d..1632f983a 100644 --- a/libfreerdp/codec/rfx_neon.c +++ b/libfreerdp/codec/rfx_neon.c @@ -51,21 +51,18 @@ rfx_quantization_decode_block_NEON(INT16 * buffer, const int buffer_size, const while(buf < buf_end); } -void -rfx_quantization_decode_NEON(INT16 * buffer, const UINT32 * quantization_values) +void rfx_quantization_decode_NEON(INT16 * buffer, const UINT32 * quantVals) { - rfx_quantization_decode_block_NEON(buffer, 4096, 5); - - rfx_quantization_decode_block_NEON(buffer, 1024, quantization_values[8] - 6); /* HL1 */ - rfx_quantization_decode_block_NEON(buffer + 1024, 1024, quantization_values[7] - 6); /* LH1 */ - rfx_quantization_decode_block_NEON(buffer + 2048, 1024, quantization_values[9] - 6); /* HH1 */ - rfx_quantization_decode_block_NEON(buffer + 3072, 256, quantization_values[5] - 6); /* HL2 */ - rfx_quantization_decode_block_NEON(buffer + 3328, 256, quantization_values[4] - 6); /* LH2 */ - rfx_quantization_decode_block_NEON(buffer + 3584, 256, quantization_values[6] - 6); /* HH2 */ - rfx_quantization_decode_block_NEON(buffer + 3840, 64, quantization_values[2] - 6); /* HL3 */ - rfx_quantization_decode_block_NEON(buffer + 3904, 64, quantization_values[1] - 6); /* LH3 */ - rfx_quantization_decode_block_NEON(buffer + 3968, 64, quantization_values[3] - 6); /* HH3 */ - rfx_quantization_decode_block_NEON(buffer + 4032, 64, quantization_values[0] - 6); /* LL3 */ + rfx_quantization_decode_block_NEON(&buffer[0], 1024, quantVals[8] - 1); /* HL1 */ + rfx_quantization_decode_block_NEON(&buffer[1024], 1024, quantVals[7] - 1); /* LH1 */ + rfx_quantization_decode_block_NEON(&buffer[2048], 1024, quantVals[9] - 1); /* HH1 */ + rfx_quantization_decode_block_NEON(&buffer[3072], 256, quantVals[5] - 1); /* HL2 */ + rfx_quantization_decode_block_NEON(&buffer[3328], 256, quantVals[4] - 1); /* LH2 */ + rfx_quantization_decode_block_NEON(&buffer[3584], 256, quantVals[6] - 1); /* HH2 */ + rfx_quantization_decode_block_NEON(&buffer[3840], 64, quantVals[2] - 1); /* HL3 */ + rfx_quantization_decode_block_NEON(&buffer[3904], 64, quantVals[1] - 1); /* LH3 */ + rfx_quantization_decode_block_NEON(&buffer[3968], 64, quantVals[3] - 1); /* HH3 */ + rfx_quantization_decode_block_NEON(&buffer[4032], 64, quantVals[0] - 1); /* LL3 */ } diff --git a/libfreerdp/codec/rfx_quantization.c b/libfreerdp/codec/rfx_quantization.c index b5c79e5f2..6c497a65a 100644 --- a/libfreerdp/codec/rfx_quantization.c +++ b/libfreerdp/codec/rfx_quantization.c @@ -26,21 +26,21 @@ #include "rfx_quantization.h" /* - * Band Offset Size + * Band Offset Dimensions Size * - * HL1 0 1024 - * LH1 1024 1024 - * HH1 2048 1024 + * HL1 0 32x32 1024 + * LH1 1024 32x32 1024 + * HH1 2048 32x32 1024 * - * HL2 3072 256 - * LH2 3328 256 - * HH2 3584 256 + * HL2 3072 16x16 256 + * LH2 3328 16x16 256 + * HH2 3584 16x16 256 * - * HL3 3840 64 - * LH3 3904 64 - * HH3 3968 64 + * HL3 3840 8x8 64 + * LH3 3904 8x8 64 + * HH3 3968 8x8 64 * - * LL3 4032 64 + * LL3 4032 8x8 64 */ void rfx_quantization_decode_block(const primitives_t *prims, INT16* buffer, int buffer_size, UINT32 factor) @@ -51,23 +51,20 @@ void rfx_quantization_decode_block(const primitives_t *prims, INT16* buffer, int prims->lShiftC_16s(buffer, factor, buffer, buffer_size); } -void rfx_quantization_decode(INT16* buffer, const UINT32* quantization_values) +void rfx_quantization_decode(INT16* buffer, const UINT32* quantVals) { const primitives_t* prims = primitives_get(); - /* Scale the values so that they are represented as 11.5 fixed-point number */ - rfx_quantization_decode_block(prims, buffer, 4096, 5); - - rfx_quantization_decode_block(prims, buffer, 1024, quantization_values[8] - 6); /* HL1 */ - rfx_quantization_decode_block(prims, buffer + 1024, 1024, quantization_values[7] - 6); /* LH1 */ - rfx_quantization_decode_block(prims, buffer + 2048, 1024, quantization_values[9] - 6); /* HH1 */ - rfx_quantization_decode_block(prims, buffer + 3072, 256, quantization_values[5] - 6); /* HL2 */ - rfx_quantization_decode_block(prims, buffer + 3328, 256, quantization_values[4] - 6); /* LH2 */ - rfx_quantization_decode_block(prims, buffer + 3584, 256, quantization_values[6] - 6); /* HH2 */ - rfx_quantization_decode_block(prims, buffer + 3840, 64, quantization_values[2] - 6); /* HL3 */ - rfx_quantization_decode_block(prims, buffer + 3904, 64, quantization_values[1] - 6); /* LH3 */ - rfx_quantization_decode_block(prims, buffer + 3968, 64, quantization_values[3] - 6); /* HH3 */ - rfx_quantization_decode_block(prims, buffer + 4032, 64, quantization_values[0] - 6); /* LL3 */ + rfx_quantization_decode_block(prims, &buffer[0], 1024, quantVals[8] - 1); /* HL1 */ + rfx_quantization_decode_block(prims, &buffer[1024], 1024, quantVals[7] - 1); /* LH1 */ + rfx_quantization_decode_block(prims, &buffer[2048], 1024, quantVals[9] - 1); /* HH1 */ + rfx_quantization_decode_block(prims, &buffer[3072], 256, quantVals[5] - 1); /* HL2 */ + rfx_quantization_decode_block(prims, &buffer[3328], 256, quantVals[4] - 1); /* LH2 */ + rfx_quantization_decode_block(prims, &buffer[3584], 256, quantVals[6] - 1); /* HH2 */ + rfx_quantization_decode_block(prims, &buffer[3840], 64, quantVals[2] - 1); /* HL3 */ + rfx_quantization_decode_block(prims, &buffer[3904], 64, quantVals[1] - 1); /* LH3 */ + rfx_quantization_decode_block(prims, &buffer[3968], 64, quantVals[3] - 1); /* HH3 */ + rfx_quantization_decode_block(prims, &buffer[4032], 64, quantVals[0] - 1); /* LL3 */ } static void rfx_quantization_encode_block(INT16* buffer, int buffer_size, UINT32 factor) diff --git a/libfreerdp/codec/rfx_sse2.c b/libfreerdp/codec/rfx_sse2.c index 47dbac32f..4f54d17cd 100644 --- a/libfreerdp/codec/rfx_sse2.c +++ b/libfreerdp/codec/rfx_sse2.c @@ -82,22 +82,20 @@ rfx_quantization_decode_block_sse2(INT16* buffer, const int buffer_size, const U } while(ptr < buf_end); } -static void rfx_quantization_decode_sse2(INT16* buffer, const UINT32* quantization_values) +static void rfx_quantization_decode_sse2(INT16* buffer, const UINT32* quantVals) { _mm_prefetch_buffer((char*) buffer, 4096 * sizeof(INT16)); - rfx_quantization_decode_block_sse2(buffer, 4096, 5); - - rfx_quantization_decode_block_sse2(buffer, 1024, quantization_values[8] - 6); /* HL1 */ - rfx_quantization_decode_block_sse2(buffer + 1024, 1024, quantization_values[7] - 6); /* LH1 */ - rfx_quantization_decode_block_sse2(buffer + 2048, 1024, quantization_values[9] - 6); /* HH1 */ - rfx_quantization_decode_block_sse2(buffer + 3072, 256, quantization_values[5] - 6); /* HL2 */ - rfx_quantization_decode_block_sse2(buffer + 3328, 256, quantization_values[4] - 6); /* LH2 */ - rfx_quantization_decode_block_sse2(buffer + 3584, 256, quantization_values[6] - 6); /* HH2 */ - rfx_quantization_decode_block_sse2(buffer + 3840, 64, quantization_values[2] - 6); /* HL3 */ - rfx_quantization_decode_block_sse2(buffer + 3904, 64, quantization_values[1] - 6); /* LH3 */ - rfx_quantization_decode_block_sse2(buffer + 3968, 64, quantization_values[3] - 6); /* HH3 */ - rfx_quantization_decode_block_sse2(buffer + 4032, 64, quantization_values[0] - 6); /* LL3 */ + rfx_quantization_decode_block_sse2(&buffer[0], 1024, quantVals[8] - 1); /* HL1 */ + rfx_quantization_decode_block_sse2(&buffer[1024], 1024, quantVals[7] - 1); /* LH1 */ + rfx_quantization_decode_block_sse2(&buffer[2048], 1024, quantVals[9] - 1); /* HH1 */ + rfx_quantization_decode_block_sse2(&buffer[3072], 256, quantVals[5] - 1); /* HL2 */ + rfx_quantization_decode_block_sse2(&buffer[3328], 256, quantVals[4] - 1); /* LH2 */ + rfx_quantization_decode_block_sse2(&buffer[3584], 256, quantVals[6] - 1); /* HH2 */ + rfx_quantization_decode_block_sse2(&buffer[3840], 64, quantVals[2] - 1); /* HL3 */ + rfx_quantization_decode_block_sse2(&buffer[3904], 64, quantVals[1] - 1); /* LH3 */ + rfx_quantization_decode_block_sse2(&buffer[3968], 64, quantVals[3] - 1); /* HH3 */ + rfx_quantization_decode_block_sse2(&buffer[4032], 64, quantVals[0] - 1); /* LL3 */ } static __inline void __attribute__((ATTRIBUTES)) From 68b3d0476bd54b4ccc7f71362687df02e327338f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 19 Aug 2014 14:48:09 -0400 Subject: [PATCH 03/30] libfreerdp-codec: start work on progressive inverse DWT --- client/X11/xf_gfx.c | 67 +++++++++++--- include/freerdp/codec/progressive.h | 6 ++ libfreerdp/codec/progressive.c | 131 ++++++++++++++++++++++++++++ libfreerdp/codec/rfx_decode.c | 4 +- libfreerdp/codec/rfx_dwt.c | 12 +-- libfreerdp/codec/rfx_sse2.c | 6 +- 6 files changed, 203 insertions(+), 23 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index b99fd5e37..823e1fce8 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -477,10 +477,21 @@ int xf_SurfaceCommand_Alpha(xfContext* xfc, RdpgfxClientContext* context, RDPGFX int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) { - int status = 0; - BYTE* DstData = NULL; + int i, j; + int status; + BYTE* DstData; + RFX_RECT* rect; + int nXDst, nYDst; + int nWidth, nHeight; + int nbUpdateRects; xfGfxSurface* surface; - RECTANGLE_16 invalidRect; + REGION16 updateRegion; + RECTANGLE_16 updateRect; + RECTANGLE_16* updateRects; + REGION16 clippingRects; + RECTANGLE_16 clippingRect; + RFX_PROGRESSIVE_TILE* tile; + PROGRESSIVE_BLOCK_REGION* region; surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId); @@ -500,17 +511,51 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, printf("xf_SurfaceCommand_Progressive: status: %d\n", status); - /* fill with blue for now to distinguish from the rest */ + region = &(xfc->progressive->region); - freerdp_image_fill(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, - cmd->left, cmd->top, cmd->width, cmd->height, 0x0000FF); + region16_init(&clippingRects); - invalidRect.left = cmd->left; - invalidRect.top = cmd->top; - invalidRect.right = cmd->right; - invalidRect.bottom = cmd->bottom; + for (i = 0; i < region->numRects; i++) + { + rect = &(region->rects[i]); - region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect); + clippingRect.left = cmd->left + rect->x; + clippingRect.top = cmd->top + rect->y; + clippingRect.right = clippingRect.left + rect->width; + clippingRect.bottom = clippingRect.top + rect->height; + + region16_union_rect(&clippingRects, &clippingRects, &clippingRect); + } + + for (i = 0; i < region->numTiles; i++) + { + tile = &(region->tiles[i]); + + updateRect.left = cmd->left + tile->x; + updateRect.top = cmd->top + tile->y; + updateRect.right = updateRect.left + 64; + updateRect.bottom = updateRect.top + 64; + + region16_init(&updateRegion); + region16_intersect_rect(&updateRegion, &clippingRects, &updateRect); + updateRects = (RECTANGLE_16*) region16_rects(&updateRegion, &nbUpdateRects); + + for (j = 0; j < nbUpdateRects; j++) + { + nXDst = updateRects[j].left; + nYDst = updateRects[j].top; + nWidth = updateRects[j].right - updateRects[j].left; + nHeight = updateRects[j].bottom - updateRects[j].top; + + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, + nXDst, nYDst, nWidth, nHeight, + tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0); + + region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &updateRects[j]); + } + + region16_uninit(&updateRegion); + } if (!xfc->inGfxFrame) xf_OutputUpdate(xfc); diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index e22ab10fc..c94d2b876 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -205,6 +205,12 @@ struct _RFX_PROGRESSIVE_TILE BYTE* cbRawData; BYTE* crSrlData; BYTE* crRawData; + + int x; + int y; + int width; + int height; + BYTE* data; }; typedef struct _RFX_PROGRESSIVE_TILE RFX_PROGRESSIVE_TILE; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index c36b29a8a..08b3268c1 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -94,10 +94,106 @@ const char* progressive_get_block_type_string(UINT16 blockType) * LL3 4015 9x9 81 */ +static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int N) +{ + int N2; + int x, y, k; + INT16 *dst, *l, *h; + INT16 *l_dst, *h_dst; + INT16 *HL, *LH, *HH, *LL; + + N2 = N << 1; + + /* Inverse DWT in horizontal direction, results in 2 sub-bands in L, H order in tmp buffer idwt. */ + /* The 4 sub-bands are stored in HL(0), LH(1), HH(2), LL(3) order. */ + /* The lower part L uses LL(3) and HL(0). */ + /* The higher part H uses LH(1) and HH(2). */ + + LL = &buffer[(N * N) * 3]; + HL = &buffer[0]; + l_dst = &dwt[0]; + + LH = &buffer[N * N]; + HH = &buffer[(N * N) * 2]; + h_dst = &dwt[(N * N) * 2]; + + for (y = 0; y < N; y++) + { + /* Even coefficients */ + l_dst[0] = LL[0] - ((HL[0] + HL[0] + 1) >> 1); + h_dst[0] = LH[0] - ((HH[0] + HH[0] + 1) >> 1); + + for (k = 1; k < N; k++) + { + x = k << 1; + l_dst[x] = LL[k] - ((HL[k-1] + HL[k] + 1) >> 1); + h_dst[x] = LH[k] - ((HH[k-1] + HH[k] + 1) >> 1); + } + + /* Odd coefficients */ + for (k = 0; k < N-1; k++) + { + x = k << 1; + l_dst[x + 1] = (HL[k] << 1) + ((l_dst[x] + l_dst[x + 2]) >> 1); + h_dst[x + 1] = (HH[k] << 1) + ((h_dst[x] + h_dst[x + 2]) >> 1); + } + + x = k << 1; + l_dst[x + 1] = (HL[k] << 1) + (l_dst[x]); + h_dst[x + 1] = (HH[k] << 1) + (h_dst[x]); + + LL += N; + HL += N; + l_dst += N2; + + LH += N; + HH += N; + h_dst += N2; + } + + /* Inverse DWT in vertical direction, results are stored in original buffer. */ + for (x = 0; x < N2; x++) + { + /* Even coefficients */ + for (k = 0; k < N; k++) + { + y = k << 1; + dst = buffer + y * N2 + x; + l = dwt + k * N2 + x; + h = l + N * N2; + dst[0] = *l - (((k > 0 ? *(h - N2) : *h) + (*h) + 1) >> 1); + } + + /* Odd coefficients */ + for (k = 0; k < N; k++) + { + y = k << 1; + dst = buffer + y * N2 + x; + l = dwt + k * N2 + x; + h = l + N * N2; + dst[N2] = (*h << 1) + ((dst[0] + dst[k < N - 1 ? 2 * N2 : 0]) >> 1); + } + } +} + +void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* dwt) +{ +#if 0 + progressive_rfx_dwt_2d_decode_block(&buffer[3807], dwt, 8); + progressive_rfx_dwt_2d_decode_block(&buffer[3007], dwt, 16); + //progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 32); +#else + progressive_rfx_dwt_2d_decode_block(&buffer[3840], dwt, 8); + progressive_rfx_dwt_2d_decode_block(&buffer[3072], dwt, 16); + progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 32); +#endif +} + int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* quant, const BYTE* data, int length, INT16* buffer) { int status; + INT16* dwt; const primitives_t* prims = primitives_get(); status = rfx_rlgr_decode(data, length, buffer, 4096, 1); @@ -118,6 +214,12 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, rfx_quantization_decode_block(prims, &buffer[3951], 64, (quant->HH3 - 1)); /* HH3 */ rfx_quantization_decode_block(prims, &buffer[4015], 81, (quant->LL3 - 1)); /* LL3 */ + dwt = (INT16*) BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */ + + progressive_rfx_dwt_2d_decode(buffer, dwt); + + BufferPool_Return(progressive->bufferPool, dwt); + return 1; } @@ -130,6 +232,8 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG RFX_COMPONENT_CODEC_QUANT* quantCb; RFX_COMPONENT_CODEC_QUANT* quantCr; RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; + static const prim_size_t roi_64x64 = { 64, 64 }; + const primitives_t* prims = primitives_get(); 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); @@ -164,6 +268,7 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG } 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 */ @@ -172,6 +277,17 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG 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 */ + prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), + pSrcDst, 64 * sizeof(INT16), &roi_64x64); + + if (!tile->data) + { + tile->data = _aligned_malloc(64 * 64 * 4, 16); + } + + prims->RGBToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * sizeof(INT16), + tile->data, 64 * 4, &roi_64x64); + BufferPool_Return(progressive->bufferPool, pBuffer); return 1; @@ -296,6 +412,11 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI tile->tailData = &block[boffset]; boffset += tile->tailLen; + tile->width = 64; + tile->height = 64; + tile->x = tile->xIdx * 64; + tile->y = tile->yIdx * 64; + break; case PROGRESSIVE_WBT_TILE_FIRST: @@ -340,6 +461,11 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI tile->tailData = &block[boffset]; boffset += tile->tailLen; + tile->width = 64; + tile->height = 64; + tile->x = tile->xIdx * 64; + tile->y = tile->yIdx * 64; + break; case PROGRESSIVE_WBT_TILE_UPGRADE: @@ -397,6 +523,11 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI tile->crRawData = &block[boffset]; boffset += tile->crRawLen; + tile->width = 64; + tile->height = 64; + tile->x = tile->xIdx * 64; + tile->y = tile->yIdx * 64; + break; default: diff --git a/libfreerdp/codec/rfx_decode.c b/libfreerdp/codec/rfx_decode.c index d3baf5462..d14aff8a2 100644 --- a/libfreerdp/codec/rfx_decode.c +++ b/libfreerdp/codec/rfx_decode.c @@ -38,7 +38,7 @@ #include "rfx_decode.h" /* stride is bytes between rows in the output buffer. */ -static void rfx_decode_format_rgb(INT16* r_buf, INT16* g_buf, INT16* b_buf, +void rfx_decode_format_rgb(INT16* r_buf, INT16* g_buf, INT16* b_buf, RDP_PIXEL_FORMAT pixel_format, BYTE* dst_buf, int stride) { primitives_t *prims = primitives_get(); @@ -146,9 +146,7 @@ BOOL rfx_decode_rgb(RFX_CONTEXT* context, RFX_TILE* tile, BYTE* rgb_buffer, int pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* cr_b_buffer */ rfx_decode_component(context, y_quants, tile->YData, tile->YLen, pSrcDst[0]); /* YData */ - rfx_decode_component(context, cb_quants, tile->CbData, tile->CbLen, pSrcDst[1]); /* CbData */ - rfx_decode_component(context, cr_quants, tile->CrData, tile->CrLen, pSrcDst[2]); /* CrData */ PROFILER_ENTER(context->priv->prof_rfx_ycbcr_to_rgb); diff --git a/libfreerdp/codec/rfx_dwt.c b/libfreerdp/codec/rfx_dwt.c index 0b8448b9e..7e3b3ccc4 100644 --- a/libfreerdp/codec/rfx_dwt.c +++ b/libfreerdp/codec/rfx_dwt.c @@ -110,9 +110,9 @@ static void rfx_dwt_2d_decode_block(INT16* buffer, INT16* idwt, int subband_widt void rfx_dwt_2d_decode(INT16* buffer, INT16* dwt_buffer) { - rfx_dwt_2d_decode_block(buffer + 3840, dwt_buffer, 8); - rfx_dwt_2d_decode_block(buffer + 3072, dwt_buffer, 16); - rfx_dwt_2d_decode_block(buffer, dwt_buffer, 32); + rfx_dwt_2d_decode_block(&buffer[3840], dwt_buffer, 8); + rfx_dwt_2d_decode_block(&buffer[3072], dwt_buffer, 16); + rfx_dwt_2d_decode_block(&buffer[0], dwt_buffer, 32); } static void rfx_dwt_2d_encode_block(INT16* buffer, INT16* dwt, int subband_width) @@ -192,7 +192,7 @@ static void rfx_dwt_2d_encode_block(INT16* buffer, INT16* dwt, int subband_width void rfx_dwt_2d_encode(INT16* buffer, INT16* dwt_buffer) { - rfx_dwt_2d_encode_block(buffer, dwt_buffer, 32); - rfx_dwt_2d_encode_block(buffer + 3072, dwt_buffer, 16); - rfx_dwt_2d_encode_block(buffer + 3840, dwt_buffer, 8); + rfx_dwt_2d_encode_block(&buffer[0], dwt_buffer, 32); + rfx_dwt_2d_encode_block(&buffer[3072], dwt_buffer, 16); + rfx_dwt_2d_encode_block(&buffer[3840], dwt_buffer, 8); } diff --git a/libfreerdp/codec/rfx_sse2.c b/libfreerdp/codec/rfx_sse2.c index 4f54d17cd..f89efe81e 100644 --- a/libfreerdp/codec/rfx_sse2.c +++ b/libfreerdp/codec/rfx_sse2.c @@ -340,9 +340,9 @@ static void rfx_dwt_2d_decode_sse2(INT16* buffer, INT16* dwt_buffer) { _mm_prefetch_buffer((char*) buffer, 4096 * sizeof(INT16)); - rfx_dwt_2d_decode_block_sse2(buffer + 3840, dwt_buffer, 8); - rfx_dwt_2d_decode_block_sse2(buffer + 3072, dwt_buffer, 16); - rfx_dwt_2d_decode_block_sse2(buffer, dwt_buffer, 32); + rfx_dwt_2d_decode_block_sse2(&buffer[3840], dwt_buffer, 8); + rfx_dwt_2d_decode_block_sse2(&buffer[3072], dwt_buffer, 16); + rfx_dwt_2d_decode_block_sse2(&buffer[0], dwt_buffer, 32); } static __inline void __attribute__((ATTRIBUTES)) From 5e778d6a0cc2386d6d7b4cb520924abffd8d75c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 20 Aug 2014 17:16:34 -0400 Subject: [PATCH 04/30] libfreerdp-codec: intermediate progressive rfx iDWT --- libfreerdp/codec/progressive.c | 134 +++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 57 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 08b3268c1..3bebc1072 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -96,97 +96,117 @@ const char* progressive_get_block_type_string(UINT16 blockType) static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int N) { - int N2; + int width; + int height; int x, y, k; - INT16 *dst, *l, *h; - INT16 *l_dst, *h_dst; + int Nx2, Ne2; + INT16 *L, *H; INT16 *HL, *LH, *HH, *LL; - N2 = N << 1; + Nx2 = N * 2; + Ne2 = N * N; - /* Inverse DWT in horizontal direction, results in 2 sub-bands in L, H order in tmp buffer idwt. */ - /* The 4 sub-bands are stored in HL(0), LH(1), HH(2), LL(3) order. */ - /* The lower part L uses LL(3) and HL(0). */ - /* The higher part H uses LH(1) and HH(2). */ - - LL = &buffer[(N * N) * 3]; HL = &buffer[0]; - l_dst = &dwt[0]; + LH = &buffer[Ne2 - N]; /* (N^2 - N) */ + HH = &buffer[2 * (Ne2 - N)]; /* 2 * (N^2 - N) */ + LL = &buffer[(3 * Ne2) - (4 * N) + 1]; /* 3N^2 - 4N + 1) */ - LH = &buffer[N * N]; - HH = &buffer[(N * N) * 2]; - h_dst = &dwt[(N * N) * 2]; + L = &dwt[0]; + H = &dwt[(2 * Ne2) - N]; /* 2N^2 - N */ + + /* horizontal (LL + HL -> L) */ + + L[0] = LL[0] - ((HL[0] + HL[0] + 1) / 2); for (y = 0; y < N; y++) { /* Even coefficients */ - l_dst[0] = LL[0] - ((HL[0] + HL[0] + 1) >> 1); - h_dst[0] = LH[0] - ((HH[0] + HH[0] + 1) >> 1); for (k = 1; k < N; k++) { - x = k << 1; - l_dst[x] = LL[k] - ((HL[k-1] + HL[k] + 1) >> 1); - h_dst[x] = LH[k] - ((HH[k-1] + HH[k] + 1) >> 1); + L[k * 2] = LL[k] - ((HL[k - 1] + HL[k] + 1) / 2); } /* Odd coefficients */ - for (k = 0; k < N-1; k++) - { - x = k << 1; - l_dst[x + 1] = (HL[k] << 1) + ((l_dst[x] + l_dst[x + 2]) >> 1); - h_dst[x + 1] = (HH[k] << 1) + ((h_dst[x] + h_dst[x + 2]) >> 1); - } - x = k << 1; - l_dst[x + 1] = (HL[k] << 1) + (l_dst[x]); - h_dst[x + 1] = (HH[k] << 1) + (h_dst[x]); + for (k = 0; k < N - 1; k++) + { + L[(k * 2) + 1] = (HL[k] * 2) + ((L[k * 2] + L[(k * 2) + 2]) / 2); + } LL += N; - HL += N; - l_dst += N2; - - LH += N; - HH += N; - h_dst += N2; + HL += (N - 1); + L += (2 * N) - 1; } - /* Inverse DWT in vertical direction, results are stored in original buffer. */ - for (x = 0; x < N2; x++) + /* horizontal (LH + HH -> H) */ + + for (y = 0; y < N - 1; y++) { /* Even coefficients */ - for (k = 0; k < N; k++) + + H[0] = LH[0] - ((HH[0] + HH[0] + 1) / 2); + + for (k = 1; k < N; k++) { - y = k << 1; - dst = buffer + y * N2 + x; - l = dwt + k * N2 + x; - h = l + N * N2; - dst[0] = *l - (((k > 0 ? *(h - N2) : *h) + (*h) + 1) >> 1); + H[k * 2] = LH[k] - ((HH[k - 1] + HH[k] + 1) / 2); } /* Odd coefficients */ - for (k = 0; k < N; k++) + + for (k = 0; k < N - 1; k++) { - y = k << 1; - dst = buffer + y * N2 + x; - l = dwt + k * N2 + x; - h = l + N * N2; - dst[N2] = (*h << 1) + ((dst[0] + dst[k < N - 1 ? 2 * N2 : 0]) >> 1); + H[(k * 2) + 1] = (HH[k] * 2) + ((H[k * 2] + H[(k * 2) + 2]) / 2); + } + + LH += N; + HH += (N - 1); + H += (2 * N) - 1; + } + + /* vertical (L + H -> LL) */ + + LL = &buffer[0]; + + L = &dwt[0]; + H = &dwt[(2 * Ne2) - N]; /* 2N^2 - N */ + + for (x = 0; x < (2 * N) - 1; x++) + { + /* Even coefficients */ + + LL[0] = L[0] - ((H[0] + H[0] + 1) / 2); + + for (k = 1; k < N; k++) + { + LL = &buffer[(k * 2) * (N * 2) + x]; + L = &dwt[k * (N * 2) + x]; + H = &L[N * (N * 2)]; + + LL[0] = L[0] - (((H[-1 * (N * 2)]) + H[0] + 1) / 2); + } + + /* Odd coefficients */ + + for (k = 0; k < N - 1; k++) + { + LL = &buffer[(k * 2) * (N * 2) + x]; + L = &dwt[k * (N * 2) + x]; + H = &L[N * (N * 2)]; + + LL[N * 2] = (H[0] * 2) + ((LL[0] + LL[2 * (N * 2)]) / 2); } } } void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* dwt) { -#if 0 - progressive_rfx_dwt_2d_decode_block(&buffer[3807], dwt, 8); - progressive_rfx_dwt_2d_decode_block(&buffer[3007], dwt, 16); - //progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 32); -#else - progressive_rfx_dwt_2d_decode_block(&buffer[3840], dwt, 8); - progressive_rfx_dwt_2d_decode_block(&buffer[3072], dwt, 16); - progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 32); -#endif + if (0) + { + progressive_rfx_dwt_2d_decode_block(&buffer[3807], dwt, 9); + progressive_rfx_dwt_2d_decode_block(&buffer[3007], dwt, 17); + progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 31); + } } int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, From e54bbdab006a8e4361397b57729650bc1e769405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 20 Aug 2014 19:12:08 -0400 Subject: [PATCH 05/30] libfreerdp-codec: start new progressive rfx iDWT functions --- libfreerdp/codec/progressive.c | 319 ++++++++++++++++++++++++--------- 1 file changed, 238 insertions(+), 81 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 3bebc1072..23169542a 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -94,118 +94,275 @@ const char* progressive_get_block_type_string(UINT16 blockType) * LL3 4015 9x9 81 */ +static void progressive_rfx_idwt_x(INT16* pLowBand, int nLowStep, INT16* pHighBand, int nHighStep, + INT16* pDstBand, int nDstStep, int nLowCount, int nHighCount, int nDstCount) +{ + int i, j; + INT16 L0; + INT16 H0, H1; + INT16 X0, X1, X2; + INT16 *pL, *pH, *pX; + + printf("progressive_rfx_idwt_x: nLowStep: %d nHighStep: %d nDstStep: %d nLowCount: %d nHighCount: %d nCount: %d\n", + nLowStep, nHighStep, nDstStep, nLowCount, nHighCount, nDstCount); + + for (i = 0; i < nDstCount; i++) + { + pL = pLowBand; + pH = pHighBand; + pX = pDstBand; + + H0 = *pH; + pH++; + + L0 = *pL; + pL++; + + X0 = L0 - H0; + X2 = L0 - H0; + + for (j = 0; j < (nHighCount - 1); j++) + { + H1 = *pH; + pH++; + + L0 = *pL; + pL++; + + X2 = L0 - ((H0 + H1) / 2); + X1 = ((X0 + X2) / 2) + (2 * H0); + + pX[0] = X0; + pX[1] = X1; + pX += 2; + + X0 = X2; + H0 = H1; + } + + if (nLowCount <= (nHighCount + 1)) + { + if (nLowCount <= nHighCount) + { + pX[0] = X2; + pX[1] = X2 + (2 * H0); + } + else + { + L0 = *pL; + pL++; + + X0 = L0 - H0; + + pX[0] = X2; + pX[1] = ((X0 + X2) / 2) + (2 * H0); + pX[2] = X0; + } + } + else + { + L0 = *pL; + pL++; + + X0 = L0 - (H0 / 2); + + pX[0] = X2; + pX[1] = ((X0 + X2) / 2) + (2 * H0); + pX[2] = X0; + + L0 = *pL; + pL++; + + pX[3] = (X0 + L0) / 2; + } + + pLowBand += nLowStep; + pHighBand += nHighStep; + pDstBand += nDstStep; + } +} + +static void progressive_rfx_idwt_y(INT16* pLowBand, int nLowStep, INT16* pHighBand, int nHighStep, + INT16* pDstBand, int nDstStep, int nLowCount, int nHighCount, int nDstCount) +{ + int i, j; + INT16 L0; + INT16 H0, H1; + INT16 X0, X1, X2; + INT16 *pL, *pH, *pX; + + printf("progressive_rfx_idwt_y: nLowStep: %d nHighStep: %d nDstStep: %d nLowCount: %d nHighCount: %d nDstCount: %d\n", + nLowStep, nHighStep, nDstStep, nLowCount, nHighCount, nDstCount); + + for (i = 0; i < nDstCount; i++) + { + pL = pLowBand; + pH = pHighBand; + pX = pDstBand; + + H0 = *pH; + pH += nHighStep; + + L0 = *pL; + pL += nLowStep; + + X0 = L0 - H0; + X2 = L0 - H0; + + for (j = 0; j < (nHighCount - 1); j++) + { + H1 = *pH; + pH += nHighStep; + + L0 = *pL; + pL += nLowStep; + + X2 = L0 - ((H0 + H1) / 2); + X1 = ((X0 + X2) / 2) + (2 * H0); + + *pX = X0; + pX += nDstStep; + + *pX = X1; + pX += nDstStep; + + X0 = X2; + H0 = H1; + } + + if (nLowCount <= (nHighCount + 1)) + { + if (nLowCount <= nHighCount) + { + *pX = X2; + pX += nDstStep; + + *pX = X2 + (2 * H0); + pX += nDstStep; + } + else + { + L0 = *pL; + pL += nLowStep; + + X0 = L0 - H0; + + *pX = X2; + pX += nDstStep; + + *pX = ((X0 + X2) / 2) + (2 * H0); + pX += nDstStep; + + *pX = X0; + pX += nDstStep; + } + } + else + { + L0 = *pL; + pL += nLowStep; + + X0 = L0 - (H0 / 2); + + *pX = X2; + pX += nDstStep; + + *pX = ((X0 + X2) / 2) + (2 * H0); + pX += nDstStep; + + *pX = X0; + pX += nDstStep; + + L0 = *pL; + pL += nLowStep; + + *pX = (X0 + L0) / 2; + pX += nDstStep; + } + + pLowBand += 1; + pHighBand += 1; + pDstBand += 1; + } +} + static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int N) { - int width; - int height; - int x, y, k; - int Nx2, Ne2; + INT16* pLowBand; + INT16* pHighBand; + INT16* pDstBand; + int nLowStep; + int nHighStep; + int nDstStep; + int nLowCount; + int nHighCount; + int nDstCount; INT16 *L, *H; INT16 *HL, *LH, *HH, *LL; - Nx2 = N * 2; - Ne2 = N * N; - HL = &buffer[0]; - LH = &buffer[Ne2 - N]; /* (N^2 - N) */ - HH = &buffer[2 * (Ne2 - N)]; /* 2 * (N^2 - N) */ - LL = &buffer[(3 * Ne2) - (4 * N) + 1]; /* 3N^2 - 4N + 1) */ + LH = &buffer[(N * N) - N]; /* (N^2 - N) */ + HH = &buffer[2 * ((N * N) - N)]; /* 2 * (N^2 - N) */ + LL = &buffer[(3 * (N * N)) - (4 * N) + 1]; /* 3N^2 - 4N + 1) */ L = &dwt[0]; - H = &dwt[(2 * Ne2) - N]; /* 2N^2 - N */ + H = &dwt[(2 * (N * N)) - N]; /* 2N^2 - N */ /* horizontal (LL + HL -> L) */ - L[0] = LL[0] - ((HL[0] + HL[0] + 1) / 2); + pLowBand = LL; + nLowStep = N * N; + pHighBand = HL; + nHighStep = N * (N - 1); + pDstBand = L; + nDstStep = N + (N - 1); + nLowCount = N; + nHighCount = (N - 1); + nDstCount = (N - 1); - for (y = 0; y < N; y++) - { - /* Even coefficients */ - - for (k = 1; k < N; k++) - { - L[k * 2] = LL[k] - ((HL[k - 1] + HL[k] + 1) / 2); - } - - /* Odd coefficients */ - - for (k = 0; k < N - 1; k++) - { - L[(k * 2) + 1] = (HL[k] * 2) + ((L[k * 2] + L[(k * 2) + 2]) / 2); - } - - LL += N; - HL += (N - 1); - L += (2 * N) - 1; - } + progressive_rfx_idwt_x(pLowBand, nLowStep, pHighBand, nHighStep, pDstBand, nDstStep, nLowCount, nHighCount, nDstCount); /* horizontal (LH + HH -> H) */ - for (y = 0; y < N - 1; y++) - { - /* Even coefficients */ + pLowBand = LH; + nLowStep = N * (N - 1); + pHighBand = HH; + nHighStep = (N - 1) * (N - 1); + pDstBand = H; + nDstStep = N + (N - 1); + nLowCount = N; + nHighCount = (N - 1); + nDstCount = (N - 1); - H[0] = LH[0] - ((HH[0] + HH[0] + 1) / 2); - - for (k = 1; k < N; k++) - { - H[k * 2] = LH[k] - ((HH[k - 1] + HH[k] + 1) / 2); - } - - /* Odd coefficients */ - - for (k = 0; k < N - 1; k++) - { - H[(k * 2) + 1] = (HH[k] * 2) + ((H[k * 2] + H[(k * 2) + 2]) / 2); - } - - LH += N; - HH += (N - 1); - H += (2 * N) - 1; - } + progressive_rfx_idwt_x(pLowBand, nLowStep, pHighBand, nHighStep, pDstBand, nDstStep, nLowCount, nHighCount, nDstCount); /* vertical (L + H -> LL) */ LL = &buffer[0]; L = &dwt[0]; - H = &dwt[(2 * Ne2) - N]; /* 2N^2 - N */ + H = &dwt[(2 * (N * N)) - N]; /* 2N^2 - N */ - for (x = 0; x < (2 * N) - 1; x++) - { - /* Even coefficients */ + pLowBand = L; + nLowStep = N + (N - 1); + pHighBand = H; + nHighStep = N + (N - 1); + pDstBand = LL; + nDstStep = N + (N - 1); + nLowCount = N; + nHighCount = (N - 1); + nDstCount = N + (N - 1); - LL[0] = L[0] - ((H[0] + H[0] + 1) / 2); - - for (k = 1; k < N; k++) - { - LL = &buffer[(k * 2) * (N * 2) + x]; - L = &dwt[k * (N * 2) + x]; - H = &L[N * (N * 2)]; - - LL[0] = L[0] - (((H[-1 * (N * 2)]) + H[0] + 1) / 2); - } - - /* Odd coefficients */ - - for (k = 0; k < N - 1; k++) - { - LL = &buffer[(k * 2) * (N * 2) + x]; - L = &dwt[k * (N * 2) + x]; - H = &L[N * (N * 2)]; - - LL[N * 2] = (H[0] * 2) + ((LL[0] + LL[2 * (N * 2)]) / 2); - } - } + progressive_rfx_idwt_y(pLowBand, nLowStep, pHighBand, nHighStep, pDstBand, nDstStep, nLowCount, nHighCount, nDstCount); } void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* dwt) { - if (0) + if (1) { progressive_rfx_dwt_2d_decode_block(&buffer[3807], dwt, 9); progressive_rfx_dwt_2d_decode_block(&buffer[3007], dwt, 17); - progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 31); + //progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 33); } } From f77e5159651535af383b47a82d35c1253dd2dfdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 21 Aug 2014 16:05:39 -0400 Subject: [PATCH 06/30] libfreerdp-codec: improve progressive iDWT --- libfreerdp/codec/progressive.c | 148 ++++++++++++++++++++------------- 1 file changed, 90 insertions(+), 58 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 23169542a..0ebd3b816 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -286,84 +286,116 @@ static void progressive_rfx_idwt_y(INT16* pLowBand, int nLowStep, INT16* pHighBa } } -static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int N) +static int progressive_rfx_get_band_l_count(int level) { - INT16* pLowBand; - INT16* pHighBand; - INT16* pDstBand; - int nLowStep; - int nHighStep; - int nDstStep; - int nLowCount; - int nHighCount; - int nDstCount; - INT16 *L, *H; - INT16 *HL, *LH, *HH, *LL; + return (64 >> level) + 1; +} - HL = &buffer[0]; - LH = &buffer[(N * N) - N]; /* (N^2 - N) */ - HH = &buffer[2 * ((N * N) - N)]; /* 2 * (N^2 - N) */ - LL = &buffer[(3 * (N * N)) - (4 * N) + 1]; /* 3N^2 - 4N + 1) */ +static int progressive_rfx_get_band_h_count(int level) +{ + if (level == 1) + return (64 >> 1) - 1; + else + return (64 + (1 << (level - 1))) >> level; +} + +static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int level) +{ + int offset; + int nBandL; + int nBandH; + int nDstStepX; + int nDstStepY; + INT16 *L, *H; + INT16 *HL, *LH; + INT16 *HH, *LL; + INT16* pLowBand[3]; + INT16* pHighBand[3]; + INT16* pDstBand[3]; + int nLowStep[3]; + int nHighStep[3]; + int nDstStep[3]; + int nLowCount[3]; + int nHighCount[3]; + int nDstCount[3]; + + nBandL = progressive_rfx_get_band_l_count(level); + nBandH = progressive_rfx_get_band_h_count(level); + + offset = 0; + + HL = &buffer[offset]; + offset += (nBandH * nBandL); + + LH = &buffer[offset]; + offset += (nBandL * nBandH); + + HH = &buffer[offset]; + offset += (nBandH * nBandH); + + LL = &buffer[offset]; + offset += (nBandL * nBandL); + + nDstStepX = 2 * (nBandL + nBandH); + nDstStepY = 2 * progressive_rfx_get_band_l_count(level - 1); + + if (0) + { + nDstStepX = (nDstStepX + 15) & ~0xF; + nDstStepY = (nDstStepY + 15) & ~0xF; + } L = &dwt[0]; - H = &dwt[(2 * (N * N)) - N]; /* 2N^2 - N */ + H = &dwt[nBandL * nDstStepX]; /* horizontal (LL + HL -> L) */ - pLowBand = LL; - nLowStep = N * N; - pHighBand = HL; - nHighStep = N * (N - 1); - pDstBand = L; - nDstStep = N + (N - 1); - nLowCount = N; - nHighCount = (N - 1); - nDstCount = (N - 1); + pLowBand[0] = LL; + nLowStep[0] = 2 * nBandL; + pHighBand[0] = HL; + nHighStep[0] = 2 * nBandH; + pDstBand[0] = L; + nDstStep[0] = nDstStepX; + nLowCount[0] = nBandL; + nHighCount[0] = nBandH; + nDstCount[0] = nBandL; - progressive_rfx_idwt_x(pLowBand, nLowStep, pHighBand, nHighStep, pDstBand, nDstStep, nLowCount, nHighCount, nDstCount); + progressive_rfx_idwt_x(pLowBand[0], nLowStep[0], pHighBand[0], nHighStep[0], pDstBand[0], nDstStep[0], nLowCount[0], nHighCount[0], nDstCount[0]); /* horizontal (LH + HH -> H) */ - pLowBand = LH; - nLowStep = N * (N - 1); - pHighBand = HH; - nHighStep = (N - 1) * (N - 1); - pDstBand = H; - nDstStep = N + (N - 1); - nLowCount = N; - nHighCount = (N - 1); - nDstCount = (N - 1); + pLowBand[1] = LH; + nLowStep[1] = 2 * nBandL; + pHighBand[1] = HH; + nHighStep[1] = 2 * nBandH; + pDstBand[1] = H; + nDstStep[1] = nDstStepX; + nLowCount[1] = nBandL; + nHighCount[1] = nBandH; + nDstCount[1] = nBandH; - progressive_rfx_idwt_x(pLowBand, nLowStep, pHighBand, nHighStep, pDstBand, nDstStep, nLowCount, nHighCount, nDstCount); + progressive_rfx_idwt_x(pLowBand[1], nLowStep[1], pHighBand[1], nHighStep[1], pDstBand[1], nDstStep[1], nLowCount[1], nHighCount[1], nDstCount[1]); /* vertical (L + H -> LL) */ - LL = &buffer[0]; + pLowBand[2] = pDstBand[0]; + nLowStep[2] = nDstStep[0]; + pHighBand[2] = pDstBand[1]; + nHighStep[2] = nDstStep[1]; + pDstBand[2] = &buffer[0]; + nDstStep[2] = nDstStepY; + nLowCount[2] = nBandL; + nHighCount[2] = nBandH; + nDstCount[2] = nBandL + nBandH; - L = &dwt[0]; - H = &dwt[(2 * (N * N)) - N]; /* 2N^2 - N */ - - pLowBand = L; - nLowStep = N + (N - 1); - pHighBand = H; - nHighStep = N + (N - 1); - pDstBand = LL; - nDstStep = N + (N - 1); - nLowCount = N; - nHighCount = (N - 1); - nDstCount = N + (N - 1); - - progressive_rfx_idwt_y(pLowBand, nLowStep, pHighBand, nHighStep, pDstBand, nDstStep, nLowCount, nHighCount, nDstCount); + progressive_rfx_idwt_y(pLowBand[2], nLowStep[2], pHighBand[2], nHighStep[2], pDstBand[2], nDstStep[2], nLowCount[2], nHighCount[2], nDstCount[2]); } void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* dwt) { - if (1) - { - progressive_rfx_dwt_2d_decode_block(&buffer[3807], dwt, 9); - progressive_rfx_dwt_2d_decode_block(&buffer[3007], dwt, 17); - //progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 33); - } + progressive_rfx_dwt_2d_decode_block(&buffer[3807], dwt, 3); + progressive_rfx_dwt_2d_decode_block(&buffer[3007], dwt, 2); + progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 1); } int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, From f79ba1b364e3e3de28dc26f7cc86d8a73366332d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 21 Aug 2014 17:14:10 -0400 Subject: [PATCH 07/30] libfreerdp-codec: fix crashes --- libfreerdp/codec/progressive.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 0ebd3b816..26a61838b 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -280,9 +280,9 @@ static void progressive_rfx_idwt_y(INT16* pLowBand, int nLowStep, INT16* pHighBa pX += nDstStep; } - pLowBand += 1; - pHighBand += 1; - pDstBand += 1; + pLowBand += nLowStep; + pHighBand += nHighStep; + pDstBand += nDstStep; } } @@ -336,8 +336,8 @@ static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int l LL = &buffer[offset]; offset += (nBandL * nBandL); - nDstStepX = 2 * (nBandL + nBandH); - nDstStepY = 2 * progressive_rfx_get_band_l_count(level - 1); + nDstStepX = (nBandL + nBandH); + nDstStepY = (nBandL + nBandH); if (0) { @@ -348,6 +348,9 @@ static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int l L = &dwt[0]; H = &dwt[nBandL * nDstStepX]; + printf("L: %d H: %d LL: %d\n", + nBandL * nDstStepX, nBandH * nDstStepX, (nBandL + nBandH) * nDstStepY); + /* horizontal (LL + HL -> L) */ pLowBand[0] = LL; From 969d9011daed7633b88292238aaee11894c472e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 21 Aug 2014 19:02:26 -0400 Subject: [PATCH 08/30] libfreerdp-codec: partially working progressive iDWT --- libfreerdp/codec/progressive.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 26a61838b..353dc5b50 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -280,9 +280,9 @@ static void progressive_rfx_idwt_y(INT16* pLowBand, int nLowStep, INT16* pHighBa pX += nDstStep; } - pLowBand += nLowStep; - pHighBand += nHighStep; - pDstBand += nDstStep; + pLowBand++; + pHighBand++; + pDstBand++; } } @@ -354,9 +354,9 @@ static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int l /* horizontal (LL + HL -> L) */ pLowBand[0] = LL; - nLowStep[0] = 2 * nBandL; + nLowStep[0] = nBandL; pHighBand[0] = HL; - nHighStep[0] = 2 * nBandH; + nHighStep[0] = nBandH; pDstBand[0] = L; nDstStep[0] = nDstStepX; nLowCount[0] = nBandL; @@ -368,9 +368,9 @@ static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int l /* horizontal (LH + HH -> H) */ pLowBand[1] = LH; - nLowStep[1] = 2 * nBandL; + nLowStep[1] = nBandL; pHighBand[1] = HH; - nHighStep[1] = 2 * nBandH; + nHighStep[1] = nBandH; pDstBand[1] = H; nDstStep[1] = nDstStepX; nLowCount[1] = nBandL; From ed7312501c92edd14e2dfa6cab63bd51903e8bbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 21 Aug 2014 19:43:37 -0400 Subject: [PATCH 09/30] libfreerdp-codec: fix progressive quantization shifts --- include/freerdp/codec/progressive.h | 2 ++ libfreerdp/codec/progressive.c | 33 ++++++++++++----------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index c94d2b876..d32847496 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -255,6 +256,7 @@ struct _PROGRESSIVE_CONTEXT { BOOL Compressor; + wLog* log; wBufferPool* bufferPool; UINT32 cRects; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 353dc5b50..13ccd422f 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -103,9 +103,6 @@ static void progressive_rfx_idwt_x(INT16* pLowBand, int nLowStep, INT16* pHighBa INT16 X0, X1, X2; INT16 *pL, *pH, *pX; - printf("progressive_rfx_idwt_x: nLowStep: %d nHighStep: %d nDstStep: %d nLowCount: %d nHighCount: %d nCount: %d\n", - nLowStep, nHighStep, nDstStep, nLowCount, nHighCount, nDstCount); - for (i = 0; i < nDstCount; i++) { pL = pLowBand; @@ -191,9 +188,6 @@ static void progressive_rfx_idwt_y(INT16* pLowBand, int nLowStep, INT16* pHighBa INT16 X0, X1, X2; INT16 *pL, *pH, *pX; - printf("progressive_rfx_idwt_y: nLowStep: %d nHighStep: %d nDstStep: %d nLowCount: %d nHighCount: %d nDstCount: %d\n", - nLowStep, nHighStep, nDstStep, nLowCount, nHighCount, nDstCount); - for (i = 0; i < nDstCount; i++) { pL = pLowBand; @@ -348,9 +342,6 @@ static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int l L = &dwt[0]; H = &dwt[nBandL * nDstStepX]; - printf("L: %d H: %d LL: %d\n", - nBandL * nDstStepX, nBandH * nDstStepX, (nBandL + nBandH) * nDstStepY); - /* horizontal (LL + HL -> L) */ pLowBand[0] = LL; @@ -415,16 +406,16 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, rfx_differential_decode(&buffer[4015], 81); /* LL3 */ - rfx_quantization_decode_block(prims, &buffer[0], 1023, (quant->HL1 - 1)); /* HL1 */ - rfx_quantization_decode_block(prims, &buffer[1023], 1023, (quant->LH1 - 1)); /* LH1 */ - rfx_quantization_decode_block(prims, &buffer[2046], 961, (quant->HH1 - 1)); /* HH1 */ - rfx_quantization_decode_block(prims, &buffer[3007], 272, (quant->HL2 - 1)); /* HL2 */ - rfx_quantization_decode_block(prims, &buffer[3279], 272, (quant->LH2 - 1)); /* LH2 */ - rfx_quantization_decode_block(prims, &buffer[3551], 256, (quant->HH2 - 1)); /* HH2 */ - rfx_quantization_decode_block(prims, &buffer[3807], 72, (quant->HL3 - 1)); /* HL3 */ - rfx_quantization_decode_block(prims, &buffer[3879], 72, (quant->LH3 - 1)); /* LH3 */ - rfx_quantization_decode_block(prims, &buffer[3951], 64, (quant->HH3 - 1)); /* HH3 */ - rfx_quantization_decode_block(prims, &buffer[4015], 81, (quant->LL3 - 1)); /* LL3 */ + rfx_quantization_decode_block(prims, &buffer[0], 1023, quant->HL1); /* HL1 */ + rfx_quantization_decode_block(prims, &buffer[1023], 1023, quant->LH1); /* LH1 */ + rfx_quantization_decode_block(prims, &buffer[2046], 961, quant->HH1); /* HH1 */ + rfx_quantization_decode_block(prims, &buffer[3007], 272, quant->HL2); /* HL2 */ + rfx_quantization_decode_block(prims, &buffer[3279], 272, quant->LH2); /* LH2 */ + rfx_quantization_decode_block(prims, &buffer[3551], 256, quant->HH2); /* HH2 */ + rfx_quantization_decode_block(prims, &buffer[3807], 72, quant->HL3); /* HL3 */ + rfx_quantization_decode_block(prims, &buffer[3879], 72, quant->LH3); /* LH3 */ + rfx_quantization_decode_block(prims, &buffer[3951], 64, quant->HH3); /* HH3 */ + rfx_quantization_decode_block(prims, &buffer[4015], 81, quant->LL3); /* LL3 */ dwt = (INT16*) BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */ @@ -502,6 +493,8 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG BufferPool_Return(progressive->bufferPool, pBuffer); + WLog_Image(progressive->log, WLOG_TRACE, tile->data, 64, 64, 32); + return 1; } @@ -1059,6 +1052,8 @@ PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor) { progressive->Compressor = Compressor; + progressive->log = WLog_Get("com.freerdp.codec.progressive"); + progressive->bufferPool = BufferPool_New(TRUE, (8192 + 32) * 3, 16); progressive->cRects = 64; From 2cffa7d8f4450535cc70fe37a4449757618f2622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 25 Aug 2014 17:58:38 -0400 Subject: [PATCH 10/30] libfreerdp-codec: make use of progressive quantization factors --- include/freerdp/codec/progressive.h | 18 ++++---- libfreerdp/codec/progressive.c | 68 +++++++++++++++++------------ 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index d32847496..5c983cba0 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -48,15 +48,6 @@ #define PROGRESSIVE_BLOCKS_REGION 0x0002 #define PROGRESSIVE_BLOCKS_TILE 0x0004 -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; @@ -72,6 +63,15 @@ struct _RFX_COMPONENT_CODEC_QUANT }; typedef struct _RFX_COMPONENT_CODEC_QUANT RFX_COMPONENT_CODEC_QUANT; +struct _RFX_PROGRESSIVE_CODEC_QUANT +{ + BYTE quality; + RFX_COMPONENT_CODEC_QUANT yQuantValues; + RFX_COMPONENT_CODEC_QUANT cbQuantValues; + RFX_COMPONENT_CODEC_QUANT crQuantValues; +}; +typedef struct _RFX_PROGRESSIVE_CODEC_QUANT RFX_PROGRESSIVE_CODEC_QUANT; + struct _PROGRESSIVE_BLOCK { UINT16 blockType; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 13ccd422f..b3974a710 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -392,8 +392,8 @@ void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* dwt) progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 1); } -int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, - RFX_COMPONENT_CODEC_QUANT* quant, const BYTE* data, int length, INT16* buffer) +int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* quant, + RFX_COMPONENT_CODEC_QUANT* quantProg, const BYTE* data, int length, INT16* buffer) { int status; INT16* dwt; @@ -406,16 +406,16 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, rfx_differential_decode(&buffer[4015], 81); /* LL3 */ - rfx_quantization_decode_block(prims, &buffer[0], 1023, quant->HL1); /* HL1 */ - rfx_quantization_decode_block(prims, &buffer[1023], 1023, quant->LH1); /* LH1 */ - rfx_quantization_decode_block(prims, &buffer[2046], 961, quant->HH1); /* HH1 */ - rfx_quantization_decode_block(prims, &buffer[3007], 272, quant->HL2); /* HL2 */ - rfx_quantization_decode_block(prims, &buffer[3279], 272, quant->LH2); /* LH2 */ - rfx_quantization_decode_block(prims, &buffer[3551], 256, quant->HH2); /* HH2 */ - rfx_quantization_decode_block(prims, &buffer[3807], 72, quant->HL3); /* HL3 */ - rfx_quantization_decode_block(prims, &buffer[3879], 72, quant->LH3); /* LH3 */ - rfx_quantization_decode_block(prims, &buffer[3951], 64, quant->HH3); /* HH3 */ - rfx_quantization_decode_block(prims, &buffer[4015], 81, quant->LL3); /* LL3 */ + rfx_quantization_decode_block(prims, &buffer[0], 1023, quant->HL1 + quantProg->HL1); /* HL1 */ + rfx_quantization_decode_block(prims, &buffer[1023], 1023, quant->LH1 + quantProg->LH1); /* LH1 */ + rfx_quantization_decode_block(prims, &buffer[2046], 961, quant->HH1 + quantProg->HH1); /* HH1 */ + rfx_quantization_decode_block(prims, &buffer[3007], 272, quant->HL2 + quantProg->HL2); /* HL2 */ + rfx_quantization_decode_block(prims, &buffer[3279], 272, quant->LH2 + quantProg->LH2); /* LH2 */ + rfx_quantization_decode_block(prims, &buffer[3551], 256, quant->HH2 + quantProg->HH2); /* HH2 */ + rfx_quantization_decode_block(prims, &buffer[3807], 72, quant->HL3 + quantProg->HL3); /* HL3 */ + rfx_quantization_decode_block(prims, &buffer[3879], 72, quant->LH3 + quantProg->LH3); /* LH3 */ + rfx_quantization_decode_block(prims, &buffer[3951], 64, quant->HH3 + quantProg->HH3); /* HH3 */ + rfx_quantization_decode_block(prims, &buffer[4015], 81, quant->LL3 + quantProg->LL3); /* LL3 */ dwt = (INT16*) BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */ @@ -434,6 +434,9 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG RFX_COMPONENT_CODEC_QUANT* quantY; RFX_COMPONENT_CODEC_QUANT* quantCb; RFX_COMPONENT_CODEC_QUANT* quantCr; + RFX_COMPONENT_CODEC_QUANT* quantProgY; + RFX_COMPONENT_CODEC_QUANT* quantProgCb; + RFX_COMPONENT_CODEC_QUANT* quantProgCr; RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; static const prim_size_t roi_64x64 = { 64, 64 }; const primitives_t* prims = primitives_get(); @@ -470,15 +473,19 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG quantProgVal = &(region->quantProgVals[tile->quality]); } + quantProgY = &(quantProgVal->yQuantValues); + quantProgCb = &(quantProgVal->cbQuantValues); + quantProgCr = &(quantProgVal->crQuantValues); + 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 */ + progressive_rfx_decode_component(progressive, quantY, quantProgY, tile->yData, tile->yLen, pSrcDst[0]); /* Y */ + progressive_rfx_decode_component(progressive, quantCb, quantProgCb, tile->cbData, tile->cbLen, pSrcDst[1]); /* Cb */ + progressive_rfx_decode_component(progressive, quantCr, quantProgCr, tile->crData, tile->crLen, pSrcDst[2]); /* Cr */ prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), pSrcDst, 64 * sizeof(INT16), &roi_64x64); @@ -770,6 +777,20 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI return (int) offset; } +void progressive_component_codec_quant_read(BYTE* block, RFX_COMPONENT_CODEC_QUANT* quantVal) +{ + quantVal->LL3 = block[0] & 0x0F; + quantVal->HL3 = block[0] >> 4; + quantVal->LH3 = block[1] & 0x0F; + quantVal->HH3 = block[1] >> 4; + quantVal->HL2 = block[2] & 0x0F; + quantVal->LH2 = block[2] >> 4; + quantVal->HH2 = block[3] & 0x0F; + quantVal->HL1 = block[3] >> 4; + quantVal->LH1 = block[4] & 0x0F; + quantVal->HH1 = block[4] >> 4; +} + int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) { @@ -949,16 +970,7 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN 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; + progressive_component_codec_quant_read(&block[boffset], quantVal); boffset += 5; } @@ -981,9 +993,9 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN { 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); + progressive_component_codec_quant_read(&block[boffset + 1], &(quantProgVal->yQuantValues)); + progressive_component_codec_quant_read(&block[boffset + 6], &(quantProgVal->cbQuantValues)); + progressive_component_codec_quant_read(&block[boffset + 11], &(quantProgVal->crQuantValues)); boffset += 16; } From ec53dd612e99f9a3455341c19dc7efab37c1a8db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 25 Aug 2014 19:50:42 -0400 Subject: [PATCH 11/30] libfreerdp-codec: fix progressive codec tile drawing offset, fix dequantization --- client/X11/xf_gfx.c | 13 ++++++++--- libfreerdp/codec/progressive.c | 40 +++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 823e1fce8..a5feee0a7 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -482,6 +482,7 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, BYTE* DstData; RFX_RECT* rect; int nXDst, nYDst; + int nXSrc, nYSrc; int nWidth, nHeight; int nbUpdateRects; xfGfxSurface* surface; @@ -531,6 +532,9 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, { tile = &(region->tiles[i]); + if (tile->blockType == PROGRESSIVE_WBT_TILE_UPGRADE) + continue; + updateRect.left = cmd->left + tile->x; updateRect.top = cmd->top + tile->y; updateRect.right = updateRect.left + 64; @@ -547,9 +551,12 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, nWidth = updateRects[j].right - updateRects[j].left; nHeight = updateRects[j].bottom - updateRects[j].top; - freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, surface->scanline, - nXDst, nYDst, nWidth, nHeight, - tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0); + nXSrc = nXDst - (cmd->left + tile->x); + nYSrc = nYDst - (cmd->top + tile->y); + + freerdp_image_copy(surface->data, PIXEL_FORMAT_XRGB32, + surface->scanline, nXDst, nYDst, nWidth, nHeight, + tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, nXSrc, nYSrc); region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &updateRects[j]); } diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index b3974a710..d88265664 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -406,16 +406,26 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPO rfx_differential_decode(&buffer[4015], 81); /* LL3 */ - rfx_quantization_decode_block(prims, &buffer[0], 1023, quant->HL1 + quantProg->HL1); /* HL1 */ - rfx_quantization_decode_block(prims, &buffer[1023], 1023, quant->LH1 + quantProg->LH1); /* LH1 */ - rfx_quantization_decode_block(prims, &buffer[2046], 961, quant->HH1 + quantProg->HH1); /* HH1 */ - rfx_quantization_decode_block(prims, &buffer[3007], 272, quant->HL2 + quantProg->HL2); /* HL2 */ - rfx_quantization_decode_block(prims, &buffer[3279], 272, quant->LH2 + quantProg->LH2); /* LH2 */ - rfx_quantization_decode_block(prims, &buffer[3551], 256, quant->HH2 + quantProg->HH2); /* HH2 */ - rfx_quantization_decode_block(prims, &buffer[3807], 72, quant->HL3 + quantProg->HL3); /* HL3 */ - rfx_quantization_decode_block(prims, &buffer[3879], 72, quant->LH3 + quantProg->LH3); /* LH3 */ - rfx_quantization_decode_block(prims, &buffer[3951], 64, quant->HH3 + quantProg->HH3); /* HH3 */ - rfx_quantization_decode_block(prims, &buffer[4015], 81, quant->LL3 + quantProg->LL3); /* LL3 */ +#if 0 + printf("quant: HL1: %d LH1: %d HH1: %d HL2: %d LH2: %d HH2: %d HL3: %d LH3: %d HH3: %d LL3: %d\n", + quant->HL1, quant->LH1, quant->HH1, quant->HL2, quant->LH2, quant->HH2, + quant->HL3, quant->LH3, quant->HH3, quant->LL3); + + printf("quantProg: HL1: %d LH1: %d HH1: %d HL2: %d LH2: %d HH2: %d HL3: %d LH3: %d HH3: %d LL3: %d\n", + quantProg->HL1, quantProg->LH1, quantProg->HH1, quantProg->HL2, quantProg->LH2, quantProg->HH2, + quantProg->HL3, quantProg->LH3, quantProg->HH3, quantProg->LL3); +#endif + + rfx_quantization_decode_block(prims, &buffer[0], 1023, quant->HL1 - 1 + quantProg->HL1); /* HL1 */ + rfx_quantization_decode_block(prims, &buffer[1023], 1023, quant->LH1 - 1 + quantProg->LH1); /* LH1 */ + rfx_quantization_decode_block(prims, &buffer[2046], 961, quant->HH1 - 1 + quantProg->HH1); /* HH1 */ + rfx_quantization_decode_block(prims, &buffer[3007], 272, quant->HL2 - 1 + quantProg->HL2); /* HL2 */ + rfx_quantization_decode_block(prims, &buffer[3279], 272, quant->LH2 - 1 + quantProg->LH2); /* LH2 */ + rfx_quantization_decode_block(prims, &buffer[3551], 256, quant->HH2 - 1 + quantProg->HH2); /* HH2 */ + rfx_quantization_decode_block(prims, &buffer[3807], 72, quant->HL3 - 1 + quantProg->HL3); /* HL3 */ + rfx_quantization_decode_block(prims, &buffer[3879], 72, quant->LH3 - 1 + quantProg->LH3); /* LH3 */ + rfx_quantization_decode_block(prims, &buffer[3951], 64, quant->HH3 - 1 + quantProg->HH3); /* HH3 */ + rfx_quantization_decode_block(prims, &buffer[4015], 81, quant->LL3 - 1 + quantProg->LL3); /* LL3 */ dwt = (INT16*) BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */ @@ -441,7 +451,7 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG static const prim_size_t roi_64x64 = { 64, 64 }; const primitives_t* prims = primitives_get(); - 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", + printf("ProgressiveTileFirst: quantIdx Y: %d Cb: %d Cr: %d xIdx: %d yIdx: %d flags: 0x%02X 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); @@ -593,7 +603,7 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI 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->flags = block[boffset + 7] & 1; /* 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) */ @@ -629,6 +639,8 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI tile->x = tile->xIdx * 64; tile->y = tile->yIdx * 64; + tile->flags &= 1; + break; case PROGRESSIVE_WBT_TILE_FIRST: @@ -641,7 +653,7 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI 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->flags = block[boffset + 7] & 1; /* 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) */ @@ -685,6 +697,8 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI if ((tile->blockLen - boffset) < 20) return -1032; + tile->flags = 0; + tile->quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ tile->quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ tile->quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */ From 4773403243414fdf98b66d9b395901e56483b6db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 26 Aug 2014 14:36:33 -0400 Subject: [PATCH 12/30] libfreerdp-codec: partial YCbCr diffing support --- include/freerdp/codec/progressive.h | 1 + libfreerdp/codec/progressive.c | 79 +++++++++++++++++++---------- 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index 5c983cba0..058415613 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -212,6 +212,7 @@ struct _RFX_PROGRESSIVE_TILE int width; int height; BYTE* data; + BYTE* yCbCrData; }; typedef struct _RFX_PROGRESSIVE_TILE RFX_PROGRESSIVE_TILE; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index d88265664..6c8d201c6 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -293,16 +293,16 @@ static int progressive_rfx_get_band_h_count(int level) return (64 + (1 << (level - 1))) >> level; } -static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int level) +static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* temp, int level) { int offset; int nBandL; int nBandH; int nDstStepX; int nDstStepY; - INT16 *L, *H; INT16 *HL, *LH; INT16 *HH, *LL; + INT16 *L, *H, *LLx; INT16* pLowBand[3]; INT16* pHighBand[3]; INT16* pDstBand[3]; @@ -333,14 +333,15 @@ static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int l nDstStepX = (nBandL + nBandH); nDstStepY = (nBandL + nBandH); - if (0) - { - nDstStepX = (nDstStepX + 15) & ~0xF; - nDstStepY = (nDstStepY + 15) & ~0xF; - } + offset = 0; - L = &dwt[0]; - H = &dwt[nBandL * nDstStepX]; + L = &temp[offset]; + offset += (nBandL * nDstStepX); + + H = &temp[offset]; + offset += (nBandH * nDstStepX); + + LLx = &buffer[0]; /* horizontal (LL + HL -> L) */ @@ -376,7 +377,7 @@ static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int l nLowStep[2] = nDstStep[0]; pHighBand[2] = pDstBand[1]; nHighStep[2] = nDstStep[1]; - pDstBand[2] = &buffer[0]; + pDstBand[2] = LLx; nDstStep[2] = nDstStepY; nLowCount[2] = nBandL; nHighCount[2] = nBandH; @@ -385,18 +386,27 @@ static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* dwt, int l progressive_rfx_idwt_y(pLowBand[2], nLowStep[2], pHighBand[2], nHighStep[2], pDstBand[2], nDstStep[2], nLowCount[2], nHighCount[2], nDstCount[2]); } -void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* dwt) +void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* temp, INT16* current, BOOL diff) { - progressive_rfx_dwt_2d_decode_block(&buffer[3807], dwt, 3); - progressive_rfx_dwt_2d_decode_block(&buffer[3007], dwt, 2); - progressive_rfx_dwt_2d_decode_block(&buffer[0], dwt, 1); + const primitives_t* prims = primitives_get(); + + progressive_rfx_dwt_2d_decode_block(&buffer[3807], temp, 3); + progressive_rfx_dwt_2d_decode_block(&buffer[3007], temp, 2); + progressive_rfx_dwt_2d_decode_block(&buffer[0], temp, 1); + + if (diff) + { + prims->add_16s(buffer, current, buffer, 4096); + } + + CopyMemory(current, buffer, 4096 * 2); } int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* quant, - RFX_COMPONENT_CODEC_QUANT* quantProg, const BYTE* data, int length, INT16* buffer) + RFX_COMPONENT_CODEC_QUANT* quantProg, const BYTE* data, int length, INT16* buffer, INT16* current, BOOL diff) { int status; - INT16* dwt; + INT16* temp; const primitives_t* prims = primitives_get(); status = rfx_rlgr_decode(data, length, buffer, 4096, 1); @@ -427,19 +437,21 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPO rfx_quantization_decode_block(prims, &buffer[3951], 64, quant->HH3 - 1 + quantProg->HH3); /* HH3 */ rfx_quantization_decode_block(prims, &buffer[4015], 81, quant->LL3 - 1 + quantProg->LL3); /* LL3 */ - dwt = (INT16*) BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */ + temp = (INT16*) BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */ - progressive_rfx_dwt_2d_decode(buffer, dwt); + progressive_rfx_dwt_2d_decode(buffer, temp, current, diff); - BufferPool_Return(progressive->bufferPool, dwt); + BufferPool_Return(progressive->bufferPool, temp); return 1; } int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) { + BOOL diff; BYTE* pBuffer; INT16* pSrcDst[3]; + INT16* pCurrent[3]; PROGRESSIVE_BLOCK_REGION* region; RFX_COMPONENT_CODEC_QUANT* quantY; RFX_COMPONENT_CODEC_QUANT* quantCb; @@ -483,28 +495,41 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG quantProgVal = &(region->quantProgVals[tile->quality]); } + diff = tile->flags & RFX_TILE_DIFFERENCE; + quantProgY = &(quantProgVal->yQuantValues); quantProgCb = &(quantProgVal->cbQuantValues); quantProgCr = &(quantProgVal->crQuantValues); + if (!tile->data) + { + tile->data = (BYTE*) _aligned_malloc(64 * 64 * 4, 16); + } + + if (!tile->yCbCrData) + { + tile->yCbCrData = (BYTE*) _aligned_malloc((8192 + 32) * 3, 16); + } + + pBuffer = tile->yCbCrData; + + pCurrent[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ + pCurrent[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ + pCurrent[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */ + 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, quantProgY, tile->yData, tile->yLen, pSrcDst[0]); /* Y */ - progressive_rfx_decode_component(progressive, quantCb, quantProgCb, tile->cbData, tile->cbLen, pSrcDst[1]); /* Cb */ - progressive_rfx_decode_component(progressive, quantCr, quantProgCr, tile->crData, tile->crLen, pSrcDst[2]); /* Cr */ + progressive_rfx_decode_component(progressive, quantY, quantProgY, tile->yData, tile->yLen, pSrcDst[0], pCurrent[0], diff); /* Y */ + progressive_rfx_decode_component(progressive, quantCb, quantProgCb, tile->cbData, tile->cbLen, pSrcDst[1], pCurrent[1], diff); /* Cb */ + progressive_rfx_decode_component(progressive, quantCr, quantProgCr, tile->crData, tile->crLen, pSrcDst[2], pCurrent[2], diff); /* Cr */ prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), pSrcDst, 64 * sizeof(INT16), &roi_64x64); - if (!tile->data) - { - tile->data = _aligned_malloc(64 * 64 * 4, 16); - } - prims->RGBToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * sizeof(INT16), tile->data, 64 * 4, &roi_64x64); From 656dd760c557dbac07e3d21a3c70712e2f725096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 26 Aug 2014 16:15:22 -0400 Subject: [PATCH 13/30] libfreerdp-codec: fix sub-band diffing --- client/X11/xf_gfx.c | 9 +- include/freerdp/codec/progressive.h | 23 +++- libfreerdp/codec/progressive.c | 166 ++++++++++++++++++++++++---- 3 files changed, 173 insertions(+), 25 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index a5feee0a7..6ca4acf48 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -499,10 +499,12 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, if (!surface) return -1; + progressive_create_surface_context(xfc->progressive, cmd->surfaceId, surface->width, surface->height); + DstData = surface->data; status = progressive_decompress(xfc->progressive, cmd->data, cmd->length, &DstData, - PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height); + PIXEL_FORMAT_XRGB32, surface->scanline, cmd->left, cmd->top, cmd->width, cmd->height, cmd->surfaceId); if (status < 0) { @@ -530,7 +532,7 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, for (i = 0; i < region->numTiles; i++) { - tile = &(region->tiles[i]); + tile = region->tiles[i]; if (tile->blockType == PROGRESSIVE_WBT_TILE_UPGRADE) continue; @@ -649,6 +651,7 @@ int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* cr int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface) { xfGfxSurface* surface = NULL; + xfContext* xfc = (xfContext*) context->custom; surface = (xfGfxSurface*) context->GetSurfaceData(context, deleteSurface->surfaceId); @@ -661,6 +664,8 @@ int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* de context->SetSurfaceData(context, deleteSurface->surfaceId, NULL); + progressive_delete_surface_context(xfc->progressive, deleteSurface->surfaceId); + return 1; } diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index 058415613..e7d9c4993 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -231,7 +231,7 @@ struct _PROGRESSIVE_BLOCK_REGION RFX_RECT* rects; RFX_COMPONENT_CODEC_QUANT* quantVals; RFX_PROGRESSIVE_CODEC_QUANT* quantProgVals; - RFX_PROGRESSIVE_TILE* tiles; + RFX_PROGRESSIVE_TILE** tiles; }; typedef struct _PROGRESSIVE_BLOCK_REGION PROGRESSIVE_BLOCK_REGION; @@ -253,6 +253,18 @@ struct _PROGRESSIVE_BLOCK_FRAME_END }; typedef struct _PROGRESSIVE_BLOCK_FRAME_END PROGRESSIVE_BLOCK_FRAME_END; +struct _PROGRESSIVE_SURFACE_CONTEXT +{ + UINT16 id; + UINT32 width; + UINT32 height; + UINT32 gridWidth; + UINT32 gridHeight; + UINT32 gridSize; + RFX_PROGRESSIVE_TILE* tiles; +}; +typedef struct _PROGRESSIVE_SURFACE_CONTEXT PROGRESSIVE_SURFACE_CONTEXT; + struct _PROGRESSIVE_CONTEXT { BOOL Compressor; @@ -264,7 +276,7 @@ struct _PROGRESSIVE_CONTEXT RFX_RECT* rects; UINT32 cTiles; - RFX_PROGRESSIVE_TILE* tiles; + RFX_PROGRESSIVE_TILE** tiles; UINT32 cQuant; RFX_COMPONENT_CODEC_QUANT* quantVals; @@ -274,6 +286,8 @@ struct _PROGRESSIVE_CONTEXT PROGRESSIVE_BLOCK_REGION region; RFX_PROGRESSIVE_CODEC_QUANT quantProgValFull; + + wHashTable* SurfaceContexts; }; typedef struct _PROGRESSIVE_CONTEXT PROGRESSIVE_CONTEXT; @@ -284,7 +298,10 @@ extern "C" { FREERDP_API int progressive_compress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize); FREERDP_API 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** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, UINT16 surfaceId); + +FREERDP_API int progressive_create_surface_context(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId, UINT32 width, UINT32 height); +FREERDP_API int progressive_delete_surface_context(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId); FREERDP_API void progressive_context_reset(PROGRESSIVE_CONTEXT* progressive); diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 6c8d201c6..aca2956e4 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -76,6 +76,80 @@ const char* progressive_get_block_type_string(UINT16 blockType) return "PROGRESSIVE_WBT_UNKNOWN"; } +int progressive_set_surface_data(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId, void* pData) +{ + ULONG_PTR key; + + key = ((ULONG_PTR) surfaceId) + 1; + + if (pData) + HashTable_Add(progressive->SurfaceContexts, (void*) key, pData); + else + HashTable_Remove(progressive->SurfaceContexts, (void*) key); + + return 1; +} + +void* progressive_get_surface_data(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId) +{ + ULONG_PTR key; + void* pData = NULL; + + key = ((ULONG_PTR) surfaceId) + 1; + + pData = HashTable_GetItemValue(progressive->SurfaceContexts, (void*) key); + + return pData; +} + +int progressive_create_surface_context(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId, UINT32 width, UINT32 height) +{ + PROGRESSIVE_SURFACE_CONTEXT* surface; + + surface = (PROGRESSIVE_SURFACE_CONTEXT*) progressive_get_surface_data(progressive, surfaceId); + + if (!surface) + { + surface = (PROGRESSIVE_SURFACE_CONTEXT*) malloc(sizeof(PROGRESSIVE_SURFACE_CONTEXT)); + + if (!surface) + return -1; + + surface->id = surfaceId; + surface->width = width; + surface->height = height; + surface->gridWidth = (width + (width % 64)) / 64; + surface->gridHeight = (height + (height % 64)) / 64; + surface->gridSize = surface->gridWidth * surface->gridHeight; + + surface->tiles = (RFX_PROGRESSIVE_TILE*) calloc(surface->gridSize, sizeof(RFX_PROGRESSIVE_TILE)); + + if (!surface->tiles) + return -1; + + progressive_set_surface_data(progressive, surfaceId, (void*) surface); + } + + return 1; +} + +int progressive_delete_surface_context(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId) +{ + PROGRESSIVE_SURFACE_CONTEXT* surface; + + surface = (PROGRESSIVE_SURFACE_CONTEXT*) progressive_get_surface_data(progressive, surfaceId); + + if (surface) + { + progressive_set_surface_data(progressive, surfaceId, NULL); + + free(surface->tiles); + free(surface); + } + + return 1; +} + /* * Band Offset Dimensions Size * @@ -583,15 +657,20 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR return 1; } -int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UINT32 blocksLen) +int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UINT32 blocksLen, PROGRESSIVE_SURFACE_CONTEXT* surface) { BYTE* block; + UINT16 xIdx; + UINT16 yIdx; + UINT16 zIdx; UINT16 index; UINT32 boffset; + UINT16 blockType; + UINT32 blockLen; UINT32 count = 0; UINT32 offset = 0; RFX_PROGRESSIVE_TILE* tile; - RFX_PROGRESSIVE_TILE* tiles; + RFX_PROGRESSIVE_TILE** tiles; PROGRESSIVE_BLOCK_REGION* region; region = &(progressive->region); @@ -603,24 +682,35 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI 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) */ + blockType = *((UINT16*) &block[boffset + 0]); /* blockType (2 bytes) */ + blockLen = *((UINT32*) &block[boffset + 2]); /* blockLen (4 bytes) */ boffset += 6; - printf("%s\n", progressive_get_block_type_string(tile->blockType)); + printf("%s\n", progressive_get_block_type_string(blockType)); - if ((blocksLen - offset) < tile->blockLen) + if ((blocksLen - offset) < blockLen) return -1003; - switch (tile->blockType) + switch (blockType) { case PROGRESSIVE_WBT_TILE_SIMPLE: - if ((tile->blockLen - boffset) < 16) + if ((blockLen - boffset) < 16) return -1022; + xIdx = *((UINT16*) &block[boffset + 3]); /* xIdx (2 bytes) */ + yIdx = *((UINT16*) &block[boffset + 5]); /* yIdx (2 bytes) */ + + zIdx = (yIdx * surface->gridWidth) + xIdx; + + if (zIdx >= surface->gridSize) + return -1; + + tiles[count] = tile = &(surface->tiles[zIdx]); + + tile->blockType = blockType; + tile->blockLen = blockLen; + tile->quality = 0xFF; /* simple tiles use no progressive techniques */ tile->quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ @@ -670,9 +760,22 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI case PROGRESSIVE_WBT_TILE_FIRST: - if ((tile->blockLen - boffset) < 17) + if ((blockLen - boffset) < 17) return -1027; + xIdx = *((UINT16*) &block[boffset + 3]); /* xIdx (2 bytes) */ + yIdx = *((UINT16*) &block[boffset + 5]); /* yIdx (2 bytes) */ + + zIdx = (yIdx * surface->gridWidth) + xIdx; + + if (zIdx >= surface->gridSize) + return -1; + + tiles[count] = tile = &(surface->tiles[zIdx]); + + tile->blockType = blockType; + tile->blockLen = blockLen; + tile->quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ tile->quantIdxCb = block[boffset + 1]; /* quantIdxCb (1 byte) */ tile->quantIdxCr = block[boffset + 2]; /* quantIdxCr (1 byte) */ @@ -719,9 +822,22 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI case PROGRESSIVE_WBT_TILE_UPGRADE: - if ((tile->blockLen - boffset) < 20) + if ((blockLen - boffset) < 20) return -1032; + xIdx = *((UINT16*) &block[boffset + 3]); /* xIdx (2 bytes) */ + yIdx = *((UINT16*) &block[boffset + 5]); /* yIdx (2 bytes) */ + + zIdx = (yIdx * surface->gridWidth) + xIdx; + + if (zIdx >= surface->gridSize) + return -1; + + tiles[count] = tile = &(surface->tiles[zIdx]); + + tile->blockType = blockType; + tile->blockLen = blockLen; + tile->flags = 0; tile->quantIdxY = block[boffset + 0]; /* quantIdxY (1 byte) */ @@ -786,10 +902,10 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI break; } - if (boffset != tile->blockLen) + if (boffset != blockLen) return -1040; - offset += tile->blockLen; + offset += blockLen; count++; } @@ -798,7 +914,7 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI for (index = 0; index < region->numTiles; index++) { - tile = &tiles[index]; + tile = tiles[index]; switch (tile->blockType) { @@ -831,7 +947,7 @@ void progressive_component_codec_quant_read(BYTE* block, RFX_COMPONENT_CODEC_QUA } 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** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, UINT16 surfaceId) { int status; BYTE* block; @@ -849,9 +965,15 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN PROGRESSIVE_BLOCK_CONTEXT context; PROGRESSIVE_BLOCK_FRAME_BEGIN frameBegin; PROGRESSIVE_BLOCK_FRAME_END frameEnd; + PROGRESSIVE_SURFACE_CONTEXT* surface; RFX_COMPONENT_CODEC_QUANT* quantVal; RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; + surface = (PROGRESSIVE_SURFACE_CONTEXT*) progressive_get_surface_data(progressive, surfaceId); + + if (!surface) + return -1001; + blocks = pSrcData; blocksLen = SrcSize; @@ -1043,8 +1165,8 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN if (region->numTiles > progressive->cTiles) { - progressive->tiles = (RFX_PROGRESSIVE_TILE*) realloc(progressive->tiles, - region->numTiles * sizeof(RFX_PROGRESSIVE_TILE)); + progressive->tiles = (RFX_PROGRESSIVE_TILE**) realloc(progressive->tiles, + region->numTiles * sizeof(RFX_PROGRESSIVE_TILE*)); progressive->cTiles = region->numTiles; } @@ -1056,7 +1178,7 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN printf("numRects: %d numTiles: %d numQuant: %d numProgQuant: %d\n", region->numRects, region->numTiles, region->numQuant, region->numProgQuant); - status = progressive_process_tiles(progressive, &block[boffset], region->tileDataSize); + status = progressive_process_tiles(progressive, &block[boffset], region->tileDataSize, surface); if (status < 0) return status; @@ -1114,7 +1236,7 @@ PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor) return NULL; progressive->cTiles = 64; - progressive->tiles = (RFX_PROGRESSIVE_TILE*) malloc(progressive->cTiles * sizeof(RFX_PROGRESSIVE_TILE)); + progressive->tiles = (RFX_PROGRESSIVE_TILE**) malloc(progressive->cTiles * sizeof(RFX_PROGRESSIVE_TILE*)); if (!progressive->tiles) return NULL; @@ -1134,6 +1256,8 @@ PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor) ZeroMemory(&(progressive->quantProgValFull), sizeof(RFX_PROGRESSIVE_CODEC_QUANT)); progressive->quantProgValFull.quality = 100; + progressive->SurfaceContexts = HashTable_New(TRUE); + progressive_context_reset(progressive); } @@ -1152,6 +1276,8 @@ void progressive_context_free(PROGRESSIVE_CONTEXT* progressive) free(progressive->quantVals); free(progressive->quantProgVals); + HashTable_Free(progressive->SurfaceContexts); + free(progressive); } From 51d1d4261665ca739081f44757d454ac45b7c3c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 27 Aug 2014 15:15:37 -0400 Subject: [PATCH 14/30] libfreerdp-codec: fix progressive tile diffing --- libfreerdp/codec/progressive.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index aca2956e4..8979239d2 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -464,16 +464,14 @@ void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* temp, INT16* current, B { const primitives_t* prims = primitives_get(); + if (diff) + prims->add_16s(buffer, current, buffer, 4096); + + CopyMemory(current, buffer, 4096 * 2); + progressive_rfx_dwt_2d_decode_block(&buffer[3807], temp, 3); progressive_rfx_dwt_2d_decode_block(&buffer[3007], temp, 2); progressive_rfx_dwt_2d_decode_block(&buffer[0], temp, 1); - - if (diff) - { - prims->add_16s(buffer, current, buffer, 4096); - } - - CopyMemory(current, buffer, 4096 * 2); } int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* quant, @@ -620,6 +618,9 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR RFX_COMPONENT_CODEC_QUANT* quantY; RFX_COMPONENT_CODEC_QUANT* quantCb; RFX_COMPONENT_CODEC_QUANT* quantCr; + RFX_COMPONENT_CODEC_QUANT* quantProgY; + RFX_COMPONENT_CODEC_QUANT* quantProgCb; + RFX_COMPONENT_CODEC_QUANT* quantProgCr; 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", @@ -654,6 +655,10 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR quantProgVal = &(region->quantProgVals[tile->quality]); } + quantProgY = &(quantProgVal->yQuantValues); + quantProgCb = &(quantProgVal->cbQuantValues); + quantProgCr = &(quantProgVal->crQuantValues); + return 1; } @@ -686,7 +691,7 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI blockLen = *((UINT32*) &block[boffset + 2]); /* blockLen (4 bytes) */ boffset += 6; - printf("%s\n", progressive_get_block_type_string(blockType)); + //printf("%s\n", progressive_get_block_type_string(blockType)); if ((blocksLen - offset) < blockLen) return -1003; From 32766b06474e9c879a39d26a249cc4a71cd4d46e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 27 Aug 2014 17:02:15 -0400 Subject: [PATCH 15/30] libfreerdp-codec: start computing BitPos --- include/freerdp/codec/progressive.h | 6 +- libfreerdp/codec/progressive.c | 115 ++++++++++++++++++++-------- 2 files changed, 86 insertions(+), 35 deletions(-) diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index e7d9c4993..35fd37ad9 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -212,7 +212,11 @@ struct _RFX_PROGRESSIVE_TILE int width; int height; BYTE* data; - BYTE* yCbCrData; + BYTE* current; + + RFX_COMPONENT_CODEC_QUANT yBitPos; + RFX_COMPONENT_CODEC_QUANT cbBitPos; + RFX_COMPONENT_CODEC_QUANT crBitPos; }; typedef struct _RFX_PROGRESSIVE_TILE RFX_PROGRESSIVE_TILE; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 8979239d2..945f9284d 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -474,8 +474,8 @@ void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* temp, INT16* current, B progressive_rfx_dwt_2d_decode_block(&buffer[0], temp, 1); } -int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* quant, - RFX_COMPONENT_CODEC_QUANT* quantProg, const BYTE* data, int length, INT16* buffer, INT16* current, BOOL diff) +int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* bitPos, + const BYTE* data, int length, INT16* buffer, INT16* current, BOOL diff) { int status; INT16* temp; @@ -488,26 +488,16 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPO rfx_differential_decode(&buffer[4015], 81); /* LL3 */ -#if 0 - printf("quant: HL1: %d LH1: %d HH1: %d HL2: %d LH2: %d HH2: %d HL3: %d LH3: %d HH3: %d LL3: %d\n", - quant->HL1, quant->LH1, quant->HH1, quant->HL2, quant->LH2, quant->HH2, - quant->HL3, quant->LH3, quant->HH3, quant->LL3); - - printf("quantProg: HL1: %d LH1: %d HH1: %d HL2: %d LH2: %d HH2: %d HL3: %d LH3: %d HH3: %d LL3: %d\n", - quantProg->HL1, quantProg->LH1, quantProg->HH1, quantProg->HL2, quantProg->LH2, quantProg->HH2, - quantProg->HL3, quantProg->LH3, quantProg->HH3, quantProg->LL3); -#endif - - rfx_quantization_decode_block(prims, &buffer[0], 1023, quant->HL1 - 1 + quantProg->HL1); /* HL1 */ - rfx_quantization_decode_block(prims, &buffer[1023], 1023, quant->LH1 - 1 + quantProg->LH1); /* LH1 */ - rfx_quantization_decode_block(prims, &buffer[2046], 961, quant->HH1 - 1 + quantProg->HH1); /* HH1 */ - rfx_quantization_decode_block(prims, &buffer[3007], 272, quant->HL2 - 1 + quantProg->HL2); /* HL2 */ - rfx_quantization_decode_block(prims, &buffer[3279], 272, quant->LH2 - 1 + quantProg->LH2); /* LH2 */ - rfx_quantization_decode_block(prims, &buffer[3551], 256, quant->HH2 - 1 + quantProg->HH2); /* HH2 */ - rfx_quantization_decode_block(prims, &buffer[3807], 72, quant->HL3 - 1 + quantProg->HL3); /* HL3 */ - rfx_quantization_decode_block(prims, &buffer[3879], 72, quant->LH3 - 1 + quantProg->LH3); /* LH3 */ - rfx_quantization_decode_block(prims, &buffer[3951], 64, quant->HH3 - 1 + quantProg->HH3); /* HH3 */ - rfx_quantization_decode_block(prims, &buffer[4015], 81, quant->LL3 - 1 + quantProg->LL3); /* LL3 */ + rfx_quantization_decode_block(prims, &buffer[0], 1023, bitPos->HL1 - 1); /* HL1 */ + rfx_quantization_decode_block(prims, &buffer[1023], 1023, bitPos->LH1 - 1); /* LH1 */ + rfx_quantization_decode_block(prims, &buffer[2046], 961, bitPos->HH1 - 1); /* HH1 */ + rfx_quantization_decode_block(prims, &buffer[3007], 272, bitPos->HL2 - 1); /* HL2 */ + rfx_quantization_decode_block(prims, &buffer[3279], 272, bitPos->LH2 - 1); /* LH2 */ + rfx_quantization_decode_block(prims, &buffer[3551], 256, bitPos->HH2 - 1); /* HH2 */ + rfx_quantization_decode_block(prims, &buffer[3807], 72, bitPos->HL3 - 1); /* HL3 */ + rfx_quantization_decode_block(prims, &buffer[3879], 72, bitPos->LH3 - 1); /* LH3 */ + rfx_quantization_decode_block(prims, &buffer[3951], 64, bitPos->HH3 - 1); /* HH3 */ + rfx_quantization_decode_block(prims, &buffer[4015], 81, bitPos->LL3 - 1); /* LL3 */ temp = (INT16*) BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */ @@ -518,6 +508,34 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPO return 1; } +void progressive_rfx_quant_add(RFX_COMPONENT_CODEC_QUANT* q1, RFX_COMPONENT_CODEC_QUANT* q2, RFX_COMPONENT_CODEC_QUANT* dst) +{ + dst->HL1 = q1->HL1 + q2->HL1; /* HL1 */ + dst->LH1 = q1->LH1 + q2->LH1; /* LH1 */ + dst->HH1 = q1->HH1 + q2->HH1; /* HH1 */ + dst->HL2 = q1->HL2 + q2->HL2; /* HL2 */ + dst->LH2 = q1->LH2 + q2->LH2; /* LH2 */ + dst->HH2 = q1->HH2 + q2->HH2; /* HH2 */ + dst->HL3 = q1->HL3 + q2->HL3; /* HL3 */ + dst->LH3 = q1->LH3 + q2->LH3; /* LH3 */ + dst->HH3 = q1->HH3 + q2->HH3; /* HH3 */ + dst->LL3 = q1->LL3 + q2->LL3; /* LL3 */ +} + +void progressive_rfx_quant_sub(RFX_COMPONENT_CODEC_QUANT* q1, RFX_COMPONENT_CODEC_QUANT* q2, RFX_COMPONENT_CODEC_QUANT* dst) +{ + dst->HL1 = q1->HL1 - q2->HL1; /* HL1 */ + dst->LH1 = q1->LH1 - q2->LH1; /* LH1 */ + dst->HH1 = q1->HH1 - q2->HH1; /* HH1 */ + dst->HL2 = q1->HL2 - q2->HL2; /* HL2 */ + dst->LH2 = q1->LH2 - q2->LH2; /* LH2 */ + dst->HH2 = q1->HH2 - q2->HH2; /* HH2 */ + dst->HL3 = q1->HL3 - q2->HL3; /* HL3 */ + dst->LH3 = q1->LH3 - q2->LH3; /* LH3 */ + dst->HH3 = q1->HH3 - q2->HH3; /* HH3 */ + dst->LL3 = q1->LL3 - q2->LL3; /* LL3 */ +} + int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) { BOOL diff; @@ -573,17 +591,21 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG quantProgCb = &(quantProgVal->cbQuantValues); quantProgCr = &(quantProgVal->crQuantValues); + progressive_rfx_quant_add(quantY, quantProgY, &(tile->yBitPos)); + progressive_rfx_quant_add(quantCb, quantProgCb, &(tile->cbBitPos)); + progressive_rfx_quant_add(quantCr, quantProgCr, &(tile->crBitPos)); + if (!tile->data) { tile->data = (BYTE*) _aligned_malloc(64 * 64 * 4, 16); } - if (!tile->yCbCrData) + if (!tile->current) { - tile->yCbCrData = (BYTE*) _aligned_malloc((8192 + 32) * 3, 16); + tile->current = (BYTE*) _aligned_malloc((8192 + 32) * 3, 16); } - pBuffer = tile->yCbCrData; + pBuffer = tile->current; pCurrent[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ pCurrent[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ @@ -595,9 +617,9 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG 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, quantProgY, tile->yData, tile->yLen, pSrcDst[0], pCurrent[0], diff); /* Y */ - progressive_rfx_decode_component(progressive, quantCb, quantProgCb, tile->cbData, tile->cbLen, pSrcDst[1], pCurrent[1], diff); /* Cb */ - progressive_rfx_decode_component(progressive, quantCr, quantProgCr, tile->crData, tile->crLen, pSrcDst[2], pCurrent[2], diff); /* Cr */ + progressive_rfx_decode_component(progressive, &(tile->yBitPos), tile->yData, tile->yLen, pSrcDst[0], pCurrent[0], diff); /* Y */ + progressive_rfx_decode_component(progressive, &(tile->crBitPos), tile->cbData, tile->cbLen, pSrcDst[1], pCurrent[1], diff); /* Cb */ + progressive_rfx_decode_component(progressive, &(tile->cbBitPos), tile->crData, tile->crLen, pSrcDst[2], pCurrent[2], diff); /* Cr */ prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), pSrcDst, 64 * sizeof(INT16), &roi_64x64); @@ -614,14 +636,21 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) { + RFX_COMPONENT_CODEC_QUANT* q; PROGRESSIVE_BLOCK_REGION* region; + RFX_COMPONENT_CODEC_QUANT yBitPos; + RFX_COMPONENT_CODEC_QUANT cbBitPos; + RFX_COMPONENT_CODEC_QUANT crBitPos; + RFX_COMPONENT_CODEC_QUANT yNumBits; + RFX_COMPONENT_CODEC_QUANT cbNumBits; + RFX_COMPONENT_CODEC_QUANT crNumBits; RFX_COMPONENT_CODEC_QUANT* quantY; RFX_COMPONENT_CODEC_QUANT* quantCb; RFX_COMPONENT_CODEC_QUANT* quantCr; RFX_COMPONENT_CODEC_QUANT* quantProgY; RFX_COMPONENT_CODEC_QUANT* quantProgCb; RFX_COMPONENT_CODEC_QUANT* quantProgCr; - RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; + RFX_PROGRESSIVE_CODEC_QUANT* quantProg; 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); @@ -645,19 +674,37 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR if (tile->quality == 0xFF) { - quantProgVal = &(progressive->quantProgValFull); + quantProg = &(progressive->quantProgValFull); } else { if (tile->quality >= region->numProgQuant) return -1; - quantProgVal = &(region->quantProgVals[tile->quality]); + quantProg = &(region->quantProgVals[tile->quality]); } - quantProgY = &(quantProgVal->yQuantValues); - quantProgCb = &(quantProgVal->cbQuantValues); - quantProgCr = &(quantProgVal->crQuantValues); + quantProgY = &(quantProg->yQuantValues); + quantProgCb = &(quantProg->cbQuantValues); + quantProgCr = &(quantProg->crQuantValues); + + progressive_rfx_quant_add(quantY, quantProgY, &yBitPos); + progressive_rfx_quant_add(quantCb, quantProgCb, &cbBitPos); + progressive_rfx_quant_add(quantCr, quantProgCr, &crBitPos); + + progressive_rfx_quant_sub(&(tile->yBitPos), &yBitPos, &yNumBits); + progressive_rfx_quant_sub(&(tile->cbBitPos), &cbBitPos, &cbNumBits); + progressive_rfx_quant_sub(&(tile->crBitPos), &crBitPos, &crNumBits); + + q = &(tile->yBitPos); + printf("Old yBitPos: HL1: %02d LH1: %02d HH1: %02d HL2: %02d LH2: %02d HH2: %02d HL3: %02d LH3: %02d HH3: %02d LL3: %02d\n", + q->HL1, q->LH1, q->HH1, q->HL2, q->LH2, q->HH2, q->HL3, q->LH3, q->HH3, q->LL3); + q = &(yBitPos); + printf("New yBitPos: HL1: %02d LH1: %02d HH1: %02d HL2: %02d LH2: %02d HH2: %02d HL3: %02d LH3: %02d HH3: %02d LL3: %02d\n", + q->HL1, q->LH1, q->HH1, q->HL2, q->LH2, q->HH2, q->HL3, q->LH3, q->HH3, q->LL3); + q = &(yNumBits); + printf(" yNumBits: HL1: %02d LH1: %02d HH1: %02d HL2: %02d LH2: %02d HH2: %02d HL3: %02d LH3: %02d HH3: %02d LL3: %02d\n", + q->HL1, q->LH1, q->HH1, q->HL2, q->LH2, q->HH2, q->HL3, q->LH3, q->HH3, q->LL3); return 1; } From 59b8bd0bd14304ea70b40dd4fc90536bacbbdc3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 27 Aug 2014 18:34:37 -0400 Subject: [PATCH 16/30] libfreerdp-codec: start reading progressive RAW bytes --- libfreerdp/codec/progressive.c | 130 ++++++++++++++++++++++++++++++--- 1 file changed, 120 insertions(+), 10 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 945f9284d..c81c389e8 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -508,6 +508,109 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPO return 1; } +struct _RFX_PROGRESSIVE_UPGRADE_STATE +{ + BOOL nonLL; + wBitStream* srl; + wBitStream* raw; + + /* SRL state */ + + int k; + int kp; + int nz; + BOOL mode; +}; +typedef struct _RFX_PROGRESSIVE_UPGRADE_STATE RFX_PROGRESSIVE_UPGRADE_STATE; + +int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* buffer, int length, UINT32 bitPos, UINT32 numBits) +{ + int index; + INT16 input; + wBitStream* srl; + wBitStream* raw; + + srl = state->srl; + raw = state->raw; + + if (!state->nonLL) + { + for (index = 0; index < length; index++) + { + raw->mask = ((1 << numBits) - 1); + input = (INT16) ((raw->accumulator >> (32 - numBits)) & raw->mask); + BitStream_Shift(raw, numBits); + + buffer[index] += (input << bitPos); + } + + return 1; + } + + for (index = 0; index < length; index++) + { + if (buffer[index] > 0) + { + /* sign > 0, read from raw */ + + raw->mask = ((1 << numBits) - 1); + input = (INT16) ((raw->accumulator >> (32 - numBits)) & raw->mask); + BitStream_Shift(raw, numBits); + + buffer[index] += (input << bitPos); + } + else if (buffer[index] > 0) + { + /* sign < 0, read from raw */ + + raw->mask = ((1 << numBits) - 1); + input = (INT16) ((raw->accumulator >> (32 - numBits)) & raw->mask); + BitStream_Shift(raw, numBits); + + buffer[index] -= (input << bitPos); + } + else + { + /* sign == 0, read from srl */ + } + } + + return 1; +} + +int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* bitPos, + RFX_COMPONENT_CODEC_QUANT* numBits, INT16* buffer, const BYTE* srlData, int srlLen, const BYTE* rawData, int rawLen) +{ + wBitStream s_srl; + wBitStream s_raw; + RFX_PROGRESSIVE_UPGRADE_STATE state; + + state.srl = &s_srl; + state.raw = &s_raw; + + BitStream_Attach(state.srl, srlData, srlLen); + BitStream_Fetch(state.srl); + + BitStream_Attach(state.raw, rawData, rawLen); + BitStream_Fetch(state.raw); + + state.nonLL = TRUE; + progressive_rfx_upgrade_block(&state, &buffer[0], 1023, bitPos->HL1, numBits->HL1); /* HL1 */ + progressive_rfx_upgrade_block(&state, &buffer[1023], 1023, bitPos->LH1, numBits->LH1); /* LH1 */ + progressive_rfx_upgrade_block(&state, &buffer[2046], 961, bitPos->HH1, numBits->HH1); /* HH1 */ + progressive_rfx_upgrade_block(&state, &buffer[3007], 272, bitPos->HL2, numBits->HL2); /* HL2 */ + progressive_rfx_upgrade_block(&state, &buffer[3279], 272, bitPos->LH2, numBits->LH2); /* LH2 */ + progressive_rfx_upgrade_block(&state, &buffer[3551], 256, bitPos->HH2, numBits->HH2); /* HH2 */ + progressive_rfx_upgrade_block(&state, &buffer[3807], 72, bitPos->HL3, numBits->HL3); /* HL3 */ + progressive_rfx_upgrade_block(&state, &buffer[3879], 72, bitPos->LH3, numBits->LH3); /* LH3 */ + progressive_rfx_upgrade_block(&state, &buffer[3951], 64, bitPos->HH3, numBits->HH3); /* HH3 */ + + state.nonLL = FALSE; + progressive_rfx_upgrade_block(&state, &buffer[4015], 81, bitPos->LL3, numBits->LL3); /* LL3 */ + + return 1; +} + void progressive_rfx_quant_add(RFX_COMPONENT_CODEC_QUANT* q1, RFX_COMPONENT_CODEC_QUANT* q2, RFX_COMPONENT_CODEC_QUANT* dst) { dst->HL1 = q1->HL1 + q2->HL1; /* HL1 */ @@ -636,7 +739,8 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) { - RFX_COMPONENT_CODEC_QUANT* q; + BYTE* pBuffer; + INT16* pCurrent[3]; PROGRESSIVE_BLOCK_REGION* region; RFX_COMPONENT_CODEC_QUANT yBitPos; RFX_COMPONENT_CODEC_QUANT cbBitPos; @@ -696,15 +800,21 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR progressive_rfx_quant_sub(&(tile->cbBitPos), &cbBitPos, &cbNumBits); progressive_rfx_quant_sub(&(tile->crBitPos), &crBitPos, &crNumBits); - q = &(tile->yBitPos); - printf("Old yBitPos: HL1: %02d LH1: %02d HH1: %02d HL2: %02d LH2: %02d HH2: %02d HL3: %02d LH3: %02d HH3: %02d LL3: %02d\n", - q->HL1, q->LH1, q->HH1, q->HL2, q->LH2, q->HH2, q->HL3, q->LH3, q->HH3, q->LL3); - q = &(yBitPos); - printf("New yBitPos: HL1: %02d LH1: %02d HH1: %02d HL2: %02d LH2: %02d HH2: %02d HL3: %02d LH3: %02d HH3: %02d LL3: %02d\n", - q->HL1, q->LH1, q->HH1, q->HL2, q->LH2, q->HH2, q->HL3, q->LH3, q->HH3, q->LL3); - q = &(yNumBits); - printf(" yNumBits: HL1: %02d LH1: %02d HH1: %02d HL2: %02d LH2: %02d HH2: %02d HL3: %02d LH3: %02d HH3: %02d LL3: %02d\n", - q->HL1, q->LH1, q->HH1, q->HL2, q->LH2, q->HH2, q->HL3, q->LH3, q->HH3, q->LL3); + CopyMemory(&(tile->yBitPos), &yBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->cbBitPos), &cbBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->crBitPos), &crBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT)); + + pBuffer = tile->current; + pCurrent[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ + pCurrent[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ + pCurrent[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */ + + progressive_rfx_upgrade_component(progressive, &yBitPos, &yNumBits, pCurrent[0], + tile->ySrlData, tile->ySrlLen, tile->yRawData, tile->yRawLen); /* Y */ + progressive_rfx_upgrade_component(progressive, &cbBitPos, &cbNumBits, pCurrent[1], + tile->cbSrlData, tile->cbSrlLen, tile->cbRawData, tile->cbRawLen); /* Cb */ + progressive_rfx_upgrade_component(progressive, &crBitPos, &crNumBits, pCurrent[2], + tile->crSrlData, tile->crSrlLen, tile->crRawData, tile->crRawLen); /* Cr */ return 1; } From e15baf618425867ca45cb2ddfb6eb10baaebd708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 28 Aug 2014 12:14:28 -0400 Subject: [PATCH 17/30] libfreerdp-codec: add code for SRL parsing --- include/freerdp/codec/progressive.h | 1 + libfreerdp/codec/progressive.c | 537 ++++++++++++++++++++-------- 2 files changed, 387 insertions(+), 151 deletions(-) diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index 35fd37ad9..f6fd26732 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -214,6 +214,7 @@ struct _RFX_PROGRESSIVE_TILE BYTE* data; BYTE* current; + int pass; RFX_COMPONENT_CODEC_QUANT yBitPos; RFX_COMPONENT_CODEC_QUANT cbBitPos; RFX_COMPONENT_CODEC_QUANT crBitPos; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index c81c389e8..b82c84f1f 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -76,6 +76,122 @@ const char* progressive_get_block_type_string(UINT16 blockType) return "PROGRESSIVE_WBT_UNKNOWN"; } +void progressive_rfx_quant_ladd(RFX_COMPONENT_CODEC_QUANT* q, int val) +{ + q->HL1 += val; /* HL1 */ + q->LH1 += val; /* LH1 */ + q->HH1 += val; /* HH1 */ + q->HL2 += val; /* HL2 */ + q->LH2 += val; /* LH2 */ + q->HH2 += val; /* HH2 */ + q->HL3 += val; /* HL3 */ + q->LH3 += val; /* LH3 */ + q->HH3 += val; /* HH3 */ + q->LL3 += val; /* LL3 */ +} + +void progressive_rfx_quant_add(RFX_COMPONENT_CODEC_QUANT* q1, RFX_COMPONENT_CODEC_QUANT* q2, RFX_COMPONENT_CODEC_QUANT* dst) +{ + dst->HL1 = q1->HL1 + q2->HL1; /* HL1 */ + dst->LH1 = q1->LH1 + q2->LH1; /* LH1 */ + dst->HH1 = q1->HH1 + q2->HH1; /* HH1 */ + dst->HL2 = q1->HL2 + q2->HL2; /* HL2 */ + dst->LH2 = q1->LH2 + q2->LH2; /* LH2 */ + dst->HH2 = q1->HH2 + q2->HH2; /* HH2 */ + dst->HL3 = q1->HL3 + q2->HL3; /* HL3 */ + dst->LH3 = q1->LH3 + q2->LH3; /* LH3 */ + dst->HH3 = q1->HH3 + q2->HH3; /* HH3 */ + dst->LL3 = q1->LL3 + q2->LL3; /* LL3 */ +} + +void progressive_rfx_quant_lsub(RFX_COMPONENT_CODEC_QUANT* q, int val) +{ + q->HL1 -= val; /* HL1 */ + q->LH1 -= val; /* LH1 */ + q->HH1 -= val; /* HH1 */ + q->HL2 -= val; /* HL2 */ + q->LH2 -= val; /* LH2 */ + q->HH2 -= val; /* HH2 */ + q->HL3 -= val; /* HL3 */ + q->LH3 -= val; /* LH3 */ + q->HH3 -= val; /* HH3 */ + q->LL3 -= val; /* LL3 */ +} + +void progressive_rfx_quant_sub(RFX_COMPONENT_CODEC_QUANT* q1, RFX_COMPONENT_CODEC_QUANT* q2, RFX_COMPONENT_CODEC_QUANT* dst) +{ + dst->HL1 = q1->HL1 - q2->HL1; /* HL1 */ + dst->LH1 = q1->LH1 - q2->LH1; /* LH1 */ + dst->HH1 = q1->HH1 - q2->HH1; /* HH1 */ + dst->HL2 = q1->HL2 - q2->HL2; /* HL2 */ + dst->LH2 = q1->LH2 - q2->LH2; /* LH2 */ + dst->HH2 = q1->HH2 - q2->HH2; /* HH2 */ + dst->HL3 = q1->HL3 - q2->HL3; /* HL3 */ + dst->LH3 = q1->LH3 - q2->LH3; /* LH3 */ + dst->HH3 = q1->HH3 - q2->HH3; /* HH3 */ + dst->LL3 = q1->LL3 - q2->LL3; /* LL3 */ +} + +BOOL progressive_rfx_quant_lcmp_less_equal(RFX_COMPONENT_CODEC_QUANT* q, int val) +{ + if (q->HL1 > val) return FALSE; /* HL1 */ + if (q->LH1 > val) return FALSE; /* LH1 */ + if (q->HH1 > val) return FALSE; /* HH1 */ + if (q->HL2 > val) return FALSE; /* HL2 */ + if (q->LH2 > val) return FALSE; /* LH2 */ + if (q->HH2 > val) return FALSE; /* HH2 */ + if (q->HL3 > val) return FALSE; /* HL3 */ + if (q->LH3 > val) return FALSE; /* LH3 */ + if (q->HH3 > val) return FALSE; /* HH3 */ + if (q->LL3 > val) return FALSE; /* LL3 */ + return TRUE; +} + +BOOL progressive_rfx_quant_cmp_less_equal(RFX_COMPONENT_CODEC_QUANT* q1, RFX_COMPONENT_CODEC_QUANT* q2) +{ + if (q1->HL1 > q2->HL1) return FALSE; /* HL1 */ + if (q1->LH1 > q2->LH1) return FALSE; /* LH1 */ + if (q1->HH1 > q2->HH1) return FALSE; /* HH1 */ + if (q1->HL2 > q2->HL2) return FALSE; /* HL2 */ + if (q1->LH2 > q2->LH2) return FALSE; /* LH2 */ + if (q1->HH2 > q2->HH2) return FALSE; /* HH2 */ + if (q1->HL3 > q2->HL3) return FALSE; /* HL3 */ + if (q1->LH3 > q2->LH3) return FALSE; /* LH3 */ + if (q1->HH3 > q2->HH3) return FALSE; /* HH3 */ + if (q1->LL3 > q2->LL3) return FALSE; /* LL3 */ + return TRUE; +} + +BOOL progressive_rfx_quant_lcmp_greater_equal(RFX_COMPONENT_CODEC_QUANT* q, int val) +{ + if (q->HL1 < val) return FALSE; /* HL1 */ + if (q->LH1 < val) return FALSE; /* LH1 */ + if (q->HH1 < val) return FALSE; /* HH1 */ + if (q->HL2 < val) return FALSE; /* HL2 */ + if (q->LH2 < val) return FALSE; /* LH2 */ + if (q->HH2 < val) return FALSE; /* HH2 */ + if (q->HL3 < val) return FALSE; /* HL3 */ + if (q->LH3 < val) return FALSE; /* LH3 */ + if (q->HH3 < val) return FALSE; /* HH3 */ + if (q->LL3 < val) return FALSE; /* LL3 */ + return TRUE; +} + +BOOL progressive_rfx_quant_cmp_greater_equal(RFX_COMPONENT_CODEC_QUANT* q1, RFX_COMPONENT_CODEC_QUANT* q2) +{ + if (q1->HL1 < q2->HL1) return FALSE; /* HL1 */ + if (q1->LH1 < q2->LH1) return FALSE; /* LH1 */ + if (q1->HH1 < q2->HH1) return FALSE; /* HH1 */ + if (q1->HL2 < q2->HL2) return FALSE; /* HL2 */ + if (q1->LH2 < q2->LH2) return FALSE; /* LH2 */ + if (q1->HH2 < q2->HH2) return FALSE; /* HH2 */ + if (q1->HL3 < q2->HL3) return FALSE; /* HL3 */ + if (q1->LH3 < q2->LH3) return FALSE; /* LH3 */ + if (q1->HH3 < q2->HH3) return FALSE; /* HH3 */ + if (q1->LL3 < q2->LL3) return FALSE; /* LL3 */ + return TRUE; +} + int progressive_set_surface_data(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId, void* pData) { ULONG_PTR key; @@ -474,7 +590,7 @@ void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* temp, INT16* current, B progressive_rfx_dwt_2d_decode_block(&buffer[0], temp, 1); } -int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* bitPos, +int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* shift, const BYTE* data, int length, INT16* buffer, INT16* current, BOOL diff) { int status; @@ -488,16 +604,16 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPO rfx_differential_decode(&buffer[4015], 81); /* LL3 */ - rfx_quantization_decode_block(prims, &buffer[0], 1023, bitPos->HL1 - 1); /* HL1 */ - rfx_quantization_decode_block(prims, &buffer[1023], 1023, bitPos->LH1 - 1); /* LH1 */ - rfx_quantization_decode_block(prims, &buffer[2046], 961, bitPos->HH1 - 1); /* HH1 */ - rfx_quantization_decode_block(prims, &buffer[3007], 272, bitPos->HL2 - 1); /* HL2 */ - rfx_quantization_decode_block(prims, &buffer[3279], 272, bitPos->LH2 - 1); /* LH2 */ - rfx_quantization_decode_block(prims, &buffer[3551], 256, bitPos->HH2 - 1); /* HH2 */ - rfx_quantization_decode_block(prims, &buffer[3807], 72, bitPos->HL3 - 1); /* HL3 */ - rfx_quantization_decode_block(prims, &buffer[3879], 72, bitPos->LH3 - 1); /* LH3 */ - rfx_quantization_decode_block(prims, &buffer[3951], 64, bitPos->HH3 - 1); /* HH3 */ - rfx_quantization_decode_block(prims, &buffer[4015], 81, bitPos->LL3 - 1); /* LL3 */ + rfx_quantization_decode_block(prims, &buffer[0], 1023, shift->HL1); /* HL1 */ + rfx_quantization_decode_block(prims, &buffer[1023], 1023, shift->LH1); /* LH1 */ + rfx_quantization_decode_block(prims, &buffer[2046], 961, shift->HH1); /* HH1 */ + rfx_quantization_decode_block(prims, &buffer[3007], 272, shift->HL2); /* HL2 */ + rfx_quantization_decode_block(prims, &buffer[3279], 272, shift->LH2); /* LH2 */ + rfx_quantization_decode_block(prims, &buffer[3551], 256, shift->HH2); /* HH2 */ + rfx_quantization_decode_block(prims, &buffer[3807], 72, shift->HL3); /* HL3 */ + rfx_quantization_decode_block(prims, &buffer[3879], 72, shift->LH3); /* LH3 */ + rfx_quantization_decode_block(prims, &buffer[3951], 64, shift->HH3); /* HH3 */ + rfx_quantization_decode_block(prims, &buffer[4015], 81, shift->LL3); /* LL3 */ temp = (INT16*) BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */ @@ -508,6 +624,116 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPO return 1; } +int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) +{ + BOOL diff; + BYTE* pBuffer; + INT16* pSrcDst[3]; + INT16* pCurrent[3]; + PROGRESSIVE_BLOCK_REGION* region; + RFX_COMPONENT_CODEC_QUANT shiftY; + RFX_COMPONENT_CODEC_QUANT shiftCb; + RFX_COMPONENT_CODEC_QUANT shiftCr; + RFX_COMPONENT_CODEC_QUANT* quantY; + RFX_COMPONENT_CODEC_QUANT* quantCb; + RFX_COMPONENT_CODEC_QUANT* quantCr; + RFX_COMPONENT_CODEC_QUANT* quantProgY; + RFX_COMPONENT_CODEC_QUANT* quantProgCb; + RFX_COMPONENT_CODEC_QUANT* quantProgCr; + RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; + static const prim_size_t roi_64x64 = { 64, 64 }; + const primitives_t* prims = primitives_get(); + + tile->pass = 1; + + diff = tile->flags & RFX_TILE_DIFFERENCE; + + printf("ProgressiveTileFirst: quantIdx Y: %d Cb: %d Cr: %d xIdx: %d yIdx: %d flags: 0x%02X 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]); + } + + quantProgY = &(quantProgVal->yQuantValues); + quantProgCb = &(quantProgVal->cbQuantValues); + quantProgCr = &(quantProgVal->crQuantValues); + + progressive_rfx_quant_add(quantY, quantProgY, &shiftY); + progressive_rfx_quant_lsub(&shiftY, 1); /* -6 + 5 = -1 */ + progressive_rfx_quant_add(quantCb, quantProgCb, &shiftCb); + progressive_rfx_quant_lsub(&shiftCb, 1); /* -6 + 5 = -1 */ + progressive_rfx_quant_add(quantCr, quantProgCr, &shiftCr); + progressive_rfx_quant_lsub(&shiftCr, 1); /* -6 + 5 = -1 */ + + CopyMemory(&(tile->yBitPos), quantProgY, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->cbBitPos), quantProgCb, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->crBitPos), quantProgCr, sizeof(RFX_COMPONENT_CODEC_QUANT)); + + if (!tile->data) + { + tile->data = (BYTE*) _aligned_malloc(64 * 64 * 4, 16); + } + + if (!tile->current) + { + tile->current = (BYTE*) _aligned_malloc((8192 + 32) * 3, 16); + } + + pBuffer = tile->current; + + pCurrent[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ + pCurrent[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ + pCurrent[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */ + + 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, &shiftY, tile->yData, tile->yLen, pSrcDst[0], pCurrent[0], diff); /* Y */ + progressive_rfx_decode_component(progressive, &shiftCb, tile->cbData, tile->cbLen, pSrcDst[1], pCurrent[1], diff); /* Cb */ + progressive_rfx_decode_component(progressive, &shiftCr, tile->crData, tile->crLen, pSrcDst[2], pCurrent[2], diff); /* Cr */ + + prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), + pSrcDst, 64 * sizeof(INT16), &roi_64x64); + + prims->RGBToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * sizeof(INT16), + tile->data, 64 * 4, &roi_64x64); + + BufferPool_Return(progressive->bufferPool, pBuffer); + + WLog_Image(progressive->log, WLOG_TRACE, tile->data, 64, 64, 32); + + return 1; +} + struct _RFX_PROGRESSIVE_UPGRADE_STATE { BOOL nonLL; @@ -523,6 +749,102 @@ struct _RFX_PROGRESSIVE_UPGRADE_STATE }; typedef struct _RFX_PROGRESSIVE_UPGRADE_STATE RFX_PROGRESSIVE_UPGRADE_STATE; +INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numBits) +{ + UINT32 bit; + UINT32 max; + UINT32 mag; + UINT32 sign; + wBitStream* bs = state->srl; + + if (state->nz) + { + state->nz--; + return 0; + } + + state->k = state->kp / 8; + + if (!state->mode) + { + /* zero encoding */ + + bit = (bs->accumulator & 0x80000000) ? 1 : 0; + BitStream_Shift(bs, 1); + + if (!bit) + { + /* '0' bit, nz >= (1 << k), nz = (1 << k) */ + + state->nz = (1 << state->k); + + state->kp += 4; + + if (state->kp > 80) + state->kp = 80; + + state->k = state->kp / 8; + + state->nz--; + return 0; + } + else + { + /* '1' bit, nz < (1 << k), nz = next k bits */ + + bs->mask = ((1 << state->k) - 1); + state->nz = ((bs->accumulator >> (32 - state->k)) & bs->mask); + BitStream_Shift(bs, state->k); + + if (state->nz) + { + state->mode = 1; /* unary encoding is next */ + state->nz--; + return 0; + } + } + } + + state->mode = 0; /* zero encoding is next */ + + /* unary encoding */ + + /* read sign bit */ + + sign = (bs->accumulator & 0x80000000) ? 1 : 0; + BitStream_Shift(bs, 1); + + if (numBits < 2) + return sign ? -1 : 1; + + mag = 0; + max = (1 << numBits) - 1; + + if (numBits != 2) + { + do + { + bit = (bs->accumulator & 0x80000000) ? 1 : 0; + BitStream_Shift(bs, 1); + + if (bit) + break; + + mag++; + } + while (mag <= max); + } + + state->kp -= 6; + + if (state->kp < 0) + state->kp = 0; + + state->k = state->kp / 8; + + return sign ? -mag : mag; +} + int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* buffer, int length, UINT32 bitPos, UINT32 numBits) { int index; @@ -530,6 +852,11 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b wBitStream* srl; wBitStream* raw; + printf("bitPos: %d numBits: %d\n", bitPos, numBits); + + if (numBits < 1) + return 1; + srl = state->srl; raw = state->raw; @@ -572,6 +899,10 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b else { /* sign == 0, read from srl */ + + input = progressive_rfx_srl_read(state, numBits); + + buffer[index] += (input << bitPos); } } @@ -581,10 +912,19 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* bitPos, RFX_COMPONENT_CODEC_QUANT* numBits, INT16* buffer, const BYTE* srlData, int srlLen, const BYTE* rawData, int rawLen) { + int aRawLen; + int aSrlLen; wBitStream s_srl; wBitStream s_raw; RFX_PROGRESSIVE_UPGRADE_STATE state; + ZeroMemory(&s_srl, sizeof(wBitStream)); + ZeroMemory(&s_raw, sizeof(wBitStream)); + ZeroMemory(&state, sizeof(RFX_PROGRESSIVE_UPGRADE_STATE)); + + state.kp = 8; + state.k = state.kp / 8; + state.srl = &s_srl; state.raw = &s_raw; @@ -608,131 +948,24 @@ int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMP state.nonLL = FALSE; progressive_rfx_upgrade_block(&state, &buffer[4015], 81, bitPos->LL3, numBits->LL3); /* LL3 */ - return 1; -} + aRawLen = (state.raw->position + 7) / 8; + aSrlLen = (state.srl->position + 7) / 8; -void progressive_rfx_quant_add(RFX_COMPONENT_CODEC_QUANT* q1, RFX_COMPONENT_CODEC_QUANT* q2, RFX_COMPONENT_CODEC_QUANT* dst) -{ - dst->HL1 = q1->HL1 + q2->HL1; /* HL1 */ - dst->LH1 = q1->LH1 + q2->LH1; /* LH1 */ - dst->HH1 = q1->HH1 + q2->HH1; /* HH1 */ - dst->HL2 = q1->HL2 + q2->HL2; /* HL2 */ - dst->LH2 = q1->LH2 + q2->LH2; /* LH2 */ - dst->HH2 = q1->HH2 + q2->HH2; /* HH2 */ - dst->HL3 = q1->HL3 + q2->HL3; /* HL3 */ - dst->LH3 = q1->LH3 + q2->LH3; /* LH3 */ - dst->HH3 = q1->HH3 + q2->HH3; /* HH3 */ - dst->LL3 = q1->LL3 + q2->LL3; /* LL3 */ -} - -void progressive_rfx_quant_sub(RFX_COMPONENT_CODEC_QUANT* q1, RFX_COMPONENT_CODEC_QUANT* q2, RFX_COMPONENT_CODEC_QUANT* dst) -{ - dst->HL1 = q1->HL1 - q2->HL1; /* HL1 */ - dst->LH1 = q1->LH1 - q2->LH1; /* LH1 */ - dst->HH1 = q1->HH1 - q2->HH1; /* HH1 */ - dst->HL2 = q1->HL2 - q2->HL2; /* HL2 */ - dst->LH2 = q1->LH2 - q2->LH2; /* LH2 */ - dst->HH2 = q1->HH2 - q2->HH2; /* HH2 */ - dst->HL3 = q1->HL3 - q2->HL3; /* HL3 */ - dst->LH3 = q1->LH3 - q2->LH3; /* LH3 */ - dst->HH3 = q1->HH3 - q2->HH3; /* HH3 */ - dst->LL3 = q1->LL3 - q2->LL3; /* LL3 */ -} - -int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) -{ - BOOL diff; - BYTE* pBuffer; - INT16* pSrcDst[3]; - INT16* pCurrent[3]; - PROGRESSIVE_BLOCK_REGION* region; - RFX_COMPONENT_CODEC_QUANT* quantY; - RFX_COMPONENT_CODEC_QUANT* quantCb; - RFX_COMPONENT_CODEC_QUANT* quantCr; - RFX_COMPONENT_CODEC_QUANT* quantProgY; - RFX_COMPONENT_CODEC_QUANT* quantProgCb; - RFX_COMPONENT_CODEC_QUANT* quantProgCr; - RFX_PROGRESSIVE_CODEC_QUANT* quantProgVal; - static const prim_size_t roi_64x64 = { 64, 64 }; - const primitives_t* prims = primitives_get(); - - printf("ProgressiveTileFirst: quantIdx Y: %d Cb: %d Cr: %d xIdx: %d yIdx: %d flags: 0x%02X 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) + if ((aRawLen != rawLen) || (aSrlLen != srlLen)) { - quantProgVal = &(progressive->quantProgValFull); + int pRawLen = 0; + int pSrlLen = 0; + + if (rawLen) + pRawLen = (int) ((((float) aRawLen) / ((float) rawLen)) * 100.0f); + + if (srlLen) + pSrlLen = (int) ((((float) aSrlLen) / ((float) srlLen)) * 100.0f); + + printf("RAW: %d/%d %d%% SRL: %d/%d %d%%\n", + aRawLen, rawLen, pRawLen, + aSrlLen, srlLen, pSrlLen); } - else - { - if (tile->quality >= region->numProgQuant) - return -1; - - quantProgVal = &(region->quantProgVals[tile->quality]); - } - - diff = tile->flags & RFX_TILE_DIFFERENCE; - - quantProgY = &(quantProgVal->yQuantValues); - quantProgCb = &(quantProgVal->cbQuantValues); - quantProgCr = &(quantProgVal->crQuantValues); - - progressive_rfx_quant_add(quantY, quantProgY, &(tile->yBitPos)); - progressive_rfx_quant_add(quantCb, quantProgCb, &(tile->cbBitPos)); - progressive_rfx_quant_add(quantCr, quantProgCr, &(tile->crBitPos)); - - if (!tile->data) - { - tile->data = (BYTE*) _aligned_malloc(64 * 64 * 4, 16); - } - - if (!tile->current) - { - tile->current = (BYTE*) _aligned_malloc((8192 + 32) * 3, 16); - } - - pBuffer = tile->current; - - pCurrent[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ - pCurrent[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ - pCurrent[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */ - - 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, &(tile->yBitPos), tile->yData, tile->yLen, pSrcDst[0], pCurrent[0], diff); /* Y */ - progressive_rfx_decode_component(progressive, &(tile->crBitPos), tile->cbData, tile->cbLen, pSrcDst[1], pCurrent[1], diff); /* Cb */ - progressive_rfx_decode_component(progressive, &(tile->cbBitPos), tile->crData, tile->crLen, pSrcDst[2], pCurrent[2], diff); /* Cr */ - - prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), - pSrcDst, 64 * sizeof(INT16), &roi_64x64); - - prims->RGBToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * sizeof(INT16), - tile->data, 64 * 4, &roi_64x64); - - BufferPool_Return(progressive->bufferPool, pBuffer); - - WLog_Image(progressive->log, WLOG_TRACE, tile->data, 64, 64, 32); return 1; } @@ -742,9 +975,6 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR BYTE* pBuffer; INT16* pCurrent[3]; PROGRESSIVE_BLOCK_REGION* region; - RFX_COMPONENT_CODEC_QUANT yBitPos; - RFX_COMPONENT_CODEC_QUANT cbBitPos; - RFX_COMPONENT_CODEC_QUANT crBitPos; RFX_COMPONENT_CODEC_QUANT yNumBits; RFX_COMPONENT_CODEC_QUANT cbNumBits; RFX_COMPONENT_CODEC_QUANT crNumBits; @@ -756,8 +986,10 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR RFX_COMPONENT_CODEC_QUANT* quantProgCr; RFX_PROGRESSIVE_CODEC_QUANT* quantProg; - 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); + tile->pass++; + + printf("ProgressiveTileUpgrade: pass: %d 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->pass, 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); @@ -792,28 +1024,24 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR quantProgCb = &(quantProg->cbQuantValues); quantProgCr = &(quantProg->crQuantValues); - progressive_rfx_quant_add(quantY, quantProgY, &yBitPos); - progressive_rfx_quant_add(quantCb, quantProgCb, &cbBitPos); - progressive_rfx_quant_add(quantCr, quantProgCr, &crBitPos); + progressive_rfx_quant_sub(&(tile->yBitPos), quantProgY, &yNumBits); + progressive_rfx_quant_sub(&(tile->cbBitPos), quantProgCb, &cbNumBits); + progressive_rfx_quant_sub(&(tile->crBitPos), quantProgCr, &crNumBits); - progressive_rfx_quant_sub(&(tile->yBitPos), &yBitPos, &yNumBits); - progressive_rfx_quant_sub(&(tile->cbBitPos), &cbBitPos, &cbNumBits); - progressive_rfx_quant_sub(&(tile->crBitPos), &crBitPos, &crNumBits); - - CopyMemory(&(tile->yBitPos), &yBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT)); - CopyMemory(&(tile->cbBitPos), &cbBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT)); - CopyMemory(&(tile->crBitPos), &crBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->yBitPos), quantProgY, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->cbBitPos), quantProgCb, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->crBitPos), quantProgCr, sizeof(RFX_COMPONENT_CODEC_QUANT)); pBuffer = tile->current; pCurrent[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ pCurrent[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ pCurrent[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */ - progressive_rfx_upgrade_component(progressive, &yBitPos, &yNumBits, pCurrent[0], + progressive_rfx_upgrade_component(progressive, quantProgY, &yNumBits, pCurrent[0], tile->ySrlData, tile->ySrlLen, tile->yRawData, tile->yRawLen); /* Y */ - progressive_rfx_upgrade_component(progressive, &cbBitPos, &cbNumBits, pCurrent[1], + progressive_rfx_upgrade_component(progressive, quantProgCb, &cbNumBits, pCurrent[1], tile->cbSrlData, tile->cbSrlLen, tile->cbRawData, tile->cbRawLen); /* Cb */ - progressive_rfx_upgrade_component(progressive, &crBitPos, &crNumBits, pCurrent[2], + progressive_rfx_upgrade_component(progressive, quantProgCr, &crNumBits, pCurrent[2], tile->crSrlData, tile->crSrlLen, tile->crRawData, tile->crRawLen); /* Cr */ return 1; @@ -1295,6 +1523,12 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN quantVal = &(region->quantVals[index]); progressive_component_codec_quant_read(&block[boffset], quantVal); boffset += 5; + + if (!progressive_rfx_quant_lcmp_greater_equal(quantVal, 6)) + return -1; + + if (!progressive_rfx_quant_lcmp_less_equal(quantVal, 15)) + return -1; } if ((blockLen - boffset) < (region->numProgQuant * 16)) @@ -1316,6 +1550,7 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN { quantProgVal = &(region->quantProgVals[index]); quantProgVal->quality = block[boffset + 0]; + progressive_component_codec_quant_read(&block[boffset + 1], &(quantProgVal->yQuantValues)); progressive_component_codec_quant_read(&block[boffset + 6], &(quantProgVal->cbQuantValues)); progressive_component_codec_quant_read(&block[boffset + 11], &(quantProgVal->crQuantValues)); From 49cede6e019ebf2636126b7771c83dbca0decf0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 28 Aug 2014 15:14:01 -0400 Subject: [PATCH 18/30] libfreerdp-codec: add separate sign array --- include/freerdp/codec/progressive.h | 1 + libfreerdp/codec/progressive.c | 185 ++++++++++++++++++---------- 2 files changed, 124 insertions(+), 62 deletions(-) diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index f6fd26732..708c7f57d 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -215,6 +215,7 @@ struct _RFX_PROGRESSIVE_TILE BYTE* current; int pass; + BYTE* sign; RFX_COMPONENT_CODEC_QUANT yBitPos; RFX_COMPONENT_CODEC_QUANT cbBitPos; RFX_COMPONENT_CODEC_QUANT crBitPos; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index b82c84f1f..ae4b41014 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -576,7 +576,7 @@ static void progressive_rfx_dwt_2d_decode_block(INT16* buffer, INT16* temp, int progressive_rfx_idwt_y(pLowBand[2], nLowStep[2], pHighBand[2], nHighStep[2], pDstBand[2], nDstStep[2], nLowCount[2], nHighCount[2], nDstCount[2]); } -void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* temp, INT16* current, BOOL diff) +void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* temp, INT16* current, INT16* sign, BOOL diff) { const primitives_t* prims = primitives_get(); @@ -590,8 +590,16 @@ void progressive_rfx_dwt_2d_decode(INT16* buffer, INT16* temp, INT16* current, B progressive_rfx_dwt_2d_decode_block(&buffer[0], temp, 1); } +void progressive_rfx_decode_block(const primitives_t* prims, INT16* buffer, int length, UINT32 shift) +{ + if (!shift) + return; + + prims->lShiftC_16s(buffer, shift, buffer, length); +} + int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* shift, - const BYTE* data, int length, INT16* buffer, INT16* current, BOOL diff) + const BYTE* data, int length, INT16* buffer, INT16* current, INT16* sign, BOOL diff) { int status; INT16* temp; @@ -602,22 +610,24 @@ int progressive_rfx_decode_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPO if (status < 0) return status; + CopyMemory(sign, buffer, 4096 * 2); + rfx_differential_decode(&buffer[4015], 81); /* LL3 */ - rfx_quantization_decode_block(prims, &buffer[0], 1023, shift->HL1); /* HL1 */ - rfx_quantization_decode_block(prims, &buffer[1023], 1023, shift->LH1); /* LH1 */ - rfx_quantization_decode_block(prims, &buffer[2046], 961, shift->HH1); /* HH1 */ - rfx_quantization_decode_block(prims, &buffer[3007], 272, shift->HL2); /* HL2 */ - rfx_quantization_decode_block(prims, &buffer[3279], 272, shift->LH2); /* LH2 */ - rfx_quantization_decode_block(prims, &buffer[3551], 256, shift->HH2); /* HH2 */ - rfx_quantization_decode_block(prims, &buffer[3807], 72, shift->HL3); /* HL3 */ - rfx_quantization_decode_block(prims, &buffer[3879], 72, shift->LH3); /* LH3 */ - rfx_quantization_decode_block(prims, &buffer[3951], 64, shift->HH3); /* HH3 */ - rfx_quantization_decode_block(prims, &buffer[4015], 81, shift->LL3); /* LL3 */ + progressive_rfx_decode_block(prims, &buffer[0], 1023, shift->HL1); /* HL1 */ + progressive_rfx_decode_block(prims, &buffer[1023], 1023, shift->LH1); /* LH1 */ + progressive_rfx_decode_block(prims, &buffer[2046], 961, shift->HH1); /* HH1 */ + progressive_rfx_decode_block(prims, &buffer[3007], 272, shift->HL2); /* HL2 */ + progressive_rfx_decode_block(prims, &buffer[3279], 272, shift->LH2); /* LH2 */ + progressive_rfx_decode_block(prims, &buffer[3551], 256, shift->HH2); /* HH2 */ + progressive_rfx_decode_block(prims, &buffer[3807], 72, shift->HL3); /* HL3 */ + progressive_rfx_decode_block(prims, &buffer[3879], 72, shift->LH3); /* LH3 */ + progressive_rfx_decode_block(prims, &buffer[3951], 64, shift->HH3); /* HH3 */ + progressive_rfx_decode_block(prims, &buffer[4015], 81, shift->LL3); /* LL3 */ temp = (INT16*) BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */ - progressive_rfx_dwt_2d_decode(buffer, temp, current, diff); + progressive_rfx_dwt_2d_decode(buffer, temp, current, sign, diff); BufferPool_Return(progressive->bufferPool, temp); @@ -628,6 +638,7 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG { BOOL diff; BYTE* pBuffer; + INT16* pSign[3]; INT16* pSrcDst[3]; INT16* pCurrent[3]; PROGRESSIVE_BLOCK_REGION* region; @@ -700,26 +711,34 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG tile->data = (BYTE*) _aligned_malloc(64 * 64 * 4, 16); } + if (!tile->sign) + { + tile->sign = (BYTE*) _aligned_malloc((8192 + 32) * 3, 16); + } + if (!tile->current) { tile->current = (BYTE*) _aligned_malloc((8192 + 32) * 3, 16); } - pBuffer = tile->current; + pBuffer = tile->sign; + pSign[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ + pSign[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ + pSign[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */ + pBuffer = tile->current; pCurrent[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ pCurrent[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ pCurrent[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */ 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, &shiftY, tile->yData, tile->yLen, pSrcDst[0], pCurrent[0], diff); /* Y */ - progressive_rfx_decode_component(progressive, &shiftCb, tile->cbData, tile->cbLen, pSrcDst[1], pCurrent[1], diff); /* Cb */ - progressive_rfx_decode_component(progressive, &shiftCr, tile->crData, tile->crLen, pSrcDst[2], pCurrent[2], diff); /* Cr */ + progressive_rfx_decode_component(progressive, &shiftY, tile->yData, tile->yLen, pSrcDst[0], pCurrent[0], pSign[0], diff); /* Y */ + progressive_rfx_decode_component(progressive, &shiftCb, tile->cbData, tile->cbLen, pSrcDst[1], pCurrent[1], pSign[1], diff); /* Cb */ + progressive_rfx_decode_component(progressive, &shiftCr, tile->crData, tile->crLen, pSrcDst[2], pCurrent[2], pSign[2], diff); /* Cr */ prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), pSrcDst, 64 * sizeof(INT16), &roi_64x64); @@ -763,8 +782,6 @@ INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numB return 0; } - state->k = state->kp / 8; - if (!state->mode) { /* zero encoding */ @@ -788,20 +805,23 @@ INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numB state->nz--; return 0; } - else - { - /* '1' bit, nz < (1 << k), nz = next k bits */ + /* '1' bit, nz < (1 << k), nz = next k bits */ + + state->nz = 0; + + if (state->k) + { bs->mask = ((1 << state->k) - 1); state->nz = ((bs->accumulator >> (32 - state->k)) & bs->mask); BitStream_Shift(bs, state->k); + } - if (state->nz) - { - state->mode = 1; /* unary encoding is next */ - state->nz--; - return 0; - } + if (state->nz) + { + state->mode = 1; /* unary encoding is next */ + state->nz--; + return 0; } } @@ -814,9 +834,6 @@ INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numB sign = (bs->accumulator & 0x80000000) ? 1 : 0; BitStream_Shift(bs, 1); - if (numBits < 2) - return sign ? -1 : 1; - mag = 0; max = (1 << numBits) - 1; @@ -845,16 +862,16 @@ INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numB return sign ? -mag : mag; } -int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* buffer, int length, UINT32 bitPos, UINT32 numBits) +int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* buffer, INT16* sign, int length, UINT32 bitPos, UINT32 numBits) { int index; INT16 input; wBitStream* srl; wBitStream* raw; - printf("bitPos: %d numBits: %d\n", bitPos, numBits); + //printf("bitPos: %d numBits: %d\n", bitPos, numBits); - if (numBits < 1) + if (!numBits) return 1; srl = state->srl; @@ -876,17 +893,15 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b for (index = 0; index < length; index++) { - if (buffer[index] > 0) + if (sign[index] > 0) { /* sign > 0, read from raw */ raw->mask = ((1 << numBits) - 1); input = (INT16) ((raw->accumulator >> (32 - numBits)) & raw->mask); BitStream_Shift(raw, numBits); - - buffer[index] += (input << bitPos); } - else if (buffer[index] > 0) + else if (sign[index] < 0) { /* sign < 0, read from raw */ @@ -894,23 +909,25 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b input = (INT16) ((raw->accumulator >> (32 - numBits)) & raw->mask); BitStream_Shift(raw, numBits); - buffer[index] -= (input << bitPos); + input *= -1; } else { /* sign == 0, read from srl */ input = progressive_rfx_srl_read(state, numBits); - - buffer[index] += (input << bitPos); } + + buffer[index] += (input << bitPos); + sign[index] = input; } return 1; } int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* bitPos, - RFX_COMPONENT_CODEC_QUANT* numBits, INT16* buffer, const BYTE* srlData, int srlLen, const BYTE* rawData, int rawLen) + RFX_COMPONENT_CODEC_QUANT* numBits, INT16* buffer, INT16* current, INT16* sign, + const BYTE* srlData, int srlLen, const BYTE* rawData, int rawLen) { int aRawLen; int aSrlLen; @@ -924,7 +941,6 @@ int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMP state.kp = 8; state.k = state.kp / 8; - state.srl = &s_srl; state.raw = &s_raw; @@ -935,18 +951,20 @@ int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMP BitStream_Fetch(state.raw); state.nonLL = TRUE; - progressive_rfx_upgrade_block(&state, &buffer[0], 1023, bitPos->HL1, numBits->HL1); /* HL1 */ - progressive_rfx_upgrade_block(&state, &buffer[1023], 1023, bitPos->LH1, numBits->LH1); /* LH1 */ - progressive_rfx_upgrade_block(&state, &buffer[2046], 961, bitPos->HH1, numBits->HH1); /* HH1 */ - progressive_rfx_upgrade_block(&state, &buffer[3007], 272, bitPos->HL2, numBits->HL2); /* HL2 */ - progressive_rfx_upgrade_block(&state, &buffer[3279], 272, bitPos->LH2, numBits->LH2); /* LH2 */ - progressive_rfx_upgrade_block(&state, &buffer[3551], 256, bitPos->HH2, numBits->HH2); /* HH2 */ - progressive_rfx_upgrade_block(&state, &buffer[3807], 72, bitPos->HL3, numBits->HL3); /* HL3 */ - progressive_rfx_upgrade_block(&state, &buffer[3879], 72, bitPos->LH3, numBits->LH3); /* LH3 */ - progressive_rfx_upgrade_block(&state, &buffer[3951], 64, bitPos->HH3, numBits->HH3); /* HH3 */ + progressive_rfx_upgrade_block(&state, ¤t[0], &sign[0], 1023, bitPos->HL1, numBits->HL1); /* HL1 */ + progressive_rfx_upgrade_block(&state, ¤t[1023], &sign[1023], 1023, bitPos->LH1, numBits->LH1); /* LH1 */ + progressive_rfx_upgrade_block(&state, ¤t[2046], &sign[2046], 961, bitPos->HH1, numBits->HH1); /* HH1 */ + progressive_rfx_upgrade_block(&state, ¤t[3007], &sign[3007], 272, bitPos->HL2, numBits->HL2); /* HL2 */ + progressive_rfx_upgrade_block(&state, ¤t[3279], &sign[3279], 272, bitPos->LH2, numBits->LH2); /* LH2 */ + progressive_rfx_upgrade_block(&state, ¤t[3551], &sign[3551], 256, bitPos->HH2, numBits->HH2); /* HH2 */ + progressive_rfx_upgrade_block(&state, ¤t[3807], &sign[3807], 72, bitPos->HL3, numBits->HL3); /* HL3 */ + progressive_rfx_upgrade_block(&state, ¤t[3879], &sign[3879], 72, bitPos->LH3, numBits->LH3); /* LH3 */ + progressive_rfx_upgrade_block(&state, ¤t[3951], &sign[3951], 64, bitPos->HH3, numBits->HH3); /* HH3 */ state.nonLL = FALSE; - progressive_rfx_upgrade_block(&state, &buffer[4015], 81, bitPos->LL3, numBits->LL3); /* LL3 */ + progressive_rfx_upgrade_block(&state, ¤t[4015], &sign[4015], 81, bitPos->LL3, numBits->LL3); /* LL3 */ + + CopyMemory(buffer, current, 4096 * 2); aRawLen = (state.raw->position + 7) / 8; aSrlLen = (state.srl->position + 7) / 8; @@ -965,6 +983,8 @@ int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMP printf("RAW: %d/%d %d%% SRL: %d/%d %d%%\n", aRawLen, rawLen, pRawLen, aSrlLen, srlLen, pSrlLen); + + return -1; } return 1; @@ -972,7 +992,10 @@ int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMP int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PROGRESSIVE_TILE* tile) { + int status; BYTE* pBuffer; + INT16* pSign[3]; + INT16* pSrcDst[3]; INT16* pCurrent[3]; PROGRESSIVE_BLOCK_REGION* region; RFX_COMPONENT_CODEC_QUANT yNumBits; @@ -985,9 +1008,14 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR RFX_COMPONENT_CODEC_QUANT* quantProgCb; RFX_COMPONENT_CODEC_QUANT* quantProgCr; RFX_PROGRESSIVE_CODEC_QUANT* quantProg; + static const prim_size_t roi_64x64 = { 64, 64 }; + const primitives_t* prims = primitives_get(); tile->pass++; + if (tile->pass > 2) + return 1; /* skip for now */ + printf("ProgressiveTileUpgrade: pass: %d 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->pass, tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, tile->xIdx, tile->yIdx, tile->quality, tile->ySrlLen, tile->yRawLen, tile->cbSrlLen, tile->cbRawLen, tile->crSrlLen, tile->crRawLen); @@ -1032,23 +1060,53 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR CopyMemory(&(tile->cbBitPos), quantProgCb, sizeof(RFX_COMPONENT_CODEC_QUANT)); CopyMemory(&(tile->crBitPos), quantProgCr, sizeof(RFX_COMPONENT_CODEC_QUANT)); + pBuffer = tile->sign; + pSign[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ + pSign[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ + pSign[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */ + pBuffer = tile->current; pCurrent[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ pCurrent[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ pCurrent[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */ - progressive_rfx_upgrade_component(progressive, quantProgY, &yNumBits, pCurrent[0], - tile->ySrlData, tile->ySrlLen, tile->yRawData, tile->yRawLen); /* Y */ - progressive_rfx_upgrade_component(progressive, quantProgCb, &cbNumBits, pCurrent[1], - tile->cbSrlData, tile->cbSrlLen, tile->cbRawData, tile->cbRawLen); /* Cb */ - progressive_rfx_upgrade_component(progressive, quantProgCr, &crNumBits, pCurrent[2], - tile->crSrlData, tile->crSrlLen, tile->crRawData, tile->crRawLen); /* Cr */ + 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 */ + + status = progressive_rfx_upgrade_component(progressive, quantProgY, &yNumBits, + pSrcDst[0], pCurrent[0], pSign[0], tile->ySrlData, tile->ySrlLen, tile->yRawData, tile->yRawLen); /* Y */ + + if (status < 0) + return -1; + + status = progressive_rfx_upgrade_component(progressive, quantProgCb, &cbNumBits, + pSrcDst[1], pCurrent[1], pSign[1], tile->cbSrlData, tile->cbSrlLen, tile->cbRawData, tile->cbRawLen); /* Cb */ + + if (status < 0) + return -1; + + status = progressive_rfx_upgrade_component(progressive, quantProgCr, &crNumBits, + pSrcDst[2], pCurrent[2], pSign[2], tile->crSrlData, tile->crSrlLen, tile->crRawData, tile->crRawLen); /* Cr */ + + if (status < 0) + return -1; + + prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), + pSrcDst, 64 * sizeof(INT16), &roi_64x64); + + prims->RGBToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * sizeof(INT16), + tile->data, 64 * 4, &roi_64x64); + + BufferPool_Return(progressive->bufferPool, pBuffer); return 1; } int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UINT32 blocksLen, PROGRESSIVE_SURFACE_CONTEXT* surface) { + int status; BYTE* block; UINT16 xIdx; UINT16 yIdx; @@ -1310,13 +1368,16 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI { case PROGRESSIVE_WBT_TILE_SIMPLE: case PROGRESSIVE_WBT_TILE_FIRST: - progressive_decompress_tile_first(progressive, tile); + status = progressive_decompress_tile_first(progressive, tile); break; case PROGRESSIVE_WBT_TILE_UPGRADE: - progressive_decompress_tile_upgrade(progressive, tile); + status = progressive_decompress_tile_upgrade(progressive, tile); break; } + + if (status < 0) + return -1; } return (int) offset; From 6abd9e6be071756a41d950c1fd9f2fdb8d335038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 2 Sep 2014 13:31:40 -0400 Subject: [PATCH 19/30] libfreerdp-codec: add more progressive test functions --- include/freerdp/codec/progressive.h | 6 + libfreerdp/codec/progressive.c | 212 +++++++++++++++++++++++----- 2 files changed, 183 insertions(+), 35 deletions(-) diff --git a/include/freerdp/codec/progressive.h b/include/freerdp/codec/progressive.h index 708c7f57d..e18310ed8 100644 --- a/include/freerdp/codec/progressive.h +++ b/include/freerdp/codec/progressive.h @@ -219,6 +219,12 @@ struct _RFX_PROGRESSIVE_TILE RFX_COMPONENT_CODEC_QUANT yBitPos; RFX_COMPONENT_CODEC_QUANT cbBitPos; RFX_COMPONENT_CODEC_QUANT crBitPos; + RFX_COMPONENT_CODEC_QUANT yQuant; + RFX_COMPONENT_CODEC_QUANT cbQuant; + RFX_COMPONENT_CODEC_QUANT crQuant; + RFX_COMPONENT_CODEC_QUANT yProgQuant; + RFX_COMPONENT_CODEC_QUANT cbProgQuant; + RFX_COMPONENT_CODEC_QUANT crProgQuant; }; typedef struct _RFX_PROGRESSIVE_TILE RFX_PROGRESSIVE_TILE; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index ae4b41014..650031a3b 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -76,6 +76,20 @@ const char* progressive_get_block_type_string(UINT16 blockType) return "PROGRESSIVE_WBT_UNKNOWN"; } +void progressive_component_codec_quant_read(BYTE* block, RFX_COMPONENT_CODEC_QUANT* quantVal) +{ + quantVal->LL3 = block[0] & 0x0F; + quantVal->HL3 = block[0] >> 4; + quantVal->LH3 = block[1] & 0x0F; + quantVal->HH3 = block[1] >> 4; + quantVal->HL2 = block[2] & 0x0F; + quantVal->LH2 = block[2] >> 4; + quantVal->HH2 = block[3] & 0x0F; + quantVal->HL1 = block[3] >> 4; + quantVal->LH1 = block[4] & 0x0F; + quantVal->HH1 = block[4] >> 4; +} + void progressive_rfx_quant_ladd(RFX_COMPONENT_CODEC_QUANT* q, int val) { q->HL1 += val; /* HL1 */ @@ -192,6 +206,21 @@ BOOL progressive_rfx_quant_cmp_greater_equal(RFX_COMPONENT_CODEC_QUANT* q1, RFX_ return TRUE; } +BOOL progressive_rfx_quant_cmp_equal(RFX_COMPONENT_CODEC_QUANT* q1, RFX_COMPONENT_CODEC_QUANT* q2) +{ + if (q1->HL1 != q2->HL1) return FALSE; /* HL1 */ + if (q1->LH1 != q2->LH1) return FALSE; /* LH1 */ + if (q1->HH1 != q2->HH1) return FALSE; /* HH1 */ + if (q1->HL2 != q2->HL2) return FALSE; /* HL2 */ + if (q1->LH2 != q2->LH2) return FALSE; /* LH2 */ + if (q1->HH2 != q2->HH2) return FALSE; /* HH2 */ + if (q1->HL3 != q2->HL3) return FALSE; /* HL3 */ + if (q1->LH3 != q2->LH3) return FALSE; /* LH3 */ + if (q1->HH3 != q2->HH3) return FALSE; /* HH3 */ + if (q1->LL3 != q2->LL3) return FALSE; /* LL3 */ + return TRUE; +} + int progressive_set_surface_data(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId, void* pData) { ULONG_PTR key; @@ -695,6 +724,18 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG quantProgCb = &(quantProgVal->cbQuantValues); quantProgCr = &(quantProgVal->crQuantValues); + CopyMemory(&(tile->yQuant), quantY, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->cbQuant), quantCb, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->crQuant), quantCr, sizeof(RFX_COMPONENT_CODEC_QUANT)); + + CopyMemory(&(tile->yProgQuant), quantProgY, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->cbProgQuant), quantProgCb, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->crProgQuant), quantProgCr, sizeof(RFX_COMPONENT_CODEC_QUANT)); + + progressive_rfx_quant_add(quantY, quantProgY, &(tile->yBitPos)); + progressive_rfx_quant_add(quantCb, quantProgCb, &(tile->cbBitPos)); + progressive_rfx_quant_add(quantCr, quantProgCr, &(tile->crBitPos)); + progressive_rfx_quant_add(quantY, quantProgY, &shiftY); progressive_rfx_quant_lsub(&shiftY, 1); /* -6 + 5 = -1 */ progressive_rfx_quant_add(quantCb, quantProgCb, &shiftCb); @@ -702,10 +743,6 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG progressive_rfx_quant_add(quantCr, quantProgCr, &shiftCr); progressive_rfx_quant_lsub(&shiftCr, 1); /* -6 + 5 = -1 */ - CopyMemory(&(tile->yBitPos), quantProgY, sizeof(RFX_COMPONENT_CODEC_QUANT)); - CopyMemory(&(tile->cbBitPos), quantProgCb, sizeof(RFX_COMPONENT_CODEC_QUANT)); - CopyMemory(&(tile->crBitPos), quantProgCr, sizeof(RFX_COMPONENT_CODEC_QUANT)); - if (!tile->data) { tile->data = (BYTE*) _aligned_malloc(64 * 64 * 4, 16); @@ -834,22 +871,21 @@ INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numB sign = (bs->accumulator & 0x80000000) ? 1 : 0; BitStream_Shift(bs, 1); - mag = 0; + if (numBits == 1) + return sign ? -1 : 1; + + mag = 1; max = (1 << numBits) - 1; - if (numBits != 2) + while (mag < max) { - do - { - bit = (bs->accumulator & 0x80000000) ? 1 : 0; - BitStream_Shift(bs, 1); + bit = (bs->accumulator & 0x80000000) ? 1 : 0; + BitStream_Shift(bs, 1); - if (bit) - break; + if (bit) + break; - mag++; - } - while (mag <= max); + mag++; } state->kp -= 6; @@ -925,6 +961,102 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b return 1; } +int progressive_rfx_upgrade_block_count_raw(BOOL nonLL, INT16* sign, int length, int numBits) +{ + int index; + int count = 0; + + if (numBits < 0) + return 0; + + if (!nonLL) + { + count = length; + return (count * numBits); + } + + for (index = 0; index < length; index++) + { + if (sign[index] != 0) + count++; + } + + return (count * numBits); +} + +int progressive_rfx_upgrade_component_count_raw(RFX_COMPONENT_CODEC_QUANT* numBits, INT16* sign, int delta) +{ + int count = 0; + + count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[0], 1023, numBits->HL1 + delta); /* HL1 */ + count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[1023], 1023, numBits->LH1 + delta); /* LH1 */ + count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[2046], 961, numBits->HH1 + delta); /* HH1 */ + count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[3007], 272, numBits->HL2 + delta); /* HL2 */ + count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[3279], 272, numBits->LH2 + delta); /* LH2 */ + count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[3551], 256, numBits->HH2 + delta); /* HH2 */ + count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[3807], 72, numBits->HL3 + delta); /* HL3 */ + count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[3879], 72, numBits->LH3 + delta); /* LH3 */ + count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[3951], 64, numBits->HH3 + delta); /* HH3 */ + count += progressive_rfx_upgrade_block_count_raw(FALSE, &sign[4015], 81, numBits->LL3 + delta); /* LL3 */ + + return (count + 7) / 8; +} + +int progressive_rfx_upgrade_component_fix_count(RFX_COMPONENT_CODEC_QUANT* numBits, INT16* sign, int rawLen) +{ + int delta = 0; + int count = 0; + int p_count = 0; + int count_n[3] = { 0 }; + int p_count_n[3] = { 0 }; + int count_p[3] = { 0 }; + int p_count_p[3] = { 0 }; + + count_n[0] = progressive_rfx_upgrade_component_count_raw(numBits, sign, -1); + count_n[1] = progressive_rfx_upgrade_component_count_raw(numBits, sign, -2); + count_n[2] = progressive_rfx_upgrade_component_count_raw(numBits, sign, -3); + + count = progressive_rfx_upgrade_component_count_raw(numBits, sign, 0); + + count_p[0] = progressive_rfx_upgrade_component_count_raw(numBits, sign, 1); + count_p[1] = progressive_rfx_upgrade_component_count_raw(numBits, sign, 2); + count_p[2] = progressive_rfx_upgrade_component_count_raw(numBits, sign, 3); + + if (rawLen) + { + p_count_n[0] = (int) ((((float) count_n[0]) / ((float) rawLen)) * 100.0f); + p_count_n[1] = (int) ((((float) count_n[1]) / ((float) rawLen)) * 100.0f); + p_count_n[2] = (int) ((((float) count_n[2]) / ((float) rawLen)) * 100.0f); + + p_count = (int) ((((float) count) / ((float) rawLen)) * 100.0f); + + p_count_p[0] = (int) ((((float) count_p[0]) / ((float) rawLen)) * 100.0f); + p_count_p[1] = (int) ((((float) count_p[1]) / ((float) rawLen)) * 100.0f); + p_count_p[2] = (int) ((((float) count_p[2]) / ((float) rawLen)) * 100.0f); + } + + if (p_count_n[0] == 100) + delta = -1; + if (p_count_n[1] == 100) + delta = -2; + if (p_count_n[2] == 100) + delta = -3; + + if (p_count_p[0] == 100) + delta = 1; + if (p_count_p[1] == 100) + delta = 2; + if (p_count_p[2] == 100) + delta = 3; + + printf("NumBitsFix: -3: %d -2: %d -1: %d 0: %d 1: %d 2: %d 3: %d\n", + p_count_n[2], p_count_n[1], p_count_n[0], p_count, p_count_p[0], p_count_p[1], p_count_p[2]); + printf("NumBitsFix HL1: %d LH1: %d HH1: %d HL2: %d LH2: %d HH2: %d HL3: %d LH3: %d HH3: %d LL3: %d\n", + numBits->HL1, numBits->LH1, numBits->HH1, numBits->HL2, numBits->LH2, numBits->HH2, numBits->HL3, numBits->LH3, numBits->HH3, numBits->LL3); + + return delta; +} + int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* bitPos, RFX_COMPONENT_CODEC_QUANT* numBits, INT16* buffer, INT16* current, INT16* sign, const BYTE* srlData, int srlLen, const BYTE* rawData, int rawLen) @@ -939,6 +1071,8 @@ int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMP ZeroMemory(&s_raw, sizeof(wBitStream)); ZeroMemory(&state, sizeof(RFX_PROGRESSIVE_UPGRADE_STATE)); + progressive_rfx_upgrade_component_fix_count(numBits, sign, rawLen); + state.kp = 8; state.k = state.kp / 8; state.srl = &s_srl; @@ -998,6 +1132,9 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR INT16* pSrcDst[3]; INT16* pCurrent[3]; PROGRESSIVE_BLOCK_REGION* region; + RFX_COMPONENT_CODEC_QUANT yBitPos; + RFX_COMPONENT_CODEC_QUANT cbBitPos; + RFX_COMPONENT_CODEC_QUANT crBitPos; RFX_COMPONENT_CODEC_QUANT yNumBits; RFX_COMPONENT_CODEC_QUANT cbNumBits; RFX_COMPONENT_CODEC_QUANT crNumBits; @@ -1052,13 +1189,32 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR quantProgCb = &(quantProg->cbQuantValues); quantProgCr = &(quantProg->crQuantValues); - progressive_rfx_quant_sub(&(tile->yBitPos), quantProgY, &yNumBits); - progressive_rfx_quant_sub(&(tile->cbBitPos), quantProgCb, &cbNumBits); - progressive_rfx_quant_sub(&(tile->crBitPos), quantProgCr, &crNumBits); + if (!progressive_rfx_quant_cmp_equal(quantY, &(tile->yQuant))) + printf("warning: non-progressive quantY has changed!\n"); + if (!progressive_rfx_quant_cmp_equal(quantCb, &(tile->cbQuant))) + printf("warning: non-progressive quantCb has changed!\n"); + if (!progressive_rfx_quant_cmp_equal(quantCr, &(tile->crQuant))) + printf("warning: non-progressive quantCr has changed!\n"); - CopyMemory(&(tile->yBitPos), quantProgY, sizeof(RFX_COMPONENT_CODEC_QUANT)); - CopyMemory(&(tile->cbBitPos), quantProgCb, sizeof(RFX_COMPONENT_CODEC_QUANT)); - CopyMemory(&(tile->crBitPos), quantProgCr, sizeof(RFX_COMPONENT_CODEC_QUANT)); + progressive_rfx_quant_add(quantY, quantProgY, &yBitPos); + progressive_rfx_quant_add(quantCb, quantProgCb, &cbBitPos); + progressive_rfx_quant_add(quantCr, quantProgCr, &crBitPos); + + progressive_rfx_quant_sub(&(tile->yBitPos), &yBitPos, &yNumBits); + progressive_rfx_quant_sub(&(tile->cbBitPos), &cbBitPos, &cbNumBits); + progressive_rfx_quant_sub(&(tile->crBitPos), &crBitPos, &crNumBits); + + CopyMemory(&(tile->yBitPos), &yBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->cbBitPos), &cbBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->crBitPos), &crBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT)); + + CopyMemory(&(tile->yQuant), quantY, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->cbQuant), quantCb, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->crQuant), quantCr, sizeof(RFX_COMPONENT_CODEC_QUANT)); + + CopyMemory(&(tile->yProgQuant), quantProgY, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->cbProgQuant), quantProgCb, sizeof(RFX_COMPONENT_CODEC_QUANT)); + CopyMemory(&(tile->crProgQuant), quantProgCr, sizeof(RFX_COMPONENT_CODEC_QUANT)); pBuffer = tile->sign; pSign[0] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 0) + 16])); /* Y/R buffer */ @@ -1383,20 +1539,6 @@ int progressive_process_tiles(PROGRESSIVE_CONTEXT* progressive, BYTE* blocks, UI return (int) offset; } -void progressive_component_codec_quant_read(BYTE* block, RFX_COMPONENT_CODEC_QUANT* quantVal) -{ - quantVal->LL3 = block[0] & 0x0F; - quantVal->HL3 = block[0] >> 4; - quantVal->LH3 = block[1] & 0x0F; - quantVal->HH3 = block[1] >> 4; - quantVal->HL2 = block[2] & 0x0F; - quantVal->LH2 = block[2] >> 4; - quantVal->HH2 = block[3] & 0x0F; - quantVal->HL1 = block[3] >> 4; - quantVal->LH1 = block[4] & 0x0F; - quantVal->HH1 = block[4] >> 4; -} - int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, UINT16 surfaceId) { From f79be532f0d6b415026ff6c1ef60c17808fb4f5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 2 Sep 2014 18:15:36 -0400 Subject: [PATCH 20/30] libfreerdp-codec: fix and improve SRL decoder --- libfreerdp/codec/progressive.c | 182 ++----- .../codec/test/TestFreeRDPCodecProgressive.c | 488 +++++++++++++++++- 2 files changed, 540 insertions(+), 130 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 650031a3b..909d0886d 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -688,8 +688,10 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG diff = tile->flags & RFX_TILE_DIFFERENCE; +#if 0 printf("ProgressiveTileFirst: quantIdx Y: %d Cb: %d Cr: %d xIdx: %d yIdx: %d flags: 0x%02X 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); +#endif region = &(progressive->region); @@ -798,7 +800,6 @@ struct _RFX_PROGRESSIVE_UPGRADE_STATE /* SRL state */ - int k; int kp; int nz; BOOL mode; @@ -807,6 +808,7 @@ typedef struct _RFX_PROGRESSIVE_UPGRADE_STATE RFX_PROGRESSIVE_UPGRADE_STATE; INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numBits) { + int k; UINT32 bit; UINT32 max; UINT32 mag; @@ -819,6 +821,8 @@ INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numB return 0; } + k = state->kp / 8; + if (!state->mode) { /* zero encoding */ @@ -830,35 +834,35 @@ INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numB { /* '0' bit, nz >= (1 << k), nz = (1 << k) */ - state->nz = (1 << state->k); + state->nz = (1 << k); state->kp += 4; if (state->kp > 80) state->kp = 80; - state->k = state->kp / 8; - state->nz--; return 0; } - - /* '1' bit, nz < (1 << k), nz = next k bits */ - - state->nz = 0; - - if (state->k) + else { - bs->mask = ((1 << state->k) - 1); - state->nz = ((bs->accumulator >> (32 - state->k)) & bs->mask); - BitStream_Shift(bs, state->k); - } + /* '1' bit, nz < (1 << k), nz = next k bits */ - if (state->nz) - { + state->nz = 0; state->mode = 1; /* unary encoding is next */ - state->nz--; - return 0; + + if (k) + { + bs->mask = ((1 << k) - 1); + state->nz = ((bs->accumulator >> (32 - k)) & bs->mask); + BitStream_Shift(bs, k); + } + + if (state->nz) + { + state->nz--; + return 0; + } } } @@ -871,6 +875,11 @@ INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numB sign = (bs->accumulator & 0x80000000) ? 1 : 0; BitStream_Shift(bs, 1); + state->kp -= 6; + + if (state->kp < 0) + state->kp = 0; + if (numBits == 1) return sign ? -1 : 1; @@ -888,18 +897,12 @@ INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numB mag++; } - state->kp -= 6; - - if (state->kp < 0) - state->kp = 0; - - state->k = state->kp / 8; - return sign ? -mag : mag; } int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* buffer, INT16* sign, int length, UINT32 bitPos, UINT32 numBits) { + int pad; int index; INT16 input; wBitStream* srl; @@ -924,6 +927,21 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b buffer[index] += (input << bitPos); } + /* This is the last band, read padding bits from RAW and SRL bit streams */ + + pad = (raw->position % 8) ? (8 - (raw->position % 8)) : 0; + + if (pad) + BitStream_Shift(raw, pad); + + pad = (srl->position % 8) ? (8 - (srl->position % 8)) : 0; + + if (pad) + BitStream_Shift(srl, pad); + + if (BitStream_GetRemainingLength(srl) == 8) + BitStream_Shift(srl, 8); + return 1; } @@ -961,102 +979,6 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b return 1; } -int progressive_rfx_upgrade_block_count_raw(BOOL nonLL, INT16* sign, int length, int numBits) -{ - int index; - int count = 0; - - if (numBits < 0) - return 0; - - if (!nonLL) - { - count = length; - return (count * numBits); - } - - for (index = 0; index < length; index++) - { - if (sign[index] != 0) - count++; - } - - return (count * numBits); -} - -int progressive_rfx_upgrade_component_count_raw(RFX_COMPONENT_CODEC_QUANT* numBits, INT16* sign, int delta) -{ - int count = 0; - - count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[0], 1023, numBits->HL1 + delta); /* HL1 */ - count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[1023], 1023, numBits->LH1 + delta); /* LH1 */ - count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[2046], 961, numBits->HH1 + delta); /* HH1 */ - count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[3007], 272, numBits->HL2 + delta); /* HL2 */ - count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[3279], 272, numBits->LH2 + delta); /* LH2 */ - count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[3551], 256, numBits->HH2 + delta); /* HH2 */ - count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[3807], 72, numBits->HL3 + delta); /* HL3 */ - count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[3879], 72, numBits->LH3 + delta); /* LH3 */ - count += progressive_rfx_upgrade_block_count_raw(TRUE, &sign[3951], 64, numBits->HH3 + delta); /* HH3 */ - count += progressive_rfx_upgrade_block_count_raw(FALSE, &sign[4015], 81, numBits->LL3 + delta); /* LL3 */ - - return (count + 7) / 8; -} - -int progressive_rfx_upgrade_component_fix_count(RFX_COMPONENT_CODEC_QUANT* numBits, INT16* sign, int rawLen) -{ - int delta = 0; - int count = 0; - int p_count = 0; - int count_n[3] = { 0 }; - int p_count_n[3] = { 0 }; - int count_p[3] = { 0 }; - int p_count_p[3] = { 0 }; - - count_n[0] = progressive_rfx_upgrade_component_count_raw(numBits, sign, -1); - count_n[1] = progressive_rfx_upgrade_component_count_raw(numBits, sign, -2); - count_n[2] = progressive_rfx_upgrade_component_count_raw(numBits, sign, -3); - - count = progressive_rfx_upgrade_component_count_raw(numBits, sign, 0); - - count_p[0] = progressive_rfx_upgrade_component_count_raw(numBits, sign, 1); - count_p[1] = progressive_rfx_upgrade_component_count_raw(numBits, sign, 2); - count_p[2] = progressive_rfx_upgrade_component_count_raw(numBits, sign, 3); - - if (rawLen) - { - p_count_n[0] = (int) ((((float) count_n[0]) / ((float) rawLen)) * 100.0f); - p_count_n[1] = (int) ((((float) count_n[1]) / ((float) rawLen)) * 100.0f); - p_count_n[2] = (int) ((((float) count_n[2]) / ((float) rawLen)) * 100.0f); - - p_count = (int) ((((float) count) / ((float) rawLen)) * 100.0f); - - p_count_p[0] = (int) ((((float) count_p[0]) / ((float) rawLen)) * 100.0f); - p_count_p[1] = (int) ((((float) count_p[1]) / ((float) rawLen)) * 100.0f); - p_count_p[2] = (int) ((((float) count_p[2]) / ((float) rawLen)) * 100.0f); - } - - if (p_count_n[0] == 100) - delta = -1; - if (p_count_n[1] == 100) - delta = -2; - if (p_count_n[2] == 100) - delta = -3; - - if (p_count_p[0] == 100) - delta = 1; - if (p_count_p[1] == 100) - delta = 2; - if (p_count_p[2] == 100) - delta = 3; - - printf("NumBitsFix: -3: %d -2: %d -1: %d 0: %d 1: %d 2: %d 3: %d\n", - p_count_n[2], p_count_n[1], p_count_n[0], p_count, p_count_p[0], p_count_p[1], p_count_p[2]); - printf("NumBitsFix HL1: %d LH1: %d HH1: %d HL2: %d LH2: %d HH2: %d HL3: %d LH3: %d HH3: %d LL3: %d\n", - numBits->HL1, numBits->LH1, numBits->HH1, numBits->HL2, numBits->LH2, numBits->HH2, numBits->HL3, numBits->LH3, numBits->HH3, numBits->LL3); - - return delta; -} - int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* bitPos, RFX_COMPONENT_CODEC_QUANT* numBits, INT16* buffer, INT16* current, INT16* sign, const BYTE* srlData, int srlLen, const BYTE* rawData, int rawLen) @@ -1071,10 +993,8 @@ int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMP ZeroMemory(&s_raw, sizeof(wBitStream)); ZeroMemory(&state, sizeof(RFX_PROGRESSIVE_UPGRADE_STATE)); - progressive_rfx_upgrade_component_fix_count(numBits, sign, rawLen); - state.kp = 8; - state.k = state.kp / 8; + state.mode = 0; state.srl = &s_srl; state.raw = &s_raw; @@ -1114,9 +1034,11 @@ int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMP if (srlLen) pSrlLen = (int) ((((float) aSrlLen) / ((float) srlLen)) * 100.0f); - printf("RAW: %d/%d %d%% SRL: %d/%d %d%%\n", - aRawLen, rawLen, pRawLen, - aSrlLen, srlLen, pSrlLen); + printf("RAW: %d/%d %d%% (%d/%d:%d)\tSRL: %d/%d %d%% (%d/%d:%d)\n", + aRawLen, rawLen, pRawLen, state.raw->position, rawLen * 8, + (rawLen * 8) - state.raw->position, + aSrlLen, srlLen, pSrlLen, state.srl->position, srlLen * 8, + (srlLen * 8) - state.srl->position); return -1; } @@ -1151,10 +1073,12 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR tile->pass++; if (tile->pass > 2) - return 1; /* skip for now */ + return -1; /* skip for now */ +#if 0 printf("ProgressiveTileUpgrade: pass: %d 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->pass, tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, tile->xIdx, tile->yIdx, tile->quality, tile->ySrlLen, tile->yRawLen, tile->cbSrlLen, tile->cbRawLen, tile->crSrlLen, tile->crRawLen); +#endif region = &(progressive->region); @@ -1581,7 +1505,7 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN blockLen = *((UINT32*) &block[boffset + 2]); /* blockLen (4 bytes) */ boffset += 6; - printf("%s\n", progressive_get_block_type_string(blockType)); + //printf("%s\n", progressive_get_block_type_string(blockType)); if ((blocksLen - offset) < blockLen) return -1003; diff --git a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c index 320329300..0a5ebba5a 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c @@ -1,10 +1,496 @@ #include +#include #include #include -int TestFreeRDPCodecProgressive(int argc, char* argv[]) +/** + * Microsoft Progressive Codec Sample Data + * (available under NDA only) + * + * ____. + * + * readme.pdf + * + * bitmaps/ + * 1920by1080-SampleImage1.bmp + * 1920by1080-SampleImage2.bmp + * 1920by1080-SampleImage3.bmp + * + * compress/ + * enc_0_0_025_sampleimage1.bin + * enc_0_0_050_sampleimage1.bin + * enc_0_0_075_sampleimage1.bin + * enc_0_0_100_sampleimage1.bin + * enc_0_1_025_sampleimage1.bin + * enc_0_1_050_sampleimage1.bin + * enc_0_1_075_sampleimage1.bin + * enc_0_1_100_sampleimage1.bin + * enc_0_2_025_sampleimage1.bin + * enc_0_2_050_sampleimage1.bin + * enc_0_2_075_sampleimage1.bin + * enc_0_2_100_sampleimage1.bin + * enc_0_3_025_sampleimage1.bin + * enc_0_3_050_sampleimage1.bin + * enc_0_3_075_sampleimage1.bin + * enc_0_3_100_sampleimage1.bin + * enc_1_0_025_sampleimage2.bin + * enc_1_0_050_sampleimage2.bin + * enc_1_0_075_sampleimage2.bin + * enc_1_0_100_sampleimage2.bin + * enc_1_1_025_sampleimage2.bin + * enc_1_1_050_sampleimage2.bin + * enc_1_1_075_sampleimage2.bin + * enc_1_1_100_sampleimage2.bin + * enc_1_2_025_sampleimage2.bin + * enc_1_2_050_sampleimage2.bin + * enc_1_2_075_sampleimage2.bin + * enc_1_2_100_sampleimage2.bin + * enc_1_3_025_sampleimage2.bin + * enc_1_3_050_sampleimage2.bin + * enc_1_3_075_sampleimage2.bin + * enc_1_3_100_sampleimage2.bin + * enc_2_0_025_sampleimage3.bin + * enc_2_0_050_sampleimage3.bin + * enc_2_0_075_sampleimage3.bin + * enc_2_0_100_sampleimage3.bin + * enc_2_1_025_sampleimage3.bin + * enc_2_1_050_sampleimage3.bin + * enc_2_1_075_sampleimage3.bin + * enc_2_1_100_sampleimage3.bin + * enc_2_2_025_sampleimage3.bin + * enc_2_2_050_sampleimage3.bin + * enc_2_2_075_sampleimage3.bin + * enc_2_2_100_sampleimage3.bin + * enc_2_3_025_sampleimage3.bin + * enc_2_3_050_sampleimage3.bin + * enc_2_3_075_sampleimage3.bin + * enc_2_3_100_sampleimage3.bin + * + * decompress/ + * dec_0_0_025_sampleimage1.bmp + * dec_0_0_050_sampleimage1.bmp + * dec_0_0_075_sampleimage1.bmp + * dec_0_0_100_sampleimage1.bmp + * dec_0_1_025_sampleimage1.bmp + * dec_0_1_050_sampleimage1.bmp + * dec_0_1_075_sampleimage1.bmp + * dec_0_1_100_sampleimage1.bmp + * dec_0_2_025_sampleimage1.bmp + * dec_0_2_050_sampleimage1.bmp + * dec_0_2_075_sampleimage1.bmp + * dec_0_2_100_sampleimage1.bmp + * dec_0_3_025_sampleimage1.bmp + * dec_0_3_050_sampleimage1.bmp + * dec_0_3_075_sampleimage1.bmp + * dec_0_3_100_sampleimage1.bmp + * dec_1_0_025_sampleimage2.bmp + * dec_1_0_050_sampleimage2.bmp + * dec_1_0_075_sampleimage2.bmp + * dec_1_0_100_sampleimage2.bmp + * dec_1_1_025_sampleimage2.bmp + * dec_1_1_050_sampleimage2.bmp + * dec_1_1_075_sampleimage2.bmp + * dec_1_1_100_sampleimage2.bmp + * dec_1_2_025_sampleimage2.bmp + * dec_1_2_050_sampleimage2.bmp + * dec_1_2_075_sampleimage2.bmp + * dec_1_2_100_sampleimage2.bmp + * dec_1_3_025_sampleimage2.bmp + * dec_1_3_050_sampleimage2.bmp + * dec_1_3_075_sampleimage2.bmp + * dec_1_3_100_sampleimage2.bmp + * dec_2_0_025_sampleimage3.bmp + * dec_2_0_050_sampleimage3.bmp + * dec_2_0_075_sampleimage3.bmp + * dec_2_0_100_sampleimage3.bmp + * dec_2_1_025_sampleimage3.bmp + * dec_2_1_050_sampleimage3.bmp + * dec_2_1_075_sampleimage3.bmp + * dec_2_1_100_sampleimage3.bmp + * dec_2_2_025_sampleimage3.bmp + * dec_2_2_050_sampleimage3.bmp + * dec_2_2_075_sampleimage3.bmp + * dec_2_2_100_sampleimage3.bmp + * dec_2_3_025_sampleimage3.bmp + * dec_2_3_050_sampleimage3.bmp + * dec_2_3_075_sampleimage3.bmp + * dec_2_3_100_sampleimage3.bmp + */ + +struct _EGFX_SAMPLE_FILE { + BYTE* buffer; + UINT32 size; +}; +typedef struct _EGFX_SAMPLE_FILE EGFX_SAMPLE_FILE; + +BYTE* test_progressive_load_file(char* path, char* file, UINT32* size) +{ + FILE* fp; + BYTE* buffer; + char* filename; + + filename = GetCombinedPath(path, file); + + fp = fopen(filename, "r"); + + if (!fp) + return NULL; + + fseek(fp, 0, SEEK_END); + *size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + buffer = (BYTE*) malloc(*size); + + if (!buffer) + return NULL; + + if (fread(buffer, *size, 1, fp) != 1) + return NULL; + + free(filename); + fclose(fp); + + return buffer; +} + +int test_progressive_load_files(char* ms_sample_path, EGFX_SAMPLE_FILE files[3][4][4]) +{ + int imageNo = 0; + int quarterNo = 0; + int passNo = 0; + + /* image 1 */ + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_0_025_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_0_050_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_0_075_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_0_100_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_1_025_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_1_050_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_1_075_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_1_100_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_2_025_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_2_050_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_2_075_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_2_100_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_3_025_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_3_050_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_3_075_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_0_3_100_sampleimage1.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + imageNo++; + + /* image 2 */ + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_0_025_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_0_050_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_0_075_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_0_100_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_1_025_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_1_050_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_1_075_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_1_100_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_2_025_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_2_050_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_2_075_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_2_100_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_3_025_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_3_050_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_3_075_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_1_3_100_sampleimage2.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + imageNo++; + + /* image 3 */ + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_0_025_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_0_050_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_0_075_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_0_100_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_1_025_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_1_050_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_1_075_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_1_100_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_2_025_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_2_050_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_2_075_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_2_100_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_3_025_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_3_050_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_3_075_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + files[imageNo][quarterNo][passNo].buffer = test_progressive_load_file(ms_sample_path, + "compress/enc_2_3_100_sampleimage3.bin", &(files[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + /* check if all test data has been loaded */ + + for (imageNo = 0; imageNo < 3; imageNo++) + { + for (quarterNo = 0; quarterNo < 4; quarterNo++) + { + for (passNo = 0; passNo < 4; passNo++) + { + if (!files[imageNo][quarterNo][passNo].buffer) + return -1; + } + } + } + + return 1; +} + +static int g_Width = 0; +static int g_Height = 0; +static int g_DstStep = 0; +static BYTE* g_DstData = NULL; + +int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE files[4], int count) +{ + int pass; + int status; + + for (pass = 0; pass < count; pass++) + { + status = progressive_decompress(progressive, files[pass].buffer, files[pass].size, + &g_DstData, PIXEL_FORMAT_XRGB32, g_DstStep, 0, 0, g_Width, g_Height, 0); + + printf("ProgressiveDecompress: status: %d pass: %d\n", status, pass + 1); + } + + return 1; +} + +int test_progressive_ms_sample(char* ms_sample_path) +{ + int count; + int status; + EGFX_SAMPLE_FILE files[3][4][4]; + PROGRESSIVE_CONTEXT* progressive; + + g_Width = 1920; + g_Height = 1080; + g_DstStep = g_Width * 4; + + status = test_progressive_load_files(ms_sample_path, files); + + if (status < 0) + return -1; + + count = 2; + + progressive = progressive_context_new(FALSE); + + g_DstData = _aligned_malloc(g_DstStep * g_Height, 16); + + progressive_create_surface_context(progressive, 0, g_Width, g_Height); + + /* image 1 */ + + if (1) + { + test_progressive_decode(progressive, files[0][0], count); + test_progressive_decode(progressive, files[0][1], count); + test_progressive_decode(progressive, files[0][2], count); + test_progressive_decode(progressive, files[0][3], count); + } + + /* image 2 */ + + if (1) + { + test_progressive_decode(progressive, files[1][0], count); + test_progressive_decode(progressive, files[1][1], count); + test_progressive_decode(progressive, files[1][2], count); + test_progressive_decode(progressive, files[1][3], count); + } + + /* image 3 */ + + if (1) + { + test_progressive_decode(progressive, files[2][0], count); + test_progressive_decode(progressive, files[2][1], count); + test_progressive_decode(progressive, files[2][2], count); + test_progressive_decode(progressive, files[2][3], count); + } + + progressive_context_free(progressive); + + _aligned_free(g_DstData); + return 0; } +int TestFreeRDPCodecProgressive(int argc, char* argv[]) +{ + char* ms_sample_path; + + ms_sample_path = _strdup("/tmp/EGFX_PROGRESSIVE_MS_SAMPLE"); + + if (PathFileExistsA(ms_sample_path)) + return test_progressive_ms_sample(ms_sample_path); + + free(ms_sample_path); + + return 0; +} From 1491c5a7f977f641a14d5bf13017744497c457d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Tue, 2 Sep 2014 19:25:01 -0400 Subject: [PATCH 21/30] libfreerdp-codec: initial partial upgrade tile support --- client/X11/xf_gfx.c | 9 +-- libfreerdp/codec/progressive.c | 71 ++++++++++++------- .../codec/test/TestFreeRDPCodecProgressive.c | 2 +- 3 files changed, 50 insertions(+), 32 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 6ca4acf48..50e4bf8d5 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -512,7 +512,8 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, return -1; } - printf("xf_SurfaceCommand_Progressive: status: %d\n", status); + printf("xf_SurfaceCommand_Progressive: status: %d surfaceId: %d contextId: %d\n", status, + cmd->surfaceId, cmd->contextId); region = &(xfc->progressive->region); @@ -534,9 +535,6 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, { tile = region->tiles[i]; - if (tile->blockType == PROGRESSIVE_WBT_TILE_UPGRADE) - continue; - updateRect.left = cmd->left + tile->x; updateRect.top = cmd->top + tile->y; updateRect.right = updateRect.left + 64; @@ -616,6 +614,9 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext) { + printf("DeleteEncodingContext: surfaceId: %d codecId: %d\n", + deleteEncodingContext->surfaceId, + deleteEncodingContext->codecContextId); return 1; } diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index 909d0886d..a1b2fa216 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -787,7 +787,7 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG BufferPool_Return(progressive->bufferPool, pBuffer); - WLog_Image(progressive->log, WLOG_TRACE, tile->data, 64, 64, 32); + //WLog_Image(progressive->log, WLOG_TRACE, tile->data, 64, 64, 32); return 1; } @@ -900,7 +900,8 @@ INT16 progressive_rfx_srl_read(RFX_PROGRESSIVE_UPGRADE_STATE* state, UINT32 numB return sign ? -mag : mag; } -int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* buffer, INT16* sign, int length, UINT32 bitPos, UINT32 numBits) +int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* buffer, + INT16* sign, int length, UINT32 shift, UINT32 bitPos, UINT32 numBits) { int pad; int index; @@ -908,8 +909,6 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b wBitStream* srl; wBitStream* raw; - //printf("bitPos: %d numBits: %d\n", bitPos, numBits); - if (!numBits) return 1; @@ -924,7 +923,7 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b input = (INT16) ((raw->accumulator >> (32 - numBits)) & raw->mask); BitStream_Shift(raw, numBits); - buffer[index] += (input << bitPos); + buffer[index] += (input << shift); } /* This is the last band, read padding bits from RAW and SRL bit streams */ @@ -972,17 +971,18 @@ int progressive_rfx_upgrade_block(RFX_PROGRESSIVE_UPGRADE_STATE* state, INT16* b input = progressive_rfx_srl_read(state, numBits); } - buffer[index] += (input << bitPos); + buffer[index] += (input << shift); sign[index] = input; } return 1; } -int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* bitPos, - RFX_COMPONENT_CODEC_QUANT* numBits, INT16* buffer, INT16* current, INT16* sign, - const BYTE* srlData, int srlLen, const BYTE* rawData, int rawLen) +int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMPONENT_CODEC_QUANT* shift, + RFX_COMPONENT_CODEC_QUANT* bitPos, RFX_COMPONENT_CODEC_QUANT* numBits, INT16* buffer, + INT16* current, INT16* sign, const BYTE* srlData, int srlLen, const BYTE* rawData, int rawLen) { + INT16* temp; int aRawLen; int aSrlLen; wBitStream s_srl; @@ -1005,20 +1005,18 @@ int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMP BitStream_Fetch(state.raw); state.nonLL = TRUE; - progressive_rfx_upgrade_block(&state, ¤t[0], &sign[0], 1023, bitPos->HL1, numBits->HL1); /* HL1 */ - progressive_rfx_upgrade_block(&state, ¤t[1023], &sign[1023], 1023, bitPos->LH1, numBits->LH1); /* LH1 */ - progressive_rfx_upgrade_block(&state, ¤t[2046], &sign[2046], 961, bitPos->HH1, numBits->HH1); /* HH1 */ - progressive_rfx_upgrade_block(&state, ¤t[3007], &sign[3007], 272, bitPos->HL2, numBits->HL2); /* HL2 */ - progressive_rfx_upgrade_block(&state, ¤t[3279], &sign[3279], 272, bitPos->LH2, numBits->LH2); /* LH2 */ - progressive_rfx_upgrade_block(&state, ¤t[3551], &sign[3551], 256, bitPos->HH2, numBits->HH2); /* HH2 */ - progressive_rfx_upgrade_block(&state, ¤t[3807], &sign[3807], 72, bitPos->HL3, numBits->HL3); /* HL3 */ - progressive_rfx_upgrade_block(&state, ¤t[3879], &sign[3879], 72, bitPos->LH3, numBits->LH3); /* LH3 */ - progressive_rfx_upgrade_block(&state, ¤t[3951], &sign[3951], 64, bitPos->HH3, numBits->HH3); /* HH3 */ + progressive_rfx_upgrade_block(&state, ¤t[0], &sign[0], 1023, shift->HL1, bitPos->HL1, numBits->HL1); /* HL1 */ + progressive_rfx_upgrade_block(&state, ¤t[1023], &sign[1023], 1023, shift->LH1, bitPos->LH1, numBits->LH1); /* LH1 */ + progressive_rfx_upgrade_block(&state, ¤t[2046], &sign[2046], 961, shift->HH1, bitPos->HH1, numBits->HH1); /* HH1 */ + progressive_rfx_upgrade_block(&state, ¤t[3007], &sign[3007], 272, shift->HL2, bitPos->HL2, numBits->HL2); /* HL2 */ + progressive_rfx_upgrade_block(&state, ¤t[3279], &sign[3279], 272, shift->LH2, bitPos->LH2, numBits->LH2); /* LH2 */ + progressive_rfx_upgrade_block(&state, ¤t[3551], &sign[3551], 256, shift->HH2, bitPos->HH2, numBits->HH2); /* HH2 */ + progressive_rfx_upgrade_block(&state, ¤t[3807], &sign[3807], 72, shift->HL3, bitPos->HL3, numBits->HL3); /* HL3 */ + progressive_rfx_upgrade_block(&state, ¤t[3879], &sign[3879], 72, shift->LH3, bitPos->LH3, numBits->LH3); /* LH3 */ + progressive_rfx_upgrade_block(&state, ¤t[3951], &sign[3951], 64, shift->HH3, bitPos->HH3, numBits->HH3); /* HH3 */ state.nonLL = FALSE; - progressive_rfx_upgrade_block(&state, ¤t[4015], &sign[4015], 81, bitPos->LL3, numBits->LL3); /* LL3 */ - - CopyMemory(buffer, current, 4096 * 2); + progressive_rfx_upgrade_block(&state, ¤t[4015], &sign[4015], 81, shift->LL3, bitPos->LL3, numBits->LL3); /* LL3 */ aRawLen = (state.raw->position + 7) / 8; aSrlLen = (state.srl->position + 7) / 8; @@ -1043,6 +1041,16 @@ int progressive_rfx_upgrade_component(PROGRESSIVE_CONTEXT* progressive, RFX_COMP return -1; } + temp = (INT16*) BufferPool_Take(progressive->bufferPool, -1); /* DWT buffer */ + + CopyMemory(buffer, current, 4096 * 2); + + progressive_rfx_dwt_2d_decode_block(&buffer[3807], temp, 3); + progressive_rfx_dwt_2d_decode_block(&buffer[3007], temp, 2); + progressive_rfx_dwt_2d_decode_block(&buffer[0], temp, 1); + + BufferPool_Return(progressive->bufferPool, temp); + return 1; } @@ -1054,6 +1062,9 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR INT16* pSrcDst[3]; INT16* pCurrent[3]; PROGRESSIVE_BLOCK_REGION* region; + RFX_COMPONENT_CODEC_QUANT shiftY; + RFX_COMPONENT_CODEC_QUANT shiftCb; + RFX_COMPONENT_CODEC_QUANT shiftCr; RFX_COMPONENT_CODEC_QUANT yBitPos; RFX_COMPONENT_CODEC_QUANT cbBitPos; RFX_COMPONENT_CODEC_QUANT crBitPos; @@ -1072,9 +1083,6 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR tile->pass++; - if (tile->pass > 2) - return -1; /* skip for now */ - #if 0 printf("ProgressiveTileUpgrade: pass: %d 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->pass, tile->quantIdxY, tile->quantIdxCb, tile->quantIdxCr, tile->xIdx, tile->yIdx, tile->quality, tile->ySrlLen, tile->yRawLen, tile->cbSrlLen, tile->cbRawLen, tile->crSrlLen, tile->crRawLen); @@ -1128,6 +1136,13 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR progressive_rfx_quant_sub(&(tile->cbBitPos), &cbBitPos, &cbNumBits); progressive_rfx_quant_sub(&(tile->crBitPos), &crBitPos, &crNumBits); + progressive_rfx_quant_add(quantY, quantProgY, &shiftY); + progressive_rfx_quant_lsub(&shiftY, 1); /* -6 + 5 = -1 */ + progressive_rfx_quant_add(quantCb, quantProgCb, &shiftCb); + progressive_rfx_quant_lsub(&shiftCb, 1); /* -6 + 5 = -1 */ + progressive_rfx_quant_add(quantCr, quantProgCr, &shiftCr); + progressive_rfx_quant_lsub(&shiftCr, 1); /* -6 + 5 = -1 */ + CopyMemory(&(tile->yBitPos), &yBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT)); CopyMemory(&(tile->cbBitPos), &cbBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT)); CopyMemory(&(tile->crBitPos), &crBitPos, sizeof(RFX_COMPONENT_CODEC_QUANT)); @@ -1155,19 +1170,19 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR pSrcDst[1] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 1) + 16])); /* Cb/G buffer */ pSrcDst[2] = (INT16*)((BYTE*)(&pBuffer[((8192 + 32) * 2) + 16])); /* Cr/B buffer */ - status = progressive_rfx_upgrade_component(progressive, quantProgY, &yNumBits, + status = progressive_rfx_upgrade_component(progressive, &shiftY, quantProgY, &yNumBits, pSrcDst[0], pCurrent[0], pSign[0], tile->ySrlData, tile->ySrlLen, tile->yRawData, tile->yRawLen); /* Y */ if (status < 0) return -1; - status = progressive_rfx_upgrade_component(progressive, quantProgCb, &cbNumBits, + status = progressive_rfx_upgrade_component(progressive, &shiftCb, quantProgCb, &cbNumBits, pSrcDst[1], pCurrent[1], pSign[1], tile->cbSrlData, tile->cbSrlLen, tile->cbRawData, tile->cbRawLen); /* Cb */ if (status < 0) return -1; - status = progressive_rfx_upgrade_component(progressive, quantProgCr, &crNumBits, + status = progressive_rfx_upgrade_component(progressive, &shiftCr, quantProgCr, &crNumBits, pSrcDst[2], pCurrent[2], pSign[2], tile->crSrlData, tile->crSrlLen, tile->crRawData, tile->crRawLen); /* Cr */ if (status < 0) @@ -1181,6 +1196,8 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR BufferPool_Return(progressive->bufferPool, pBuffer); + WLog_Image(progressive->log, WLOG_TRACE, tile->data, 64, 64, 32); + return 1; } diff --git a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c index 0a5ebba5a..4192176d7 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c @@ -436,7 +436,7 @@ int test_progressive_ms_sample(char* ms_sample_path) if (status < 0) return -1; - count = 2; + count = 3; progressive = progressive_context_new(FALSE); From 320b1d35edd67a6c555c3669a198e2347de722f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 3 Sep 2014 16:20:50 -0400 Subject: [PATCH 22/30] libwinpr-utils: centralize bitmap utils --- include/freerdp/utils/bitmap.h | 35 -------- libfreerdp/gdi/gdi.c | 4 +- libfreerdp/utils/CMakeLists.txt | 1 - libfreerdp/utils/bitmap.c | 110 ----------------------- winpr/include/winpr/image.h | 71 +++++++++++++++ winpr/libwinpr/utils/CMakeLists.txt | 1 + winpr/libwinpr/utils/image.c | 76 ++++++++++++++++ winpr/libwinpr/utils/wlog/ImageMessage.c | 82 ++--------------- 8 files changed, 156 insertions(+), 224 deletions(-) delete mode 100644 include/freerdp/utils/bitmap.h delete mode 100644 libfreerdp/utils/bitmap.c create mode 100644 winpr/include/winpr/image.h create mode 100644 winpr/libwinpr/utils/image.c diff --git a/include/freerdp/utils/bitmap.h b/include/freerdp/utils/bitmap.h deleted file mode 100644 index b9d4dcf94..000000000 --- a/include/freerdp/utils/bitmap.h +++ /dev/null @@ -1,35 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Bitmap File Format Utils - * - * Copyright 2011 Marc-Andre Moreau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FREERDP_UTILS_BITMAP_H -#define FREERDP_UTILS_BITMAP_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -FREERDP_API void freerdp_bitmap_write(char* filename, void* data, int width, int height, int bpp); - -#ifdef __cplusplus -} -#endif - -#endif /* FREERDP_UTILS_BITMAP_H */ diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index ee767cfd3..71251c518 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -26,11 +26,11 @@ #include #include +#include #include #include #include -#include #include #include #include @@ -828,7 +828,7 @@ void gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits_co #ifdef DUMP_REMOTEFX_TILES sprintf(tile_bitmap, "/tmp/rfx/tile_%d.bmp", tilenum++); - freerdp_bitmap_write(tile_bitmap, gdi->tile->bitmap->data, 64, 64, 32); + winpr_bitmap_write(tile_bitmap, gdi->tile->bitmap->data, 64, 64, 32); #endif diff --git a/libfreerdp/utils/CMakeLists.txt b/libfreerdp/utils/CMakeLists.txt index 1db46f1a0..ad2a419ee 100644 --- a/libfreerdp/utils/CMakeLists.txt +++ b/libfreerdp/utils/CMakeLists.txt @@ -20,7 +20,6 @@ set(MODULE_PREFIX "FREERDP_UTILS") set(${MODULE_PREFIX}_SRCS event.c - bitmap.c passphrase.c pcap.c profiler.c diff --git a/libfreerdp/utils/bitmap.c b/libfreerdp/utils/bitmap.c deleted file mode 100644 index ed316ba8f..000000000 --- a/libfreerdp/utils/bitmap.c +++ /dev/null @@ -1,110 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Bitmap File Format Utils - * - * Copyright 2011 Marc-Andre Moreau - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include - -#include -#include - -typedef struct -{ - BYTE magic[2]; -} BITMAP_MAGIC; - -typedef struct -{ - UINT32 filesz; - UINT16 creator1; - UINT16 creator2; - UINT32 bmp_offset; -} BITMAP_CORE_HEADER; - -typedef struct -{ - UINT32 header_sz; - INT32 width; - INT32 height; - UINT16 nplanes; - UINT16 bitspp; - UINT32 compress_type; - UINT32 bmp_bytesz; - INT32 hres; - INT32 vres; - UINT32 ncolors; - UINT32 nimpcolors; -} BITMAP_INFO_HEADER; - -void freerdp_bitmap_write(char* filename, void* data, int width, int height, int bpp) -{ - FILE* fp; - BITMAP_MAGIC magic; - BITMAP_CORE_HEADER header; - BITMAP_INFO_HEADER info_header; - - fp = fopen(filename, "w+b"); - - if (fp == NULL) - { - DEBUG_WARN( "failed to open file %s\n", filename); - return; - } - - magic.magic[0] = 'B'; - magic.magic[1] = 'M'; - - header.creator1 = 0; - header.creator2 = 0; - - header.bmp_offset = - sizeof(BITMAP_MAGIC) + - sizeof(BITMAP_CORE_HEADER) + - sizeof(BITMAP_INFO_HEADER); - - info_header.bmp_bytesz = width * height * (bpp / 8); - - header.filesz = - header.bmp_offset + - info_header.bmp_bytesz; - - info_header.width = width; - info_header.height = (-1) * height; - info_header.nplanes = 1; - info_header.bitspp = bpp; - info_header.compress_type = 0; - info_header.hres = width; - info_header.vres = height; - info_header.ncolors = 0; - info_header.nimpcolors = 0; - info_header.header_sz = sizeof(BITMAP_INFO_HEADER); - - fwrite((void*) &magic, sizeof(BITMAP_MAGIC), 1, fp); - fwrite((void*) &header, sizeof(BITMAP_CORE_HEADER), 1, fp); - fwrite((void*) &info_header, sizeof(BITMAP_INFO_HEADER), 1, fp); - fwrite((void*) data, info_header.bmp_bytesz, 1, fp); - - fclose(fp); -} - diff --git a/winpr/include/winpr/image.h b/winpr/include/winpr/image.h new file mode 100644 index 000000000..3dda5f7c6 --- /dev/null +++ b/winpr/include/winpr/image.h @@ -0,0 +1,71 @@ +/** + * WinPR: Windows Portable Runtime + * Image Utils + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_IMAGE_H +#define WINPR_IMAGE_H + +#include +#include + +/* + * Bitmap data structures + */ + +struct _WINPR_BITMAP_MAGIC +{ + BYTE magic[2]; +}; +typedef struct _WINPR_BITMAP_MAGIC WINPR_BITMAP_MAGIC; + +struct _WINPR_BITMAP_CORE_HEADER +{ + UINT32 filesz; + UINT16 creator1; + UINT16 creator2; + UINT32 bmp_offset; +}; +typedef struct _WINPR_BITMAP_CORE_HEADER WINPR_BITMAP_CORE_HEADER; + +struct _WINPR_BITMAP_INFO_HEADER +{ + UINT32 header_sz; + INT32 width; + INT32 height; + UINT16 nplanes; + UINT16 bitspp; + UINT32 compress_type; + UINT32 bmp_bytesz; + INT32 hres; + INT32 vres; + UINT32 ncolors; + UINT32 nimpcolors; +}; +typedef struct _WINPR_BITMAP_INFO_HEADER WINPR_BITMAP_INFO_HEADER; + +#ifdef __cplusplus +extern "C" { +#endif + +WINPR_API int winpr_bitmap_write(char* filename, BYTE* data, int width, int height, int bpp); + +#ifdef __cplusplus +} +#endif + +#endif /* WINPR_IMAGE_H */ diff --git a/winpr/libwinpr/utils/CMakeLists.txt b/winpr/libwinpr/utils/CMakeLists.txt index 8f677937f..3b2839e68 100644 --- a/winpr/libwinpr/utils/CMakeLists.txt +++ b/winpr/libwinpr/utils/CMakeLists.txt @@ -75,6 +75,7 @@ set(${MODULE_PREFIX}_SRCS ini.c sam.c ntlm.c + image.c print.c stream.c debug.c diff --git a/winpr/libwinpr/utils/image.c b/winpr/libwinpr/utils/image.c new file mode 100644 index 000000000..31fc643b6 --- /dev/null +++ b/winpr/libwinpr/utils/image.c @@ -0,0 +1,76 @@ +/** + * WinPR: Windows Portable Runtime + * Image Utils + * + * Copyright 2014 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +int winpr_bitmap_write(char* filename, BYTE* data, int width, int height, int bpp) +{ + FILE* fp; + WINPR_BITMAP_MAGIC magic; + WINPR_BITMAP_CORE_HEADER header; + WINPR_BITMAP_INFO_HEADER info_header; + + fp = fopen(filename, "w+b"); + + if (!fp) + { + fprintf(stderr, "failed to open file %s\n", filename); + return -1; + } + + magic.magic[0] = 'B'; + magic.magic[1] = 'M'; + + header.creator1 = 0; + header.creator2 = 0; + + header.bmp_offset = sizeof(WINPR_BITMAP_MAGIC) + + sizeof(WINPR_BITMAP_CORE_HEADER) + + sizeof(WINPR_BITMAP_INFO_HEADER); + + info_header.bmp_bytesz = width * height * (bpp / 8); + + header.filesz = header.bmp_offset + info_header.bmp_bytesz; + + info_header.width = width; + info_header.height = (-1) * height; + info_header.nplanes = 1; + info_header.bitspp = bpp; + info_header.compress_type = 0; + info_header.hres = width; + info_header.vres = height; + info_header.ncolors = 0; + info_header.nimpcolors = 0; + info_header.header_sz = sizeof(WINPR_BITMAP_INFO_HEADER); + + fwrite((void*) &magic, sizeof(WINPR_BITMAP_MAGIC), 1, fp); + fwrite((void*) &header, sizeof(WINPR_BITMAP_CORE_HEADER), 1, fp); + fwrite((void*) &info_header, sizeof(WINPR_BITMAP_INFO_HEADER), 1, fp); + fwrite((void*) data, info_header.bmp_bytesz, 1, fp); + + fclose(fp); + + return 1; +} diff --git a/winpr/libwinpr/utils/wlog/ImageMessage.c b/winpr/libwinpr/utils/wlog/ImageMessage.c index 89af777c5..1866ed1de 100644 --- a/winpr/libwinpr/utils/wlog/ImageMessage.c +++ b/winpr/libwinpr/utils/wlog/ImageMessage.c @@ -23,88 +23,18 @@ #include +#include + #include "wlog/ImageMessage.h" -#include -#include - -typedef struct -{ - BYTE magic[2]; -} BITMAP_MAGIC; - -typedef struct -{ - UINT32 filesz; - UINT16 creator1; - UINT16 creator2; - UINT32 bmp_offset; -} BITMAP_CORE_HEADER; - -typedef struct -{ - UINT32 header_sz; - INT32 width; - INT32 height; - UINT16 nplanes; - UINT16 bitspp; - UINT32 compress_type; - UINT32 bmp_bytesz; - INT32 hres; - INT32 vres; - UINT32 ncolors; - UINT32 nimpcolors; -} BITMAP_INFO_HEADER; - int WLog_ImageMessage_Write(char* filename, void* data, int width, int height, int bpp) { - FILE* fp; - BITMAP_MAGIC magic; - BITMAP_CORE_HEADER header; - BITMAP_INFO_HEADER info_header; + int status; - fp = fopen(filename, "w+b"); + status = winpr_bitmap_write(filename, data, width, height, bpp); - if (!fp) - { - fprintf(stderr, "failed to open file %s\n", filename); + if (status < 0) return -1; - } - magic.magic[0] = 'B'; - magic.magic[1] = 'M'; - - header.creator1 = 0; - header.creator2 = 0; - - header.bmp_offset = - sizeof(BITMAP_MAGIC) + - sizeof(BITMAP_CORE_HEADER) + - sizeof(BITMAP_INFO_HEADER); - - info_header.bmp_bytesz = width * height * (bpp / 8); - - header.filesz = - header.bmp_offset + - info_header.bmp_bytesz; - - info_header.width = width; - info_header.height = (-1) * height; - info_header.nplanes = 1; - info_header.bitspp = bpp; - info_header.compress_type = 0; - info_header.hres = width; - info_header.vres = height; - info_header.ncolors = 0; - info_header.nimpcolors = 0; - info_header.header_sz = sizeof(BITMAP_INFO_HEADER); - - fwrite((void*) &magic, sizeof(BITMAP_MAGIC), 1, fp); - fwrite((void*) &header, sizeof(BITMAP_CORE_HEADER), 1, fp); - fwrite((void*) &info_header, sizeof(BITMAP_INFO_HEADER), 1, fp); - fwrite((void*) data, info_header.bmp_bytesz, 1, fp); - - fclose(fp); - - return 0; + return 1; } From fd7b9669a507abc397d4329a710434818017c2c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Wed, 3 Sep 2014 18:46:57 -0400 Subject: [PATCH 23/30] libfreerdp-codec: improve progressive unit tests --- libfreerdp/codec/progressive.c | 2 +- .../codec/test/TestFreeRDPCodecProgressive.c | 421 +++++++++++++++++- winpr/include/winpr/image.h | 48 +- winpr/libwinpr/utils/image.c | 205 +++++++-- 4 files changed, 595 insertions(+), 81 deletions(-) diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index a1b2fa216..eb6e46ba1 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -1196,7 +1196,7 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR BufferPool_Return(progressive->bufferPool, pBuffer); - WLog_Image(progressive->log, WLOG_TRACE, tile->data, 64, 64, 32); + //WLog_Image(progressive->log, WLOG_TRACE, tile->data, 64, 64, 32); return 1; } diff --git a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c index 4192176d7..2896fbdb6 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c @@ -1,7 +1,10 @@ #include #include +#include #include +#include + #include /** @@ -399,15 +402,320 @@ int test_progressive_load_files(char* ms_sample_path, EGFX_SAMPLE_FILE files[3][ return 1; } +static void fill_bitmap_alpha_channel(BYTE* data, int width, int height, BYTE value) +{ + int i, j; + UINT32* pixel; + + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + pixel = (UINT32*) &data[((i * width) + j) * 4]; + *pixel = ((*pixel & 0x00FFFFFF) | (value << 24)); + } + } +} + +BYTE* test_progressive_load_bitmap(char* path, char* file, UINT32* size) +{ + int status; + BYTE* buffer; + wImage* image; + char* filename; + + filename = GetCombinedPath(path, file); + + if (!filename) + return NULL; + + image = winpr_image_new(); + + if (!image) + return NULL; + + status = winpr_image_read(image, filename); + + if (status < 0) + return NULL; + + buffer = image->data; + *size = image->height * image->scanline; + + fill_bitmap_alpha_channel(image->data, image->width, image->height, 0xFF); + + winpr_image_free(image, FALSE); + free(filename); + + return buffer; +} + +int test_progressive_load_bitmaps(char* ms_sample_path, EGFX_SAMPLE_FILE bitmaps[3][4][4]) +{ + int imageNo = 0; + int quarterNo = 0; + int passNo = 0; + + /* image 1 */ + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_0_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_0_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_0_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_0_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_1_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_1_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_1_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_1_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_2_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_2_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_2_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_2_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_3_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_3_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_3_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_0_3_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + imageNo++; + + /* image 2 */ + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_0_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_0_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_0_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_0_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_1_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_1_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_1_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_1_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_2_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_2_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_2_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_2_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_3_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_3_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_3_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_1_3_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + imageNo++; + + /* image 3 */ + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_0_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_0_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_0_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_0_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_1_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_1_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_1_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_1_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_2_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_2_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_2_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_2_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + quarterNo = (quarterNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_3_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_3_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_3_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, + "decompress/dec_2_3_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + passNo = (passNo + 1) % 4; + + /* check if all test data has been loaded */ + + for (imageNo = 0; imageNo < 3; imageNo++) + { + for (quarterNo = 0; quarterNo < 4; quarterNo++) + { + for (passNo = 0; passNo < 4; passNo++) + { + if (!bitmaps[imageNo][quarterNo][passNo].buffer) + return -1; + } + } + } + + return 1; +} + static int g_Width = 0; static int g_Height = 0; static int g_DstStep = 0; static BYTE* g_DstData = NULL; -int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE files[4], int count) +int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE files[4], EGFX_SAMPLE_FILE bitmaps[4], int quarter, int count) { int pass; + int index; int status; + int nXSrc, nYSrc; + int nXDst, nYDst; + int nWidth, nHeight; + RECTANGLE_16 tileRect; + RECTANGLE_16 updateRect; + RECTANGLE_16 clippingRect; + RFX_PROGRESSIVE_TILE* tile; + PROGRESSIVE_BLOCK_REGION* region; + + clippingRect.left = 0; + clippingRect.top = 0; + clippingRect.right = g_Width; + clippingRect.bottom = g_Height; for (pass = 0; pass < count; pass++) { @@ -415,6 +723,80 @@ int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE f &g_DstData, PIXEL_FORMAT_XRGB32, g_DstStep, 0, 0, g_Width, g_Height, 0); printf("ProgressiveDecompress: status: %d pass: %d\n", status, pass + 1); + + region = &(progressive->region); + + switch (quarter) + { + case 0: + clippingRect.left = 0; + clippingRect.top = 0; + clippingRect.right = g_Width / 2; + clippingRect.bottom = g_Height /2; + break; + + case 1: + clippingRect.left = g_Width / 2; + clippingRect.top = g_Height / 2; + clippingRect.right = g_Width; + clippingRect.bottom = g_Height; + break; + + case 2: + clippingRect.left = g_Width / 2; + clippingRect.top = 0; + clippingRect.right = g_Width; + clippingRect.bottom = g_Height / 2; + break; + + case 3: + clippingRect.left = 0; + clippingRect.top = g_Height / 2; + clippingRect.right = g_Width / 2; + clippingRect.bottom = g_Height; + break; + } + + for (index = 0; index < region->numTiles; index++) + { + tile = region->tiles[index]; + + tileRect.left = tile->x; + tileRect.top = tile->y; + tileRect.right = tile->x + tile->width; + tileRect.bottom = tile->y + tile->height; + + rectangles_intersection(&tileRect, &clippingRect, &updateRect); + + nXDst = updateRect.left; + nYDst = updateRect.top; + nWidth = updateRect.right - updateRect.left; + nHeight = updateRect.bottom - updateRect.top; + + nXSrc = nXDst - tile->x; + nYSrc = nYDst - tile->y; + + freerdp_image_copy(g_DstData, PIXEL_FORMAT_XRGB32, g_DstStep, + nXDst, nYDst, nWidth, nHeight, tile->data, + PIXEL_FORMAT_XRGB32, 64 * 4, nXSrc, nYSrc); + } + + if (memcmp(g_DstData, bitmaps[pass].buffer, bitmaps[pass].size) != 0) + { + printf("bitmap decompression error\n"); + + printf("GOOD: "); + winpr_HexDump(bitmaps[pass].buffer, 16); + + printf("BAD: "); + winpr_HexDump(g_DstData, 16); + } + else + { + printf("bitmap decompression success\n"); + } + + WLog_Image(progressive->log, WLOG_TRACE, g_DstData, g_Width, g_Height, 32); } return 1; @@ -425,6 +807,7 @@ int test_progressive_ms_sample(char* ms_sample_path) int count; int status; EGFX_SAMPLE_FILE files[3][4][4]; + EGFX_SAMPLE_FILE bitmaps[3][4][4]; PROGRESSIVE_CONTEXT* progressive; g_Width = 1920; @@ -436,7 +819,12 @@ int test_progressive_ms_sample(char* ms_sample_path) if (status < 0) return -1; - count = 3; + status = test_progressive_load_bitmaps(ms_sample_path, bitmaps); + + if (status < 0) + return -1; + + count = 2; progressive = progressive_context_new(FALSE); @@ -448,30 +836,31 @@ int test_progressive_ms_sample(char* ms_sample_path) if (1) { - test_progressive_decode(progressive, files[0][0], count); - test_progressive_decode(progressive, files[0][1], count); - test_progressive_decode(progressive, files[0][2], count); - test_progressive_decode(progressive, files[0][3], count); + test_progressive_decode(progressive, files[0][0], bitmaps[0][0], 0, count); + test_progressive_decode(progressive, files[0][1], bitmaps[0][1], 1, count); + test_progressive_decode(progressive, files[0][2], bitmaps[0][2], 2, count); + test_progressive_decode(progressive, files[0][3], bitmaps[0][3], 3, count); } /* image 2 */ - if (1) + if (0) { - test_progressive_decode(progressive, files[1][0], count); - test_progressive_decode(progressive, files[1][1], count); - test_progressive_decode(progressive, files[1][2], count); - test_progressive_decode(progressive, files[1][3], count); + /* decompressed image set is incorrect for this one */ + test_progressive_decode(progressive, files[1][0], bitmaps[1][0], 0, count); + test_progressive_decode(progressive, files[1][1], bitmaps[1][1], 1, count); + test_progressive_decode(progressive, files[1][2], bitmaps[1][2], 2, count); + test_progressive_decode(progressive, files[1][3], bitmaps[1][3], 3, count); } /* image 3 */ - if (1) + if (0) { - test_progressive_decode(progressive, files[2][0], count); - test_progressive_decode(progressive, files[2][1], count); - test_progressive_decode(progressive, files[2][2], count); - test_progressive_decode(progressive, files[2][3], count); + test_progressive_decode(progressive, files[2][0], bitmaps[2][0], 0, count); + test_progressive_decode(progressive, files[2][1], bitmaps[2][1], 1, count); + test_progressive_decode(progressive, files[2][2], bitmaps[2][2], 2, count); + test_progressive_decode(progressive, files[2][3], bitmaps[2][3], 3, count); } progressive_context_free(progressive); diff --git a/winpr/include/winpr/image.h b/winpr/include/winpr/image.h index 3dda5f7c6..313200533 100644 --- a/winpr/include/winpr/image.h +++ b/winpr/include/winpr/image.h @@ -23,46 +23,28 @@ #include #include -/* - * Bitmap data structures - */ - -struct _WINPR_BITMAP_MAGIC +struct _wImage { - BYTE magic[2]; + int width; + int height; + BYTE* data; + int scanline; + int bitsPerPixel; + int bytesPerPixel; }; -typedef struct _WINPR_BITMAP_MAGIC WINPR_BITMAP_MAGIC; - -struct _WINPR_BITMAP_CORE_HEADER -{ - UINT32 filesz; - UINT16 creator1; - UINT16 creator2; - UINT32 bmp_offset; -}; -typedef struct _WINPR_BITMAP_CORE_HEADER WINPR_BITMAP_CORE_HEADER; - -struct _WINPR_BITMAP_INFO_HEADER -{ - UINT32 header_sz; - INT32 width; - INT32 height; - UINT16 nplanes; - UINT16 bitspp; - UINT32 compress_type; - UINT32 bmp_bytesz; - INT32 hres; - INT32 vres; - UINT32 ncolors; - UINT32 nimpcolors; -}; -typedef struct _WINPR_BITMAP_INFO_HEADER WINPR_BITMAP_INFO_HEADER; +typedef struct _wImage wImage; #ifdef __cplusplus extern "C" { #endif -WINPR_API int winpr_bitmap_write(char* filename, BYTE* data, int width, int height, int bpp); +WINPR_API int winpr_bitmap_write(const char* filename, BYTE* data, int width, int height, int bpp); + +WINPR_API int winpr_image_write(wImage* image, const char* filename); +WINPR_API int winpr_image_read(wImage* image, const char* filename); + +WINPR_API wImage* winpr_image_new(); +WINPR_API void winpr_image_free(wImage* image, BOOL bFreeBuffer); #ifdef __cplusplus } diff --git a/winpr/libwinpr/utils/image.c b/winpr/libwinpr/utils/image.c index 31fc643b6..9672fed79 100644 --- a/winpr/libwinpr/utils/image.c +++ b/winpr/libwinpr/utils/image.c @@ -25,12 +25,63 @@ #include -int winpr_bitmap_write(char* filename, BYTE* data, int width, int height, int bpp) +/** + * Refer to "Compressed Image File Formats: JPEG, PNG, GIF, XBM, BMP" book + */ + +#if defined(__APPLE__) +#pragma pack(1) +#else +#pragma pack(push, 1) +#endif + +struct _WINPR_BITMAP_FILE_HEADER +{ + BYTE bfType[2]; + UINT32 bfSize; + UINT16 bfReserved1; + UINT16 bfReserved2; + UINT32 bfOffBits; +}; +typedef struct _WINPR_BITMAP_FILE_HEADER WINPR_BITMAP_FILE_HEADER; + +struct _WINPR_BITMAP_INFO_HEADER +{ + UINT32 biSize; + INT32 biWidth; + INT32 biHeight; + UINT16 biPlanes; + UINT16 biBitCount; + UINT32 biCompression; + UINT32 biSizeImage; + INT32 biXPelsPerMeter; + INT32 biYPelsPerMeter; + UINT32 biClrUsed; + UINT32 biClrImportant; +}; +typedef struct _WINPR_BITMAP_INFO_HEADER WINPR_BITMAP_INFO_HEADER; + +struct _WINPR_BITMAP_CORE_HEADER +{ + UINT32 bcSize; + UINT16 bcWidth; + UINT16 bcHeight; + UINT16 bcPlanes; + UINT16 bcBitCount; +}; +typedef struct _WINPR_BITMAP_CORE_HEADER WINPR_BITMAP_CORE_HEADER; + +#if defined(__APPLE__) +#pragma pack() +#else +#pragma pack(pop) +#endif + +int winpr_bitmap_write(const char* filename, BYTE* data, int width, int height, int bpp) { FILE* fp; - WINPR_BITMAP_MAGIC magic; - WINPR_BITMAP_CORE_HEADER header; - WINPR_BITMAP_INFO_HEADER info_header; + WINPR_BITMAP_FILE_HEADER bf; + WINPR_BITMAP_INFO_HEADER bi; fp = fopen(filename, "w+b"); @@ -40,37 +91,129 @@ int winpr_bitmap_write(char* filename, BYTE* data, int width, int height, int bp return -1; } - magic.magic[0] = 'B'; - magic.magic[1] = 'M'; + bf.bfType[0] = 'B'; + bf.bfType[1] = 'M'; + bf.bfReserved1 = 0; + bf.bfReserved2 = 0; + bf.bfOffBits = sizeof(WINPR_BITMAP_FILE_HEADER) + sizeof(WINPR_BITMAP_INFO_HEADER); + bi.biSizeImage = width * height * (bpp / 8); + bf.bfSize = bf.bfOffBits + bi.biSizeImage; - header.creator1 = 0; - header.creator2 = 0; + bi.biWidth = width; + bi.biHeight = -1 * height; + bi.biPlanes = 1; + bi.biBitCount = bpp; + bi.biCompression = 0; + bi.biXPelsPerMeter = width; + bi.biYPelsPerMeter = height; + bi.biClrUsed = 0; + bi.biClrImportant = 0; + bi.biSize = sizeof(WINPR_BITMAP_INFO_HEADER); - header.bmp_offset = sizeof(WINPR_BITMAP_MAGIC) + - sizeof(WINPR_BITMAP_CORE_HEADER) + - sizeof(WINPR_BITMAP_INFO_HEADER); - - info_header.bmp_bytesz = width * height * (bpp / 8); - - header.filesz = header.bmp_offset + info_header.bmp_bytesz; - - info_header.width = width; - info_header.height = (-1) * height; - info_header.nplanes = 1; - info_header.bitspp = bpp; - info_header.compress_type = 0; - info_header.hres = width; - info_header.vres = height; - info_header.ncolors = 0; - info_header.nimpcolors = 0; - info_header.header_sz = sizeof(WINPR_BITMAP_INFO_HEADER); - - fwrite((void*) &magic, sizeof(WINPR_BITMAP_MAGIC), 1, fp); - fwrite((void*) &header, sizeof(WINPR_BITMAP_CORE_HEADER), 1, fp); - fwrite((void*) &info_header, sizeof(WINPR_BITMAP_INFO_HEADER), 1, fp); - fwrite((void*) data, info_header.bmp_bytesz, 1, fp); + fwrite((void*) &bf, sizeof(WINPR_BITMAP_FILE_HEADER), 1, fp); + fwrite((void*) &bi, sizeof(WINPR_BITMAP_INFO_HEADER), 1, fp); + fwrite((void*) data, bi.biSizeImage, 1, fp); fclose(fp); return 1; } + +int winpr_image_write(wImage* image, const char* filename) +{ + return winpr_bitmap_write(filename, image->data, image->width, image->height, image->bitsPerPixel); +} + +int winpr_image_read(wImage* image, const char* filename) +{ + FILE* fp; + int index; + BOOL vFlip; + BYTE* pDstData; + WINPR_BITMAP_FILE_HEADER bf; + WINPR_BITMAP_INFO_HEADER bi; + + fp = fopen(filename, "r+b"); + + if (!fp) + { + fprintf(stderr, "failed to open file %s\n", filename); + return -1; + } + + fread((void*) &bf, sizeof(WINPR_BITMAP_FILE_HEADER), 1, fp); + + if ((bf.bfType[0] != 'B') || (bf.bfType[1] != 'M')) + return -1; + + fread((void*) &bi, sizeof(WINPR_BITMAP_INFO_HEADER), 1, fp); + + if (ftell(fp) != bf.bfOffBits) + { + fseek(fp, bf.bfOffBits, SEEK_SET); + } + + image->width = bi.biWidth; + + if (bi.biHeight < 0) + { + vFlip = FALSE; + image->height = -1 * bi.biHeight; + } + else + { + vFlip = TRUE; + image->height = bi.biHeight; + } + + image->bitsPerPixel = bi.biBitCount; + image->bytesPerPixel = (image->bitsPerPixel / 8); + image->scanline = (bi.biSizeImage / bi.biHeight); + + image->data = (BYTE*) malloc(bi.biSizeImage); + + if (!image->data) + return -1; + + if (!vFlip) + { + fread((void*) image->data, bi.biSizeImage, 1, fp); + } + else + { + pDstData = &(image->data[(image->height - 1) * image->scanline]); + + for (index = 0; index < image->height; index++) + { + fread((void*) pDstData, image->scanline, 1, fp); + pDstData -= image->scanline; + } + } + + fclose(fp); + + return 1; +} + +wImage* winpr_image_new() +{ + wImage* image; + + image = (wImage*) calloc(1, sizeof(wImage)); + + if (!image) + return NULL; + + return image; +} + +void winpr_image_free(wImage* image, BOOL bFreeBuffer) +{ + if (!image) + return; + + if (bFreeBuffer) + free(image->data); + + free(image); +} From 37aabc50d1e3e1f88bc38a1344bc7cc6efac3528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 4 Sep 2014 13:09:46 -0400 Subject: [PATCH 24/30] libfreerdp-codec: improve YCbCr to RGB color conversion --- include/freerdp/primitives.h | 5 + libfreerdp/codec/progressive.c | 10 +- .../codec/test/TestFreeRDPCodecProgressive.c | 278 +++++++++++++----- libfreerdp/primitives/prim_colors.c | 61 +++- libfreerdp/primitives/prim_colors.h | 1 + 5 files changed, 268 insertions(+), 87 deletions(-) diff --git a/include/freerdp/primitives.h b/include/freerdp/primitives.h index bb518c2d6..be0a01816 100644 --- a/include/freerdp/primitives.h +++ b/include/freerdp/primitives.h @@ -136,6 +136,10 @@ typedef pstatus_t (*__sign_16s_t)( const INT16 *pSrc, INT16 *pDst, INT32 len); +typedef pstatus_t (*__yCbCrToRGB_16s8u_P3AC4R_t)( + const INT16* pSrc[3], INT32 srcStep, + BYTE* pDst, INT32 dstStep, + const prim_size_t* roi); typedef pstatus_t (*__yCbCrToRGB_16s16s_P3P3_t)( const INT16 *pSrc[3], INT32 srcStep, INT16 *pDst[3], INT32 dstStep, @@ -199,6 +203,7 @@ typedef struct /* Sign */ __sign_16s_t sign_16s; /* Color conversions */ + __yCbCrToRGB_16s8u_P3AC4R_t yCbCrToRGB_16s8u_P3AC4R; __yCbCrToRGB_16s16s_P3P3_t yCbCrToRGB_16s16s_P3P3; __RGBToYCbCr_16s16s_P3P3_t RGBToYCbCr_16s16s_P3P3; __RGBToRGB_16s8u_P3AC4R_t RGBToRGB_16s8u_P3AC4R; diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index eb6e46ba1..f63b6896b 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -779,10 +779,7 @@ int progressive_decompress_tile_first(PROGRESSIVE_CONTEXT* progressive, RFX_PROG progressive_rfx_decode_component(progressive, &shiftCb, tile->cbData, tile->cbLen, pSrcDst[1], pCurrent[1], pSign[1], diff); /* Cb */ progressive_rfx_decode_component(progressive, &shiftCr, tile->crData, tile->crLen, pSrcDst[2], pCurrent[2], pSign[2], diff); /* Cr */ - prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), - pSrcDst, 64 * sizeof(INT16), &roi_64x64); - - prims->RGBToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * sizeof(INT16), + prims->yCbCrToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * 2, tile->data, 64 * 4, &roi_64x64); BufferPool_Return(progressive->bufferPool, pBuffer); @@ -1188,10 +1185,7 @@ int progressive_decompress_tile_upgrade(PROGRESSIVE_CONTEXT* progressive, RFX_PR if (status < 0) return -1; - prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * sizeof(INT16), - pSrcDst, 64 * sizeof(INT16), &roi_64x64); - - prims->RGBToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * sizeof(INT16), + prims->yCbCrToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * 2, tile->data, 64 * 4, &roi_64x64); BufferPool_Return(progressive->bufferPool, pBuffer); diff --git a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c index 2896fbdb6..ac466b9d3 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c @@ -128,6 +128,126 @@ struct _EGFX_SAMPLE_FILE }; typedef struct _EGFX_SAMPLE_FILE EGFX_SAMPLE_FILE; +static int g_Width = 0; +static int g_Height = 0; +static int g_DstStep = 0; +static BYTE* g_DstData = NULL; + +static void test_fill_image_alpha_channel(BYTE* data, int width, int height, BYTE value) +{ + int i, j; + UINT32* pixel; + + for (i = 0; i < height; i++) + { + for (j = 0; j < width; j++) + { + pixel = (UINT32*) &data[((i * width) + j) * 4]; + *pixel = ((*pixel & 0x00FFFFFF) | (value << 24)); + } + } +} + +static void* test_image_memset32(UINT32* ptr, UINT32 fill, size_t length) +{ + while (length--) + { + *ptr++ = fill; + } + + return (void*) ptr; +} + +static int test_image_fill(BYTE* pDstData, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight, UINT32 color) +{ + int y; + UINT32* pDstPixel; + + if (nDstStep < 0) + nDstStep = 4 * nWidth; + + for (y = 0; y < nHeight; y++) + { + pDstPixel = (UINT32*) &pDstData[((nYDst + y) * nDstStep) + (nXDst * 4)]; + test_image_memset32(pDstPixel, color, nWidth); + } + + return 1; +} + +static int test_image_fill_quarter(BYTE* pDstData, int nDstStep, int nWidth, int nHeight, UINT32 color, int quarter) +{ + int x = 0; + int y = 0; + int width = 0; + int height = 0; + + switch (quarter) + { + case 0: + x = 0; + y = 0; + width = nWidth / 2; + height = nHeight /2; + break; + + case 1: + x = nWidth / 2; + y = nHeight / 2; + width = nWidth; + height = nHeight; + break; + + case 2: + x = nWidth / 2; + y = 0; + width = nWidth; + height = nHeight / 2; + break; + + case 3: + x = 0; + y = nHeight / 2; + width = nWidth / 2; + height = nHeight; + break; + } + + test_image_fill(pDstData, nDstStep, x, y, width, height, 0xFF000000); + + return 1; +} + +static int test_image_fill_unused_quarters(BYTE* pDstData, int nDstStep, int nWidth, int nHeight, UINT32 color, int quarter) +{ + if (quarter == 0) + { + test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 1); + test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 2); + test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 3); + } + else if (quarter == 1) + { + test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 0); + test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 2); + test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 3); + } + else if (quarter == 2) + { + test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 0); + test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 1); + test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 3); + } + else if (quarter == 3) + { + test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 0); + test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 1); + test_image_fill_quarter(pDstData, nDstStep, nWidth, nHeight, color, 2); + } + + return 1; +} + BYTE* test_progressive_load_file(char* path, char* file, UINT32* size) { FILE* fp; @@ -402,22 +522,7 @@ int test_progressive_load_files(char* ms_sample_path, EGFX_SAMPLE_FILE files[3][ return 1; } -static void fill_bitmap_alpha_channel(BYTE* data, int width, int height, BYTE value) -{ - int i, j; - UINT32* pixel; - - for (i = 0; i < height; i++) - { - for (j = 0; j < width; j++) - { - pixel = (UINT32*) &data[((i * width) + j) * 4]; - *pixel = ((*pixel & 0x00FFFFFF) | (value << 24)); - } - } -} - -BYTE* test_progressive_load_bitmap(char* path, char* file, UINT32* size) +BYTE* test_progressive_load_bitmap(char* path, char* file, UINT32* size, int quarter) { int status; BYTE* buffer; @@ -442,7 +547,8 @@ BYTE* test_progressive_load_bitmap(char* path, char* file, UINT32* size) buffer = image->data; *size = image->height * image->scanline; - fill_bitmap_alpha_channel(image->data, image->width, image->height, 0xFF); + test_fill_image_alpha_channel(image->data, image->width, image->height, 0xFF); + test_image_fill_unused_quarters(image->data, image->scanline, image->width, image->height, quarter, 0xFF000000); winpr_image_free(image, FALSE); free(filename); @@ -459,73 +565,73 @@ int test_progressive_load_bitmaps(char* ms_sample_path, EGFX_SAMPLE_FILE bitmaps /* image 1 */ bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_0_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_0_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_0_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_0_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_0_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_0_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_0_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_0_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_1_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_1_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_1_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_1_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_1_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_1_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_1_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_1_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_2_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_2_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_2_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_2_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_2_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_2_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_2_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_2_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_3_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_3_025_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_3_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_3_050_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_3_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_3_075_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_0_3_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_0_3_100_sampleimage1.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; imageNo++; @@ -533,73 +639,73 @@ int test_progressive_load_bitmaps(char* ms_sample_path, EGFX_SAMPLE_FILE bitmaps /* image 2 */ bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_0_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_0_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_0_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_0_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_0_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_0_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_0_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_0_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_1_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_1_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_1_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_1_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_1_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_1_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_1_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_1_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_2_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_2_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_2_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_2_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_2_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_2_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_2_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_2_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_3_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_3_025_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_3_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_3_050_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_3_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_3_075_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_1_3_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_1_3_100_sampleimage2.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; imageNo++; @@ -607,73 +713,73 @@ int test_progressive_load_bitmaps(char* ms_sample_path, EGFX_SAMPLE_FILE bitmaps /* image 3 */ bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_0_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_0_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_0_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_0_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_0_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_0_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_0_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_0_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_1_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_1_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_1_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_1_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_1_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_1_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_1_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_1_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_2_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_2_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_2_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_2_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_2_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_2_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_2_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_2_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; quarterNo = (quarterNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_3_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_3_025_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_3_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_3_050_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_3_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_3_075_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; bitmaps[imageNo][quarterNo][passNo].buffer = test_progressive_load_bitmap(ms_sample_path, - "decompress/dec_2_3_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size)); + "decompress/dec_2_3_100_sampleimage3.bmp", &(bitmaps[imageNo][quarterNo][passNo].size), quarterNo); passNo = (passNo + 1) % 4; /* check if all test data has been loaded */ @@ -693,13 +799,23 @@ int test_progressive_load_bitmaps(char* ms_sample_path, EGFX_SAMPLE_FILE bitmaps return 1; } -static int g_Width = 0; -static int g_Height = 0; -static int g_DstStep = 0; -static BYTE* g_DstData = NULL; +int test_memcmp(const BYTE* mem1, const BYTE* mem2, int size) +{ + int index = 0; + + while ((index < size) && (*mem1 == *mem2)) + { + mem1++; + mem2++; + index++; + } + + return (index == size) ? 1 : -index; +} int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE files[4], EGFX_SAMPLE_FILE bitmaps[4], int quarter, int count) { + int cmp; int pass; int index; int status; @@ -773,6 +889,9 @@ int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE f nWidth = updateRect.right - updateRect.left; nHeight = updateRect.bottom - updateRect.top; + if ((nWidth <= 0) || (nHeight <= 0)) + continue; + nXSrc = nXDst - tile->x; nYSrc = nYDst - tile->y; @@ -781,22 +900,22 @@ int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE f PIXEL_FORMAT_XRGB32, 64 * 4, nXSrc, nYSrc); } - if (memcmp(g_DstData, bitmaps[pass].buffer, bitmaps[pass].size) != 0) + cmp = test_memcmp(g_DstData, bitmaps[pass].buffer, bitmaps[pass].size); + + if (cmp <= 0) { - printf("bitmap decompression error\n"); + cmp *= -1; + + printf("bitmap decompression error: %d/%d\n", cmp, bitmaps[pass].size); printf("GOOD: "); - winpr_HexDump(bitmaps[pass].buffer, 16); + winpr_HexDump(&bitmaps[pass].buffer[cmp], 16); printf("BAD: "); - winpr_HexDump(g_DstData, 16); - } - else - { - printf("bitmap decompression success\n"); + winpr_HexDump(&g_DstData[cmp], 16); } - WLog_Image(progressive->log, WLOG_TRACE, g_DstData, g_Width, g_Height, 32); + //WLog_Image(progressive->log, WLOG_TRACE, g_DstData, g_Width, g_Height, 32); } return 1; @@ -836,6 +955,7 @@ int test_progressive_ms_sample(char* ms_sample_path) if (1) { + test_image_fill(g_DstData, g_DstStep, 0, 0, g_Width, g_Height, 0xFF000000); test_progressive_decode(progressive, files[0][0], bitmaps[0][0], 0, count); test_progressive_decode(progressive, files[0][1], bitmaps[0][1], 1, count); test_progressive_decode(progressive, files[0][2], bitmaps[0][2], 2, count); @@ -847,6 +967,7 @@ int test_progressive_ms_sample(char* ms_sample_path) if (0) { /* decompressed image set is incorrect for this one */ + test_image_fill(g_DstData, g_DstStep, 0, 0, g_Width, g_Height, 0xFF000000); test_progressive_decode(progressive, files[1][0], bitmaps[1][0], 0, count); test_progressive_decode(progressive, files[1][1], bitmaps[1][1], 1, count); test_progressive_decode(progressive, files[1][2], bitmaps[1][2], 2, count); @@ -857,6 +978,7 @@ int test_progressive_ms_sample(char* ms_sample_path) if (0) { + test_image_fill(g_DstData, g_DstStep, 0, 0, g_Width, g_Height, 0xFF000000); test_progressive_decode(progressive, files[2][0], bitmaps[2][0], 0, count); test_progressive_decode(progressive, files[2][1], bitmaps[2][1], 1, count); test_progressive_decode(progressive, files[2][2], bitmaps[2][2], 2, count); diff --git a/libfreerdp/primitives/prim_colors.c b/libfreerdp/primitives/prim_colors.c index a7de64339..7478fceee 100644 --- a/libfreerdp/primitives/prim_colors.c +++ b/libfreerdp/primitives/prim_colors.c @@ -33,6 +33,64 @@ #endif /* !MINMAX */ /* ------------------------------------------------------------------------- */ + +pstatus_t general_yCbCrToRGB_16s8u_P3AC4R(const INT16* pSrc[3], int srcStep, + BYTE* pDst, int dstStep, const prim_size_t* roi) +{ + int x, y; + INT16 R, G, B; + double Y, Cb, Cr; + BYTE* pRGB = pDst; + const INT16* pY = pSrc[0]; + const INT16* pCb = pSrc[1]; + const INT16* pCr = pSrc[2]; + int srcPad = (srcStep - (roi->width * 2)) / 2; + int dstPad = (dstStep - (roi->width * 4)) / 4; + + for (y = 0; y < roi->height; y++) + { + for (x = 0; x < roi->width; x++) + { + Y = (double) ((*pY++ >> 1) + 2048); + Cb = (double) (*pCb++ >> 1); + Cr = (double) (*pCr++ >> 1); + + R = (INT16) (((int) (Y + (1.402524948120117L * Cr) + 8.0L)) >> 4); + G = (INT16) (((int) (Y - (0.3437300026416779L * Cb) - (0.7144010066986084L * Cr) + 8.0L)) >> 4); + B = (INT16) (((int) (Y + (1.769904971122742L * Cb) + 8.0L)) >> 4); + + if (R < 0) + R = 0; + else if (R > 255) + R = 255; + + if (G < 0) + G = 0; + else if (G > 255) + G = 255; + + if (B < 0) + B = 0; + else if (B > 255) + B = 255; + + *pRGB++ = (BYTE) B; + *pRGB++ = (BYTE) G; + *pRGB++ = (BYTE) R; + *pRGB++ = 0xFF; + } + + pY += srcPad; + pCb += srcPad; + pCr += srcPad; + pRGB += dstPad; + } + + return PRIMITIVES_SUCCESS; +} + +/* ------------------------------------------------------------------------- */ + pstatus_t general_yCbCrToRGB_16s16s_P3P3( const INT16 *pSrc[3], INT32 srcStep, INT16 *pDst[3], INT32 dstStep, @@ -217,9 +275,10 @@ pstatus_t general_RGBToRGB_16s8u_P3AC4R( /* ------------------------------------------------------------------------- */ void primitives_init_colors(primitives_t* prims) { - prims->RGBToRGB_16s8u_P3AC4R = general_RGBToRGB_16s8u_P3AC4R; + prims->yCbCrToRGB_16s8u_P3AC4R = general_yCbCrToRGB_16s8u_P3AC4R; prims->yCbCrToRGB_16s16s_P3P3 = general_yCbCrToRGB_16s16s_P3P3; prims->RGBToYCbCr_16s16s_P3P3 = general_RGBToYCbCr_16s16s_P3P3; + prims->RGBToRGB_16s8u_P3AC4R = general_RGBToRGB_16s8u_P3AC4R; primitives_init_colors_opt(prims); } diff --git a/libfreerdp/primitives/prim_colors.h b/libfreerdp/primitives/prim_colors.h index 15b76d997..773bbaeeb 100644 --- a/libfreerdp/primitives/prim_colors.h +++ b/libfreerdp/primitives/prim_colors.h @@ -22,6 +22,7 @@ #ifndef __PRIM_COLORS_H_INCLUDED__ #define __PRIM_COLORS_H_INCLUDED__ +pstatus_t general_yCbCrToRGB_16s8u_P3AC4R(const INT16* pSrc[3], int srcStep, BYTE* pDst, int dstStep, const prim_size_t* roi); pstatus_t general_yCbCrToRGB_16s16s_P3P3(const INT16 *pSrc[3], INT32 srcStep, INT16 *pDst[3], INT32 dstStep, const prim_size_t *roi); pstatus_t general_RGBToYCbCr_16s16s_P3P3(const INT16 *pSrc[3], INT32 srcStep, INT16 *pDst[3], INT32 dstStep, const prim_size_t *roi); pstatus_t general_RGBToRGB_16s8u_P3AC4R(const INT16 *pSrc[3], int srcStep, BYTE *pDst, int dstStep, const prim_size_t *roi); From ccb31efe631b47f7c778d5869b542748b6e33f7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 4 Sep 2014 15:46:20 -0400 Subject: [PATCH 25/30] libfreerdp-primitives: migrate tests to ctest --- libfreerdp/primitives/CMakeLists.txt | 2 +- libfreerdp/primitives/test/.gitignore | 1 + libfreerdp/primitives/test/CMakeLists.txt | 178 ++----- ..._16to32bpp.c => TestPrimitives16to32bpp.c} | 25 +- .../test/{test_add.c => TestPrimitivesAdd.c} | 22 + ..._alphaComp.c => TestPrimitivesAlphaComp.c} | 22 + .../{test_andor.c => TestPrimitivesAndOr.c} | 35 ++ .../{test_colors.c => TestPrimitivesColors.c} | 35 ++ .../{test_copy.c => TestPrimitivesCopy.c} | 22 + .../test/{test_set.c => TestPrimitivesSet.c} | 48 ++ .../{test_shift.c => TestPrimitivesShift.c} | 61 +++ .../{test_sign.c => TestPrimitivesSign.c} | 22 + .../{test_YCoCg.c => TestPrimitivesYCoCg.c} | 23 +- libfreerdp/primitives/test/prim_test.c | 488 ++---------------- libfreerdp/primitives/test/prim_test.h | 23 +- 15 files changed, 390 insertions(+), 617 deletions(-) rename libfreerdp/primitives/test/{test_16to32bpp.c => TestPrimitives16to32bpp.c} (94%) rename libfreerdp/primitives/test/{test_add.c => TestPrimitivesAdd.c} (92%) rename libfreerdp/primitives/test/{test_alphaComp.c => TestPrimitivesAlphaComp.c} (95%) rename libfreerdp/primitives/test/{test_andor.c => TestPrimitivesAndOr.c} (92%) rename libfreerdp/primitives/test/{test_colors.c => TestPrimitivesColors.c} (92%) rename libfreerdp/primitives/test/{test_copy.c => TestPrimitivesCopy.c} (89%) rename libfreerdp/primitives/test/{test_set.c => TestPrimitivesSet.c} (92%) rename libfreerdp/primitives/test/{test_shift.c => TestPrimitivesShift.c} (88%) rename libfreerdp/primitives/test/{test_sign.c => TestPrimitivesSign.c} (90%) rename libfreerdp/primitives/test/{test_YCoCg.c => TestPrimitivesYCoCg.c} (91%) diff --git a/libfreerdp/primitives/CMakeLists.txt b/libfreerdp/primitives/CMakeLists.txt index f544b350e..9bc898c18 100644 --- a/libfreerdp/primitives/CMakeLists.txt +++ b/libfreerdp/primitives/CMakeLists.txt @@ -100,6 +100,6 @@ endif() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp") if(BUILD_TESTING AND ((NOT WIN32) AND (NOT APPLE))) -# add_subdirectory(test) + add_subdirectory(test) endif() diff --git a/libfreerdp/primitives/test/.gitignore b/libfreerdp/primitives/test/.gitignore index 082fee1c1..f25c3eed1 100644 --- a/libfreerdp/primitives/test/.gitignore +++ b/libfreerdp/primitives/test/.gitignore @@ -1,2 +1,3 @@ prim_test +TestPrimitives.c diff --git a/libfreerdp/primitives/test/CMakeLists.txt b/libfreerdp/primitives/test/CMakeLists.txt index 972cee3b8..c5fe100c8 100644 --- a/libfreerdp/primitives/test/CMakeLists.txt +++ b/libfreerdp/primitives/test/CMakeLists.txt @@ -1,155 +1,49 @@ -# FreeRDP: A Remote Desktop Protocol Client -# primitives test makefile builder -# vi:ts=4 sw=4: -# -# (c) Copyright 2012 Hewlett-Packard Development Company, L.P. -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing permissions -# and limitations under the License. -# -# TODO: Integrate this into the testing framework, in some form. -# Right now this produces a standalone test that covers both functionality -# and performance of the primitives library entrypoints. +set(MODULE_NAME "TestPrimitives") +set(MODULE_PREFIX "TEST_FREERDP_PRIMITIVES") -cmake_minimum_required(VERSION 2.8) -set(MODULE_NAME "prim_test") -set(MODULE_PREFIX "PRIMITIVES_LIBRARY_TEST") +set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c) -set(PRIMITIVE_TEST_CFILES +set(${MODULE_PREFIX}_TESTS + TestPrimitives16to32bpp.c + TestPrimitivesAdd.c + TestPrimitivesAlphaComp.c + TestPrimitivesAndOr.c + TestPrimitivesColors.c + TestPrimitivesCopy.c + TestPrimitivesSet.c + TestPrimitivesShift.c + TestPrimitivesSign.c + TestPrimitivesYCoCg.c) + +create_test_sourcelist(${MODULE_PREFIX}_SRCS + ${${MODULE_PREFIX}_DRIVER} + ${${MODULE_PREFIX}_TESTS}) + +set(${MODULE_PREFIX}_EXTRA_SRCS prim_test.c - test_16to32bpp.c - test_add.c - test_alphaComp.c - test_andor.c - test_colors.c - test_copy.c - test_set.c - test_shift.c - test_sign.c - test_YCoCg.c - ../prim_16to32bpp.c - ../prim_add.c - ../prim_andor.c - ../prim_alphaComp.c - ../prim_colors.c - ../prim_copy.c - ../prim_set.c - ../prim_shift.c - ../prim_sign.c - ../prim_YCoCg.c - ../prim_16to32bpp_opt.c - ../prim_add_opt.c - ../prim_alphaComp_opt.c - ../prim_andor_opt.c - ../prim_colors_opt.c - ../prim_set_opt.c - ../prim_shift_opt.c - ../prim_sign_opt.c - ../prim_YCoCg_opt.c - ../primitives.c - ) - -set(PRIMITIVE_TEST_HEADERS - measure.h prim_test.h - ../prim_internal.h -) + measure.h) -set(PRIMITIVE_TEST_SRCS - ${PRIMITIVE_TEST_CFILES} - ${PRIMITIVE_TEST_HEADERS} - ) +add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS} ${${MODULE_PREFIX}_EXTRA_SRCS}) -include_directories(. ../../.. ../../../include ../../../winpr/include) -add_definitions(-DPRIM_STATIC=auto -DALL_PRIMITIVES_VERSIONS -DHAVE_CONFIG_H) +set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS + MONOLITHIC ${MONOLITHIC_BUILD} + MODULE freerdp + MODULES freerdp-primitives) + +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr) -# If these haven't been set by the caller, set them now to defaults. -if(NOT DEFINED WITH_IPP) - set(WITH_IPP FALSE) -endif() -if(NOT DEFINED WITH_SSE2) - if (CMAKE_SYSTEM_PROCESSOR MATCHES "arm*") - set(WITH_SSE2 FALSE) - else() - set(WITH_SSE2 TRUE) - endif() -endif() -if(NOT DEFINED WITH_NEON) - if (CMAKE_SYSTEM_PROCESSOR MATCHES "arm*") - set(WITH_NEON TRUE) - else() - set(WITH_NEON FALSE) - endif() -endif() +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) -if(WITH_SSE2) - if(CMAKE_COMPILER_IS_GNUCC) - set(OPTFLAGS "${OPTFLAGS} -msse2 -mssse3 -O2 -Wdeclaration-after-statement") - endif() +add_definitions(-DPRIM_STATIC=auto -DALL_PRIMITIVES_VERSIONS) - if(MSVC) - set(OPTFLAGS "${OPTFLAGS} /arch:SSE2") - endif() -elseif(WITH_NEON) - if(CMAKE_COMPILER_IS_GNUCC) - set(OPTFLAGS "${OPTFLAGS} -mfpu=neon -mfloat-abi=${ARM_FP_ABI} -O2") - endif() - # TODO: Add MSVC equivalent -endif() +set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}") -add_executable(prim_test ${PRIMITIVE_TEST_SRCS}) - -if(WITH_IPP) - if(NOT DEFINED IPP_FOUND) - include(../../../cmake/FindIPP.cmake) - endif() - - # IPP PATH debugging messages - message(IPP_FOUND=${IPP_FOUND}) - message(IPP_VERSION_STR=${IPP_VERSION_STR}) - message(IPP_VERSION_MAJOR=${IPP_VERSION_MAJOR}) - message(IPP_VERSION_MINOR=${IPP_VERSION_MINOR}) - message(IPP_VERSION_BUILD=${IPP_VERSION_BUILD}) - message(IPP_ROOT_DIR=${IPP_ROOT_DIR}) - message(IPP_INCLUDE_DIRS=${IPP_INCLUDE_DIRS}) - message(IPP_LIBRARY_DIRS=${IPP_LIBRARY_DIRS}) - message(IPP_LIBRARIES=${IPP_LIBRARIES}) - message(IPP_COMPILER_LIBRARY_DIRS=${IPP_COMPILER_LIBRARY_DIRS}) - message(IPP_COMPILER_LIBRARIES=${IPP_COMPILER_LIBRARIES}) - message(IPP_LIBRARY_LIST=${IPP_LIBRARY_LIST}) - message(IPP_LIB_PREFIX=${IPP_LIB_PREFIX}) - message(IPP_LIB_SUFFIX=${IPP_LIB_SUFFIX}) - message(IPP_PREFIX=${IPP_PREFIX}) - message(IPP_SUFFIX=${IPP_SUFFIX}) - message(IPPCORE=${IPPCORE}) - message(IPPS=${IPPS}) - message(IPPI=${IPPI}) - message(IPPCC=${IPPCC}) - message(IPPCV=${IPPCV}) - message(IPPVM=${IPPVM}) - - if(CMAKE_COMPILER_IS_GNUCC) - foreach(INCLDIR ${IPP_INCLUDE_DIRS}) - set(OPTFLAGS "${OPTFLAGS} -I${INCLDIR}") - endforeach(INCLDIR) - endif() - target_link_libraries(prim_test ${IPP_LIBRARY_LIST}) -endif() - -set_property(SOURCE ${PRIMITIVE_TEST_CFILES} PROPERTY COMPILE_FLAGS ${OPTFLAGS}) - -find_library(WINPR_SYSINFO NAMES winpr-sysinfo HINTS ../../../winpr/libwinpr/sysinfo) -target_link_libraries(prim_test rt ${WINPR_SYSINFO}) - -if(NOT TESTING_OUTPUT_DIRECTORY) - set(TESTING_OUTPUT_DIRECTORY .) -endif() -add_test(prim_test ${TESTING_OUTPUT_DIRECTORY}/prim_test functionality) +foreach(test ${${MODULE_PREFIX}_TESTS}) + get_filename_component(TestName ${test} NAME_WE) + add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName}) +endforeach() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Test") + diff --git a/libfreerdp/primitives/test/test_16to32bpp.c b/libfreerdp/primitives/test/TestPrimitives16to32bpp.c similarity index 94% rename from libfreerdp/primitives/test/test_16to32bpp.c rename to libfreerdp/primitives/test/TestPrimitives16to32bpp.c index dc0c60317..03a070e40 100644 --- a/libfreerdp/primitives/test/test_16to32bpp.c +++ b/libfreerdp/primitives/test/TestPrimitives16to32bpp.c @@ -28,6 +28,8 @@ static const int RGB_TRIAL_ITERATIONS = 1000; static const float TEST_TIME = 4.0; +extern BOOL g_TestPrimitivesPerformance; + extern pstatus_t general_RGB565ToARGB_16u32u_C3C4( const UINT16* pSrc, INT32 srcStep, UINT32* pDst, INT32 dstStep, @@ -134,7 +136,7 @@ static BOOL try_16To32( /* ------------------------------------------------------------------------- */ int test_RGB565ToARGB_16u32u_C3C4_func(void) { - INT16 ALIGN(data16[4096+3]); + UINT16 ALIGN(data16[4096+3]); BOOL success; success = TRUE; @@ -176,7 +178,6 @@ int test_RGB565ToARGB_16u32u_C3C4_speed(void) { UINT16 ALIGN(src[4096]); UINT32 ALIGN(dst[4096]); - int i; int size_array[] = { 64 }; get_random_data(src, sizeof(src)); @@ -186,3 +187,23 @@ int test_RGB565ToARGB_16u32u_C3C4_speed(void) size_array, 1, RGB_TRIAL_ITERATIONS, TEST_TIME); return SUCCESS; } + +int TestPrimitives16to32bpp(int argc, char* argv[]) +{ + int status; + + status = test_RGB565ToARGB_16u32u_C3C4_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_RGB565ToARGB_16u32u_C3C4_speed(); + + if (status != SUCCESS) + return 1; + } + + return 0; +} diff --git a/libfreerdp/primitives/test/test_add.c b/libfreerdp/primitives/test/TestPrimitivesAdd.c similarity index 92% rename from libfreerdp/primitives/test/test_add.c rename to libfreerdp/primitives/test/TestPrimitivesAdd.c index 453e2a7de..08ab41ff4 100644 --- a/libfreerdp/primitives/test/test_add.c +++ b/libfreerdp/primitives/test/TestPrimitivesAdd.c @@ -23,6 +23,8 @@ static const int ADD16S_PRETEST_ITERATIONS = 300000*64; static const int TEST_TIME = 2.0; // seconds +extern BOOL g_TestPrimitivesPerformance; + extern pstatus_t general_add_16s( const INT16 *pSrc1, const INT16 *pSrc2, INT16 *pDst, int len); extern pstatus_t sse3_add_16s( @@ -112,3 +114,23 @@ int test_add16s_speed(void) test_sizes, NUM_TEST_SIZES, ADD16S_PRETEST_ITERATIONS, TEST_TIME); return SUCCESS; } + +int TestPrimitivesAdd(int argc, char* argv[]) +{ + int status; + + status = test_add16s_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_add16s_speed(); + + if (status != SUCCESS) + return 1; + } + + return 0; +} diff --git a/libfreerdp/primitives/test/test_alphaComp.c b/libfreerdp/primitives/test/TestPrimitivesAlphaComp.c similarity index 95% rename from libfreerdp/primitives/test/test_alphaComp.c rename to libfreerdp/primitives/test/TestPrimitivesAlphaComp.c index c3b5e9ca1..18332dcb5 100644 --- a/libfreerdp/primitives/test/test_alphaComp.c +++ b/libfreerdp/primitives/test/TestPrimitivesAlphaComp.c @@ -22,6 +22,8 @@ static const int ALPHA_PRETEST_ITERATIONS = 5000000; static const float TEST_TIME = 5.0; +extern BOOL g_TestPrimitivesPerformance; + static const int block_size[] = { 4, 64, 256 }; #define NUM_BLOCK_SIZES (sizeof(block_size)/sizeof(int)) #define MAX_BLOCK_SIZE 256 @@ -233,3 +235,23 @@ int test_alphaComp_speed(void) return SUCCESS; } + +int TestPrimitivesAlphaComp(int argc, char* argv[]) +{ + int status; + + status = test_alphaComp_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_alphaComp_speed(); + + if (status != SUCCESS) + return 1; + } + + return 0; +} diff --git a/libfreerdp/primitives/test/test_andor.c b/libfreerdp/primitives/test/TestPrimitivesAndOr.c similarity index 92% rename from libfreerdp/primitives/test/test_andor.c rename to libfreerdp/primitives/test/TestPrimitivesAndOr.c index d82991408..24d73d43a 100644 --- a/libfreerdp/primitives/test/test_andor.c +++ b/libfreerdp/primitives/test/TestPrimitivesAndOr.c @@ -23,6 +23,8 @@ static const int ANDOR_PRETEST_ITERATIONS = 100000; static const int TEST_TIME = 2.0; // seconds +extern BOOL g_TestPrimitivesPerformance; + extern pstatus_t general_andC_32u(const UINT32 *pSrc, UINT32 val, UINT32 *pDst, int len); extern pstatus_t sse3_andC_32u(const UINT32 *pSrc, UINT32 val, @@ -185,3 +187,36 @@ int test_or_32u_speed(void) test_sizes, NUM_TEST_SIZES, ANDOR_PRETEST_ITERATIONS, TEST_TIME); return SUCCESS; } + +int TestPrimitivesAndOr(int argc, char* argv[]) +{ + int status; + + status = test_and_32u_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_and_32u_speed(); + + if (status != SUCCESS) + return 1; + } + + status = test_or_32u_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_or_32u_speed(); + + if (status != SUCCESS) + return 1; + } + + return 0; +} diff --git a/libfreerdp/primitives/test/test_colors.c b/libfreerdp/primitives/test/TestPrimitivesColors.c similarity index 92% rename from libfreerdp/primitives/test/test_colors.c rename to libfreerdp/primitives/test/TestPrimitivesColors.c index 628cb5d5e..717328246 100644 --- a/libfreerdp/primitives/test/test_colors.c +++ b/libfreerdp/primitives/test/TestPrimitivesColors.c @@ -23,6 +23,8 @@ static const int RGB_TRIAL_ITERATIONS = 1000; static const int YCBCR_TRIAL_ITERATIONS = 1000; static const float TEST_TIME = 4.0; +extern BOOL g_TestPrimitivesPerformance; + extern pstatus_t general_RGBToRGB_16s8u_P3AC4R(const INT16 *pSrc[3], int srcStep, BYTE *pDst, int dstStep, const prim_size_t *roi); extern pstatus_t sse2_RGBToRGB_16s8u_P3AC4R(const INT16 *pSrc[3], @@ -241,3 +243,36 @@ int test_yCbCrToRGB_16s16s_P3P3_speed(void) size_array, 1, YCBCR_TRIAL_ITERATIONS, TEST_TIME); return SUCCESS; } + +int TestPrimitivesColors(int argc, char* argv[]) +{ + int status; + + status = test_RGBToRGB_16s8u_P3AC4R_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_RGBToRGB_16s8u_P3AC4R_speed(); + + if (status != SUCCESS) + return 1; + } + + status = test_yCbCrToRGB_16s16s_P3P3_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_yCbCrToRGB_16s16s_P3P3_speed(); + + if (status != SUCCESS) + return 1; + } + + return 0; +} diff --git a/libfreerdp/primitives/test/test_copy.c b/libfreerdp/primitives/test/TestPrimitivesCopy.c similarity index 89% rename from libfreerdp/primitives/test/test_copy.c rename to libfreerdp/primitives/test/TestPrimitivesCopy.c index 13b4f57f2..189969d7c 100644 --- a/libfreerdp/primitives/test/test_copy.c +++ b/libfreerdp/primitives/test/TestPrimitivesCopy.c @@ -26,6 +26,8 @@ static const int TEST_TIME = 1.0; // seconds extern pstatus_t sse3_copy_8u(const BYTE *pSrc, BYTE *pDst, int len); #endif +extern BOOL g_TestPrimitivesPerformance; + /* ------------------------------------------------------------------------- */ int test_copy8u_func(void) { @@ -84,3 +86,23 @@ int test_copy8u_speed(void) test_sizes, NUM_TEST_SIZES, MEMCPY_PRETEST_ITERATIONS, TEST_TIME); return SUCCESS; } + +int TestPrimitivesCopy(int argc, char* argv[]) +{ + int status; + + status = test_copy8u_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_copy8u_speed(); + + if (status != SUCCESS) + return 1; + } + + return 0; +} diff --git a/libfreerdp/primitives/test/test_set.c b/libfreerdp/primitives/test/TestPrimitivesSet.c similarity index 92% rename from libfreerdp/primitives/test/test_set.c rename to libfreerdp/primitives/test/TestPrimitivesSet.c index 32d22c71d..3d689eeff 100644 --- a/libfreerdp/primitives/test/test_set.c +++ b/libfreerdp/primitives/test/TestPrimitivesSet.c @@ -23,6 +23,8 @@ static const int MEMSET8_PRETEST_ITERATIONS = 100000000; static const int MEMSET32_PRETEST_ITERATIONS = 40000000; static const float TEST_TIME = 1.0; +extern BOOL g_TestPrimitivesPerformance; + extern pstatus_t general_set_8u(BYTE val, BYTE *pDst, int len); extern pstatus_t sse2_set_8u(BYTE val, BYTE *pDst, int len); extern pstatus_t general_set_32s(INT32 val, INT32 *pDst, int len); @@ -303,3 +305,49 @@ int test_set32s_speed(void) #endif return SUCCESS; } + +int TestPrimitivesSet(int argc, char* argv[]) +{ + int status; + + status = test_set8u_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_set8u_speed(); + + if (status != SUCCESS) + return 1; + } + + status = test_set32s_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_set32s_speed(); + + if (status != SUCCESS) + return 1; + } + + status = test_set32u_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_set32u_speed(); + + if (status != SUCCESS) + return 1; + } + + return 0; +} diff --git a/libfreerdp/primitives/test/test_shift.c b/libfreerdp/primitives/test/TestPrimitivesShift.c similarity index 88% rename from libfreerdp/primitives/test/test_shift.c rename to libfreerdp/primitives/test/TestPrimitivesShift.c index 588187a4b..693c12b34 100644 --- a/libfreerdp/primitives/test/test_shift.c +++ b/libfreerdp/primitives/test/TestPrimitivesShift.c @@ -23,6 +23,8 @@ static const int SHIFT_PRETEST_ITERATIONS = 50000; static const float TEST_TIME = 1.0; +extern BOOL g_TestPrimitivesPerformance; + extern pstatus_t general_lShiftC_16s( const INT16 *pSrc, int val, INT16 *pDst, int len); extern pstatus_t general_rShiftC_16s( @@ -187,3 +189,62 @@ int test_rShift_16u_speed(void) test_sizes, NUM_TEST_SIZES, SHIFT_PRETEST_ITERATIONS, TEST_TIME); return SUCCESS; } + +int TestPrimitivesShift(int argc, char* argv[]) +{ + int status; + + status = test_lShift_16s_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_lShift_16s_speed(); + + if (status != SUCCESS) + return 1; + } + + status = test_lShift_16u_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_lShift_16u_speed(); + + if (status != SUCCESS) + return 1; + } + + status = test_rShift_16s_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_rShift_16s_speed(); + + if (status != SUCCESS) + return 1; + } + + status = test_rShift_16u_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_rShift_16u_speed(); + + if (status != SUCCESS) + return 1; + } + + return 0; +} diff --git a/libfreerdp/primitives/test/test_sign.c b/libfreerdp/primitives/test/TestPrimitivesSign.c similarity index 90% rename from libfreerdp/primitives/test/test_sign.c rename to libfreerdp/primitives/test/TestPrimitivesSign.c index beb22ee1d..0d06d64bc 100644 --- a/libfreerdp/primitives/test/test_sign.c +++ b/libfreerdp/primitives/test/TestPrimitivesSign.c @@ -22,6 +22,8 @@ static const int SIGN_PRETEST_ITERATIONS = 100000; static const float TEST_TIME = 1.0; +extern BOOL g_TestPrimitivesPerformance; + extern pstatus_t general_sign_16s(const INT16 *pSrc, INT16 *pDst, int len); #ifdef WITH_SSE2 extern pstatus_t ssse3_sign_16s(const INT16 *pSrc, INT16 *pDst, int len); @@ -101,3 +103,23 @@ int test_sign16s_speed(void) test_sizes, NUM_TEST_SIZES, SIGN_PRETEST_ITERATIONS, TEST_TIME); return SUCCESS; } + +int TestPrimitivesSign(int argc, char* argv[]) +{ + int status; + + status = test_sign16s_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_sign16s_speed(); + + if (status != SUCCESS) + return 1; + } + + return 0; +} diff --git a/libfreerdp/primitives/test/test_YCoCg.c b/libfreerdp/primitives/test/TestPrimitivesYCoCg.c similarity index 91% rename from libfreerdp/primitives/test/test_YCoCg.c rename to libfreerdp/primitives/test/TestPrimitivesYCoCg.c index f09acd5de..d6f4d4289 100644 --- a/libfreerdp/primitives/test/test_YCoCg.c +++ b/libfreerdp/primitives/test/TestPrimitivesYCoCg.c @@ -26,6 +26,8 @@ static const int YCOCG_TRIAL_ITERATIONS = 20000; static const float TEST_TIME = 4.0; +extern BOOL g_TestPrimitivesPerformance; + extern pstatus_t general_YCoCgRToRGB_8u_AC4R(const BYTE *pSrc, INT32 srcStep, BYTE *pDst, INT32 dstStep, UINT32 width, UINT32 height, UINT8 shift, BOOL withAlpha, BOOL invert); @@ -97,7 +99,6 @@ int test_YCoCgRToRGB_8u_AC4R_speed(void) { INT32 ALIGN(in[4096]); INT32 ALIGN(out[4096]); - int i; int size_array[] = { 64 }; get_random_data(in, sizeof(in)); @@ -107,3 +108,23 @@ int test_YCoCgRToRGB_8u_AC4R_speed(void) size_array, 1, YCOCG_TRIAL_ITERATIONS, TEST_TIME); return SUCCESS; } + +int TestPrimitivesYCoCg(int argc, char* argv[]) +{ + int status; + + status = test_YCoCgRToRGB_8u_AC4R_func(); + + if (status != SUCCESS) + return 1; + + if (g_TestPrimitivesPerformance) + { + status = test_YCoCgRToRGB_8u_AC4R_speed(); + + if (status != SUCCESS) + return 1; + } + + return 0; +} diff --git a/libfreerdp/primitives/test/prim_test.c b/libfreerdp/primitives/test/prim_test.c index e9824a181..a19b5f64b 100644 --- a/libfreerdp/primitives/test/prim_test.c +++ b/libfreerdp/primitives/test/prim_test.c @@ -18,108 +18,22 @@ #include "prim_test.h" +#include #include #include -#include -#include + #include +#include #ifdef HAVE_UNISTD_H #include #endif -#include -#include - +BOOL g_TestPrimitivesPerformance = FALSE; int test_sizes[] = { 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 }; -int Quiet = 0; - - /* ------------------------------------------------------------------------- */ -typedef struct -{ - UINT32 flag; - const char *str; -} flagpair_t; - -static const flagpair_t flags[] = -{ -#ifdef _M_IX86_AMD64 - { PF_MMX_INSTRUCTIONS_AVAILABLE, "MMX" }, - { PF_3DNOW_INSTRUCTIONS_AVAILABLE, "3DNow" }, - { PF_SSE_INSTRUCTIONS_AVAILABLE, "SSE" }, - { PF_SSE2_INSTRUCTIONS_AVAILABLE, "SSE2" }, - { PF_SSE3_INSTRUCTIONS_AVAILABLE, "SSE3" }, -#elif defined(_M_ARM) - { PF_ARM_VFP3, "VFP3" }, - { PF_ARM_INTEL_WMMX, "IWMMXT" }, - { PF_ARM_NEON_INSTRUCTIONS_AVAILABLE, "NEON" }, -#endif -}; - -static const flagpair_t flags_extended[] = -{ -#ifdef _M_IX86_AMD64 - { PF_EX_3DNOW_PREFETCH, "3DNow-PF" }, - { PF_EX_SSSE3, "SSSE3" }, - { PF_EX_SSE41, "SSE4.1" }, - { PF_EX_SSE42, "SSE4.2" }, - { PF_EX_AVX, "AVX" }, - { PF_EX_FMA, "FMA" }, - { PF_EX_AVX_AES, "AVX-AES" }, - { PF_EX_AVX2, "AVX2" }, -#elif defined(_M_ARM) - { PF_EX_ARM_VFP1, "VFP1"}, - { PF_EX_ARM_VFP4, "VFP4" }, -#endif -}; - -void primitives_flags_str(char* str, size_t len) -{ - int i; - - *str = '\0'; - --len; /* for the '/0' */ - - for (i = 0; i < sizeof(flags) / sizeof(flagpair_t); ++i) - { - if (IsProcessorFeaturePresent(flags[i].flag)) - { - int slen = strlen(flags[i].str) + 1; - - if (len < slen) - break; - - if (*str != '\0') - strcat(str, " "); - - strcat(str, flags[i].str); - len -= slen; - } - } - for (i = 0; i < sizeof(flags_extended) / sizeof(flagpair_t); ++i) - { - if (IsProcessorFeaturePresentEx(flags_extended[i].flag)) - { - int slen = strlen(flags_extended[i].str) + 1; - - if (len < slen) - break; - - if (*str != '\0') - strcat(str, " "); - - strcat(str, flags_extended[i].str); - len -= slen; - } - } -} - -/* ------------------------------------------------------------------------- */ -static void get_random_data_lrand( - void *buffer, - size_t size) +static void get_random_data_lrand(void *buffer, size_t size) { static int seeded = 0; long int *ptr = (long int *) buffer; @@ -145,11 +59,9 @@ static void get_random_data_lrand( } /* ------------------------------------------------------------------------- */ -void get_random_data( - void *buffer, - size_t size) +void get_random_data(void *buffer, size_t size) { -#ifdef linux +#ifdef __linux__ size_t offset = 0; int fd = open("/dev/urandom", O_RDONLY); if (fd < 0) @@ -171,373 +83,39 @@ void get_random_data( } /* ------------------------------------------------------------------------- */ -float _delta_time( - const struct timespec *t0, - const struct timespec *t1) +float _delta_time(const struct timespec *t0, const struct timespec *t1) { - INT64 secs = (INT64) (t1->tv_sec) - (INT64) (t0->tv_sec); - long nsecs = t1->tv_nsec - t0->tv_nsec; + INT64 secs = (INT64) (t1->tv_sec) - (INT64) (t0->tv_sec); + long nsecs = t1->tv_nsec - t0->tv_nsec; double retval; - if (nsecs < 0) + if (nsecs < 0) { - --secs; - nsecs += 1000000000; - } - retval = (double) secs + (double) nsecs / (double) 1000000000.0; - return (retval < 0.0) ? 0.0 : (float) retval; + --secs; + nsecs += 1000000000; + } + + retval = (double) secs + (double) nsecs / (double) 1000000000.0; + return (retval < 0.0) ? 0.0 : (float) retval; } /* ------------------------------------------------------------------------- */ -void _floatprint( - float t, - char *output) +void _floatprint(float t, char *output) { - /* I don't want to link against -lm, so avoid log,exp,... */ - float f = 10.0; + /* I don't want to link against -lm, so avoid log,exp,... */ + float f = 10.0; int i; - while (t > f) f *= 10.0; - f /= 1000.0; - i = ((int) (t/f+0.5)) * (int) f; - if (t < 0.0) sprintf(output, "%f", t); - else if (i == 0) sprintf(output, "%d", (int) (t+0.5)); - else if (t < 1e+3) sprintf(output, "%3d", i); - else if (t < 1e+6) sprintf(output, "%3d,%03d", - i/1000, i % 1000); - else if (t < 1e+9) sprintf(output, "%3d,%03d,000", - i/1000000, (i % 1000000) / 1000); - else if (t < 1e+12) sprintf(output, "%3d,%03d,000,000", - i/1000000000, (i % 1000000000) / 1000000); - else sprintf(output, "%f", t); -} - -/* ------------------------------------------------------------------------- */ -/* Specific areas to test: */ -#define TEST_COPY8 (1<<0) -#define TEST_SET8 (1<<1) -#define TEST_SET32S (1<<2) -#define TEST_SET32U (1<<3) -#define TEST_SIGN16S (1<<4) -#define TEST_ADD16S (1<<5) -#define TEST_LSHIFT16S (1<<6) -#define TEST_LSHIFT16U (1<<7) -#define TEST_RSHIFT16S (1<<8) -#define TEST_RSHIFT16U (1<<9) -#define TEST_RGB (1<<10) -#define TEST_ALPHA (1<<11) -#define TEST_AND (1<<12) -#define TEST_OR (1<<13) -#define TEST_YCOCG (1<<14) -#define TEST_16TO32 (1<<15) - -/* Specific types of testing: */ -#define TEST_FUNCTIONALITY (1<<0) -#define TEST_PERFORMANCE (1<<1) - -/* ------------------------------------------------------------------------- */ - -typedef struct -{ - const char *testStr; - UINT32 bits; -} test_t; - -static const test_t testList[] = -{ - { "all", 0xFFFFFFFFU }, - { "copy", TEST_COPY8 }, - { "copy8", TEST_COPY8 }, - { "set", TEST_SET8|TEST_SET32S|TEST_SET32U }, - { "set8", TEST_SET8 }, - { "set32", TEST_SET32S|TEST_SET32U }, - { "set32s", TEST_SET32S }, - { "set32u", TEST_SET32U }, - { "sign", TEST_SIGN16S }, - { "sign16s", TEST_SIGN16S }, - { "add", TEST_ADD16S }, - { "add16s", TEST_ADD16S }, - { "lshift", TEST_LSHIFT16S|TEST_LSHIFT16U }, - { "rshift", TEST_RSHIFT16S|TEST_RSHIFT16U }, - { "shift", TEST_LSHIFT16S|TEST_LSHIFT16U|TEST_RSHIFT16S|TEST_RSHIFT16U }, - { "lshift16s", TEST_LSHIFT16S }, - { "lshift16u", TEST_LSHIFT16U }, - { "rshift16s", TEST_RSHIFT16S }, - { "rshift16u", TEST_RSHIFT16U }, - { "rgb", TEST_RGB }, - { "color", TEST_RGB }, - { "colors", TEST_RGB }, - { "ycocg", TEST_YCOCG }, - { "alpha", TEST_ALPHA }, - { "and", TEST_AND }, - { "or", TEST_OR }, - { "16to32", TEST_16TO32 } -}; - -#define NUMTESTS (sizeof(testList)/sizeof(test_t)) - -static const test_t testTypeList[] = -{ - { "functionality", TEST_FUNCTIONALITY }, - { "performance", TEST_PERFORMANCE }, -}; - -#define NUMTESTTYPES (sizeof(testTypeList)/sizeof(test_t)) - -int main(int argc, char** argv) -{ - int i; - char hints[1024]; - UINT32 testSet = 0; - UINT32 testTypes = 0; - int results = SUCCESS; - - /* Parse command line for the test set. */ - - for (i = 1; i < argc; ++i) - { - int j; - BOOL found = 0; - - for (j=0; j f) f *= 10.0; + f /= 1000.0; + i = ((int) (t/f+0.5)) * (int) f; + if (t < 0.0) sprintf(output, "%f", t); + else if (i == 0) sprintf(output, "%d", (int) (t+0.5)); + else if (t < 1e+3) sprintf(output, "%3d", i); + else if (t < 1e+6) sprintf(output, "%3d,%03d", + i/1000, i % 1000); + else if (t < 1e+9) sprintf(output, "%3d,%03d,000", + i/1000000, (i % 1000000) / 1000); + else if (t < 1e+12) sprintf(output, "%3d,%03d,000,000", + i/1000000000, (i % 1000000000) / 1000000); + else sprintf(output, "%f", t); } diff --git a/libfreerdp/primitives/test/prim_test.h b/libfreerdp/primitives/test/prim_test.h index e336e3eb5..42f8777c9 100644 --- a/libfreerdp/primitives/test/prim_test.h +++ b/libfreerdp/primitives/test/prim_test.h @@ -20,31 +20,22 @@ #ifndef __PRIMTEST_H_INCLUDED__ #define __PRIMTEST_H_INCLUDED__ -#include -#include +#include +#include #include - -#include -#include -#include +#include #include -#include + +#include "measure.h" #ifdef WITH_IPP #include #include #endif -#define BLOCK_ALIGNMENT 16 -#ifdef __GNUC__ -#define ALIGN(x) x __attribute((aligned(BLOCK_ALIGNMENT))) -#define POSSIBLY_UNUSED(x) x __attribute((unused)) -#else -/* TODO: Someone needs to finish this for non-GNU C */ -#define ALIGN(x) x -#define POSSIBLY_UNUSED(x) x -#endif +#define ALIGN(x) x DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) + #define ABS(_x_) ((_x_) < 0 ? (-(_x_)) : (_x_)) #define MAX_TEST_SIZE 4096 From be60bddec0a0d38e64387acc195a2e5e18976275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 4 Sep 2014 16:34:29 -0400 Subject: [PATCH 26/30] libfreerdp-primitives: add YCbCr color converter test --- .../codec/test/TestFreeRDPCodecProgressive.c | 2 +- libfreerdp/primitives/test/CMakeLists.txt | 1 + .../primitives/test/TestPrimitivesYCbCr.c | 2183 +++++++++++++++++ 3 files changed, 2185 insertions(+), 1 deletion(-) create mode 100644 libfreerdp/primitives/test/TestPrimitivesYCbCr.c diff --git a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c index ac466b9d3..af35d1fc7 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c @@ -799,7 +799,7 @@ int test_progressive_load_bitmaps(char* ms_sample_path, EGFX_SAMPLE_FILE bitmaps return 1; } -int test_memcmp(const BYTE* mem1, const BYTE* mem2, int size) +static int test_memcmp(const BYTE* mem1, const BYTE* mem2, int size) { int index = 0; diff --git a/libfreerdp/primitives/test/CMakeLists.txt b/libfreerdp/primitives/test/CMakeLists.txt index c5fe100c8..8b7162455 100644 --- a/libfreerdp/primitives/test/CMakeLists.txt +++ b/libfreerdp/primitives/test/CMakeLists.txt @@ -14,6 +14,7 @@ set(${MODULE_PREFIX}_TESTS TestPrimitivesSet.c TestPrimitivesShift.c TestPrimitivesSign.c + TestPrimitivesYCbCr.c TestPrimitivesYCoCg.c) create_test_sourcelist(${MODULE_PREFIX}_SRCS diff --git a/libfreerdp/primitives/test/TestPrimitivesYCbCr.c b/libfreerdp/primitives/test/TestPrimitivesYCbCr.c new file mode 100644 index 000000000..0a1301ec5 --- /dev/null +++ b/libfreerdp/primitives/test/TestPrimitivesYCbCr.c @@ -0,0 +1,2183 @@ + +#include "prim_test.h" + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +static INT16 TEST_Y_COMPONENT[4096] = +{ + -32, +16, +64, +272, -32, -16, +0, -16, + -32, -24, -16, -8, +0, -24, -48, -72, + -96, -90, -84, -78, -72, -98, -124, -150, + -176, -192, -208, -224, -240, -256, -272, -288, + -304, -304, -304, -304, -304, -336, -368, -400, + -432, -450, -468, -486, -504, -522, -540, -558, + -576, -598, -620, -642, -664, -686, -708, -730, + -752, -768, -784, -800, -816, -816, -816, -816, + +68, +120, +172, +240, +53, +55, +57, +43, + +30, +32, +34, +36, +38, +20, +2, -16, + -34, -36, -38, -40, -42, -68, -94, -120, + -146, -148, -151, -186, -220, -227, -233, -240, + -247, -254, -261, -268, -275, -302, -329, -356, + -384, -403, -423, -443, -463, -484, -506, -528, + -550, -572, -594, -616, -639, -673, -707, -709, + -712, -733, -754, -775, -796, -796, -796, -796, + +168, +224, +281, +209, +138, +126, +115, +103, + +92, +88, +84, +80, +76, +64, +52, +40, + +28, +18, +8, -2, -12, -38, -64, -90, + -116, -105, -95, -148, -201, -198, -195, -192, + -190, -204, -218, -232, -247, -269, -291, -313, + -336, -357, -379, -400, -422, -447, -473, -498, + -524, -546, -569, -591, -614, -660, -707, -689, + -672, -698, -724, -750, -776, -776, -776, -776, + +268, +312, +357, +273, +191, +181, +172, +162, + +154, +144, +134, +124, +114, +108, +102, +80, + +58, +56, +54, +52, +50, +24, -2, -44, + -86, -61, -38, -93, -149, -137, -124, -144, + -165, -170, -175, -196, -218, -235, -252, -269, + -288, -310, -334, -357, -381, -409, -439, -468, + -498, -520, -543, -565, -589, -647, -706, -668, + -632, -663, -694, -725, -756, -756, -756, -756, + +368, +401, +434, +339, +244, +237, +230, +223, + +216, +200, +184, +168, +152, +152, +152, +120, + +88, +94, +100, +106, +112, +86, +60, +2, + -56, -18, +19, -39, -98, -76, -55, -97, + -140, -136, -133, -161, -190, -202, -215, -227, + -240, -265, -290, -315, -340, -373, -406, -439, + -472, -495, -518, -541, -564, -635, -706, -649, + -592, -628, -664, -700, -736, -736, -736, -736, + +404, +556, +454, +383, +313, +531, +239, +282, + +326, +304, +282, +260, +238, +246, +254, +118, + +238, +196, +154, +32, -90, -88, -86, +76, + +238, +243, +247, +29, -191, -232, -272, -121, + +29, -62, -153, -149, -145, -162, -180, -197, + -216, -240, -265, -289, -315, -345, -376, -406, + -438, -446, -456, -497, -539, -595, -653, -502, + -608, -625, -642, -675, -708, -708, -708, -708, + +440, +713, +475, +428, +382, +827, +249, +342, + +436, +408, +380, +352, +324, +340, +356, -140, + -124, +42, +208, +214, +220, +250, +280, +406, + +532, +504, +476, +352, +229, +125, +22, -146, + -314, -244, -175, -138, -101, -123, -146, -169, + -192, -216, -241, -265, -290, -318, -347, -375, + -404, -399, -395, -454, -514, -557, -601, -356, + -624, -622, -620, -650, -680, -680, -680, -680, + +604, +677, +495, +457, +419, +770, +354, +386, + +418, +416, +414, +380, +346, +258, -342, -302, + -6, +288, +582, +604, +626, +588, +550, +688, + +826, +829, +833, +724, +616, +481, +348, +181, + +15, -139, -292, -175, -56, -83, -112, -139, + -168, -192, -216, -240, -265, -291, -317, -343, + -370, -351, -333, -411, -489, -486, -484, -402, + -576, -587, -598, -625, -652, -652, -652, -652, + +1280, +1154, +1028, +998, +968, +970, +460, +430, + +400, +424, +448, +408, +368, +432, -528, -208, + +112, +534, +956, +994, +1032, +926, +820, +970, + +1120, +1155, +1190, +1097, +1004, +839, +674, +509, + +344, +223, +102, +45, -12, -45, -78, -111, + -144, -168, -192, -216, -240, -264, -288, -312, + -336, -304, -272, -368, -464, -416, -368, -448, + -528, -552, -576, -600, -624, -624, -624, -624, + +770, +671, +573, +554, +536, +629, +467, +464, + +462, +492, +523, +490, +457, +281, -405, -101, + +204, +599, +995, +1310, +1370, +1297, +1225, +1296, + +1368, +1432, +1498, +1402, +1308, +1184, +1062, +874, + +688, +586, +485, +303, +123, -82, -32, -76, + -122, -174, -226, -199, -171, -193, -216, -238, + -261, -314, -368, -325, -283, -360, -438, -451, + -465, -515, -565, -583, -601, -617, -633, -633, + +772, +701, +630, +623, +616, +545, +474, +499, + +524, +561, +599, +572, +546, +131, -283, +6, + +296, +665, +1034, +1627, +1708, +1669, +1630, +1623, + +1616, +1711, +1806, +1709, +1612, +1531, +1450, +1241, + +1032, +950, +869, +563, +258, -120, +15, -42, + -100, -180, -261, -182, -103, -123, -144, -165, + -186, -325, -464, -283, -102, -305, -508, -455, + -402, -478, -554, -566, -578, -610, -642, -642, + +774, +730, +687, +675, +664, +620, +577, +581, + +586, +597, +610, +590, +571, -147, -96, +209, + +516, +794, +1073, +1575, +1822, +1976, +1875, +1869, + +1864, +1988, +2114, +2014, +1916, +1876, +1838, +1606, + +1376, +1266, +1156, +902, +137, -61, -3, -120, + -238, -122, -7, -69, -130, -164, -200, -219, + -239, -271, -304, -128, -209, -297, -386, -426, + -467, -937, -895, -549, -459, -667, -619, -619, + +776, +760, +744, +728, +712, +696, +680, +664, + +648, +635, +622, +609, +596, -425, +90, +413, + +736, +924, +1112, +1524, +1936, +2284, +2120, +2116, + +2112, +2267, +2422, +2321, +2220, +2223, +2226, +1973, + +1720, +1582, +1444, +1242, +16, -2, -20, +58, + +136, -65, -267, -212, -158, -207, -257, -274, + -292, -218, -144, +26, -316, -290, -264, -142, + -20, +2956, +2860, -788, -852, -980, -596, -596, + +826, +807, +789, +770, +752, +749, +747, +744, + +742, +677, +613, +516, +421, -285, +288, +573, + +860, +1081, +1303, +1668, +2034, +2313, +2337, +2344, + +2352, +2452, +2554, +2574, +2596, +2506, +2418, +2248, + +2080, +1961, +1843, +925, +7, +40, +74, +748, + +654, +453, +251, +48, -154, -107, -61, -111, + -161, -28, +104, +45, -271, -274, -278, -842, + +1411, +3007, +3323, +327, -1389, -1197, -493, -493, + +876, +855, +834, +813, +792, +803, +814, +825, + +836, +720, +605, +681, +758, +110, +487, +735, + +984, +1239, +1494, +1813, +2132, +2343, +2554, +2573, + +2592, +2639, +2686, +2829, +2972, +2791, +2610, +2525, + +2440, +2341, +2243, +608, -2, +83, +169, +1438, + +1172, +970, +768, +565, +363, +249, +135, +52, + -30, -95, -160, -193, -226, -259, -292, +763, + -742, +2290, +1738, -1118, -902, -902, -390, -390, + +926, +902, +879, +855, +832, +824, +817, +809, + +802, +763, +724, +397, +2375, +970, +589, +848, + +1108, +1396, +1685, +1941, +2198, +2468, +2739, +2785, + +2832, +2888, +2946, +3178, +2900, +3058, +2962, +2848, + +2736, +2896, +2546, -364, +309, +205, +871, +1760, + +1626, +1471, +1317, +1145, +975, +844, +714, +599, + +485, +351, +216, +146, +75, -355, +750, +2687, + +529, -1067, -615, -835, -799, -847, -383, -383, + +976, +950, +924, +898, +872, +846, +820, +794, + +768, +806, +844, +882, +1432, +2598, +692, +962, + +1232, +1554, +1876, +2070, +2264, +2594, +2924, +2998, + +3072, +3139, +3206, +3273, +2316, +3071, +3314, +3173, + +3032, +2941, +1826, -57, +108, +73, +1574, +2083, + +2080, +1973, +1866, +1727, +1588, +1441, +1294, +1147, + +1000, +796, +592, +484, +376, +828, +256, +772, + -248, -72, -408, +984, -184, -536, -376, -376, + +1026, +997, +969, +941, +913, +888, +864, +840, + +816, +762, +709, +768, +1339, +2269, +2176, +1411, + +1414, +1677, +1941, +2188, +2436, +2730, +3023, +3157, + +3291, +3349, +3409, +3420, +2152, +3000, +3594, +3403, + +3213, +3233, +951, +12, +97, -303, +2883, +2755, + +2373, +2312, +2252, +2143, +2036, +1861, +1687, +1544, + +1403, +1254, +1106, +974, +842, +1229, +1105, +21, + +217, +46, -381, +1912, +3181, +2765, +301, -723, + +1076, +1045, +1015, +984, +954, +931, +909, +886, + +864, +719, +575, +654, +1246, +1685, +3149, +1604, + +1596, +1801, +2006, +2307, +2609, +2866, +3123, +3316, + +3510, +3561, +3613, +3568, +1988, +2931, +3875, +3634, + +3394, +3527, +76, +81, +86, +859, +3168, +2917, + +2666, +2652, +2639, +2561, +2484, +2282, +2081, +1943, + +1806, +1713, +1621, +1464, +1308, +1119, +931, +550, + +170, -92, -354, +1560, +3986, +1970, -558, -558, + +1126, +1092, +1060, +1027, +995, +973, +953, +932, + +912, +899, +888, -340, +1249, +1756, +2521, +2421, + +1810, +2036, +2263, +2521, +2781, +3066, +3350, +3443, + +3537, +3612, +3688, +3476, +2496, +3021, +3803, +3833, + +3863, +2843, +33, +133, -21, +2099, +3197, +3061, + +2927, +2944, +2961, +2882, +2804, +2607, +2410, +2309, + +2209, +2139, +2071, +1842, +1614, +1328, +1044, +663, + +283, +10, -263, -488, -201, -201, -457, -457, + +1176, +1141, +1106, +1071, +1036, +1017, +998, +979, + +960, +825, +690, +203, +740, +1573, +1894, +3239, + +2024, +2272, +2521, +2737, +2954, +3010, +3067, +3315, + +3564, +3664, +3764, +3384, +3004, +3112, +3732, +3776, + +3820, +1905, -10, +187, -128, +3341, +3226, +3207, + +3188, +3236, +3284, +3204, +3124, +2932, +2740, +2676, + +2612, +2567, +2522, +2221, +1920, +1539, +1158, +777, + +396, +112, -172, -488, -292, -324, -356, -356, + +1194, +1162, +1131, +1099, +1069, +1047, +1026, +972, + +920, +969, +507, +380, +767, +1428, +1834, +2799, + +2486, +2347, +2721, +2919, +3118, +3290, +3462, +3266, + +3071, +3157, +3243, +3521, +3800, +3674, +3548, +3710, + +3873, +874, +179, +91, +517, +3439, +3291, +3333, + +3377, +3403, +3430, +3361, +3292, +3174, +3057, +3004, + +2951, +2761, +2572, +2222, +1874, +1554, +1235, +883, + +533, +220, -93, -470, -335, -319, -303, -303, + +1212, +1184, +1157, +1129, +1102, +1078, +1055, +967, + +880, +1114, +325, +559, +794, +1284, +1775, +2361, + +2948, +2423, +2923, +3103, +3283, +3314, +3346, +3474, + +3602, +3674, +3747, +3659, +3572, +3980, +3877, +3901, + +3926, -157, +368, +253, +1674, +3795, +3356, +3461, + +3566, +3571, +3577, +3518, +3460, +3417, +3375, +3332, + +3290, +2956, +2623, +2225, +1828, +1570, +1313, +991, + +670, +328, -14, -452, -378, -314, -250, -250, + +1230, +1206, +1182, +1158, +1135, +1109, +1083, +1025, + +968, +779, +78, +481, +885, +1284, +1939, +2466, + +3250, +2626, +2772, +3157, +3543, +3514, +3486, +3729, + +3717, +3775, +3834, +3780, +3728, +3934, +3885, +3915, + +2667, +92, +333, +173, +2831, +3701, +3549, +3587, + +3627, +3642, +3659, +3643, +3628, +3675, +3724, +3436, + +3149, +2847, +2545, +2275, +2006, +1730, +1454, +1114, + +775, +388, +1, -402, -293, -309, -325, -325, + +1248, +1228, +1208, +1188, +1168, +1140, +1112, +1084, + +1056, +700, +344, +660, +976, +1284, +2104, +2316, + +3040, +2319, +2110, +2189, +2268, +2691, +3114, +3729, + +3832, +3877, +3922, +3903, +3884, +3889, +3894, +3931, + +1408, +341, +298, +95, +3988, +3609, +3742, +3715, + +3688, +3715, +3742, +3769, +3796, +3679, +3562, +3285, + +3008, +2738, +2468, +2326, +2184, +1890, +1596, +1238, + +880, +448, +16, -352, -208, -304, -400, -400, + +1296, +1284, +1272, +1260, +1249, +1165, +1081, +1093, + +1106, +232, +382, +677, +971, +973, +1232, +834, + +693, +537, +639, +564, +490, +563, +637, -106, + +944, +2358, +3773, +3795, +4074, +3964, +3855, +4337, + +212, +204, +197, +1341, +4023, +3813, +3860, +3810, + +3762, +3766, +3771, +3776, +3781, +3603, +3427, +3201, + +2977, +2838, +2699, +2400, +2101, +1982, +1607, +1280, + +954, +545, -120, -321, -266, -314, -362, -362, + +1344, +1340, +1337, +1333, +1330, +1190, +1051, +1103, + +1156, +20, +933, +950, +967, +919, +872, +889, + +906, +805, +705, +733, +761, +740, +720, +668, + +616, +328, +40, +1640, +3752, +3784, +3816, +3208, + +40, +581, +97, +2589, +4058, +4018, +3979, +3907, + +3836, +3818, +3801, +3784, +3767, +3529, +3292, +3375, + +3458, +3706, +3954, +3754, +3555, +2843, +1619, +1067, + +516, +386, -256, -290, -324, -324, -324, -324, + +1392, +1364, +1337, +1309, +1283, +1247, +1212, +968, + +982, +1424, +1099, +1079, +1058, +1072, +1088, +815, + +799, +1056, +802, +772, +743, +645, +547, +769, + +736, +649, +563, +332, +102, +1939, +4033, +1982, + +444, +332, -36, +4076, +4093, +4047, +4001, +3955, + +3910, +3870, +3830, +3791, +3752, +3806, +3861, +3835, + +3811, +3678, +3545, +3380, +3216, +3639, +3806, +2341, + +1134, +1091, +24, -387, -286, -286, -286, -286, + +1440, +1389, +1338, +1287, +1236, +1305, +1374, +1091, + +1320, +1037, +1267, +1208, +1150, +715, +281, +486, + +1204, +1564, +901, +1325, +1750, +1830, +1911, +1383, + +344, +459, +574, +817, +548, +351, +666, +757, + +336, +340, +856, +4028, +4128, +4076, +4024, +4004, + +3984, +3922, +3861, +3799, +3738, +3828, +3919, +3785, + +3652, +3394, +3137, +3007, +2878, +2900, +2923, +3105, + +3800, +1284, +1328, +28, -248, -248, -248, -248, + +1456, +1406, +1358, +1309, +1261, +1209, +1159, +1444, + +1218, +1265, +33, -654, -1342, -977, -356, +394, + +1401, +1753, +1338, +1738, +2140, +2575, +3009, +3524, + +3784, +2536, +1033, +265, +522, +440, +615, +629, + +388, +403, +2211, +4051, +4099, +4078, +4058, +3990, + +3922, +3910, +3898, +3886, +3875, +3805, +3735, +3553, + +3373, +3126, +2879, +2585, +2291, +2026, +1762, +2649, + +3026, +2303, +2092, +665, -250, -250, -250, -250, + +1472, +1425, +1379, +1332, +1286, +1371, +1457, +1030, + -932, -1834, -1712, -1237, -763, -621, +33, +815, + +1598, +1943, +1776, +2153, +2531, +2808, +3085, +3362, + +3640, +4102, +4052, +3042, +496, +530, +564, +502, + +440, +211, +3055, +3818, +4070, +4081, +4093, +3976, + +3860, +3898, +3936, +3974, +4013, +3783, +3553, +3323, + +3094, +2858, +2623, +2420, +2217, +1921, +1626, +915, + +2764, +250, +296, +22, -252, -252, -252, -252, + +1488, +1443, +1399, +1371, +1343, +1308, +1530, -408, + -1834, -1589, -1089, -811, -535, -281, +485, +1171, + +1859, +2132, +2150, +2503, +2857, +3105, +3352, +3536, + +3720, +3875, +3775, +4298, +4054, +2123, +449, +502, + +556, +546, +26, +2113, +3945, +4115, +4031, +3946, + +3862, +3838, +3814, +3982, +3894, +3488, +3338, +3140, + +2943, +2622, +2302, +2030, +1758, +1495, +1234, +1259, + +774, -347, -188, -189, -190, -222, -254, -254, + +1504, +1462, +1420, +1410, +1400, +1246, +1604, -1334, + -1712, -1089, -978, -643, -308, +59, +938, +1529, + +2120, +2322, +2524, +2854, +3184, +3402, +3620, +3710, + +3800, +3905, +4010, +4019, +4028, +3973, +334, +503, + +672, +627, +582, +409, +236, +2359, +3970, +3917, + +3864, +3778, +3692, +3990, +3776, +3194, +3124, +2958, + +2792, +2387, +1982, +1641, +1300, +1071, +842, +69, + -192, -176, -160, -144, -128, -192, -256, -256, + +1546, +1496, +1447, +1430, +1413, +1627, +1330, -2102, + -1184, -819, -712, -395, -80, +405, +1148, +1713, + +2280, +2486, +2692, +2995, +3297, +3467, +3638, +3712, + +3787, +3915, +4045, +3917, +4047, +3097, +357, +655, + +699, +198, +466, +381, +297, +376, +200, +1815, + +3431, +3568, +3961, +4114, +3755, +3310, +3121, +2804, + +2487, +2208, +1931, +1189, +447, +37, -116, -254, + -136, -111, -86, -109, -132, -196, -260, -260, + +1588, +1531, +1475, +1450, +1426, +1497, +33, -1591, + -1168, -807, -446, -149, +148, +753, +1358, +1899, + +2440, +2650, +2861, +3136, +3411, +3533, +3656, +3715, + +3774, +3927, +4080, +3817, +4066, +2223, +380, +553, + +214, +3610, +350, +354, +358, +442, +526, +226, + -74, +286, +1158, +1678, +1686, +1634, +1582, +1114, + +646, +239, -168, -31, +107, -228, -51, -65, + -80, -46, -12, -74, -136, -200, -264, -264, + +1630, +1565, +1502, +1470, +1439, +1590, -817, -1399, + -960, -633, -308, -14, +280, +875, +1472, +1971, + +2472, +2718, +2965, +3229, +3492, +3582, +3674, +3701, + +3729, +3793, +3859, +4147, +4181, +707, +563, +417, + +1297, +3917, +4234, +2198, +163, +267, +372, +348, + +325, +108, +147, +186, -31, +38, +107, +96, + +85, +61, +38, -162, -106, -126, +111, +876, + -152, -93, -34, -87, -140, -204, -268, -268, + +1672, +1601, +1530, +1491, +1452, +1685, -1666, -1209, + -752, -461, -170, +121, +412, +999, +1586, +2045, + +2504, +2787, +3071, +3322, +3574, +3633, +3693, +3688, + +3684, +3661, +3638, +3711, +2760, +473, +746, +283, + +2380, +4225, +4022, +4043, +4064, +2141, +218, +215, + +212, +186, +160, +230, +300, +234, +168, +102, + +36, -117, -269, +218, +1218, +2025, +2833, +1048, + -224, -140, -56, -100, -144, -208, -272, -272, + +1626, +1607, +1589, +1458, +1585, +692, -1479, -1107, + -736, -451, -168, +115, +400, +805, +1468, +1937, + +2408, +2703, +2999, +3327, +3655, +3568, +3482, +3620, + +3759, +3439, +3121, +1601, +851, +819, +533, +437, + +3415, +4252, +4066, +4055, +4045, +4084, +4124, +2995, + +1867, +1068, +269, +62, -145, -38, +69, +704, + +1339, +2183, +3028, +2816, +2861, +2953, +2790, -349, + +96, -19, -134, -137, -140, -204, -268, -268, + +1580, +1614, +1649, +1427, +1718, -300, -1293, -1006, + -720, -443, -166, +111, +388, +613, +1350, +1831, + +2312, +2620, +2928, +3076, +3225, +3249, +3273, +3297, + +3322, +3475, +3628, +3333, +1502, +655, +832, +593, + +3938, +4024, +4110, +4068, +4026, +3980, +3934, +3984, + +4034, +3998, +3962, +3990, +4018, +3786, +3554, +3610, + +3666, +3459, +3253, +3111, +2969, +2858, +2236, -210, + -96, -154, -212, -174, -136, -200, -264, -264, + +1662, +1653, +1644, +1619, +1851, -988, -1266, -985, + -704, -401, -100, +9, +120, +403, +944, +1579, + +2216, +2504, +2793, +2873, +2954, +2976, +2999, +3085, + +3173, +3237, +3303, +3575, +521, +553, +587, +1771, + +3981, +4019, +4058, +4032, +4007, +3971, +3936, +3948, + +3961, +3920, +3879, +3806, +3989, +3866, +3743, +3636, + +3529, +3375, +3222, +3069, +2916, +2907, +1362, -119, + -64, -113, -162, -147, -132, -196, -260, -260, + +1744, +1692, +1640, +1556, +1472, -1932, -1240, -964, + -688, -361, -34, +165, +364, +707, +1050, +1585, + +2120, +2389, +2658, +2671, +2684, +2705, +2726, +2875, + +3024, +3001, +2978, +2283, +564, +965, +342, +2951, + +4024, +4015, +4006, +3997, +3988, +3963, +3938, +3913, + +3888, +3842, +3796, +3622, +3960, +3946, +3932, +3662, + +3392, +3292, +3192, +3028, +2864, +2956, +488, -28, + -32, -72, -112, -120, -128, -192, -256, -256, + +1834, +1635, +1692, +1718, +208, -1663, -1229, -924, + -619, -283, +50, +256, +719, +705, +948, +1126, + +1562, +1845, +2129, +2236, +2344, +2447, +2551, +2654, + +2759, +2738, +2719, +1562, +663, +623, +327, +4207, + +3992, +4012, +4034, +3990, +3948, +3922, +3898, +3872, + +3848, +3774, +3701, +3484, +3523, +3726, +3929, +3812, + +3695, +3604, +3513, +3407, +3300, +3350, -440, -231, + -22, -48, -74, -100, -126, -174, -222, -222, + +1924, +1578, +1745, +1880, -1057, -1394, -1219, -884, + -550, -207, +135, +93, +563, +449, +847, +669, + +1004, +1302, +1600, +1802, +2005, +2191, +2377, +2435, + +2494, +2477, +2460, +843, +763, +794, +1337, +3928, + +3960, +4011, +4062, +3985, +3908, +3883, +3858, +3833, + +3808, +3707, +3607, +3603, +3599, +3506, +3414, +3706, + +3998, +3916, +3835, +3786, +3737, +2208, -345, +78, + -12, -24, -36, -80, -124, -156, -188, -188, + +1598, +1585, +1829, +2154, -1873, -1413, -1208, -556, + -417, -514, -102, +440, +214, +191, +681, +435, + +702, +870, +1039, +1224, +1409, +1709, +2010, +2039, + +2069, +2086, +1849, +795, +766, +596, +2474, +3953, + +3896, +3928, +3962, +3914, +3868, +3842, +3818, +3792, + +3768, +3687, +3608, +3577, +3546, +3462, +3379, +3312, + +3245, +3364, +3484, +3189, +2893, +858, -154, +35, + -34, -48, -62, -108, -154, -154, -154, -154, + +1784, +1849, +1915, +892, -1666, -1176, -1711, -741, + -796, -822, +175, -748, +378, +191, +517, +202, + +400, +439, +479, +646, +814, +1229, +1645, +1644, + +1644, +1697, +1239, +748, +770, +399, +3613, +3978, + +3832, +3847, +3862, +3845, +3828, +3803, +3778, +3753, + +3728, +3669, +3611, +3552, +3494, +3419, +3345, +3174, + +3004, +2813, +2623, +2592, +2562, -237, +37, -9, + -56, -72, -88, -136, -184, -152, -120, -120, + +1802, +1900, +2255, -286, -1290, -1129, -712, -391, + -327, -385, -445, +201, -178, +436, +27, -45, + -118, +204, +270, +384, +498, +685, +874, +998, + +1123, +1252, +1127, +794, +717, +1161, +3654, +3843, + +3776, +3788, +3802, +3782, +3764, +3616, +3726, +3690, + +3656, +3595, +3536, +3476, +3417, +3341, +3265, +3078, + +2891, +2687, +2484, +2617, +1982, -28, +8, +14, + +18, -18, -54, +6, +66, -30, -126, -126, + +1820, +1696, +2084, -2232, -1939, -570, -1762, -1834, + -1394, -461, -552, -387, -223, -1110, -462, -37, + -124, -31, -451, -134, +183, +143, +104, +353, + +602, +809, +1017, +841, +665, +1924, +3696, +3708, + +3720, +3731, +3742, +3721, +3700, +3431, +3674, +3629, + +3584, +3523, +3462, +3401, +3341, +3264, +3187, +2982, + +2778, +2562, +2346, +2386, +891, -77, -20, +36, + +92, +36, -20, -108, -196, -164, -132, -132, + +1710, +1955, +1177, -2833, -955, -2075, -2172, -364, + -1885, -1352, -820, -1599, -843, -1249, -887, -652, + -674, -554, -435, -636, -325, -304, -282, -101, + -175, +493, +906, +871, +580, +2767, +3674, +3653, + +3632, +3656, +3682, +3626, +3572, +3436, +3558, +3534, + +3512, +3449, +3388, +3325, +3264, +3186, +3108, +2902, + +2697, +2500, +2304, +2219, +343, +179, +271, +154, + +38, -6, -50, -110, -170, -154, -138, -138, + +1600, +1959, -242, -2667, -2020, -2557, -2582, -1455, + +696, +316, +960, +2052, +2120, +1940, +1760, +1292, + +824, -310, -932, -1394, -832, -750, -668, -298, + -440, +434, +796, +902, +496, +3610, +3652, +3598, + +3544, +3583, +3622, +3533, +3444, +3443, +3442, +3441, + +3440, +3377, +3314, +3251, +3188, +3109, +3030, +2823, + +2616, +2439, +2262, +2053, -204, +179, +50, +17, + -16, -48, -80, -112, -144, -144, -144, -144, + +1956, +1852, -2091, -3025, -1145, +322, +2045, +1672, + +1555, +1328, +1614, +1916, +1706, +1622, +1282, +1502, + +1466, +1301, +1393, +940, -792, -1548, -768, -820, + -617, +926, +934, +909, +1397, +3323, +3456, +3446, + +3436, +3393, +3351, +3388, +3426, +3373, +3321, +3444, + +3313, +3264, +3217, +3153, +3090, +2997, +2906, +2686, + +2467, +2290, +2115, +1282, -61, +136, +79, +36, + -5, -37, -69, -101, -133, -133, -133, -133, + +1800, +1746, +669, +1992, +1779, +1665, +1552, +1727, + +1390, +1317, +1245, +1269, +1293, +1560, +1316, +1456, + +1084, +1121, +1158, +971, +1297, +726, -869, -1343, + -794, +1419, +1072, +917, +2299, +3036, +3261, +3294, + +3328, +3204, +3080, +3244, +3409, +3305, +3201, +3449, + +3186, +3153, +3121, +3056, +2992, +2887, +2783, +2550, + +2318, +2143, +1968, +513, +82, +95, +108, +57, + +6, -26, -58, -90, -122, -122, -122, -122, + +1516, +1832, +1636, +1905, +1406, +1344, +1283, +1589, + +1641, +1465, +1291, +1277, +1263, +1386, +1254, +1314, + +1118, +1116, +1115, +905, +953, +1160, +1111, +118, + -363, +807, +698, +700, +2240, +3325, +2361, +2934, + +3252, +2998, +2745, +2924, +3103, +3155, +2952, +3277, + +3091, +3057, +3024, +2959, +2894, +2776, +2659, +2414, + +2169, +2074, +1981, +255, +65, +68, +73, +44, + +17, -15, -47, -79, -111, -111, -111, -111, + +1744, +1662, +1581, +1563, +1546, +1536, +1527, +1453, + +1380, +1359, +1339, +1286, +1234, +1213, +1193, +1172, + +1152, +1112, +1073, +1097, +1122, +826, +1043, +1067, + +1092, +964, +837, +741, +2182, +2078, +2487, +2831, + +2664, +2793, +2923, +2860, +2798, +3007, +2705, +3106, + +2996, +2962, +2928, +2862, +2796, +2666, +2536, +2278, + +2020, +1751, +1482, -259, +48, +43, +38, +33, + +28, -4, -36, -68, -100, -100, -100, -100, + +1684, +1640, +1596, +1584, +1573, +1543, +1513, +1451, + +1391, +1359, +1329, +1282, +1236, +1213, +1190, +1168, + +1146, +1107, +1069, +1063, +1058, +920, +1038, +996, + +955, +924, +894, +880, +1635, +1679, +2235, +2439, + +2132, +2451, +2771, +2580, +2644, +2713, +2528, +2742, + +2701, +2828, +2699, +2570, +2442, +2383, +2324, +2105, + +1887, +1732, +811, -79, +55, +62, +71, +46, + +23, -7, -37, -67, -97, -113, -129, -129, + +1624, +1618, +1612, +1606, +1601, +1551, +1501, +1451, + +1402, +1361, +1320, +1279, +1239, +1214, +1189, +1164, + +1140, +1103, +1067, +1031, +995, +1014, +1034, +926, + +818, +885, +953, +1021, +1089, +1024, +1472, +2048, + +2112, +2110, +2109, +2044, +2491, +2421, +2352, +2379, + +2406, +2694, +2471, +2279, +2088, +2100, +2113, +1933, + +1754, +1715, +140, +101, +62, +83, +104, +61, + +18, -10, -38, -66, -94, -126, -158, -158, + +1724, +1788, +1852, +1692, +1532, +1494, +1456, +1418, + +1381, +1345, +1311, +1275, +1241, +1214, +1187, +1160, + +1134, +1098, +1064, +1029, +995, +996, +998, +935, + +873, +877, +883, +792, +702, +657, +1125, +1832, + +2284, +1193, +1638, +1796, +2209, +2320, +2176, +2239, + +2047, +2560, +2562, +1891, +1734, +1673, +1613, +1744, + +1621, +1152, -83, -8, +69, +70, +73, +42, + +13, -13, -39, -65, -91, -139, -187, -187, + +1824, +1702, +1580, +1522, +1464, +1438, +1412, +1386, + +1360, +1331, +1302, +1273, +1244, +1215, +1186, +1157, + +1128, +1095, +1062, +1029, +996, +979, +962, +945, + +928, +871, +814, +821, +828, +803, +1290, +1617, + +1944, +2068, +1168, +1292, +1416, +1708, +1488, +1844, + +1688, +2171, +2142, +1249, +1380, +1503, +1626, +1045, + -48, +79, +206, +141, +76, +59, +42, +25, + +8, -16, -40, -64, -88, -152, -216, -216, + +1688, +1615, +1542, +1501, +1460, +1429, +1398, +1367, + +1336, +1309, +1284, +1257, +1232, +1205, +1180, +1153, + +1128, +1092, +1058, +1022, +988, +968, +950, +930, + +912, +861, +812, +793, +776, +595, +672, +971, + +1272, +330, +924, +1038, +1152, +1298, +1444, +1910, + +1608, +1531, +1200, +515, +344, +259, +176, +251, + +72, +122, +174, +128, +84, +64, +46, +26, + +8, -18, -44, -70, -96, -144, -192, -192, + +1552, +1528, +1504, +1480, +1456, +1420, +1384, +1348, + +1312, +1289, +1266, +1243, +1220, +1197, +1174, +1151, + +1128, +1091, +1054, +1017, +980, +959, +938, +917, + +896, +853, +810, +767, +724, +645, +566, +583, + +600, +640, +680, +528, +376, +376, +888, +1464, + +1016, +637, +258, +295, +332, +297, +262, +227, + +192, +167, +142, +117, +92, +71, +50, +29, + +8, -20, -48, -76, -104, -136, -168, -168, + +1544, +1521, +1498, +1475, +1452, +1411, +1370, +1329, + +1288, +1267, +1248, +1227, +1208, +1187, +1168, +1147, + +1128, +1088, +1050, +1010, +972, +948, +926, +902, + +880, +843, +808, +771, +736, +677, +620, +609, + +600, +614, +628, +546, +464, +238, +2060, +1690, + +1576, +1709, +308, +313, +320, +285, +252, +217, + +184, +162, +142, +120, +100, +76, +54, +30, + +8, -22, -52, -82, -112, -128, -144, -144, + +1536, +1514, +1492, +1470, +1448, +1402, +1356, +1310, + +1264, +1247, +1230, +1213, +1196, +1179, +1162, +1145, + +1128, +1087, +1046, +1005, +964, +939, +914, +889, + +864, +835, +806, +777, +748, +711, +674, +637, + +600, +588, +576, +564, +552, +612, +160, +1916, + +1112, +223, +358, +333, +308, +275, +242, +209, + +176, +159, +142, +125, +108, +83, +58, +33, + +8, -24, -56, -88, -120, -120, -120, -120, + +1536, +1514, +1492, +1470, +1448, +1402, +1356, +1310, + +1264, +1246, +1230, +1212, +1196, +1178, +1162, +1144, + +1128, +1086, +1046, +1004, +964, +938, +914, +888, + +864, +834, +806, +776, +748, +710, +674, +636, + +600, +588, +576, +564, +552, +644, +480, +108, + +504, +158, +326, +316, +308, +274, +242, +208, + +176, +158, +142, +124, +108, +82, +58, +32, + +8, -24, -56, -88, -120, -120, -120, -120, + +1536, +1514, +1492, +1470, +1448, +1402, +1356, +1310, + +1264, +1247, +1230, +1213, +1196, +1179, +1162, +1145, + +1128, +1087, +1046, +1005, +964, +939, +914, +889, + +864, +835, +806, +777, +748, +711, +674, +637, + +600, +588, +576, +564, +552, +420, +288, +348, + +408, +351, +294, +301, +308, +275, +242, +209, + +176, +159, +142, +125, +108, +83, +58, +33, + +8, -24, -56, -88, -120, -120, -120, -120, + +1536, +1514, +1492, +1470, +1448, +1402, +1356, +1310, + +1264, +1246, +1230, +1212, +1196, +1178, +1162, +1144, + +1128, +1086, +1046, +1004, +964, +938, +914, +888, + +864, +834, +806, +776, +748, +710, +674, +636, + +600, +588, +576, +564, +552, +420, +288, +348, + +408, +350, +294, +300, +308, +274, +242, +208, + +176, +158, +142, +124, +108, +82, +58, +32, + +8, -24, -56, -88, -120, -120, -120, -120 +}; + +static INT16 TEST_CB_COMPONENT[4096] = +{ + +1728, +1730, +1732, +1734, +1736, +1738, +1740, +1742, + +1744, +1740, +1736, +1732, +1728, +1796, +1864, +1804, + +1744, +1754, +1764, +1774, +1784, +1794, +1804, +1814, + +1824, +1774, +1724, +1802, +1880, +1814, +1748, +1810, + +1872, +1878, +1884, +1890, +1896, +1910, +1924, +1938, + +1952, +1938, +1924, +1910, +1896, +1914, +1932, +1950, + +1968, +1974, +1980, +1986, +1992, +1998, +2004, +2010, + +2016, +2016, +2016, +2016, +2016, +2016, +2016, +2016, + +1710, +1697, +1684, +1704, +1723, +1726, +1730, +1733, + +1737, +1738, +1740, +1741, +1743, +1758, +1774, +1757, + +1741, +1762, +1783, +1788, +1793, +1774, +1755, +1784, + +1813, +1817, +1821, +1825, +1829, +1857, +1885, +1881, + +1877, +1849, +1821, +1857, +1894, +1904, +1914, +1924, + +1935, +1928, +1922, +1915, +1909, +1922, +1936, +1949, + +1963, +1974, +1985, +1997, +2008, +2009, +2011, +2012, + +2014, +2017, +2020, +2023, +2026, +2026, +2026, +2026, + +1692, +1664, +1637, +1674, +1711, +1715, +1720, +1725, + +1730, +1737, +1744, +1751, +1758, +1721, +1684, +1711, + +1738, +1770, +1802, +1802, +1802, +1754, +1706, +1754, + +1802, +1860, +1918, +1848, +1778, +1900, +2022, +1952, + +1882, +1820, +1759, +1825, +1892, +1898, +1905, +1911, + +1918, +1919, +1920, +1921, +1922, +1931, +1940, +1949, + +1958, +1974, +1991, +2008, +2025, +2021, +2018, +2015, + +2012, +2018, +2024, +2030, +2036, +2036, +2036, +2036, + +1674, +1631, +1589, +1644, +1698, +1703, +1710, +1716, + +1723, +1735, +1748, +1760, +1773, +1763, +1754, +1760, + +1767, +1794, +1821, +1800, +1779, +1830, +1881, +1900, + +1919, +2047, +2175, +2015, +1855, +1879, +1903, +1927, + +1951, +1759, +1824, +1856, +1890, +1892, +1895, +1897, + +1901, +1909, +1918, +1926, +1935, +1939, +1944, +1948, + +1953, +1974, +1996, +2019, +2041, +2032, +2025, +2017, + +2010, +2019, +2028, +2037, +2046, +2046, +2046, +2046, + +1656, +1599, +1543, +1614, +1686, +1693, +1701, +1708, + +1716, +1734, +1752, +1770, +1788, +1806, +1824, +1810, + +1796, +1818, +1840, +2054, +2268, +1650, +1032, +510, + -12, -70, -128, +390, +908, +1602, +2296, +2158, + +2020, +1699, +1890, +1889, +1888, +1887, +1886, +1885, + +1884, +1900, +1916, +1932, +1948, +1948, +1948, +1948, + +1948, +1975, +2003, +2030, +2058, +2045, +2033, +2020, + +2008, +2020, +2032, +2044, +2056, +2056, +2056, +2056, + +1590, +1570, +1551, +1612, +1673, +1579, +1742, +1713, + +1685, +1672, +1660, +1711, +1763, +1694, +1626, +1941, + +2001, +2060, +583, -654, -1891, -2046, -2201, -2084, + -1967, -2049, -2131, -2053, -1975, -1751, -1527, +41, + +1609, +2374, +1859, +2000, +1886, +1898, +1912, +1909, + +1907, +1900, +1894, +1919, +1945, +1944, +1944, +1943, + +1943, +1967, +1992, +2017, +2042, +2032, +2023, +2014, + +2006, +2017, +2028, +2039, +2050, +2050, +2050, +2050, + +1524, +1542, +1560, +1610, +1661, +1467, +1785, +1719, + +1654, +1611, +1568, +1653, +1738, +1839, +1940, +793, + -866, -2050, -2210, -2082, -1954, -1902, -1850, -1862, + -1874, -1980, -2086, -1936, -1786, -1776, -1766, -1820, + -1874, -534, +1829, +2112, +1884, +1911, +1939, +1934, + +1930, +1901, +1872, +1907, +1942, +1941, +1940, +1939, + +1938, +1960, +1982, +2004, +2027, +2021, +2015, +2009, + +2004, +2014, +2024, +2034, +2044, +2044, +2044, +2044, + +1586, +1641, +1697, +1704, +1712, +1577, +1699, +1660, + +1623, +1613, +1604, +1642, +1681, +1791, -402, -2036, + -1877, -2144, -1899, -1942, -1985, -1918, -1851, -1880, + -1909, -1959, -2009, -1931, -1853, -1801, -1749, -1617, + -1485, -1939, -1882, +96, +2074, +1971, +1869, +1895, + +1921, +1885, +1850, +1894, +1939, +1937, +1936, +1934, + +1933, +1952, +1972, +1991, +2011, +2008, +2006, +2003, + +2002, +2011, +2020, +2029, +2038, +2038, +2038, +2038, + +1136, +1229, +1322, +1287, +1252, +1433, +1614, +1603, + +1592, +1616, +1640, +1632, +1624, +2256, -1720, -1792, + -1864, -1982, -2100, -2058, -2016, -1934, -1852, -1898, + -1944, -1938, -1932, -1926, -1920, -1826, -1732, -1670, + -1608, -1552, -1496, -1664, -1320, +2288, +1800, +1856, + +1912, +1870, +1828, +1882, +1936, +1934, +1932, +1930, + +1928, +1945, +1962, +1979, +1996, +1997, +1998, +1999, + +2000, +2008, +2016, +2024, +2032, +2032, +2032, +2032, + +1552, +1624, +1698, +1674, +1652, +1644, +1638, +1614, + +1592, +1611, +1630, +1681, +1733, +1146, -2000, -1787, + -1830, -1924, -2019, -2049, -2080, -1986, -1893, -1895, + -1898, -1896, -1894, -1860, -1827, -1779, -1731, -1667, + -1604, -1615, -1626, -1878, -594, +2063, +1903, +2016, + +1873, +2132, +1880, +1884, +1888, +1921, +1955, +1941, + +1927, +1925, +1925, +1955, +1987, +2005, +2025, +2043, + +2063, +1995, +1927, +2099, +2015, +2095, +2175, +2175, + +1456, +1509, +1562, +1551, +1540, +1601, +1662, +1627, + +1592, +1606, +1621, +1731, +1842, +37, -2281, -1782, + -1796, -1867, -1938, -2041, -2144, -2039, -1934, -1893, + -1852, -1854, -1857, -1795, -1734, -1732, -1731, -1665, + -1600, -1678, -1757, -1836, +645, +2094, +2007, +1920, + +1322, +2139, +1933, +1886, +1840, +1909, +1979, +1952, + +1926, +1907, +1888, +1933, +1978, +2015, +2052, +2089, + +2126, +1982, +1838, +2174, +1998, +2158, +2318, +2318, + +1488, +1520, +1554, +1554, +1556, +1588, +1622, +1606, + +1592, +1569, +1547, +1700, +1855, -993, -2049, -1825, + -1858, -1905, -1953, -2016, -2080, -1995, -1911, -1858, + -1806, -1812, -1819, -1729, -1641, -1685, -1730, -1678, + -1628, -1677, -1727, -2194, +1947, +2125, +2046, +945, + -2205, +114, +2177, +2144, +1856, +1912, +1970, +1963, + +1957, +1935, +1915, +1925, +1937, +1991, +2047, +2181, + +2061, +2337, +2613, +1817, +2301, +2157, +2269, +2397, + +1520, +1533, +1546, +1559, +1572, +1577, +1582, +1587, + +1592, +1533, +1474, +1671, +1868, -2023, -1818, -1869, + -1920, -1944, -1968, -1992, -2016, -1952, -1888, -1824, + -1760, -1771, -1782, -1665, -1548, -1639, -1730, -1693, + -1656, -1677, -1699, -1017, +2226, +1644, +2087, -286, + -2148, -2167, -1674, +611, +2384, +2173, +1962, +1975, + +1988, +1965, +1942, +1919, +1896, +1969, +2042, +2019, + +1484, -1916, -1220, +2484, +1068, -916, +1708, +1964, + +1504, +1514, +1526, +1536, +1548, +1550, +1554, +1556, + +1560, +1581, +1604, +1786, +689, -2138, -1894, -1905, + -1918, -1926, -1935, -1943, -1952, -1878, -1805, -1731, + -1658, -1626, -1596, -1549, -1503, -1507, -1513, -1518, + -1524, -1526, -1785, +148, +2080, +1995, +2422, -2094, + -2003, -2033, -1809, -1665, -1776, -189, +1398, +2536, + +2139, +2122, +2105, +2327, +2295, +2204, +2113, +2870, + -213, -1669, -1077, -1237, -1653, -1589, +2059, +1931, + +1488, +1497, +1506, +1515, +1524, +1525, +1526, +1527, + +1528, +1631, +1735, +1902, -490, -2254, -1971, -1943, + -1916, -1909, -1902, -1895, -1888, -1805, -1722, -1639, + -1556, -1483, -1411, -1434, -1458, -1377, -1297, -1344, + -1392, -1376, -1872, +1312, +1935, +1834, +1734, -2622, + -2370, -2157, -1945, -1892, -1840, -2039, -2239, -2022, + -782, -281, +220, +433, +134, -377, -888, -1655, + -1398, -1166, -934, -1374, -1302, -726, +2410, +1898, + +1472, +1478, +1486, +1492, +1500, +1498, +1498, +1496, + +1496, +1600, +1705, +1666, -933, -1474, -2015, -1964, + -1914, -1891, -1869, -1846, -1824, -1731, -1639, -1546, + -1454, -1387, -1321, -1191, -1317, -1150, -1240, -1250, + -1260, -1545, -1575, +2459, +1885, +2057, +182, -2429, + -2225, -2088, -1952, -1928, -1904, -1905, -1907, -2149, + -1879, -1835, -1793, -1670, -1803, -1645, -1489, -1491, + -1239, -1335, -1431, -1335, -1495, +681, +2345, +2089, + +1456, +1461, +1466, +1471, +1476, +1473, +1470, +1467, + +1464, +1570, +1676, +1174, -1888, -950, -2060, -1986, + -1912, -1874, -1836, -1798, -1760, -1658, -1556, -1454, + -1352, -1292, -1232, -1204, -1688, -1180, -1184, -1156, + -1128, -1203, -254, +2071, +1836, +2281, -1370, -2237, + -2080, -2020, -1960, -1964, -1968, -2028, -2088, -2020, + -1952, -1855, -1758, -1725, -1692, -1635, -1578, -1329, + -1592, -1504, -1416, -1040, -1688, +2088, +2280, +2280, + +1428, +1438, +1450, +1460, +1472, +1463, +1454, +1493, + +1533, +1512, +1748, -160, -2068, -1346, -1137, -1775, + -1902, -1848, -1794, -1708, -1622, -1544, -1466, -1356, + -1247, -1198, -1149, -1196, -1755, -1246, -993, -1012, + -1032, -1202, +930, +2023, +1837, +2238, -2480, -2286, + -1838, -1799, -1761, -1835, -1909, -1954, -2000, -1982, + -1964, -1908, -1853, -1829, -1807, -1749, -1692, -1538, + -1642, -1526, -1410, -638, -122, +774, +1926, +1926, + +1400, +1417, +1434, +1451, +1469, +1454, +1439, +1520, + +1602, +1455, +1820, -1239, -1737, -1743, -726, -1821, + -1892, -1822, -1752, -1618, -1485, -1431, -1377, -1259, + -1142, -1104, -1066, -1188, -1823, -1313, -803, -869, + -936, -1203, +2115, +1976, +1838, +916, -2055, -1569, + -1596, -1579, -1563, -1706, -1850, -1881, -1913, -1944, + -1976, -1962, -1949, -1935, -1922, -1864, -1807, -1749, + -1692, -1548, -1404, -1004, -92, +996, +2084, +2084, + +1372, +1394, +1418, +1441, +1465, +1444, +1423, +1483, + +1543, +1765, +1732, -2204, -1533, -1611, -1179, -1274, + -1882, -1764, -1646, -1560, -1475, -1301, -1127, -1113, + -1101, -994, -887, -1052, -1730, -1395, -804, -709, + -872, -306, +2051, +1929, +2063, -151, -1597, -1347, + -1354, -1326, -1300, -1417, -1535, -1599, -1665, -1730, + -1796, -1824, -1852, -1880, -1909, -1883, -1857, -1767, + -1678, -1570, -1462, -1434, +1154, +2402, +1858, +1858, + +1344, +1373, +1403, +1432, +1462, +1435, +1409, +1446, + +1484, +1564, +621, -1890, -1842, -1737, -1633, -728, + -1872, -1706, -1541, -1503, -1466, -1428, -1391, -1225, + -1060, -884, -709, -917, -1638, -1478, -807, -551, + -808, +590, +1988, +1882, +2288, -1218, -1140, -1126, + -1112, -1075, -1038, -1129, -1220, -1319, -1418, -1517, + -1616, -1686, -1756, -1826, -1896, -1902, -1908, -1786, + -1664, -1592, -1520, -1864, +2400, +2016, +2144, +2144, + +1348, +1372, +1398, +1424, +1450, +1463, +1477, +1491, + +1505, +1729, -607, -1838, -1790, -1735, -1681, -1003, + -1350, -1710, -1558, -1519, -1480, -1382, -1285, -1379, + -1475, -1208, -941, -611, -793, -796, -800, -611, + -680, +1364, +1872, +1932, +1481, -1150, -966, -926, + -886, -868, -851, -929, -1009, -1061, -1114, -1230, + -1348, -1521, -1695, -1805, -1915, -1900, -1886, -1792, + -1698, -1604, -1766, -744, +2326, +2134, +2198, +2198, + +1352, +1373, +1395, +1417, +1439, +1492, +1546, +1536, + +1526, +1894, -1835, -1787, -1739, -1735, -1731, -1279, + -828, -1714, -1577, -1536, -1495, -1337, -1180, -1023, + -866, -764, -663, -562, -973, -371, -282, -417, + -552, +2138, +1757, +1983, +674, -1083, -793, -726, + -660, -662, -665, -731, -798, -804, -811, -945, + -1080, -1357, -1635, -1784, -1934, -1899, -1865, -1798, + -1732, -1616, -2012, +376, +2252, +2252, +2252, +2252, + +1356, +1373, +1391, +1409, +1427, +1425, +1423, +1501, + +1579, +907, -1814, -1702, -1847, -1909, -1716, -1634, + -786, -1686, -1819, -1712, -1605, -1371, -1139, -921, + -705, -656, -608, -384, -416, -233, -308, -477, + +376, +1968, +1769, +2033, -5, -839, -651, -606, + -562, -584, -606, -660, -715, -739, -763, -963, + -1164, -1432, -1702, -1843, -1985, -1977, -1971, -1884, + -1798, -2012, -2226, +2152, +2178, +2194, +2210, +2210, + +1360, +1374, +1388, +1402, +1416, +1358, +1300, +1466, + +1632, -81, -1794, -1619, -1956, -2085, -1702, -1991, + -744, -891, -526, -353, -180, -383, -586, -821, + -1056, -805, -554, -463, -372, -353, -334, -539, + +1304, +1799, +1782, +2085, -684, -597, -510, -487, + -464, -506, -548, -590, -632, -674, -716, -982, + -1248, -1509, -1770, -1903, -2036, -2057, -2078, -1971, + -1864, -1896, -1416, +2392, +2104, +2136, +2168, +2168, + +1346, +1358, +1371, +1383, +1396, +1395, +1393, +1552, + +1711, -1177, -1762, -2203, -1364, -465, +690, +1942, + +1913, +1747, +1837, +1816, +1794, +1889, +1983, +1774, + +1564, +548, -468, -299, -386, -391, -398, -147, + +1895, +1920, +1946, +1284, -401, -397, -393, -421, + -450, -478, -507, -568, -629, -722, -815, -1068, + -1321, -1697, -2074, -2082, -2091, -2129, -2168, -2030, + -1894, -2028, +142, +2280, +2114, +2082, +2050, +2050, + +1332, +1343, +1354, +1365, +1377, +1432, +1487, +1382, + +1278, -1763, -195, +1308, +1788, +1667, +1547, +1522, + +1498, +1569, +1641, +1681, +1721, +1600, +1480, +1552, + +1624, +1901, +2179, +1145, -401, -431, -462, -12, + +1974, +1786, +2111, +484, -119, -198, -277, -356, + -436, -451, -467, -547, -627, -770, -914, -898, + -882, -606, -330, -470, -611, -1435, -2259, -2091, + -1924, -2160, +1700, +2168, +2124, +2028, +1932, +1932, + +1318, +1327, +1337, +1346, +1357, +1405, +1452, +1420, + +1389, +1381, +1629, +1748, +1356, +1495, +1635, +1631, + +1627, +1551, +1732, +1689, +1647, +1728, +1809, +1730, + +1652, +1686, +1721, +1948, +1921, +874, -430, +363, + +1925, +1764, +1859, +148, -28, -95, -160, -291, + -422, -423, -426, -557, -688, -370, -309, -280, + -251, -570, -890, -858, -826, -563, -301, -1079, + -1858, -1636, +2170, +2296, +2166, +2118, +2070, +2070, + +1304, +1312, +1321, +1329, +1338, +1378, +1419, +1459, + +1500, +1452, +1404, +1420, +1436, +1580, +1724, +1484, + +1244, +1022, +1313, +1187, +1062, +1088, +1115, +1397, + +1680, +1728, +1777, +1729, +1682, +1922, +1651, +1763, + +1876, +1742, +1609, -189, +62, +8, -45, -226, + -408, -397, -387, -568, -750, -227, -217, -430, + -644, -1047, -1451, -1502, -1554, -1229, -905, -580, + -256, -856, +1616, +1912, +2208, +2208, +2208, +2208, + +1290, +1304, +1319, +1334, +1350, +1377, +1404, +1271, + +1395, +1525, +1655, +1769, +1884, +1802, +1720, +1430, + +1141, +1026, +1168, +1037, +908, +700, +491, +331, + +172, +873, +1575, +1524, +1731, +1991, +1738, +1774, + +1811, +1914, +993, -119, +48, -74, -196, -271, + -346, -407, -470, -324, -179, -213, -503, -810, + -1117, -1273, -1430, -1636, -1841, -1823, -1551, -1246, + -686, +1194, +1026, +1610, +2194, +2194, +2194, +2194, + +1276, +1297, +1319, +1341, +1363, +1376, +1390, +1340, + +1802, +1854, +1907, +1863, +1820, +1768, +1717, +1377, + +1038, +1031, +1024, +889, +755, +568, +381, +290, + +200, +19, -162, +553, +1781, +2060, +1827, +1786, + +1746, +2086, +378, -50, +35, -156, -348, -316, + -284, -419, -554, -337, -121, -456, -791, -934, + -1078, -1244, -1411, -1514, -1617, -1907, -1686, -1657, + -1116, +1964, +1972, +2076, +2180, +2180, +2180, +2180, + +1262, +1289, +1318, +1346, +1375, +1359, +1344, +1632, + +1921, +1927, +1934, +1876, +1820, +1702, +1585, +1259, + +935, +907, +880, +724, +569, +436, +302, +217, + +132, +44, -43, -99, +102, +801, +2011, +1878, + +1745, +1426, +2131, +916, -43, -191, -340, -393, + -446, -461, -478, -237, -254, -522, -790, -962, + -1135, -1519, -1647, -1760, -1872, -1446, -2045, -1827, + -1354, +2254, +2278, +2222, +2166, +2166, +2166, +2166, + +1248, +1283, +1318, +1353, +1388, +1343, +1298, +1925, + +2040, +2001, +1962, +1891, +1820, +1637, +1454, +1143, + +832, +784, +736, +560, +384, +304, +224, +144, + +64, +70, +76, +18, -40, +54, +1684, +1714, + +1744, +1790, +1836, +1882, +1928, +798, -332, -470, + -608, -505, -402, -139, -388, -589, -790, -991, + -1192, -1794, -1884, -2006, -2128, -2266, -868, +818, + +2504, +2288, +2072, +2112, +2152, +2152, +2152, +2152, + +1238, +1263, +1290, +1332, +1375, +1301, +1484, +2002, + +2009, +1973, +1939, +1871, +1805, +1608, +1411, +1118, + +826, +751, +676, +505, +334, +273, +212, +151, + +91, +69, +48, +11, -26, +482, +1758, +1771, + +1784, +2033, +1771, +1860, +1950, +1989, +2029, +884, + -260, -1156, -261, -309, -614, -922, -975, -1411, + -1848, -2062, -2019, -697, +626, +2060, +2471, +2273, + +2076, +2051, +2026, +2081, +2136, +2136, +2136, +2136, + +1228, +1245, +1263, +1313, +1363, +1260, +1670, +2080, + +1978, +1947, +1916, +1853, +1791, +1580, +1369, +1094, + +820, +718, +616, +450, +285, +243, +201, +159, + +118, +69, +20, +4, -13, +910, +1833, +1828, + +1824, +229, +1706, +1839, +1972, +1901, +1830, +1983, + +2136, +2032, +1416, +1056, +696, +280, +376, +728, + +1080, +1767, +2454, +2405, +2356, +2035, +2226, +2193, + +2160, +2070, +1980, +2050, +2120, +2120, +2120, +2120, + +1218, +1226, +1235, +1292, +1350, +1235, +1888, +2061, + +1979, +1935, +1893, +1834, +1776, +1551, +1326, +1070, + +814, +685, +556, +395, +235, +212, +189, +166, + +145, +116, +88, -68, +33, +1306, +1811, +1949, + +1576, -200, -183, +905, +1994, +1956, +1919, +1881, + +1844, +2004, +1909, +2005, +2102, +2042, +2239, +2195, + +2152, +2043, +1935, +2370, +2038, +2697, +1821, +368, + +2244, +2121, +1998, +2051, +2104, +2104, +2104, +2104, + +1208, +1208, +1209, +1273, +1338, +1210, +2107, +2043, + +1980, +1925, +1871, +1816, +1762, +1523, +1285, +1046, + +808, +652, +497, +341, +186, +182, +179, +175, + +172, +164, +157, +117, +590, +1958, +1791, +1815, + +816, +140, -24, -28, -32, +988, +2008, +2036, + +2064, +1977, +1890, +1931, +1972, +2013, +2054, +2127, + +2200, +2320, +2440, +2080, +184, -1760, -3192, +336, + +2328, +2172, +2016, +2052, +2088, +2088, +2088, +2088, + +1222, +1215, +1209, +1266, +1325, +1459, +2104, +2046, + +1989, +1945, +1903, +1861, +1819, +1612, +1406, +1136, + +866, +715, +564, +446, +328, +295, +263, +230, + +199, +481, +764, +711, +1427, +2086, +1721, +1692, + +128, -37, +55, -14, -82, -108, -135, +335, + +804, +1293, +1783, +2272, +2250, +2197, +1889, +1356, + +568, -763, -2095, -3010, -2646, -2931, -2705, +2305, + +2196, +2159, +2122, +2117, +2112, +2112, +2112, +2112, + +1236, +1223, +1210, +1261, +1313, +1708, +2103, +2050, + +1998, +1967, +1937, +1907, +1877, +1702, +1528, +1226, + +924, +778, +633, +552, +471, +409, +348, +287, + +226, +287, +349, +283, +1241, +1702, +1652, +1826, + -48, +43, +134, +1, -132, -181, -230, -343, + -456, -670, -884, -202, -544, -946, -1860, -1718, + -2088, -2311, -2534, -2469, -2404, -2311, -1706, +2483, + +2064, +2146, +2228, +2182, +2136, +2136, +2136, +2136, + +1250, +1230, +1211, +1255, +1300, +1957, +2101, +2054, + +2007, +1956, +1906, +1856, +1806, +1696, +1586, +1284, + +982, +841, +701, +657, +613, +554, +497, +438, + +381, +412, +445, +717, +1758, +1782, +1807, +1095, + -128, -70, -11, -97, -182, -253, -325, -428, + -532, -761, -991, -580, -170, -1033, -873, -1976, + -1800, -2018, -2237, -2343, -2450, -2650, -35, +2308, + +2092, +2117, +2142, +2151, +2160, +2160, +2160, +2160, + +1264, +1238, +1212, +1250, +1288, +2206, +2100, +2058, + +2016, +1946, +1876, +1806, +1736, +1690, +1644, +1342, + +1040, +905, +770, +763, +756, +701, +646, +591, + +536, +539, +542, +897, +1764, +1607, +1962, +365, + -208, -182, -156, -194, -232, -326, -420, -514, + -608, -853, -1098, -1471, -820, -97, -910, -955, + -2024, -2238, -2452, -2474, -2496, -2990, +1636, +2134, + +2120, +2088, +2056, +2120, +2184, +2184, +2184, +2184, + +1198, +1191, +1185, +1227, +1525, +2065, +2093, +2009, + +1925, +1887, +1850, +1781, +1712, +1682, +1653, +1464, + +1275, +1130, +986, +937, +889, +840, +792, +743, + +696, +684, +674, +1335, +1741, +1839, +1939, +54, + -294, -295, -297, -298, -300, -414, -527, -641, + -755, -947, -1140, -1732, -1813, -733, -166, -1038, + -887, -1234, -1581, -1609, -1636, -1158, +2392, +2279, + +2166, +2119, +2072, +2121, +2170, +2170, +2170, +2170, + +1132, +1145, +1159, +1205, +1763, +1924, +2086, +1960, + +1834, +1829, +1825, +1756, +1688, +1675, +1663, +1586, + +1510, +1356, +1202, +1112, +1023, +981, +939, +897, + +856, +831, +807, +1774, +1718, +1817, +1405, -512, + -380, -409, -438, -403, -369, -502, -635, -768, + -902, -1042, -1182, -1482, -1782, -2138, -1982, -610, + -262, -486, -711, -744, -777, +162, +2125, +1912, + +2212, +2150, +2088, +2122, +2156, +2156, +2156, +2156, + +1194, +1146, +1100, +1182, +1776, +1927, +2079, +1863, + +1903, +1978, +1799, +1843, +1632, +1619, +1608, +1612, + +1617, +1517, +1418, +1351, +1284, +1216, +1149, +1098, + +1048, +945, +1099, +1781, +1695, +1954, +422, -566, + -530, -554, -579, -571, -565, -686, -806, -927, + -1049, -1232, -1416, -1679, -1943, -2342, -2486, -2501, + -2773, -2074, -1376, -1671, -2221, +458, +2369, +2137, + +2162, +2133, +2104, +2123, +2142, +2142, +2142, +2142, + +1256, +1149, +1043, +1160, +1790, +1931, +2073, +1766, + +1972, +2129, +1774, +1931, +1576, +1565, +1554, +1639, + +1724, +1679, +1635, +1590, +1546, +1453, +1361, +1300, + +1240, +1060, +1392, +1788, +1672, +2092, -560, -620, + -680, -700, -721, -741, -762, -870, -979, -1087, + -1196, -1423, -1650, -1877, -2104, -2291, -2478, -2857, + -2724, -2895, -3067, -3110, -3666, +2547, +2103, +2107, + +2112, +2116, +2120, +2124, +2128, +2128, +2128, +2128, + +1214, +1170, +1128, +1453, +1779, +1692, +1861, +1807, + +1753, +1732, +1712, +1803, +1640, +1759, +1623, +1710, + +1799, +1666, +1790, +1755, +1719, +1628, +1539, +1497, + +1456, +1352, +1504, +1752, +1745, +1445, -902, -898, + -894, -907, -921, -935, -950, -1070, -1190, -1310, + -1431, -1641, -1852, -2062, -2273, -2431, -2590, -2812, + -2779, -2929, -3080, -3279, -2198, +2298, +2187, +2124, + +2062, +2081, +2100, +2119, +2138, +2138, +2138, +2138, + +1172, +1193, +1214, +1747, +1769, +1710, +2163, +2360, + +2046, +1592, +1651, +1677, +1704, +1954, +1693, +1783, + +1874, +1654, +1947, +1920, +1893, +1805, +1718, +1695, + +1672, +1644, +1617, +1717, +1818, +798, -1245, -1176, + -1108, -1115, -1123, -1131, -1139, -1270, -1402, -1534, + -1666, -1860, -2054, -2248, -2442, -2572, -2702, -2768, + -2834, -2964, -3094, -3192, -219, +2306, +2272, +2142, + +2012, +2046, +2080, +2114, +2148, +2148, +2148, +2148, + +1194, +1150, +1364, +1784, +1694, +1983, +2272, +1441, + +2147, +1980, +1813, +1838, +1864, +1909, +1698, +1823, + +1949, +1818, +1943, +1989, +2034, +1933, +1833, +1812, + +1792, +1712, +1633, +1649, +1923, -536, -1459, -1390, + -1322, -1354, -1388, -1421, -1455, -1566, -1678, -1789, + -1901, -2078, -2256, -2433, -2611, -2744, -2878, -2915, + -2953, -2998, -3044, -3777, +1633, +2298, +1941, +2015, + +2090, +2107, +2124, +2141, +2158, +2158, +2158, +2158, + +1216, +1109, +1514, +1823, +1620, +2001, +1870, +1803, + +1224, +1600, +1464, +1232, +1000, +1096, +1192, +1352, + +1512, +1726, +1940, +2058, +2176, +2062, +1948, +1930, + +1912, +1781, +1650, +1583, +2028, -1871, -1674, -1605, + -1536, -1595, -1654, -1713, -1772, -1863, -1954, -2045, + -2136, -2297, -2458, -2619, -2780, -2917, -3054, -3063, + -3072, -3033, -2994, -2827, +2460, +2035, +2122, +2145, + +2168, +2168, +2168, +2168, +2168, +2168, +2168, +2168, + +1190, +1271, +1610, +1756, +1647, +1523, +1144, +1324, + +1249, +1364, +1224, +1211, +1199, +1255, +1566, +1430, + +1294, +1404, +1514, +1800, +2087, +2075, +2063, +2003, + +1944, +1654, +1621, +1811, +979, -1997, -1903, -1888, + -1874, -1927, -1982, -2036, -2091, -2163, -2236, -2308, + -2381, -2513, -2646, -2778, -2911, -3005, -3100, -3114, + -3129, -3039, -3206, -1084, +2317, +2104, +2148, +2159, + +2171, +2175, +2179, +2183, +2187, +2187, +2187, +2187, + +1164, +1179, +1195, +1179, +1163, +1302, +1442, +1358, + +1274, +1385, +1496, +1447, +1399, +1158, +1429, +1508, + +1588, +1594, +1601, +1543, +1486, +1832, +2179, +2077, + +1976, +1528, +1593, +1785, -582, -2381, -2133, -2172, + -2212, -2261, -2311, -2361, -2411, -2464, -2518, -2572, + -2626, -2730, -2834, -2938, -3042, -3094, -3146, -3166, + -3186, -3046, -3418, +658, +2174, +2174, +2174, +2174, + +2174, +2182, +2190, +2198, +2206, +2206, +2206, +2206, + +1202, +1230, +1259, +1272, +1286, +1321, +1356, +1343, + +1331, +1405, +1480, +1474, +1470, +1349, +1483, +1522, + +1562, +1576, +1591, +1573, +1557, +1589, +1622, +1718, + +1816, +1690, +1820, +1694, -2015, -2556, -2330, -2376, + -2422, -2610, -2799, -2700, -2602, -2669, -2736, -2803, + -2871, -2946, -3022, -3097, -3173, -3182, -3192, -3153, + -3115, -3324, -3278, +2256, +2159, +2147, +2136, +2156, + +2177, +2189, +2201, +2213, +2225, +2225, +2225, +2225, + +1240, +1282, +1325, +1367, +1410, +1340, +1271, +1329, + +1388, +1426, +1465, +1503, +1542, +1540, +1539, +1537, + +1536, +1559, +1582, +1605, +1628, +1603, +1578, +1617, + +1656, +1596, +1536, +1604, -2936, -2476, -2528, -2580, + -2632, -2704, -2777, -2785, -2794, -2874, -2955, -3035, + -3116, -3163, -3210, -3257, -3304, -3271, -3238, -3141, + -3044, -3091, -2114, +2319, +2144, +2121, +2098, +2139, + +2180, +2196, +2212, +2228, +2244, +2244, +2244, +2244, + +1230, +1255, +1281, +1306, +1333, +1303, +1272, +1338, + +1405, +1436, +1468, +1500, +1533, +1535, +1537, +1539, + +1542, +1562, +1584, +1605, +1627, +1601, +1577, +1616, + +1656, +1807, +1959, -417, -2793, -2797, -2545, -2581, + -2618, -2687, -2757, -2794, -2833, -2901, -2968, -3036, + -3105, -3145, -3186, -3178, -3171, -3149, -3128, -3058, + -2989, -3221, -126, +2281, +2129, +2084, +2040, +2107, + +2175, +2189, +2203, +2217, +2231, +2231, +2231, +2231, + +1220, +1229, +1238, +1247, +1257, +1266, +1275, +1348, + +1422, +1447, +1473, +1499, +1525, +1530, +1536, +1542, + +1548, +1567, +1587, +1606, +1626, +1601, +1577, +1616, + +1656, +1763, +1871, +1658, -2138, -2862, -2563, -2583, + -2604, -2671, -2738, -2805, -2873, -2928, -2983, -3038, + -3094, -3128, -3162, -3100, -3038, -3028, -3018, -2976, + -2934, -3352, +1862, +2244, +2114, +2048, +1982, +2076, + +2170, +2182, +2194, +2206, +2218, +2218, +2218, +2218, + +1210, +1234, +1259, +1283, +1308, +1325, +1341, +1390, + +1439, +1457, +1477, +1496, +1516, +1525, +1535, +1544, + +1554, +1571, +1589, +1607, +1625, +1616, +1608, +1632, + +1656, +1718, +1782, +1685, +1845, +528, -2836, -2728, + -2622, -2654, -2687, -2719, -2752, -2763, -2773, -2992, + -2955, -3030, -3106, -2813, -2777, -3226, -2908, -3134, + -3359, -971, +2186, +2270, +2099, +2075, +2052, +2108, + +2165, +2175, +2185, +2195, +2205, +2205, +2205, +2205, + +1200, +1240, +1280, +1320, +1360, +1384, +1408, +1432, + +1456, +1469, +1482, +1495, +1508, +1521, +1534, +1547, + +1560, +1576, +1592, +1608, +1624, +1632, +1640, +1648, + +1656, +1675, +1694, +1713, +1732, +1871, +986, -827, + -2640, -2638, -2636, -2634, -2632, -2598, -2564, -2946, + -2816, -2933, -3050, -2783, -3028, -3169, -1774, +293, + +2360, +2179, +1998, +2041, +2084, +2103, +2122, +2141, + +2160, +2168, +2176, +2184, +2192, +2192, +2192, +2192, + +1232, +1266, +1300, +1334, +1368, +1390, +1412, +1434, + +1456, +1468, +1482, +1494, +1508, +1520, +1534, +1546, + +1560, +1578, +1596, +1614, +1632, +1640, +1648, +1656, + +1664, +1645, +1628, +1705, +1784, +2101, +1908, +1298, + +688, +1071, -594, -1587, -2580, -2891, -3202, -2281, + -2640, -2058, -1476, -94, +1032, +2278, +2244, +2209, + +2176, +2131, +2088, +2091, +2096, +2111, +2128, +2143, + +2160, +2168, +2176, +2184, +2192, +2192, +2192, +2192, + +1264, +1292, +1320, +1348, +1376, +1396, +1416, +1436, + +1456, +1469, +1482, +1495, +1508, +1521, +1534, +1547, + +1560, +1580, +1600, +1620, +1640, +1648, +1656, +1664, + +1672, +1617, +1562, +1699, +1836, +1821, +1806, +1887, + +1968, +1964, +1960, +2020, +2080, +1936, +1792, +1200, + +1632, +1889, +2146, +2083, +2020, +2093, +2166, +2079, + +1992, +2085, +2178, +2143, +2108, +2121, +2134, +2147, + +2160, +2168, +2176, +2184, +2192, +2192, +2192, +2192, + +1296, +1318, +1340, +1362, +1384, +1402, +1420, +1438, + +1456, +1468, +1482, +1494, +1508, +1520, +1534, +1546, + +1560, +1582, +1604, +1626, +1648, +1656, +1664, +1672, + +1680, +1667, +1656, +1739, +1824, +1811, +1800, +1835, + +1872, +1881, +1890, +1819, +1748, +1995, +450, +937, + +912, +715, +2056, +2019, +1984, +2035, +2088, +2059, + +2032, +2085, +2140, +2129, +2120, +2129, +2140, +2149, + +2160, +2168, +2176, +2184, +2192, +2192, +2192, +2192, + +1328, +1344, +1360, +1376, +1392, +1408, +1424, +1440, + +1456, +1469, +1482, +1495, +1508, +1521, +1534, +1547, + +1560, +1584, +1608, +1632, +1656, +1664, +1672, +1680, + +1688, +1719, +1750, +1781, +1812, +1803, +1794, +1785, + +1776, +1798, +1820, +1874, +1928, +1798, +2180, +674, + +1216, +2103, +1966, +1957, +1948, +1979, +2010, +2041, + +2072, +2087, +2102, +2117, +2132, +2139, +2146, +2153, + +2160, +2168, +2176, +2184, +2192, +2192, +2192, +2192, + +1328, +1344, +1360, +1376, +1392, +1408, +1424, +1440, + +1456, +1468, +1482, +1494, +1508, +1520, +1534, +1546, + +1560, +1584, +1608, +1632, +1656, +1664, +1672, +1680, + +1688, +1718, +1750, +1780, +1812, +1802, +1794, +1784, + +1776, +1798, +1820, +1858, +1896, +1750, +1860, +2338, + +1792, +2134, +1966, +1956, +1948, +1978, +2010, +2040, + +2072, +2086, +2102, +2116, +2132, +2138, +2146, +2152, + +2160, +2168, +2176, +2184, +2192, +2192, +2192, +2192, + +1328, +1344, +1360, +1376, +1392, +1408, +1424, +1440, + +1456, +1469, +1482, +1495, +1508, +1521, +1534, +1547, + +1560, +1584, +1608, +1632, +1656, +1664, +1672, +1680, + +1688, +1719, +1750, +1781, +1812, +1803, +1794, +1785, + +1776, +1798, +1820, +1842, +1864, +1958, +2052, +1954, + +1856, +1911, +1966, +1957, +1948, +1979, +2010, +2041, + +2072, +2087, +2102, +2117, +2132, +2139, +2146, +2153, + +2160, +2168, +2176, +2184, +2192, +2192, +2192, +2192, + +1328, +1344, +1360, +1376, +1392, +1408, +1424, +1440, + +1456, +1468, +1482, +1494, +1508, +1520, +1534, +1546, + +1560, +1584, +1608, +1632, +1656, +1664, +1672, +1680, + +1688, +1718, +1750, +1780, +1812, +1802, +1794, +1784, + +1776, +1798, +1820, +1842, +1864, +1958, +2052, +1954, + +1856, +1910, +1966, +1956, +1948, +1978, +2010, +2040, + +2072, +2086, +2102, +2116, +2132, +2138, +2146, +2152, + +2160, +2168, +2176, +2184, +2192, +2192, +2192, +2192 +}; + +static INT16 TEST_CR_COMPONENT[4096] = +{ + -2112, -2114, -2116, -2118, -2120, -2122, -2124, -2126, + -2128, -2118, -2108, -2098, -2088, -2150, -2212, -2146, + -2080, -2100, -2120, -2140, -2160, -2164, -2168, -2172, + -2176, -2092, -2008, -2052, -2096, -2132, -2168, -2076, + -1984, -2088, -2192, -2168, -2144, -2136, -2128, -2120, + -2112, -2126, -2140, -2154, -2168, -2150, -2132, -2114, + -2096, -2096, -2096, -2096, -2096, -2096, -2096, -2096, + -2096, -2080, -2064, -2048, -2032, -2032, -2032, -2032, + -2128, -2113, -2098, -2115, -2132, -2133, -2134, -2135, + -2137, -2127, -2117, -2107, -2097, -2117, -2137, -2125, + -2114, -2134, -2154, -2159, -2163, -2135, -2108, -2128, + -2149, -2132, -2116, -2116, -2115, -2115, -2114, -2098, + -2082, -2112, -2142, -2141, -2139, -2133, -2128, -2122, + -2117, -2127, -2137, -2147, -2158, -2146, -2134, -2122, + -2111, -2108, -2106, -2104, -2102, -2101, -2101, -2101, + -2101, -2087, -2073, -2059, -2045, -2045, -2045, -2045, + -2144, -2112, -2080, -2112, -2145, -2145, -2145, -2145, + -2146, -2136, -2126, -2116, -2107, -2085, -2063, -2105, + -2148, -2168, -2189, -2178, -2167, -2107, -2048, -2085, + -2122, -2173, -2225, -2180, -2135, -2098, -2061, -2120, + -2180, -2136, -2093, -2114, -2135, -2131, -2128, -2125, + -2122, -2128, -2135, -2141, -2148, -2142, -2137, -2131, + -2126, -2121, -2117, -2112, -2108, -2107, -2107, -2106, + -2106, -2094, -2082, -2070, -2058, -2058, -2058, -2058, + -2160, -2111, -2062, -2109, -2157, -2156, -2155, -2154, + -2155, -2145, -2135, -2125, -2116, -2132, -2148, -2132, + -2118, -2154, -2191, -2181, -2170, -2494, -2308, -2393, + -2479, -2470, -2461, -2243, -2282, -2353, -2167, -2174, + -2182, -2160, -2139, -2135, -2130, -2128, -2128, -2127, + -2127, -2129, -2132, -2134, -2138, -2138, -2139, -2139, + -2141, -2133, -2127, -2120, -2114, -2112, -2112, -2111, + -2111, -2101, -2091, -2081, -2071, -2071, -2071, -2071, + -2176, -2110, -2045, -2107, -2170, -2168, -2167, -2165, + -2164, -2154, -2145, -2135, -2126, -2180, -2235, -2161, + -2088, -2141, -2195, -2440, -2686, -2371, -1033, -398, + +236, +305, +375, -3, -894, -2096, -2787, -2485, + -2184, -2185, -2187, -2156, -2126, -2127, -2129, -2130, + -2132, -2131, -2130, -2129, -2128, -2135, -2142, -2149, + -2156, -2147, -2138, -2129, -2120, -2119, -2118, -2117, + -2116, -2108, -2100, -2092, -2084, -2084, -2084, -2084, + -2112, -2085, -2058, -2112, -2166, -2067, -2225, -2190, + -2157, -2107, -2057, -2104, -2151, -2119, -2088, -2632, + -2666, -2263, -837, +844, +2526, +3327, +2847, +2847, + +2847, +2726, +2606, +2967, +3070, +2968, +2867, +397, + -2074, -2745, -2137, -2281, -2169, -2202, -2236, -2190, + -2145, -2145, -2147, -2148, -2150, -2152, -2156, -2159, + -2163, -2159, -2156, -2152, -2150, -2130, -2111, -2123, + -2137, -2127, -2117, -2107, -2097, -2097, -2097, -2097, + -2048, -2060, -2073, -2118, -2163, -1967, -2284, -2217, + -2150, -2060, -1971, -2074, -2177, -2315, -2454, -1057, + +1364, +2990, +2568, +2593, +2619, +2369, +2631, +2508, + +2386, +2332, +2278, +2352, +2427, +2913, +2888, +3022, + +3156, +1302, -2088, -2406, -2213, -2279, -2345, -2251, + -2158, -2161, -2165, -2168, -2172, -2171, -2171, -2170, + -2170, -2172, -2175, -2177, -2180, -2142, -2105, -2131, + -2158, -2146, -2134, -2122, -2110, -2110, -2110, -2110, + -2112, -2163, -2215, -2235, -2255, -1994, -2247, -2194, + -2143, -2109, -2076, -2123, -2170, -2270, +700, +3527, + +2770, +2035, +2325, +2293, +2263, +2178, +2350, +2265, + +2181, +2129, +2078, +2154, +2231, +2521, +2557, +2559, + +2562, +3221, +3113, +140, -2832, -2034, -2261, -2199, + -2139, -2160, -2182, -2188, -2194, -2189, -2185, -2181, + -2177, -2185, -2193, -2201, -2210, -2154, -2098, -2138, + -2179, -2165, -2151, -2137, -2123, -2123, -2123, -2123, + -1664, -1755, -1846, -1841, -1836, -1767, -2210, -2173, + -2136, -2159, -2182, -2173, -2164, -2739, +2830, +2735, + +2640, +2361, +2082, +1995, +1908, +1989, +2070, +2023, + +1976, +1927, +1878, +1957, +2036, +2131, +2226, +2353, + +2480, +2581, +2682, +2943, +2692, -2815, -2178, -2149, + -2120, -2160, -2200, -2208, -2216, -2208, -2200, -2192, + -2184, -2198, -2212, -2226, -2240, -2166, -2092, -2146, + -2200, -2184, -2168, -2152, -2136, -2136, -2136, -2136, + -2096, -2166, -2238, -2228, -2220, -2087, -2210, -2173, + -2137, -2189, -2243, -2152, -2318, -2031, +3375, +2861, + +2605, +2305, +2007, +1851, +1697, +1756, +1815, +1810, + +1806, +1756, +1707, +1754, +1801, +1911, +2023, +2149, + +2277, +2299, +2323, +2729, +1345, -2439, -2129, -2217, + -2307, -2349, -2136, -2179, -2222, -2223, -2224, -2193, + -2162, -2171, -2180, -2190, -2199, -2198, -2198, -2213, + -2229, -2172, -2115, -2170, -2225, -2113, -2257, -2257, + -2016, -2067, -2118, -2105, -2093, -2152, -2211, -2174, + -2138, -2221, -2305, -2132, -2472, +212, +2897, +2477, + +2570, +2251, +1932, +1709, +1487, +1524, +1561, +1598, + +1636, +1586, +1537, +1552, +1567, +1693, +1820, +1947, + +2074, +2019, +1964, +2261, -514, -2321, -2080, -2031, + -1982, -2283, -2073, -2151, -2229, -2238, -2248, -2194, + -2140, -2144, -2149, -2154, -2159, -2231, -2304, -2281, + -2258, -2160, -2062, -2188, -2314, -2090, -2378, -2378, + -2064, -2094, -2126, -2125, -2125, -2152, -2179, -2159, + -2139, -2204, -2270, -2144, -2530, +1688, +2834, +2460, + +2343, +2147, +1953, +1678, +1404, +1387, +1370, +1418, + +1466, +1416, +1366, +1349, +1332, +1442, +1553, +1663, + +1775, +1817, +1861, +2415, -2405, -2457, -1999, -2035, + -281, -1464, -2393, -2378, -2363, -2301, -2240, -2195, + -2150, -2165, -2181, -2182, -2182, -2199, -2218, -2188, + -2159, -2756, -2329, -1934, -2307, -2627, -2179, -2307, + -2112, -2123, -2135, -2146, -2158, -2153, -2149, -2144, + -2140, -2188, -2236, -2156, -2588, +3164, +2772, +2444, + +2116, +2045, +1975, +1648, +1322, +1251, +1181, +1238, + +1296, +1246, +1197, +1147, +1098, +1192, +1287, +1381, + +1476, +1617, +1758, +1291, -2760, -2083, -2430, -1273, + -628, -647, -667, -1582, -2498, -2365, -2233, -2196, + -2160, -2187, -2215, -2210, -2206, -2169, -2133, -2096, + -2060, -280, -548, -2448, -1788, -860, -1980, -2236, + -2112, -2120, -2130, -2140, -2150, -2145, -2141, -2137, + -2133, -2147, -2161, -2079, -718, +3207, +2525, +2291, + +2057, +1941, +1827, +1553, +1279, +1174, +1070, +1094, + +1118, +1044, +970, +976, +983, +1001, +1019, +1165, + +1313, +1305, +1555, -212, -2491, -2189, -2401, -867, + -615, -642, -671, -603, -536, -1354, -2172, -2271, + -2370, -2340, -2311, -2330, -2349, -2315, -2282, -2697, + -1321, -420, -543, -394, -757, -741, -2261, -2261, + -2112, -2119, -2127, -2135, -2143, -2138, -2134, -2130, + -2126, -2106, -2087, -2259, +640, +2995, +2279, +2138, + +1998, +1839, +1681, +1459, +1237, +1098, +960, +950, + +940, +842, +744, +806, +869, +811, +753, +951, + +1150, +995, +1352, -1715, -2222, -2297, -2372, -463, + -602, -639, -676, -649, -623, -600, -577, -810, + -1044, -1214, -1384, -1426, -1469, -1183, -897, -483, + -582, -560, -538, -900, -750, -1134, -2542, -2286, + -2112, -2117, -2123, -2129, -2135, -2131, -2127, -2123, + -2119, -2017, -1916, -2886, +1262, +2014, +2256, +2097, + +1939, +1736, +1534, +1364, +1194, +1022, +850, +806, + +762, +736, +710, +508, +818, +604, +646, +752, + +859, +1131, +1149, -2865, -2273, -2339, -1639, -425, + -493, -522, -553, -566, -581, -677, -773, -661, + -550, -567, -585, -586, -588, -657, -727, -572, + -675, -668, -661, -798, -679, -1799, -2407, -2151, + -2112, -2116, -2120, -2124, -2128, -2124, -2120, -2116, + -2112, -2185, -2258, -1723, +1884, +1035, +2234, +2057, + +1880, +1634, +1388, +1270, +1152, +946, +740, +662, + +584, +630, +676, +466, +1280, +654, +540, +554, + +568, +757, -78, -2481, -2324, -2383, -906, -389, + -384, -407, -430, -485, -540, -499, -458, -513, + -568, -689, -810, -771, -732, -645, -558, -663, + -768, -776, -784, -696, -608, -2464, -2272, -2016, + -2104, -2110, -2116, -2122, -2129, -2105, -2081, -2105, + -2130, -2204, -2536, -84, +1856, +1148, +1209, +1701, + +1683, +1507, +1332, +1188, +1045, +837, +630, +518, + +407, +489, +572, +398, +1249, +662, +330, +383, + +436, +589, -1304, -2350, -2117, -2615, +213, -12, + -239, -265, -293, -320, -348, -377, -407, -484, + -562, -626, -691, -675, -661, -625, -590, -682, + -776, -804, -832, -540, -248, -664, -1848, -2616, + -2096, -2104, -2113, -2121, -2130, -2086, -2043, -2095, + -2148, -2225, -2815, +1555, +1829, +1519, +697, +1603, + +1486, +1381, +1276, +1107, +938, +729, +520, +375, + +230, +349, +468, +331, +1219, +670, +121, +212, + +304, +423, -2531, -2477, -2423, -1569, +309, -149, + -94, -125, -157, -157, -157, -256, -356, -456, + -556, -564, -573, -581, -590, -606, -623, -703, + -784, -832, -880, -384, +112, -1424, -2448, -2192, + -2088, -2098, -2109, -2119, -2131, -2099, -2068, -2100, + -2134, -2485, -2325, +2921, +2025, +1536, +1048, +1088, + +1385, +1270, +1156, +993, +831, +700, +570, +407, + +245, +256, +268, +343, +932, +662, +135, +185, + +236, -337, -2445, -2346, -2504, -793, +149, -75, + -45, -64, -84, -88, -93, -183, -273, -363, + -454, -454, -454, -518, -583, -619, -655, -723, + -792, -796, -800, -868, -1960, -2296, -2376, -2248, + -2080, -2093, -2106, -2119, -2132, -2113, -2094, -2107, + -2120, -2234, -813, +2752, +2222, +1555, +1401, +574, + +1284, +1160, +1036, +880, +724, +672, +620, +440, + +260, +164, +69, +357, +646, +654, +151, +159, + +168, -1096, -2361, -2217, -2586, -18, -11, -3, + +4, -4, -13, -21, -30, -110, -191, -271, + -352, -344, -336, -456, -576, -632, -688, -744, + -800, -760, -720, -584, -2496, -2400, -2304, -2304, + -2072, -2086, -2102, -2117, -2133, -2171, -2211, -2170, + -2130, -2462, +1045, +2615, +2138, +1656, +1432, +807, + +951, +1193, +924, +734, +545, +397, +250, +486, + +723, +569, +416, +311, +207, +384, +305, +242, + +180, -1825, -2295, -2348, -1891, +69, -19, -10, + -3, -7, -12, -16, -22, -65, -107, -182, + -258, -309, -361, -477, -593, -640, -688, -736, + -784, -752, -720, -1200, -2448, -2384, -2320, -2320, + -2064, -2081, -2099, -2116, -2134, -2231, -2329, -2234, + -2140, -2691, +2902, +2478, +2055, +1759, +1464, +1041, + +618, +1227, +812, +589, +366, +379, +392, +277, + +162, +207, +253, +267, +281, +114, -52, +70, + +192, -2555, -2230, -2481, -1197, +156, -28, -19, + -10, -11, -12, -13, -15, -20, -25, -94, + -164, -275, -387, -498, -610, -649, -689, -728, + -768, -744, -720, -1816, -2400, -2368, -2336, -2336, + -2056, -2075, -2095, -2115, -2135, -2178, -2222, -2138, + -2310, -1319, +2743, +2293, +2099, +1893, +1432, +1242, + +541, +1036, +1020, +699, +379, +376, +374, +275, + +177, +196, +217, +189, +162, +100, +39, +153, + -756, -2420, -2293, -2549, -502, +131, -4, -10, + -17, -14, -12, -9, -7, -7, -6, -102, + -198, -320, -444, -519, -595, -641, -689, -720, + -752, -768, -784, -2192, -2320, -2336, -2352, -2352, + -2048, -2070, -2092, -2114, -2136, -2126, -2116, -2042, + -2480, +52, +2584, +2108, +2144, +2028, +1400, +1444, + +464, +78, -308, -470, -632, -394, -156, +18, + +192, +187, +182, +113, +44, +87, +130, +237, + -1704, -2286, -2356, -2618, +192, +106, +20, -2, + -24, -18, -12, -6, +0, +6, +12, -110, + -232, -367, -502, -541, -580, -635, -690, -713, + -736, -792, -848, -2568, -2240, -2304, -2368, -2368, + -2046, -2068, -2091, -2113, -2136, -2121, -2105, -2186, + -2523, +1999, +2681, +2740, +1518, +117, -1541, -2639, + -2457, -2465, -2474, -2466, -2459, -2498, -2536, -2303, + -2070, -995, +81, -76, +24, +35, +47, -150, + -2394, -2422, -2450, -1806, +117, +85, +53, +21, + -11, -11, -11, -11, -11, -11, -11, -107, + -203, -404, -606, -615, -625, -610, -596, -693, + -791, -757, -1491, -2401, -2287, -2303, -2319, -2319, + -2044, -2067, -2090, -2113, -2137, -2116, -2095, -2074, + -2054, +2923, +219, -1748, -2692, -2563, -2435, -2114, + -2306, -2193, -2080, -2159, -2239, -2298, -2357, -2320, + -2284, -2432, -2580, -1544, +4, -16, -36, -280, + -2572, -2302, -2544, -994, +43, +64, +86, +44, + +2, -4, -10, -16, -22, -28, -34, -104, + -174, -186, -198, -178, -158, -330, -502, -674, + -846, -722, -2134, -2234, -2334, -2302, -2270, -2270, + -2042, -2065, -2089, -2112, -2137, -2159, -2180, -2154, + -2129, -2458, -2532, -2604, -2166, -2218, -2272, -2293, + -2315, -2000, -2198, -2219, -2242, -2322, -2401, -2385, + -2370, -2285, -2201, -2452, -2704, -1411, +137, -1402, + -2174, -2502, -2830, +250, +0, +28, +55, +35, + +15, +3, -9, -21, -33, -45, -57, -101, + -145, -175, -206, -220, -235, -177, -120, -414, + -709, -191, -2489, -2547, -2349, -2349, -2349, -2349, + -2040, -2064, -2089, -2113, -2138, -2202, -2267, -2235, + -2204, -2207, -2210, -2181, -2152, -2131, -2110, -2217, + -1812, -1552, -2317, -2025, -1734, -1578, -1423, -1939, + -2456, -2395, -2334, -2081, -2340, -2551, -2250, -2013, + -2288, -2446, -2093, -43, -42, -8, +25, +26, + +28, +10, -8, -26, -44, -62, -80, -98, + -116, -165, -214, -263, -312, -281, -250, -155, + -60, -940, -1820, -2348, -2364, -2396, -2428, -2428, + -2038, -2058, -2079, -2100, -2122, -2123, -2124, -2285, + -2191, -2065, -1940, -1910, -1882, -2232, -2327, -2149, + -1717, -1485, -2022, -1759, -1497, -1242, -987, -716, + -446, -1226, -2007, -2723, -2160, -2330, -2245, -2175, + -2362, -2338, -1034, +109, -28, -19, -10, +15, + +41, +19, -3, -25, -47, -89, -131, -141, + -151, -208, -266, -355, -445, -458, -472, -405, + -83, -1135, -1163, -1895, -2371, -2387, -2403, -2403, + -2036, -2053, -2071, -2089, -2107, -2044, -1982, -2080, + -1666, -1668, -1671, -1897, -2124, -2590, -2545, -2083, + -1622, -1419, -1729, -1495, -1261, -1162, -1064, -774, + -484, -314, -144, -806, -2492, -2366, -2240, -2338, + -2436, -2486, -489, +4, -15, -30, -45, +4, + +54, +28, +2, -24, -50, -116, -182, -184, + -186, -252, -318, -448, -578, -636, -694, -656, + -106, -2098, -2042, -2210, -2378, -2378, -2378, -2378, + -2034, -2047, -2062, -2076, -2091, -2093, -2096, -1650, + -1461, -1687, -1913, -2155, -2398, -2676, -2442, -2016, + -1591, -1448, -1563, -1341, -1120, -986, -853, -623, + -394, -265, -137, +200, +24, -1554, -2363, -2324, + -2286, -2122, -2727, -1220, +31, +136, -15, +25, + +67, +37, +7, -7, -21, -111, -201, -211, + -221, -295, -370, -460, -551, -509, -468, -634, + -545, -2805, -2249, -2301, -2353, -2353, -2353, -2353, + -2032, -2043, -2054, -2065, -2076, -2143, -2210, -1477, + -1768, -1962, -2156, -2414, -2672, -2762, -2340, -1950, + -1560, -1479, -1398, -1189, -980, -811, -642, -473, + -304, -217, -130, -75, -20, +27, -2486, -2311, + -2136, -2527, -2406, -2445, -2484, -979, +14, +47, + +80, +46, +12, +10, +8, -106, -220, -238, + -256, -339, -422, -473, -524, -639, -754, -1637, + -2520, -2232, -2456, -2392, -2328, -2328, -2328, -2328, + -2012, -2030, -2049, -2052, -2055, -2191, -2073, -1585, + -1867, -2081, -2296, -2526, -2757, -2653, -2294, -1886, + -1479, -1380, -1282, -1087, -893, -748, -604, -491, + -379, -243, -109, -181, +1, -606, -2493, -2283, + -2331, -2481, -2376, -2413, -2452, -2308, -2421, -1350, + -278, -124, +30, +88, +145, +127, +109, +27, + -56, -278, -501, -1107, -1714, -2162, -2612, -2532, + -2453, -2297, -2397, -2369, -2341, -2341, -2341, -2341, + -1992, -2018, -2045, -2040, -2035, -2241, -1936, -1695, + -1966, -2201, -2436, -2639, -2842, -2545, -2248, -1823, + -1398, -1282, -1166, -986, -806, -686, -566, -510, + -454, -271, -88, -289, +22, -1239, -2500, -2257, + -2526, -388, -2346, -2383, -2421, -2358, -2296, -2490, + -2684, -2342, -2001, -1627, -1254, -1176, -1099, -1501, + -1904, -2266, -2628, -2510, -2393, -2407, -2422, -2404, + -2386, -2362, -2338, -2346, -2354, -2354, -2354, -2354, + -1972, -2006, -2040, -2043, -2046, -2194, -1831, -1835, + -2097, -2336, -2576, -2735, -2895, -2564, -2234, -1839, + -1445, -1279, -1114, -916, -719, -623, -528, -528, + -529, -425, -323, -59, -53, -2527, -2443, -2517, + -2081, +170, -140, -1312, -2485, -2440, -2395, -2382, + -2370, -2400, -2431, -2509, -2589, -2559, -2530, -2500, + -2472, -2429, -2387, -2489, -2335, -2939, -2008, -1331, + -2447, -2395, -2343, -2355, -2367, -2367, -2367, -2367, + -1952, -1994, -2037, -2047, -2058, -2148, -1727, -1977, + -2228, -2472, -2716, -2832, -2948, -2584, -2220, -1856, + -1492, -1277, -1062, -847, -632, -561, -490, -547, + -604, -581, -558, -343, -1152, -2281, -2386, -2523, + -1124, -40, +19, +15, +10, -1242, -2495, -2531, + -2568, -2459, -2350, -2369, -2388, -2407, -2426, -2477, + -2528, -2593, -2659, -2212, -1254, +369, +967, -1026, + -2508, -2428, -2348, -2364, -2380, -2380, -2380, -2380, + -1948, -1996, -2044, -2060, -2077, -1957, -1837, -2069, + -2303, -2545, -2788, -2918, -3049, -2873, -2442, -2026, + -1611, -1374, -1138, -965, -793, -732, -672, -707, + -743, -847, -953, -2017, -2059, -2441, -2313, -2327, + -295, +99, -19, +23, +65, +26, -13, -629, + -1246, -1795, -2345, -2509, -2675, -2540, -2406, -1887, + -1368, -467, +434, +439, +699, +1162, +856, -2695, + -2409, -2413, -2417, -2389, -2361, -2361, -2361, -2361, + -1944, -1998, -2052, -2074, -2097, -1767, -1949, -2163, + -2378, -2619, -2860, -3005, -3150, -3163, -2664, -2197, + -1730, -1472, -1214, -1084, -954, -904, -854, -868, + -882, -859, -836, -877, -1942, -2091, -2240, -2389, + +22, -18, -57, +32, +121, +14, -93, -9, + +76, +149, +221, +166, +110, +143, +175, +239, + +304, +379, +455, +530, +605, +676, +235, -2573, + -2310, -2398, -2486, -2414, -2342, -2342, -2342, -2342, + -1940, -2000, -2060, -2072, -2084, -1640, -1964, -2144, + -2325, -2532, -2740, -2899, -3059, -3052, -2790, -2319, + -1849, -1569, -1290, -1202, -1115, -1075, -1036, -1028, + -1021, -1077, -1135, -503, -2689, -2395, -2359, -1553, + +19, -6, -30, +25, +80, +34, -12, +37, + +86, +124, +162, +137, +111, +137, +163, +237, + +312, +393, +475, +525, +574, +654, -803, -2466, + -2339, -2383, -2427, -2375, -2323, -2323, -2323, -2323, + -1936, -2002, -2068, -2070, -2072, -1514, -1980, -2126, + -2272, -2446, -2620, -2794, -2968, -2942, -2916, -2442, + -1968, -1667, -1366, -1321, -1276, -1247, -1218, -1189, + -1160, -1041, -922, -1411, -2412, -2189, -2478, -719, + +16, +6, -4, +18, +40, +54, +68, +82, + +96, +100, +104, +108, +112, +132, +152, +236, + +320, +408, +496, +520, +544, +632, -1840, -2360, + -2368, -2368, -2368, -2336, -2304, -2304, -2304, -2304, + -1898, -1921, -1944, -2111, -1766, -1551, -1848, -1985, + -2122, -2318, -2515, -2664, -2813, -3074, -3079, -2828, + -2321, -2024, -1729, -1608, -1489, -1457, -1425, -1393, + -1362, -1246, -1131, -1879, -2372, -2532, -2693, +331, + +25, +40, +55, +54, +54, +71, +88, +105, + +123, +151, +180, +208, +237, +83, -70, +48, + +167, +248, +329, +346, +363, +733, -2738, -2577, + -2416, -2395, -2374, -2353, -2332, -2332, -2332, -2332, + -1860, -1840, -1820, -2152, -1460, -1588, -1716, -1844, + -1972, -2191, -2411, -2535, -2659, -2950, -2730, -2958, + -2674, -2383, -2092, -1897, -1703, -1668, -1633, -1598, + -1564, -1452, -1340, -2348, -2333, -2365, -1885, -157, + +34, +74, +115, +91, +68, +88, +109, +129, + +150, +203, +256, +309, +362, +291, +220, +117, + +14, +88, +162, +172, +183, -702, -2612, -2282, + -2464, -2422, -2380, -2370, -2360, -2360, -2360, -2360, + -2110, -1967, -1824, -1953, -1314, -1513, -1712, -1815, + -1918, -2207, -2242, -2453, -2408, -2602, -2541, -2752, + -2707, -2692, -2679, -2409, -2140, -2054, -1968, -1867, + -1766, -1721, -1677, -2369, -2293, -2516, -948, -53, + +75, +92, +110, +95, +82, +105, +129, +152, + +177, +222, +268, +313, +359, +354, +350, +441, + +533, +472, +411, +414, +674, -1689, -2518, -2339, + -2416, -2401, -2386, -2387, -2388, -2388, -2388, -2388, + -1848, -1838, -1828, -1754, -1168, -1438, -1708, -1786, + -1864, -2225, -2075, -2372, -2158, -2255, -2353, -2546, + -2740, -2747, -2755, -2666, -2578, -2441, -2305, -2136, + -1968, -1991, -2015, -2390, -2254, -2669, -13, +51, + +116, +111, +106, +101, +96, +123, +150, +177, + +204, +242, +280, +318, +356, +418, +480, +510, + +540, +600, +661, +657, +1166, -2677, -2425, -2396, + -2368, -2380, -2392, -2404, -2416, -2416, -2416, -2416, + -1882, -1711, -1796, -1369, -1198, -1419, -1640, -1749, + -1858, -1977, -1842, -2058, -2019, -2113, -2207, -2366, + -2525, -2478, -2689, -2836, -2983, -2759, -2536, -2393, + -2250, -2194, -2139, -2357, -2318, -2018, +72, +113, + +157, +150, +145, +139, +134, +159, +186, +212, + +239, +273, +308, +342, +377, +439, +502, +548, + +595, +632, +669, +931, +170, -2666, -2430, -2403, + -2376, -2385, -2394, -2403, -2412, -2412, -2412, -2412, + -1916, -1840, -2276, -1240, -1228, -1400, -1572, -1712, + -1852, -1731, -1610, -1745, -1881, -1972, -2063, -2186, + -2310, -2211, -2625, -2751, -2877, -2822, -2768, -2650, + -2532, -2398, -2265, -2324, -2383, -1369, +156, +177, + +198, +191, +185, +178, +172, +197, +223, +248, + +274, +305, +336, +367, +398, +461, +524, +587, + +650, +664, +679, +1206, -827, -2656, -2437, -2410, + -2384, -2390, -2396, -2402, -2408, -2408, -2408, -2408, + -1950, -1953, -1956, -1063, -1194, -1317, -1440, -1435, + -1430, -1499, -1314, -1431, -1550, -1638, -1726, -1798, + -1871, -1927, -2240, -2409, -2578, -2597, -2616, -2731, + -2846, -2554, -2262, -2259, -2511, -527, +176, +207, + +239, +231, +224, +217, +210, +234, +259, +284, + +309, +336, +364, +391, +419, +482, +546, +609, + +673, +744, +816, +936, -2015, -2485, -2187, -2289, + -2392, -2395, -2398, -2401, -2404, -2404, -2404, -2404, + -1984, -2066, -1636, -886, -1160, -1234, -1308, -1414, + -1520, -2037, -2042, -1887, -1732, -1817, -1902, -1923, + -1944, -1900, -1856, -2068, -2280, -2372, -2464, -2556, + -2648, -2454, -2260, -2194, -2640, +314, +196, +238, + +280, +272, +264, +256, +248, +272, +296, +320, + +344, +368, +392, +416, +440, +504, +568, +632, + +696, +825, +954, +923, -2692, -2315, -2450, -2425, + -2400, -2400, -2400, -2400, -2400, -2400, -2400, -2400, + -2252, -1953, -1142, -1035, -1441, -1826, -2211, -2244, + -2278, -2220, -1908, -1914, -1922, -2001, -2336, -2095, + -2111, -2171, -2231, -2131, -2031, -2143, -2255, -2303, + -2352, -2306, -2260, -2359, -1689, +442, +269, +305, + +341, +333, +325, +317, +309, +329, +349, +369, + +389, +415, +441, +468, +494, +536, +579, +669, + +760, +797, +1091, -248, -2610, -2406, -2459, -2431, + -2404, -2400, -2396, -2392, -2388, -2388, -2388, -2388, + -2008, -2096, -1673, -1953, -2234, -2162, -2091, -2051, + -2012, -2149, -2286, -2199, -2113, -1930, -2259, -2012, + -2278, -2186, -2094, -2194, -2295, -2171, -2047, -2051, + -2056, -2158, -2261, -2524, -739, +570, +343, +372, + +402, +394, +386, +378, +370, +386, +402, +418, + +434, +462, +491, +520, +549, +569, +590, +707, + +824, +770, +1228, -1418, -2528, -2498, -2468, -2438, + -2408, -2400, -2392, -2384, -2376, -2376, -2376, -2376, + -1988, -2191, -2139, -2150, -2163, -2130, -2098, -2081, + -2066, -2140, -2216, -2179, -2143, -2066, -2245, -2137, + -2285, -2233, -2181, -2225, -2270, -2326, -2382, -2166, + -1952, -2250, -2549, -2465, +180, +394, +352, +407, + +463, +455, +447, +423, +399, +523, +391, +547, + +447, +493, +540, +572, +603, +633, +665, +792, + +920, +1094, +1269, -2764, -2446, -2429, -2413, -2412, + -2412, -2400, -2388, -2376, -2364, -2364, -2364, -2364, + -1968, -2031, -2094, -2093, -2092, -2099, -2106, -2113, + -2120, -2133, -2147, -2160, -2174, -2203, -2233, -2262, + -2292, -2280, -2269, -2257, -2246, -2226, -2207, -2283, + -2360, -2343, -2327, -2406, +586, -38, +363, +443, + +524, +516, +508, +468, +428, +660, +380, +676, + +460, +525, +591, +624, +658, +699, +741, +878, + +1016, +907, +286, -2575, -2364, -2361, -2358, -2387, + -2416, -2400, -2384, -2368, -2352, -2352, -2352, -2352, + -2020, -2071, -2124, -2080, -2037, -2062, -2089, -2115, + -2142, -2152, -2164, -2176, -2188, -2211, -2235, -2259, + -2283, -2275, -2267, -2260, -2253, -2249, -2246, -2290, + -2336, -2337, -2339, -1205, -71, -16, +296, +496, + +441, +469, +497, +381, +521, +635, +493, +735, + +465, +544, +624, +640, +656, +747, +839, +899, + +960, +1115, -1033, -2493, -2418, -2378, -2339, -2379, + -2420, -2408, -2396, -2384, -2372, -2372, -2372, -2372, + -2072, -2113, -2155, -2068, -1982, -2027, -2073, -2118, + -2164, -2173, -2183, -2193, -2203, -2220, -2238, -2256, + -2274, -2270, -2267, -2264, -2261, -2273, -2286, -2299, + -2312, -2332, -2352, -2052, -729, +7, +230, +550, + +358, +422, +486, +294, +614, +610, +606, +794, + +470, +564, +658, +656, +655, +797, +939, +921, + +904, +1324, -2352, -2412, -2472, -2396, -2320, -2372, + -2424, -2416, -2408, -2400, -2392, -2392, -2392, -2392, + -1996, -1930, -1865, -1960, -2055, -2087, -2120, -2153, + -2186, -2193, -2201, -2209, -2217, -2229, -2241, -2253, + -2265, -2265, -2266, -2267, -2268, -2280, -2294, -2306, + -2320, -2342, -2365, -2707, -2538, -1491, -188, +172, + +275, +327, +379, +287, +451, +505, +559, +773, + +475, +551, +628, +512, +653, +909, +654, +1007, + +1104, -739, -2583, -2506, -2430, -2397, -2365, -2396, + -2428, -2424, -2420, -2416, -2412, -2412, -2412, -2412, + -1920, -2004, -2088, -2108, -2128, -2148, -2168, -2188, + -2208, -2214, -2220, -2226, -2232, -2238, -2244, -2250, + -2256, -2261, -2266, -2271, -2276, -2289, -2302, -2315, + -2328, -2353, -2378, -2339, -2300, -2477, -1630, -719, + +192, +232, +272, +280, +288, +400, +512, +752, + +480, +539, +598, +369, +652, +767, -142, -1211, + -2792, -2547, -2302, -2345, -2388, -2399, -2410, -2421, + -2432, -2432, -2432, -2432, -2432, -2432, -2432, -2432, + -2024, -2070, -2116, -2130, -2144, -2164, -2184, -2204, + -2224, -2228, -2232, -2236, -2240, -2244, -2248, -2252, + -2256, -2262, -2270, -2276, -2284, -2296, -2310, -2322, + -2336, -2319, -2304, -2287, -2272, -2559, -2336, -1855, + -1376, -2264, -1104, -520, +64, +384, +704, +704, + +192, -44, -280, -1236, -1936, -3018, -2564, -2349, + -2392, -2390, -2390, -2388, -2388, -2398, -2410, -2420, + -2432, -2432, -2432, -2432, -2432, -2432, -2432, -2432, + -2128, -2136, -2144, -2152, -2160, -2180, -2200, -2220, + -2240, -2242, -2244, -2246, -2248, -2250, -2252, -2254, + -2256, -2265, -2274, -2283, -2292, -2305, -2318, -2331, + -2344, -2287, -2230, -2237, -2244, -2387, -2530, -2481, + -2432, -2456, -2480, -2600, -2720, -2448, -2176, -1904, + -2144, -2419, -2694, -2585, -2476, -2451, -2426, -2465, + -2504, -2491, -2478, -2433, -2388, -2399, -2410, -2421, + -2432, -2432, -2432, -2432, -2432, -2432, -2432, -2432, + -2104, -2122, -2140, -2158, -2176, -2196, -2216, -2236, + -2256, -2256, -2256, -2256, -2256, -2256, -2256, -2256, + -2256, -2266, -2278, -2288, -2300, -2312, -2326, -2338, + -2352, -2317, -2284, -2281, -2280, -2357, -2436, -2417, + -2400, -2408, -2416, -2360, -2304, -2480, -864, -1648, + -1408, -1225, -2580, -2509, -2440, -2427, -2416, -2435, + -2456, -2446, -2438, -2412, -2388, -2398, -2410, -2420, + -2432, -2432, -2432, -2432, -2432, -2432, -2432, -2432, + -2080, -2108, -2136, -2164, -2192, -2212, -2232, -2252, + -2272, -2270, -2268, -2266, -2264, -2262, -2260, -2258, + -2256, -2269, -2282, -2295, -2308, -2321, -2334, -2347, + -2360, -2349, -2338, -2327, -2316, -2329, -2342, -2355, + -2368, -2360, -2352, -2376, -2400, -2256, -2624, -1392, + -1696, -2593, -2466, -2435, -2404, -2405, -2406, -2407, + -2408, -2403, -2398, -2393, -2388, -2399, -2410, -2421, + -2432, -2432, -2432, -2432, -2432, -2432, -2432, -2432, + -2080, -2108, -2136, -2164, -2192, -2212, -2232, -2252, + -2272, -2270, -2268, -2266, -2264, -2262, -2260, -2258, + -2256, -2268, -2282, -2294, -2308, -2320, -2334, -2346, + -2360, -2348, -2338, -2326, -2316, -2328, -2342, -2354, + -2368, -2360, -2352, -2360, -2368, -2352, -2592, -2192, + -2560, -2768, -2466, -2434, -2404, -2404, -2406, -2406, + -2408, -2402, -2398, -2392, -2388, -2398, -2410, -2420, + -2432, -2432, -2432, -2432, -2432, -2432, -2432, -2432, + -2080, -2108, -2136, -2164, -2192, -2212, -2232, -2252, + -2272, -2270, -2268, -2266, -2264, -2262, -2260, -2258, + -2256, -2269, -2282, -2295, -2308, -2321, -2334, -2347, + -2360, -2349, -2338, -2327, -2316, -2329, -2342, -2355, + -2368, -2360, -2352, -2344, -2336, -2448, -2560, -2480, + -2400, -2433, -2466, -2435, -2404, -2405, -2406, -2407, + -2408, -2403, -2398, -2393, -2388, -2399, -2410, -2421, + -2432, -2432, -2432, -2432, -2432, -2432, -2432, -2432, + -2080, -2108, -2136, -2164, -2192, -2212, -2232, -2252, + -2272, -2270, -2268, -2266, -2264, -2262, -2260, -2258, + -2256, -2268, -2282, -2294, -2308, -2320, -2334, -2346, + -2360, -2348, -2338, -2326, -2316, -2328, -2342, -2354, + -2368, -2360, -2352, -2344, -2336, -2448, -2560, -2480, + -2400, -2432, -2466, -2434, -2404, -2404, -2406, -2406, + -2408, -2402, -2398, -2392, -2388, -2398, -2410, -2420, + -2432, -2432, -2432, -2432, -2432, -2432, -2432, -2432 +}; + +/** + * 64x64 XRGB Image + */ + +static UINT32 TEST_XRGB_IMAGE[4096] = +{ + 0xFF229cdf, 0xFF249de0, 0xFF259fe2, 0xFF2ca5e8, 0xFF229cdf, 0xFF229ce0, 0xFF239de0, 0xFF229ce0, + 0xFF229cdf, 0xFF229cdf, 0xFF239ce0, 0xFF249ce0, 0xFF249ce0, 0xFF219ce3, 0xFF1e9ce6, 0xFF209ae2, + 0xFF2299dd, 0xFF2199de, 0xFF209adf, 0xFF209ae0, 0xFF1f9be0, 0xFF1e9ae0, 0xFF1d99e0, 0xFF1c98e0, + 0xFF1b97df, 0xFF1e96dc, 0xFF2194d9, 0xFF1f93dd, 0xFF1d93e0, 0xFF1b94dc, 0xFF1895d8, 0xFF1c92db, + 0xFF208fde, 0xFF1b91de, 0xFF1693df, 0xFF1793df, 0xFF1992df, 0xFF1891df, 0xFF178fdf, 0xFF178edf, + 0xFF168dde, 0xFF158cdd, 0xFF148cdc, 0xFF128cda, 0xFF118cd9, 0xFF118bd9, 0xFF128ada, 0xFF1289da, + 0xFF1288db, 0xFF1187da, 0xFF1186da, 0xFF1085da, 0xFF0f85d9, 0xFF0f84d9, 0xFF0e83d9, 0xFF0d82d8, + 0xFF0d82d8, 0xFF0d81d8, 0xFF0d80d7, 0xFF0d7fd7, 0xFF0d7ed6, 0xFF0d7ed6, 0xFF0d7ed6, 0xFF0d7ed6, + 0xFF259fe1, 0xFF27a1e2, 0xFF29a2e3, 0xFF2ba4e6, 0xFF249fe1, 0xFF249fe1, 0xFF249fe1, 0xFF249ee1, + 0xFF239ee1, 0xFF249ee1, 0xFF249ee1, 0xFF259de1, 0xFF259de2, 0xFF249de2, 0xFF229de2, 0xFF229ce1, + 0xFF229bdf, 0xFF219ce0, 0xFF209ce1, 0xFF209ce2, 0xFF209ce2, 0xFF209ae0, 0xFF2199de, 0xFF1f99df, + 0xFF1d98e0, 0xFF1e97e0, 0xFF1f97e0, 0xFF1d96df, 0xFF1c95de, 0xFF1c94e0, 0xFF1c94e1, 0xFF1d93e1, + 0xFF1d92e0, 0xFF1b93de, 0xFF1a94dc, 0xFF1a93de, 0xFF1a93e0, 0xFF1992e0, 0xFF1891df, 0xFF188fdf, + 0xFF178edf, 0xFF168ede, 0xFF158edd, 0xFF148ddc, 0xFF138ddb, 0xFF138cdb, 0xFF138bdb, 0xFF128adb, + 0xFF1289db, 0xFF1288db, 0xFF1187db, 0xFF1186db, 0xFF1085db, 0xFF0f84da, 0xFF0e83d9, 0xFF0e83d9, + 0xFF0e83d9, 0xFF0e82d9, 0xFF0e81d8, 0xFF0e80d8, 0xFF0d7fd7, 0xFF0d7fd7, 0xFF0d7fd7, 0xFF0d7fd7, + 0xFF27a3e3, 0xFF2aa4e3, 0xFF2ea6e3, 0xFF2aa4e3, 0xFF26a2e3, 0xFF26a1e3, 0xFF25a1e3, 0xFF25a0e3, + 0xFF25a0e3, 0xFF25a0e3, 0xFF259fe3, 0xFF269fe3, 0xFF269ee4, 0xFF279ee1, 0xFF279edf, 0xFF259ee0, + 0xFF239ee1, 0xFF219ee2, 0xFF209ee4, 0xFF209de4, 0xFF219de3, 0xFF229be0, 0xFF2499dc, 0xFF2299de, + 0xFF1f98e0, 0xFF1d99e4, 0xFF1b9ae7, 0xFF1c98e2, 0xFF1c96dc, 0xFF1e94e3, 0xFF2092ea, 0xFF1d94e6, + 0xFF1a96e2, 0xFF1c96de, 0xFF1d95da, 0xFF1c94de, 0xFF1b94e1, 0xFF1a93e0, 0xFF1a92e0, 0xFF1991e0, + 0xFF1890e0, 0xFF1790df, 0xFF178fde, 0xFF168fde, 0xFF158edd, 0xFF148ddd, 0xFF138cdc, 0xFF138bdc, + 0xFF128adc, 0xFF1289dc, 0xFF1188dc, 0xFF1187dd, 0xFF1086dd, 0xFF0f85db, 0xFF0e83d9, 0xFF0e84da, + 0xFF0f84da, 0xFF0e83da, 0xFF0e82d9, 0xFF0e81d9, 0xFF0e80d8, 0xFF0e80d8, 0xFF0e80d8, 0xFF0e80d8, + 0xFF2aa7e5, 0xFF2da7e4, 0xFF31a8e3, 0xFF2ca6e3, 0xFF27a4e4, 0xFF27a3e4, 0xFF27a3e4, 0xFF27a3e4, + 0xFF26a2e4, 0xFF26a2e4, 0xFF27a1e5, 0xFF27a0e5, 0xFF27a0e6, 0xFF26a0e5, 0xFF25a0e4, 0xFF259fe4, + 0xFF259ee3, 0xFF239ee5, 0xFF229fe6, 0xFF229fe5, 0xFF229fe4, 0xFF13a5e6, 0xFF1b9fe8, 0xFF16a0e8, + 0xFF11a0e7, 0xFF129fef, 0xFF139ef7, 0xFF1b99ec, 0xFF179ae2, 0xFF149ce4, 0xFF1d98e5, 0xFF1c97e6, + 0xFF1b96e7, 0xFF1c98dc, 0xFF1d97df, 0xFF1c96e1, 0xFF1c94e2, 0xFF1b94e1, 0xFF1b93e1, 0xFF1a93e0, + 0xFF1a92e0, 0xFF1991e0, 0xFF1890e0, 0xFF1790df, 0xFF168fdf, 0xFF158ede, 0xFF158dde, 0xFF148cdd, + 0xFF138bdc, 0xFF128add, 0xFF1289dd, 0xFF1188de, 0xFF1187de, 0xFF0f85dc, 0xFF0d83da, 0xFF0f85db, + 0xFF1086db, 0xFF0f84db, 0xFF0f83da, 0xFF0e82da, 0xFF0e81da, 0xFF0e81da, 0xFF0e81da, 0xFF0e81da, + 0xFF2caae7, 0xFF30aae5, 0xFF34abe3, 0xFF2ea8e4, 0xFF29a6e5, 0xFF28a6e5, 0xFF28a5e5, 0xFF28a5e5, + 0xFF28a5e6, 0xFF28a4e6, 0xFF28a3e7, 0xFF28a2e7, 0xFF28a1e8, 0xFF25a2e9, 0xFF23a3ea, 0xFF25a0e8, + 0xFF279ee6, 0xFF259fe7, 0xFF23a0e9, 0xFF18a4f5, 0xFF0ea7ff, 0xFF1ba6de, 0xFF558ebb, 0xFF6f839c, + 0xFF89797e, 0xFF8d797c, 0xFF917979, 0xFF7f7b94, 0xFF5687af, 0xFF229bd6, 0xFF04a4fd, 0xFF109df4, + 0xFF1c97eb, 0xFF1c9ada, 0xFF1c98e4, 0xFF1c97e3, 0xFF1d95e2, 0xFF1c95e2, 0xFF1c94e2, 0xFF1c94e1, + 0xFF1b94e1, 0xFF1a93e1, 0xFF1a92e1, 0xFF1991e1, 0xFF1890e1, 0xFF178fe0, 0xFF158edf, 0xFF148dde, + 0xFF138cdd, 0xFF128bde, 0xFF128adf, 0xFF1289df, 0xFF1188e0, 0xFF0f85dd, 0xFF0d83da, 0xFF0f85db, + 0xFF1187dd, 0xFF1086dc, 0xFF0f84dc, 0xFF0e83db, 0xFF0e81db, 0xFF0e81db, 0xFF0e81db, 0xFF0e81db, + 0xFF30abe5, 0xFF36afe8, 0xFF34abe4, 0xFF2faae5, 0xFF2ba8e6, 0xFF36aee8, 0xFF26a6e8, 0xFF29a7e7, + 0xFF2ca8e7, 0xFF2da7e6, 0xFF2fa5e5, 0xFF2ca5e7, 0xFF29a4e9, 0xFF2ba5e5, 0xFF2ca5e2, 0xFF10aaef, + 0xFF13adf6, 0xFF23a3f8, 0xFF6091a5, 0xFFa6755d, 0xFFec5915, 0xFFff490c, 0xFFfa5504, 0xFFff590f, + 0xFFff5d1b, 0xFFff6116, 0xFFfa6412, 0xFFff550f, 0xFFff4b0d, 0xFFfb4918, 0xFFf54823, 0xFF8e737e, + 0xFF269eda, 0xFF06a2ff, 0xFF1d97e2, 0xFF1799ea, 0xFF1c97e4, 0xFF1a98e4, 0xFF1898e4, 0xFF1a96e3, + 0xFF1b95e3, 0xFF1a94e2, 0xFF1a93e0, 0xFF1992e1, 0xFF1891e2, 0xFF1790e1, 0xFF168fe0, 0xFF158fdf, + 0xFF138ede, 0xFF138ddf, 0xFF138ce0, 0xFF128be0, 0xFF1189e0, 0xFF1087de, 0xFF0f85db, 0xFF138ae0, + 0xFF0f87dc, 0xFF0f86dc, 0xFF0f85dc, 0xFF0f84dc, 0xFF0e83db, 0xFF0e83db, 0xFF0e83db, 0xFF0e83db, + 0xFF34abe2, 0xFF3cb4ec, 0xFF34ace5, 0xFF31abe6, 0xFF2daae8, 0xFF44b6eb, 0xFF24a7ea, 0xFF29aaea, + 0xFF2face9, 0xFF32a9e6, 0xFF35a7e3, 0xFF30a7e6, 0xFF2ba8ea, 0xFF25aaf0, 0xFF20adf6, 0xFF4d8ba7, + 0xFFb8674c, 0xFFff5510, 0xFFf7650c, 0xFFf86313, 0xFFfa611b, 0xFFf0671f, 0xFFfc6222, 0xFFfb6926, + 0xFFf96f29, 0xFFf67122, 0xFFf3721b, 0xFFf26b20, 0xFFf16424, 0xFFff5622, 0xFFff531f, 0xFFff4b17, + 0xFFff440e, 0xFFb1615b, 0xFF1f95e0, 0xFF129bf0, 0xFF1c9ae5, 0xFF189ae6, 0xFF159be7, 0xFF1898e6, + 0xFF1b95e5, 0xFF1b95e2, 0xFF1995e0, 0xFF1994e1, 0xFF1892e2, 0xFF1792e1, 0xFF1691e0, 0xFF1590df, + 0xFF148fdf, 0xFF148fe0, 0xFF148fe1, 0xFF128de1, 0xFF108be0, 0xFF1189de, 0xFF1186dd, 0xFF178fe4, + 0xFF0e87db, 0xFF0e87dc, 0xFF0f87dd, 0xFF0f85dc, 0xFF0e84dc, 0xFF0e84dc, 0xFF0e84dc, 0xFF0e84dc, + 0xFF36b1eb, 0xFF36b4f0, 0xFF2eafed, 0xFF2caeec, 0xFF2aadec, 0xFF41b4ef, 0xFF29abe9, 0xFF2cabe8, + 0xFF2fabe7, 0xFF31abe6, 0xFF32aae6, 0xFF2faae7, 0xFF2ca9e8, 0xFF25a7eb, 0xFF946a5f, 0xFFff3e06, + 0xFFf95618, 0xFFe27312, 0xFFf87329, 0xFFf77427, 0xFFf77626, 0xFFf27628, 0xFFf8712b, 0xFFf9772e, + 0xFFf97e30, 0xFFf77f2e, 0xFFf5812b, 0xFFf57b2c, 0xFFf5752d, 0xFFfd6a2b, 0xFFfb652a, 0xFFf65e2c, + 0xFFf1572e, 0xFFff4810, 0xFFff460f, 0xFF817680, 0xFF02a7f1, 0xFF2496ea, 0xFF199be4, 0xFF1b98e4, + 0xFF1d96e5, 0xFF1b96e2, 0xFF1a96e0, 0xFF1995e1, 0xFF1794e3, 0xFF1793e2, 0xFF1692e1, 0xFF1691e0, + 0xFF1590df, 0xFF1591e1, 0xFF1591e3, 0xFF138fe1, 0xFF108ce0, 0xFF128be0, 0xFF158ae0, 0xFF168de2, + 0xFF0f89dd, 0xFF0f88dd, 0xFF0f88dd, 0xFF0f86dd, 0xFF0f85dc, 0xFF0f85dc, 0xFF0f85dc, 0xFF0f85dc, + 0xFF5fc1e7, 0xFF57bee8, 0xFF4fbbe9, 0xFF4ebae6, 0xFF4ebae3, 0xFF51b6ee, 0xFF2eaee8, 0xFF2eade6, + 0xFF2fabe5, 0xFF2face7, 0xFF2eade9, 0xFF2eace7, 0xFF2daae5, 0xFF15b2ff, 0xFFec4310, 0xFFf15016, + 0xFFf75d1c, 0xFFf87123, 0xFFf9862a, 0xFFf6882d, 0xFFf48b31, 0xFFf48532, 0xFFf47f33, 0xFFf78535, + 0xFFfa8c37, 0xFFf88e39, 0xFFf7903a, 0xFFf88b38, 0xFFf98635, 0xFFf87e35, 0xFFf77635, 0xFFf76d34, + 0xFFf76532, 0xFFf85e31, 0xFFf95730, 0xFFff5125, 0xFFf65237, 0xFF03a5fd, 0xFF1e9be1, 0xFF1e98e3, + 0xFF1f96e5, 0xFF1c97e2, 0xFF1a97df, 0xFF1896e1, 0xFF1795e4, 0xFF1794e3, 0xFF1793e2, 0xFF1692e1, + 0xFF1692e0, 0xFF1693e2, 0xFF1794e4, 0xFF1391e2, 0xFF0f8ee0, 0xFF148ee1, 0xFF198ee3, 0xFF148ce1, + 0xFF0f8bde, 0xFF0f8ade, 0xFF0f89de, 0xFF0f88dd, 0xFF0f86dd, 0xFF0f86dd, 0xFF0f86dd, 0xFF0f86dd, + 0xFF3cb6ee, 0xFF36b4ef, 0xFF30b2f0, 0xFF30b1ee, 0xFF2fb1ec, 0xFF38b0ef, 0xFF2eaee9, 0xFF2faee8, + 0xFF31ade6, 0xFF2fafe8, 0xFF2eb1ea, 0xFF31adec, 0xFF29afee, 0xFF30aac8, 0xFFff3d05, 0xFFfa501a, + 0xFFf96021, 0xFFf87428, 0xFFf7882f, 0xFFfa9638, 0xFFf59b38, 0xFFf5973b, 0xFFf6923e, 0xFFf89440, + 0xFFfa9742, 0xFFfa9a44, 0xFFfa9d46, 0xFFf99845, 0xFFf89444, 0xFFf98d43, 0xFFfa8641, 0xFFf97d3f, + 0xFFf9743d, 0xFFf77039, 0xFFf56d35, 0xFFff6122, 0xFFbf6c63, 0xFF129eef, 0xFF229ae8, 0xFF1c99ed, + 0xFF179ce4, 0xFF1498f0, 0xFF1b94e1, 0xFF1a96e2, 0xFF1998e3, 0xFF1897e4, 0xFF1896e5, 0xFF1895e4, + 0xFF1993e2, 0xFF1792e1, 0xFF1590df, 0xFF1692e2, 0xFF1793e5, 0xFF1490e4, 0xFF128ee2, 0xFF118de3, + 0xFF108de3, 0xFF118bde, 0xFF1289d9, 0xFF0f88e2, 0xFF0c89dd, 0xFF1085e0, 0xFF0987e4, 0xFF0987e4, + 0xFF40b5e9, 0xFF3bb4e9, 0xFF37b2ea, 0xFF37b2e9, 0xFF38b1e8, 0xFF33b0ea, 0xFF2eaeeb, 0xFF30afe9, + 0xFF33afe8, 0xFF30b2ea, 0xFF2eb5ec, 0xFF34aff2, 0xFF25b4f7, 0xFF8d7f86, 0xFFf64f00, 0xFFed5c1e, + 0xFFfa6326, 0xFFf7762d, 0xFFf58a35, 0xFFfea242, 0xFFf7ab3f, 0xFFf7a843, 0xFFf7a548, 0xFFf9a34a, + 0xFFfaa24c, 0xFFfba64f, 0xFFfcaa52, 0xFFf9a652, 0xFFf7a252, 0xFFfa9c50, 0xFFfd974e, 0xFFfc8d4b, + 0xFFfb8348, 0xFFf68341, 0xFFf1823a, 0xFFf5732c, 0xFF718cac, 0xFF179af0, 0xFF2599ef, 0xFF2697e9, + 0xFF269bc6, 0xFF1696f1, 0xFF1d91e3, 0xFF1c96e3, 0xFF1b9be3, 0xFF1a99e6, 0xFF1998e9, 0xFF1b97e7, + 0xFF1c95e5, 0xFF1891df, 0xFF138dda, 0xFF1992e2, 0xFF1e98ea, 0xFF1592e6, 0xFF0b8de2, 0xFF0e8ee5, + 0xFF108fe9, 0xFF128cdf, 0xFF1489d4, 0xFF0e88e6, 0xFF088cdc, 0xFF1184e4, 0xFF0488ec, 0xFF0488ec, + 0xFF3eb6ea, 0xFF3bb5eb, 0xFF38b4eb, 0xFF38b4eb, 0xFF38b3eb, 0xFF35b2eb, 0xFF33b1ec, 0xFF34b1eb, + 0xFF35b1ea, 0xFF32b3e9, 0xFF30b5e9, 0xFF34b0f0, 0xFF23b6f8, 0xFFc56044, 0xFFf9540c, 0xFFf26322, + 0xFFf77029, 0xFFf77d2f, 0xFFf78b35, 0xFFfba142, 0xFFf6b046, 0xFFfbb44f, 0xFFf7b051, 0xFFf9af54, + 0xFFfbad56, 0xFFfcb25a, 0xFFfeb75d, 0xFFfab35f, 0xFFf6b061, 0xFFfaac5d, 0xFFfda95a, 0xFFfb9f55, + 0xFFf99551, 0xFFf7914b, 0xFFf68d45, 0xFFff7e23, 0xFF1ba5f0, 0xFF129ef4, 0xFF2896f1, 0xFF239fb1, + 0xFF6c9600, 0xFF3c9c82, 0xFF179ef8, 0xFF169cf4, 0xFF149de3, 0xFF169ae5, 0xFF1897e7, 0xFF1995e6, + 0xFF1a93e5, 0xFF1993e3, 0xFF1793e0, 0xFF1c98e6, 0xFF1a95e5, 0xFF1692e5, 0xFF138fe5, 0xFF138ceb, + 0xFF138be3, 0xFF0087e4, 0xFF007cf5, 0xFF1a86d3, 0xFF0d8cf1, 0xFF008fe2, 0xFF0d85ea, 0xFF0886f1, + 0xFF3cb7ec, 0xFF3bb7ed, 0xFF3ab6ed, 0xFF39b6ed, 0xFF38b5ed, 0xFF37b5ed, 0xFF37b4ed, 0xFF37b3ed, + 0xFF36b3ec, 0xFF34b4e9, 0xFF31b5e5, 0xFF35b1ef, 0xFF21b8fa, 0xFFfd4203, 0xFFfc581e, 0xFFf86a26, + 0xFFf47c2d, 0xFFf78431, 0xFFf98c36, 0xFFf8a041, 0xFFf6b54d, 0xFFfec05b, 0xFFf6bc5a, 0xFFf8ba5d, + 0xFFfbb861, 0xFFfdbe65, 0xFFffc469, 0xFFfbc16c, 0xFFf5bd70, 0xFFfabc6b, 0xFFfebb66, 0xFFfab160, + 0xFFf6a75a, 0xFFf89f55, 0xFFfa984f, 0xFFdf956f, 0xFF08a6fc, 0xFF259ddb, 0xFF159ff3, 0xFF4aa172, + 0xFF69a90d, 0xFF62a406, 0xFF5a981b, 0xFF34969b, 0xFF0e99ff, 0xFF1297f2, 0xFF1695e4, 0xFF1793e5, + 0xFF1892e5, 0xFF1995e6, 0xFF1a98e7, 0xFF209deb, 0xFF1593df, 0xFF1892e4, 0xFF1a91e9, 0xFF2095eb, + 0xFF259dd1, 0xFFd0f772, 0xFFc1f396, 0xFF0083f1, 0xFF1782a0, 0xFF3c7e2f, 0xFF1787cc, 0xFF0b8ada, + 0xFF3db9ed, 0xFF3cb8ed, 0xFF3bb8ed, 0xFF3ab7ed, 0xFF39b7ed, 0xFF39b7ed, 0xFF39b6ed, 0xFF3ab6ed, + 0xFF3ab6ed, 0xFF37b4ed, 0xFF34b2ec, 0xFF35abf3, 0xFF6e96b3, 0xFFff4601, 0xFFf86520, 0xFFf67329, + 0xFFf58131, 0xFFf78b37, 0xFFf9953e, 0xFFf8a649, 0xFFf8b854, 0xFFfcc260, 0xFFf8c465, 0xFFf9c36a, + 0xFFfac26e, 0xFFfac773, 0xFFfacb77, 0xFFfbcb7b, 0xFFfccb7e, 0xFFfac87b, 0xFFf8c578, 0xFFf9bc72, + 0xFFfbb46d, 0xFFf6b069, 0xFFfeaa57, 0xFF94a0a5, 0xFF13a1f3, 0xFF219df0, 0xFF199eff, 0xFF71c124, + 0xFF79b826, 0xFF72b21e, 0xFF6aaa24, 0xFF67a125, 0xFF649a19, 0xFF419d72, 0xFF1f9fcb, 0xFF1994ff, + 0xFF1399f1, 0xFF199cf4, 0xFF1ea0f8, 0xFF1b9cff, 0xFF1193f6, 0xFF1293f1, 0xFF1393ec, 0xFF0083ff, + 0xFF72cca0, 0xFFcbf982, 0xFFd0ffac, 0xFF79a046, 0xFF337700, 0xFF3a7c03, 0xFF0d8de2, 0xFF0d8edb, + 0xFF3fbbee, 0xFF3ebaed, 0xFF3db9ed, 0xFF3cb9ed, 0xFF3bb8ed, 0xFF3bb8ed, 0xFF3cb9ee, 0xFF3cb9ee, + 0xFF3db9ef, 0xFF3ab4f1, 0xFF37aff3, 0xFF32b3fe, 0xFFb48f7d, 0xFFff5907, 0xFFf37122, 0xFFf57c2b, + 0xFFf68735, 0xFFf7923d, 0xFFf89d45, 0xFFf9ac50, 0xFFf9bb5a, 0xFFf9c465, 0xFFfacd71, 0xFFfacd76, + 0xFFfacd7b, 0xFFf7cf80, 0xFFf4d286, 0xFFfcd689, 0xFFffd98c, 0xFFfbd48b, 0xFFf3cf8a, 0xFFf9c885, + 0xFFffc17f, 0xFFf5c27d, 0xFFffbc5e, 0xFF48abdc, 0xFF1e9deb, 0xFF1ea2e8, 0xFF1da8e5, 0xFF99d31c, + 0xFF8acb22, 0xFF82c427, 0xFF7abc2c, 0xFF75b429, 0xFF70ad25, 0xFF6dab17, 0xFF6ba908, 0xFF5ea912, + 0xFF519f54, 0xFF489b6d, 0xFF3e9887, 0xFF3b9592, 0xFF389880, 0xFF449663, 0xFF509446, 0xFF83b43c, + 0xFF4f851b, 0xFFafe187, 0xFF9fcc83, 0xFF368011, 0xFF43821c, 0xFF32853c, 0xFF0492f9, 0xFF1092dd, + 0xFF40bcee, 0xFF3fbcee, 0xFF3ebbee, 0xFF3dbaed, 0xFF3cbaed, 0xFF3cb9ed, 0xFF3cb9ec, 0xFF3cb9ec, + 0xFF3cb8ec, 0xFF3fb4f0, 0xFF43aff5, 0xFF0ebbe9, 0xFFffb897, 0xFFf7814d, 0xFFf57623, 0xFFf6812e, + 0xFFf88c39, 0xFFf89943, 0xFFf8a64d, 0xFFf8b257, 0xFFf9bd60, 0xFFfac96d, 0xFFfbd47b, 0xFFfad681, + 0xFFfad788, 0xFFfbd98e, 0xFFfbda93, 0xFFfae5a1, 0xFFfed692, 0xFFfadea0, 0xFFf9db98, 0xFFfad694, + 0xFFfbd090, 0xFFffd285, 0xFFffc778, 0xFF009afd, 0xFF26a8f2, 0xFF20a4f8, 0xFF53bea5, 0xFFa4da31, + 0xFF9dd638, 0xFF97d03a, 0xFF91ca3d, 0xFF8bc539, 0xFF85c035, 0xFF7dbe31, 0xFF74bc2d, 0xFF76b81c, + 0xFF77b027, 0xFF72ab25, 0xFF6da724, 0xFF6ba328, 0xFF68a31f, 0xFF58951a, 0xFF78b745, 0xFFbbf181, + 0xFF73ad4c, 0xFF417c15, 0xFF508b1e, 0xFF43861c, 0xFF498614, 0xFF17868b, 0xFF0b90f6, 0xFF168ee8, + 0xFF42beef, 0xFF41bdee, 0xFF40bcee, 0xFF3fbced, 0xFF3ebbed, 0xFF3dbaec, 0xFF3db9eb, 0xFF3cb8ea, + 0xFF3bb7e9, 0xFF39b9f0, 0xFF37bbf7, 0xFF50b5dc, 0xFFff9744, 0xFFfec49d, 0xFFf87a24, 0xFFf88530, + 0xFFf9913d, 0xFFf8a049, 0xFFf7af55, 0xFFf8b85d, 0xFFf9c065, 0xFFface75, 0xFFfcdb85, 0xFFfbde8d, + 0xFFfae195, 0xFFfee29b, 0xFFffe2a0, 0xFFfbe9a4, 0xFFffbe6b, 0xFFfdde9f, 0xFFffe8a6, 0xFFfbe3a3, + 0xFFf8dea0, 0xFFfdd899, 0xFFb6bdab, 0xFF119ff1, 0xFF1ea4e9, 0xFF1a9fff, 0xFF89d465, 0xFFb0e245, + 0xFFb0e04e, 0xFFacdc4e, 0xFFa7d94e, 0xFFa1d649, 0xFF9ad345, 0xFF97ce3d, 0xFF94c935, 0xFF8dc534, + 0xFF86c133, 0xFF7bbc32, 0xFF6fb731, 0xFF6db330, 0xFF6cae2e, 0xFF7eba3f, 0xFF70a531, 0xFF7bb54f, + 0xFF579a20, 0xFF5c9f2b, 0xFF519425, 0xFF80b965, 0xFF609a1d, 0xFF0390e3, 0xFF118ef2, 0xFF1c89f2, + 0xFF44c0ef, 0xFF43bfef, 0xFF42beee, 0xFF40bdee, 0xFF3fbcee, 0xFF3fbbed, 0xFF40baeb, 0xFF3eb9ed, + 0xFF3cb9ee, 0xFF37b9eb, 0xFF27bcf7, 0xFF949c8f, 0xFFfb9637, 0xFFf9bc7c, 0xFFf9b585, 0xFFf7994a, + 0xFFf69b43, 0xFFf6a64e, 0xFFf7b259, 0xFFf8bc66, 0xFFfac672, 0xFFfad380, 0xFFfae08d, 0xFFf9e698, + 0xFFf9eba2, 0xFFfeeaa6, 0xFFffeaab, 0xFFfcefa9, 0xFFfaba62, 0xFFfbdc99, 0xFFfff4b9, 0xFFfbecb2, + 0xFFf7e6ab, 0xFFffe5a3, 0xFF64b1d1, 0xFF199ff0, 0xFF269fe9, 0xFF0499f2, 0xFFe3f051, 0xFFd5ef58, + 0xFFc0e364, 0xFFbde165, 0xFFbae065, 0xFFb5de5d, 0xFFb0dc56, 0xFFaad74e, 0xFFa3d346, 0xFF9bd043, + 0xFF93cd3f, 0xFF8cc93e, 0xFF84c63c, 0xFF81c139, 0xFF7dbc36, 0xFF8bc746, 0xFF89c245, 0xFF63a02c, + 0xFF65aa2c, 0xFF5ea42d, 0xFF509626, 0xFFa4cf98, 0xFFd9eadd, 0xFFb9ddff, 0xFF389ef4, 0xFF008fd4, + 0xFF46c1ef, 0xFF44c0ef, 0xFF43bfef, 0xFF42beef, 0xFF40bdef, 0xFF42bced, 0xFF43baec, 0xFF40baf0, + 0xFF3dbaf4, 0xFF35b8e7, 0xFF17bdf7, 0xFFd97f50, 0xFFf79147, 0xFFf7a554, 0xFFffdbba, 0xFFf8a24d, + 0xFFf3a549, 0xFFf5ad53, 0xFFf7b55e, 0xFFf9c16f, 0xFFfbcc7f, 0xFFf9d88a, 0xFFf8e595, 0xFFf8eda2, + 0xFFf8f5ae, 0xFFfff3b2, 0xFFfff2b6, 0xFFfef5ae, 0xFFf4b659, 0xFFf9db93, 0xFFfeffcd, 0xFFfbf6c1, + 0xFFf7edb6, 0xFFfff2ac, 0xFF13a4f7, 0xFF16a5f0, 0xFF18a5e8, 0xFF56b4cd, 0xFFf1f271, 0xFFd5ef84, + 0xFFcfe67b, 0xFFcde77c, 0xFFcbe77c, 0xFFc9e672, 0xFFc7e567, 0xFFbce15f, 0xFFb1dd57, 0xFFa9dc51, + 0xFFa0da4b, 0xFF9dd749, 0xFF9ad447, 0xFF94cf43, 0xFF8fcb3f, 0xFF88c43c, 0xFF82be39, 0xFF72b430, + 0xFF63a928, 0xFF59a028, 0xFF4e9827, 0xFFa0c479, 0xFFfffbf7, 0xFF7fd3f5, 0xFF038fe2, 0xFF0e89e2, + 0xFF48c3ef, 0xFF46c2ef, 0xFF45c1f0, 0xFF43c0f0, 0xFF42bff0, 0xFF42beee, 0xFF43bdec, 0xFF41bcef, + 0xFF3fbcf2, 0xFF2fc0fe, 0xFF36bdfc, 0xFFf54c00, 0xFFff8a52, 0xFFfaa65e, 0xFFfdc48e, 0xFFfbc185, + 0xFFf5ae50, 0xFFf7b65e, 0xFFf9be6c, 0xFFfac978, 0xFFfbd485, 0xFFfede98, 0xFFffe8aa, 0xFFfdeeae, + 0xFFf9f5b2, 0xFFfcf6ba, 0xFFfff7c2, 0xFFfcf0b2, 0xFFf7cc6e, 0xFFfbde91, 0xFFfdfcca, 0xFFfffbd1, + 0xFFfffdc8, 0xFFcae4c8, 0xFF16a1f2, 0xFF1da4ef, 0xFF12a1f1, 0xFF9fd5b9, 0xFFeaf28c, 0xFFdcf095, + 0xFFd9eb90, 0xFFd9ec93, 0xFFd9ec95, 0xFFd6eb8c, 0xFFd4ea83, 0xFFc9e779, 0xFFbfe36f, 0xFFb8e368, + 0xFFb1e262, 0xFFafe05e, 0xFFaddf5a, 0xFFa3d952, 0xFF99d449, 0xFF8ecb41, 0xFF84c33a, 0xFF75b833, + 0xFF66ac2c, 0xFF5da329, 0xFF559927, 0xFF4b9421, 0xFF2499b9, 0xFF1593fe, 0xFF0993d8, 0xFF0f90d8, + 0xFF4ac5ef, 0xFF48c4f0, 0xFF46c2f0, 0xFF45c1f1, 0xFF43c0f1, 0xFF43bfef, 0xFF43bfed, 0xFF42beee, + 0xFF41bdf0, 0xFF38bbf0, 0xFF72a1b8, 0xFFff5d1e, 0xFFf97931, 0xFFf5a151, 0xFFf9ad61, 0xFFfee0bd, + 0xFFf8b758, 0xFFfabf69, 0xFFfcc87a, 0xFFfcd282, 0xFFfcdc8b, 0xFFfbde8f, 0xFFfbe193, 0xFFfbeba4, + 0xFFfbf5b5, 0xFFfaf8c2, 0xFFf9fcce, 0xFFf9ecb7, 0xFFfae183, 0xFFfee290, 0xFFfbfac8, 0xFFfdf8d8, + 0xFFfffccb, 0xFF8bcedc, 0xFF189fee, 0xFF25a3ee, 0xFF0b9dfb, 0xFFe8f6a5, 0xFFe4f1a6, 0xFFe4f0a6, + 0xFFe4efa6, 0xFFe5f1aa, 0xFFe6f2ad, 0xFFe3f1a6, 0xFFe0ef9e, 0xFFd7ec93, 0xFFcde987, 0xFFc8ea80, + 0xFFc2eb78, 0xFFc1ea73, 0xFFc0e96e, 0xFFb1e360, 0xFFa3dd53, 0xFF94d247, 0xFF86c83b, 0xFF78bc35, + 0xFF69b030, 0xFF62a52b, 0xFF5b9b27, 0xFF57920a, 0xFF0995fc, 0xFF0d96e5, 0xFF1091eb, 0xFF1091eb, + 0xFF4ac5f0, 0xFF49c4f0, 0xFF47c3f1, 0xFF45c2f1, 0xFF44c1f2, 0xFF41c1f2, 0xFF3fc1f2, 0xFF3fbff1, + 0xFF3fbcf0, 0xFF32c3fe, 0xFFbe7f6e, 0xFFfe6526, 0xFFf67b35, 0xFFf59a4d, 0xFFf8ab5c, 0xFFfbd0a0, + 0xFFf7c783, 0xFFfec16b, 0xFFfdd17f, 0xFFfbdb87, 0xFFf9e590, 0xFFf8ed9a, 0xFFf7f4a5, 0xFFfbea9a, + 0xFFffdf8e, 0xFFfce3a0, 0xFFf7e6b1, 0xFFfceecc, 0xFFfffbcb, 0xFFfff3c7, 0xFFfcf1c3, 0xFFfef5d2, + 0xFFfffcd3, 0xFF4bb5e7, 0xFF21a5ed, 0xFF1ca2ee, 0xFF3daae2, 0xFFeef6ac, 0xFFe6f2b1, 0xFFe8f2b5, + 0xFFe9f3b8, 0xFFeaf4ba, 0xFFebf5bc, 0xFFe8f3b6, 0xFFe6f2af, 0xFFe0f0a8, 0xFFdbeea2, 0xFFd6ef9a, + 0xFFd1f092, 0xFFc9ed82, 0xFFc1eb73, 0xFFb0e362, 0xFFa1dc51, 0xFF94d347, 0xFF88ca3e, 0xFF7bbf38, + 0xFF6eb433, 0xFF66a92e, 0xFF5da01b, 0xFF3d9448, 0xFF0a93f6, 0xFF0e94ec, 0xFF1193f0, 0xFF1193f0, + 0xFF4bc5f1, 0xFF4ac5f1, 0xFF48c4f1, 0xFF47c3f2, 0xFF45c3f2, 0xFF40c3f4, 0xFF3bc4f6, 0xFF3cbff3, + 0xFF3ebbf0, 0xFF2dcaff, 0xFFff5d25, 0xFFfe6d2f, 0xFFf37d39, 0xFFf59348, 0xFFf8a958, 0xFFf7c083, + 0xFFf7d7ae, 0xFFffc36d, 0xFFffda84, 0xFFfbe48c, 0xFFf7ee94, 0xFFf8ed9e, 0xFFfaeca7, 0xFFf9f1b4, + 0xFFf8f6c1, 0xFFfcf6c8, 0xFFfff6d0, 0xFFfef2d3, 0xFFfcf4ba, 0xFFfffee8, 0xFFf7fdea, 0xFFfdfde3, + 0xFFfffcdc, 0xFF0b9df1, 0xFF2aaaed, 0xFF1baaf6, 0xFF80c8da, 0xFFfdffbb, 0xFFe8f2bd, 0xFFebf4c4, + 0xFFeff7cb, 0xFFeff7cb, 0xFFeff7cb, 0xFFedf6c5, 0xFFebf5c0, 0xFFeaf4be, 0xFFe8f3bd, 0xFFe4f4b4, + 0xFFe0f6ab, 0xFFd0f191, 0xFFc1ec77, 0xFFb0e463, 0xFF9edb4e, 0xFF95d448, 0xFF8bcc42, 0xFF7fc23b, + 0xFF73b935, 0xFF6aac31, 0xFF60a510, 0xFF229687, 0xFF0b91f1, 0xFF0e93f3, 0xFF1294f5, 0xFF1294f5, + 0xFF4cc6f1, 0xFF4bc5f2, 0xFF49c5f2, 0xFF47c4f2, 0xFF46c4f2, 0xFF43c4f1, 0xFF40c4f0, 0xFF42c0f3, + 0xFF39c1f6, 0xFF5eacca, 0xFFfb591e, 0xFFf36e31, 0xFFf88135, 0xFFfb923f, 0xFFfbaf5e, 0xFFffc373, + 0xFFfde2ba, 0xFFffcd75, 0xFFffd372, 0xFFffe584, 0xFFfff796, 0xFFfef4a2, 0xFFfdf1ae, 0xFFfff8c2, + 0xFFfcf8cd, 0xFFfef8d2, 0xFFfff9d6, 0xFFfef6e1, 0xFFfcf5dd, 0xFFfffbee, 0xFFfbfce8, 0xFFfffce0, + 0xFFb2e0e8, 0xFF19a4f0, 0xFF26abec, 0xFF16a8f6, 0xFFc2e4d8, 0xFFf9fac5, 0xFFeff6cb, 0xFFf0f7ce, + 0xFFf1f8d2, 0xFFf1f8d1, 0xFFf2f9d1, 0xFFf1f9cd, 0xFFf1f9ca, 0xFFf2fbca, 0xFFf4fdca, 0xFFe7f8b6, + 0xFFdaf3a2, 0xFFcbef8a, 0xFFbcec71, 0xFFb0e661, 0xFFa5e151, 0xFF9ad949, 0xFF8fd240, 0xFF83c73b, + 0xFF77bc35, 0xFF6ab31d, 0xFF5ea905, 0xFF138dea, 0xFF1193ef, 0xFF1093f0, 0xFF0f93f0, 0xFF0f93f0, + 0xFF4dc6f2, 0xFF4cc6f2, 0xFF4ac5f3, 0xFF48c5f3, 0xFF47c5f3, 0xFF46c4ef, 0xFF46c4eb, 0xFF48c0f3, + 0xFF34c7fb, 0xFF989591, 0xFFfc6428, 0xFFf1773b, 0xFFfc8432, 0xFFff9135, 0xFFffb564, 0xFFffbe5a, + 0xFFf3ddb6, 0xFFccd097, 0xFFb4cea5, 0xFFb0d3b1, 0xFFabd7bd, 0xFFc3e1bf, 0xFFdaebc1, 0xFFf5fdc7, + 0xFFffffbd, 0xFFfffecd, 0xFFfffcdc, 0xFFfffce0, 0xFFfbfce5, 0xFFfdfbe6, 0xFFfffae7, 0xFFfffbdd, + 0xFF61c4f4, 0xFF26aaee, 0xFF22abec, 0xFF10a7f6, 0xFFffffd7, 0xFFf5f5d0, 0xFFf6fad9, 0xFFf4f9d9, + 0xFFf2f9da, 0xFFf3fad8, 0xFFf4fbd7, 0xFFf5fcd5, 0xFFf7fdd4, 0xFFf3face, 0xFFf0f7c8, 0xFFe2f4b0, + 0xFFd4f199, 0xFFc5ee82, 0xFFb7eb6b, 0xFFb1e95f, 0xFFabe754, 0xFF9fdf49, 0xFF94d83f, 0xFF87cc3a, + 0xFF7bc034, 0xFF6bb425, 0xFF5ba332, 0xFF0495f9, 0xFF1795ee, 0xFF1293ed, 0xFF0c91eb, 0xFF0c91eb, + 0xFF4fc8f3, 0xFF4dc8f3, 0xFF4cc8f4, 0xFF4bc8f4, 0xFF49c8f4, 0xFF47c5f2, 0xFF45c2ef, 0xFF42c2f8, + 0xFF34c8ff, 0xFFdf6746, 0xFFff632a, 0xFFff701b, 0xFFe18b53, 0xFFa4a185, 0xFF63c1cd, 0xFF26c0ff, + 0xFF2ab8ff, 0xFF25b5f1, 0xFF27b7f9, 0xFF26b5f6, 0xFF23b3f2, 0xFF24b5fa, 0xFF25b7ff, 0xFF189ddf, + 0xFF43bbf4, 0xFF9edae8, 0xFFf9f9dc, 0xFFf3fbe6, 0xFFffffea, 0xFFfdffe6, 0xFFfafce2, 0xFFffffff, + 0xFF1ea8ef, 0xFF1ca8f1, 0xFF1ba8f2, 0xFF5bc4f1, 0xFFffffe7, 0xFFfbf9e1, 0xFFfbfce3, 0xFFf8fbe0, + 0xFFf5fadd, 0xFFf5fbdb, 0xFFf5fbda, 0xFFf6fcd7, 0xFFf6fdd3, 0xFFf0f8c9, 0xFFebf4be, 0xFFdff2a9, + 0xFFd4f094, 0xFFc7f47b, 0xFFbaf862, 0xFFb0ef58, 0xFFa6e64e, 0xFFa3e248, 0xFF98d73a, 0xFF8acd38, + 0xFF7bc435, 0xFF70b821, 0xFF3b9c84, 0xFF0d93f4, 0xFF1394ed, 0xFF1193e9, 0xFF0f92e6, 0xFF0f92e6, + 0xFF50c9f4, 0xFF4fcaf4, 0xFF4ecaf5, 0xFF4dcaf5, 0xFF4ccaf6, 0xFF48c5f4, 0xFF45c0f3, 0xFF47c2ef, + 0xFF4ac4eb, 0xFFff521f, 0xFFa79a92, 0xFF51b7e6, 0xFF28c7ff, 0xFF2cc4f9, 0xFF31c1f1, 0xFF3fbbf0, + 0xFF37c0ef, 0xFF39b9f0, 0xFF3bb3f1, 0xFF38b5f4, 0xFF36b7f7, 0xFF32b9f0, 0xFF2fbbe8, 0xFF2fb8eb, + 0xFF2fb5ed, 0xFF20acf3, 0xFF10a3fa, 0xFF70c9f3, 0xFFf5f9df, 0xFFf6fbde, 0xFFf6fdde, 0xFFd8ebe4, + 0xFF11a5ee, 0xFF2db2f5, 0xFF14a5f8, 0xFFa5e2ec, 0xFFfffff8, 0xFFfffef3, 0xFFfffded, 0xFFfcfde6, + 0xFFf8fce0, 0xFFf7fcde, 0xFFf6fcdd, 0xFFf6fcd8, 0xFFf5fdd3, 0xFFedf7c4, 0xFFe5f1b4, 0xFFe5f5b8, + 0xFFe4f9bb, 0xFFecfed2, 0xFFf3ffe9, 0xFFedfedb, 0xFFe8f9cd, 0xFFcaef89, 0xFF9cd636, 0xFF84c72e, + 0xFF6bb826, 0xFF6cb315, 0xFF1a95d6, 0xFF1591ef, 0xFF1093eb, 0xFF1193e6, 0xFF1294e1, 0xFF1294e1, + 0xFF52cbf4, 0xFF50caf4, 0xFF4ecaf4, 0xFF4ccaf3, 0xFF4ac9f3, 0xFF48c8f5, 0xFF46c7f6, 0xFF40bfed, + 0xFF41bfeb, 0xFF41d4f9, 0xFF33c9fc, 0xFF2fc9ff, 0xFF42c3ec, 0xFF40c3f4, 0xFF3ec3fc, 0xFF35bbf4, + 0xFF33bbf3, 0xFF49bdf7, 0xFF39b7f9, 0xFF37b7f6, 0xFF35b7f2, 0xFF2eb5f4, 0xFF28b3f5, 0xFF2fbbf8, + 0xFF2fbaf2, 0xFF30b5f2, 0xFF31b0f1, 0xFF1facf6, 0xFF0dabed, 0xFF7fd2ed, 0xFFffffe6, 0xFF80d9d2, + 0xFF2faaf8, 0xFF1dafec, 0xFF03aae6, 0xFFfff8ff, 0xFFfffffe, 0xFFfffff9, 0xFFfffdf4, 0xFFfdfeeb, + 0xFFfbfee3, 0xFFf9fde1, 0xFFf7fce0, 0xFFf5fdd8, 0xFFf4fdcf, 0xFFf5fce2, 0xFFf6fde8, 0xFFf3fde8, + 0xFFf1fde9, 0xFFebfdd3, 0xFFe6fdbe, 0xFFe0f8ba, 0xFFdaf2b7, 0xFFeafcd2, 0xFFf2fde6, 0xFFb7de8d, + 0xFF84c73d, 0xFF9ab848, 0xFF14a1f9, 0xFF0494f3, 0xFF1094ef, 0xFF1095ec, 0xFF1095e9, 0xFF1095e9, + 0xFF54ccf5, 0xFF51cbf4, 0xFF4ecaf3, 0xFF4cc9f2, 0xFF49c8f1, 0xFF48cbf5, 0xFF48cef9, 0xFF40c4f3, + 0xFF49cafc, 0xFF40c2f1, 0xFF47caf5, 0xFF46c7f4, 0xFF46c4f3, 0xFF39b5ee, 0xFF2ca5e8, 0xFF2eb1e1, + 0xFF56c1ea, 0xFF6dc9e9, 0xFF37c2e5, 0xFF51caeb, 0xFF6bd2f1, 0xFF74d1f5, 0xFF7dcff9, 0xFF56c7f8, + 0xFF1fafe8, 0xFF25b1ee, 0xFF2cb3f4, 0xFF3eb5f9, 0xFF2bb3ee, 0xFF1baff5, 0xFF32b5f0, 0xFF3fb2f9, + 0xFF26a9f2, 0xFF1faeeb, 0xFF3fb8f4, 0xFFfcfff3, 0xFFffffff, 0xFFffffff, 0xFFfffefb, 0xFFfefff1, + 0xFFfeffe6, 0xFFfbffe5, 0xFFf8fde3, 0xFFf5fdd7, 0xFFf3fecb, 0xFFf5fbeb, 0xFFf7feee, 0xFFf2fdde, + 0xFFedfccf, 0xFFe3f9b0, 0xFFd9f692, 0xFFd2f48b, 0xFFccf184, 0xFFceee97, 0xFFd0eaa9, 0xFFdaebc1, + 0xFFf4fbe9, 0xFF7fc679, 0xFF5ac1ff, 0xFF1aa1eb, 0xFF1195f2, 0xFF0f96f2, 0xFF0e97f2, 0xFF0e97f2, + 0xFF54cdf5, 0xFF52ccf4, 0xFF4fcbf3, 0xFF4dc9f3, 0xFF4ac8f2, 0xFF49c6f2, 0xFF47c4f2, 0xFF49d2f3, + 0xFF46c8f3, 0xFF4dc5fc, 0xFF2c9add, 0xFF1883cd, 0xFF046cbe, 0xFF0080c5, 0xFF0f96d4, 0xFF2eaddb, + 0xFF60c6eb, 0xFF76cdef, 0xFF51caea, 0xFF69d2f0, 0xFF81daf5, 0xFF9ae4f7, 0xFFb3eff9, 0xFFcffaff, + 0xFFe3feff, 0xFF9ae1ff, 0xFF48bcf7, 0xFF11b5dd, 0xFF32aef0, 0xFF28acfc, 0xFF31b2f3, 0xFF34b1f6, + 0xFF25adf0, 0xFF26acf6, 0xFF98d1fc, 0xFFfffdf8, 0xFFffffff, 0xFFfffffb, 0xFFfefff4, 0xFFfdffee, + 0xFFfcfde7, 0xFFfbfee4, 0xFFfaffe0, 0xFFf8fde7, 0xFFf7fcef, 0xFFf3fbeb, 0xFFeffdd9, 0xFFe9fbc2, + 0xFFe3f9ac, 0xFFd9f49b, 0xFFceef8b, 0xFFc1ea76, 0xFFb4e562, 0xFFabdd5a, 0xFFa2d261, 0xFFc1e98e, + 0xFFdbe8b9, 0xFF96d4ff, 0xFF8ed0fa, 0xFF42aeee, 0xFF1095f1, 0xFF1096f1, 0xFF0f96f1, 0xFF0f96f1, + 0xFF55cef5, 0xFF53ccf4, 0xFF50cbf4, 0xFF4ecaf4, 0xFF4cc8f4, 0xFF51caf7, 0xFF57cbfa, 0xFF45c0ea, + 0xFF1a75c7, 0xFF0058ad, 0xFF015bb4, 0xFF066fc0, 0xFF0b84cd, 0xFF0093ce, 0xFF11a7e0, 0xFF3eb9e6, + 0xFF6bcbeb, 0xFF7ed1f6, 0xFF6cd3f0, 0xFF82dbf4, 0xFF98e3f9, 0xFFa5ecf7, 0xFFb2f4f5, 0xFFc7f7f9, + 0xFFddfafd, 0xFFf2ffff, 0xFFf8fff6, 0xFFbcebfe, 0xFF22b4f2, 0xFF29afff, 0xFF2fb0f7, 0xFF29b1f2, + 0xFF23b1ee, 0xFF1aa7fa, 0xFFcae6f4, 0xFFf7f8f4, 0xFFfeffff, 0xFFfefff7, 0xFFfeffed, 0xFFfcffeb, + 0xFFfbfae9, 0xFFfbfee3, 0xFFfbffdc, 0xFFfbffe9, 0xFFfbfff7, 0xFFf1fedd, 0xFFe7fbc3, 0xFFe0f6b4, + 0xFFd8f0a5, 0xFFceec94, 0xFFc4e884, 0xFFb8e678, 0xFFace36c, 0xFFa0df53, 0xFF94d455, 0xFF80bd41, + 0xFFd2e599, 0xFF2ca1f4, 0xFF30a2f6, 0xFF209cf3, 0xFF1096f1, 0xFF1096f1, 0xFF1096f1, 0xFF1096f1, + 0xFF55cef4, 0xFF53cdf4, 0xFF51cbf5, 0xFF50cbf5, 0xFF4ecaf6, 0xFF4dc9f4, 0xFF54d0fa, 0xFF2b86ce, + 0xFF0752b1, 0xFF045fb9, 0xFF0a74c9, 0xFF0882ce, 0xFF0691d4, 0xFF02a0d5, 0xFF24b5e7, 0xFF4cc4ea, + 0xFF74d3ee, 0xFF83d9f5, 0xFF7fddf4, 0xFF93e4f6, 0xFFa8ecf9, 0xFFb6f2f9, 0xFFc3f9f9, 0xFFd3fafb, + 0xFFe3fcfc, 0xFFedfefb, 0xFFf0f9f3, 0xFFffffff, 0xFFfffdff, 0xFF7edcef, 0xFF26adfd, 0xFF2aaff7, + 0xFF2db2f2, 0xFF34b1e0, 0xFF09a7f7, 0xFF8dd3f5, 0xFFfdfbf9, 0xFFfffff6, 0xFFfdffeb, 0xFFfcffe6, + 0xFFfcfce0, 0xFFf9fcde, 0xFFf7fcdd, 0xFFfcffef, 0xFFf9fdec, 0xFFe8f5d0, 0xFFdff5bd, 0xFFd9f1ad, + 0xFFd2ed9d, 0xFFc5e97e, 0xFFb8e26d, 0xFFabdd5e, 0xFF9fd74f, 0xFF98c95f, 0xFF92c735, 0xFF8bc942, + 0xFF80b34d, 0xFF009bf2, 0xFF1894f8, 0xFF1595f5, 0xFF1397f2, 0xFF1296f1, 0xFF1195f0, 0xFF1195f0, + 0xFF56cff4, 0xFF54cdf5, 0xFF52ccf5, 0xFF51cbf7, 0xFF51cbf9, 0xFF49c8f1, 0xFF51d5fa, 0xFF1662c1, + 0xFF005cbb, 0xFF0874cd, 0xFF037cce, 0xFF028dd4, 0xFF019edb, 0xFF09aedc, 0xFF37c2ee, 0xFF5acfef, + 0xFF7edcf0, 0xFF88e1f4, 0xFF92e6f8, 0xFFa5eef8, 0xFFb9f5f9, 0xFFc7f9fb, 0xFFd5fdfe, 0xFFdffdfc, + 0xFFe9fdfa, 0xFFf0fefe, 0xFFf8ffff, 0xFFfafffe, 0xFFfdfffc, 0xFFfdfbff, 0xFF1db0e8, 0xFF2ab1ee, + 0xFF37b2f5, 0xFF25b9f7, 0xFF29b4f8, 0xFF22aff5, 0xFF1baaf2, 0xFF9fd7f6, 0xFFfdffea, 0xFFfcfee0, + 0xFFfcfdd7, 0xFFf8fada, 0xFFf4f7dd, 0xFFfdfef5, 0xFFf6fae1, 0xFFdfecc3, 0xFFd8efb6, 0xFFd2eca6, + 0xFFccea95, 0xFFbce567, 0xFFabdb56, 0xFF9fd344, 0xFF92cb33, 0xFF85c824, 0xFF79b46a, 0xFF3a9eaf, + 0xFF0c97ff, 0xFF1994f9, 0xFF0f9bee, 0xFF139af0, 0xFF1699f3, 0xFF1497f1, 0xFF1295ef, 0xFF1295ef, + 0xFF58d0f5, 0xFF56cef5, 0xFF53cdf4, 0xFF53ccf6, 0xFF52cbf8, 0xFF53d6fb, 0xFF4fc8fc, 0xFF004cad, + 0xFF096fca, 0xFF0b80d4, 0xFF0588d5, 0xFF0598db, 0xFF05a8e1, 0xFF18b6e6, 0xFF3fc8f2, 0xFF63d3f3, + 0xFF86dff5, 0xFF91e4f7, 0xFF9ce9fa, 0xFFaef0f9, 0xFFc0f7f9, 0xFFcbfafb, 0xFFd7fdfd, 0xFFdefdfc, + 0xFFe6fefb, 0xFFf0fffe, 0xFFfaffff, 0xFFf2fefb, 0xFFfefffd, 0xFFc6e9fb, 0xFF1eb0ec, 0xFF30b4f6, + 0xFF30b7f8, 0xFF19a8f7, 0xFF26b0f0, 0xFF22aef3, 0xFF1eabf5, 0xFF27aafa, 0xFF1ca6f6, 0xFF7dcdea, + 0xFFdff4dd, 0xFFeaffb0, 0xFFfdfeed, 0xFFffffef, 0xFFfcf9d3, 0xFFedeeb4, 0xFFe6e9ac, 0xFFd9e68a, + 0xFFcbe367, 0xFFb9e153, 0xFFa6dd4d, 0xFF75c57f, 0xFF43adb0, 0xFF229bf3, 0xFF0a9cff, 0xFF0998f6, + 0xFF109cef, 0xFF189aee, 0xFF149ded, 0xFF159bf0, 0xFF1599f2, 0xFF1397f0, 0xFF1195ee, 0xFF1195ee, + 0xFF5ad1f6, 0xFF57cff5, 0xFF54cef4, 0xFF54cdf6, 0xFF53cbf8, 0xFF4dd3f4, 0xFF2c9add, 0xFF045ec1, + 0xFF0572c9, 0xFF0683d2, 0xFF0794dc, 0xFF08a2e2, 0xFF08b1e8, 0xFF28bfef, 0xFF48cef6, 0xFF6bd8f8, + 0xFF8fe3fa, 0xFF9be8fa, 0xFFa6edfb, 0xFFb7f3fb, 0xFFc7f9fa, 0xFFd0fbfc, 0xFFd9fdfd, 0xFFdefefd, + 0xFFe2fffc, 0xFFeffffe, 0xFFfcffff, 0xFFebfef7, 0xFFfffffe, 0xFF8fd7f8, 0xFF1eb0f1, 0xFF2eb0f6, + 0xFF18abec, 0xFFe0f7fd, 0xFF24ade9, 0xFF23acf1, 0xFF21acf8, 0xFF26aef7, 0xFF2cb0f6, 0xFF1aa9f5, + 0xFF08a3f4, 0xFF22a7f9, 0xFF4cc2f2, 0xFF6dcdef, 0xFF7ec9db, 0xFF7fcac2, 0xFF81c6c6, 0xFF61bccb, + 0xFF41b3d0, 0xFF24a7e9, 0xFF089bff, 0xFF119dff, 0xFF1a9fff, 0xFF0f99e9, 0xFF149cf9, 0xFF159cf7, + 0xFF159cf5, 0xFF179df1, 0xFF199eed, 0xFF179cef, 0xFF1599f1, 0xFF1397ef, 0xFF1195ed, 0xFF1195ed, + 0xFF5cd2f6, 0xFF59d0f5, 0xFF55cff3, 0xFF54cdf5, 0xFF53ccf8, 0xFF51d5f6, 0xFF167bcf, 0xFF0467c6, + 0xFF067bcf, 0xFF068bd7, 0xFF059cdf, 0xFF08a9e5, 0xFF0ab6eb, 0xFF2bc4f1, 0xFF4cd2f7, 0xFF6ddbf9, + 0xFF8ee5fa, 0xFF9deafb, 0xFFaceffb, 0xFFbdf5fb, 0xFFcefbfa, 0xFFd5fbfc, 0xFFdcfcfd, 0xFFdcfefd, + 0xFFddfffd, 0xFFe4fffd, 0xFFeafffd, 0xFFfffffe, 0xFFffffff, 0xFF27c0de, 0xFF26b5f6, 0xFF1fb0f9, + 0xFF4dc6ff, 0xFFfff9ef, 0xFFfefffa, 0xFF8bd8f7, 0xFF18a7f3, 0xFF1daaf4, 0xFF23acf6, 0xFF22acf3, + 0xFF22abf0, 0xFF1aa3f2, 0xFF1aa6ee, 0xFF18a8f5, 0xFF0ea2f3, 0xFF11a4f2, 0xFF14a4ff, 0xFF15a3fc, + 0xFF16a3fa, 0xFF17a2f3, 0xFF19a2ec, 0xFF0e99fe, 0xFF169bed, 0xFF00a1ff, 0xFF2b9de8, 0xFF61b5b0, + 0xFF109af7, 0xFF149cf2, 0xFF189eed, 0xFF169cef, 0xFF149af0, 0xFF1298ee, 0xFF1096ec, 0xFF1096ec, + 0xFF5fd3f7, 0xFF5bd2f5, 0xFF56d0f3, 0xFF55cef5, 0xFF53cdf7, 0xFF56d8f8, 0xFF005cc0, 0xFF0370cb, + 0xFF0785d6, 0xFF0594dc, 0xFF04a3e2, 0xFF08afe8, 0xFF0cbcee, 0xFF2ec8f3, 0xFF50d5f9, 0xFF6fdefa, + 0xFF8de7fb, 0xFF9fecfb, 0xFFb1f2fb, 0xFFc3f7fb, 0xFFd4fcfa, 0xFFd9fcfc, 0xFFdefcfd, 0xFFdbfdfd, + 0xFFd9fffd, 0xFFd9fdfb, 0xFFd9fcfa, 0xFFe5fafa, 0xFFa4eaf7, 0xFF2badfb, 0xFF2fb9fa, 0xFF1aaeed, + 0xFF99dbf8, 0xFFffffff, 0xFFfefdfc, 0xFFfffefd, 0xFFfffffd, 0xFF8cd4fa, 0xFF19a9f6, 0xFF18a9f7, + 0xFF16aaf9, 0xFF1aa7f3, 0xFF1ea5ee, 0xFF1fa7f2, 0xFF21a9f6, 0xFF1ea7f7, 0xFF1ba5f7, 0xFF17a4f9, + 0xFF12a2fb, 0xFF0b9dfd, 0xFF0399fe, 0xFF26a2fa, 0xFF6fc0b0, 0xFFcfca5e, 0xFFffe528, 0xFF74b4b3, + 0xFF0b98fa, 0xFF119af4, 0xFF179dee, 0xFF159cee, 0xFF139aef, 0xFF1198ed, 0xFF0f96eb, 0xFF0f96eb, + 0xFF5dd1f6, 0xFF5bd2f5, 0xFF58d2f4, 0xFF53cef4, 0xFF56d2fb, 0xFF40b2e6, 0xFF0164c6, 0xFF0376cf, + 0xFF0487d7, 0xFF0296dd, 0xFF01a4e4, 0xFF04b1ea, 0xFF07bdf1, 0xFF1bc8f2, 0xFF43d5fc, 0xFF64ddfb, + 0xFF85e6fb, 0xFF98ebfc, 0xFFacf1fd, 0xFFbef9ff, 0xFFcfffff, 0xFFcffdff, 0xFFcff9fb, 0xFFd2fefe, + 0xFFd5ffff, 0xFFc6f9ff, 0xFFb8efff, 0xFF5ad7d9, 0xFF40b9e9, 0xFF2fb9ff, 0xFF2bb2f0, 0xFF28afeb, + 0xFFdef0f2, 0xFFffffff, 0xFFfeffff, 0xFFfffefe, 0xFFfffefa, 0xFFfffffa, 0xFFfffff9, 0xFFc2e8f0, + 0xFF84cde7, 0xFF53bbe9, 0xFF22a9eb, 0xFF14a1ff, 0xFF069ff8, 0xFF0fa0f8, 0xFF19a3eb, 0xFF43b1e1, + 0xFF6ec2c9, 0xFFb0d79a, 0xFFf2eb6b, 0xFFebee32, 0xFFf8e647, 0xFFffe23a, 0xFFfde142, 0xFF0098f4, + 0xFF19a1fc, 0xFF169ef7, 0xFF129bf1, 0xFF139af1, 0xFF149af0, 0xFF1298ee, 0xFF1096ec, 0xFF1096ec, + 0xFF5ccff6, 0xFF5bd2f6, 0xFF5ad4f6, 0xFF52cdf2, 0xFF5ad6fe, 0xFF298cd5, 0xFF026ccc, 0xFF027bd2, + 0xFF0189d8, 0xFF0097df, 0xFF00a6e6, 0xFF00b2ed, 0xFF02bef4, 0xFF09c7f1, 0xFF35d5ff, 0xFF59ddfd, + 0xFF7ce5fb, 0xFF91eafd, 0xFFa6f0ff, 0xFFb1f2ff, 0xFFbbf5ff, 0xFFbef5fc, 0xFFc1f6f9, 0xFFc1f7f7, + 0xFFc1f9f4, 0xFFc7fdfc, 0xFFcdffff, 0xFFc2f9f8, 0xFF5acdf4, 0xFF39b1f3, 0xFF38baf5, 0xFF2ab4f7, + 0xFFfcfbf8, 0xFFfdfeff, 0xFFfeffff, 0xFFfffeff, 0xFFfffcf6, 0xFFfdfef2, 0xFFf7ffee, 0xFFfcffea, + 0xFFffffe5, 0xFFffffd8, 0xFFffffcb, 0xFFfffbf1, 0xFFffffdf, 0xFFfdfdc2, 0xFFf7ff88, 0xFFfbfe92, + 0xFFffff7f, 0xFFfdfc6c, 0xFFfaf759, 0xFFf8f059, 0xFFf7e958, 0xFFf7e359, 0xFFd0d368, 0xFF0998ff, + 0xFF189aef, 0xFF129af2, 0xFF0c99f5, 0xFF1199f3, 0xFF1599f2, 0xFF1397f0, 0xFF1195ee, 0xFF1195ee, + 0xFF5fd2f9, 0xFF5cd3f8, 0xFF59d4f6, 0xFF58d3f8, 0xFF5edaff, 0xFF1971cd, 0xFF026ecd, 0xFF037bd3, + 0xFF0488d9, 0xFF0497e0, 0xFF05a6e6, 0xFF01ade7, 0xFF00b5e8, 0xFF07beea, 0xFF23cbf5, 0xFF4cd7f8, + 0xFF74e4fc, 0xFF89e8fd, 0xFF9fecfe, 0xFFa5edfe, 0xFFabeffe, 0xFFaeeffc, 0xFFb0eff9, 0xFFb3f3f9, + 0xFFb6f6f8, 0xFFb6f9fc, 0xFFb5fcff, 0xFFdaf3ff, 0xFF1ab9f1, 0xFF28b3f4, 0xFF2bb3f6, 0xFF73cef4, + 0xFFfdfdf5, 0xFFfdfefa, 0xFFfdfffe, 0xFFfffef9, 0xFFfffdf3, 0xFFfdfeee, 0xFFfaffe9, 0xFFfdffe4, + 0xFFffffde, 0xFFffffd0, 0xFFffffc2, 0xFFfdfad7, 0xFFfffcf3, 0xFFffffc0, 0xFFfcfbc5, 0xFFfcff84, + 0xFFfcfb8b, 0xFFfbf67a, 0xFFf9f269, 0xFFf7ed5e, 0xFFf4e954, 0xFFf7e948, 0xFF87bda9, 0xFF109afc, + 0xFF179cf2, 0xFF149bf1, 0xFF119af1, 0xFF1399f2, 0xFF1698f3, 0xFF1496f1, 0xFF1294ef, 0xFF1294ef, + 0xFF62d4fc, 0xFF5dd4f9, 0xFF59d4f6, 0xFF56d1f6, 0xFF53cef5, 0xFF014ebe, 0xFF026fcd, 0xFF057bd4, + 0xFF0787da, 0xFF0996e0, 0xFF0ca5e7, 0xFF0bb0e9, 0xFF09bbeb, 0xFF15c5f3, 0xFF21d0fc, 0xFF46dafc, + 0xFF6ce3fc, 0xFF82e6fd, 0xFF97e9fe, 0xFF99e9fe, 0xFF9ce8fe, 0xFF9ee9fb, 0xFFa0e9f9, 0xFFa6eefa, + 0xFFacf3fc, 0xFFb0effc, 0xFFb5ecfb, 0xFF89ddf9, 0xFF28b4f3, 0xFF3ebef7, 0xFF1eadf7, 0xFFbde8f0, + 0xFFfefff2, 0xFFfefff3, 0xFFfdfff4, 0xFFfefef2, 0xFFfefef0, 0xFFfefeea, 0xFFfefee4, 0xFFfefede, + 0xFFfefed8, 0xFFfcffc9, 0xFFfbffba, 0xFFf6fea0, 0xFFffffce, 0xFFfff9f6, 0xFFffffc9, 0xFFfdf7be, + 0xFFf8f87a, 0xFFf9f66b, 0xFFf9f35c, 0xFFf5ee56, 0xFFf1e84f, 0xFFf8ee37, 0xFF3fa7ea, 0xFF189df5, + 0xFF179df4, 0xFF169cf1, 0xFF159bee, 0xFF169af2, 0xFF1798f5, 0xFF1596f3, 0xFF1394f1, 0xFF1394f1, + 0xFF66d7fc, 0xFF5fd1f5, 0xFF60d4f6, 0xFF59d8f9, 0xFF399ddb, 0xFF0858be, 0xFF096ccd, 0xFF0c7ad2, + 0xFF1087d7, 0xFF1296df, 0xFF13a6e8, 0xFF13b0eb, 0xFF1bc3f5, 0xFF0fc8f3, 0xFF17d0f9, 0xFF27d3f4, + 0xFF4bd7f7, 0xFF61dbf8, 0xFF77def9, 0xFF7fe0fa, 0xFF88e1fa, 0xFF8de4fb, 0xFF91e7fb, 0xFF96eafc, + 0xFF9aedfd, 0xFF9feafb, 0xFFa3e7fa, 0xFF5eccfb, 0xFF2db7f5, 0xFF24b8f9, 0xFF14b1f5, 0xFFfffbff, + 0xFFfeffec, 0xFFffffed, 0xFFffffee, 0xFFffffec, 0xFFfefdeb, 0xFFfefde4, 0xFFfefddd, 0xFFfefed6, + 0xFFfefece, 0xFFfcfdc1, 0xFFfcfcb5, 0xFFf6fb8d, 0xFFf8fc8a, 0xFFf8facc, 0xFFf8fef2, 0xFFf9ffbe, + 0xFFfbf9c2, 0xFFfbf8ac, 0xFFfcf796, 0xFFfaf491, 0xFFf7f18d, 0xFFffe5a9, 0xFF0096f7, 0xFF089af7, + 0xFF159ef7, 0xFF169df4, 0xFF169cf0, 0xFF169bf2, 0xFF1699f4, 0xFF1497f3, 0xFF1396f1, 0xFF1396f1, + 0xFF6bd9fb, 0xFF61cef1, 0xFF67d3f7, 0xFF5cdefd, 0xFF1f6cc0, 0xFF0f63bf, 0xFF0f6acd, 0xFF1478d1, + 0xFF1887d4, 0xFF1997df, 0xFF1aa6e9, 0xFF14a9e4, 0xFF1dbbef, 0xFF0dbeeb, 0xFF23c5f6, 0xFF13c6ed, + 0xFF2acbf3, 0xFF40cff4, 0xFF56d4f4, 0xFF65d7f6, 0xFF74daf7, 0xFF7bdffb, 0xFF83e5fe, 0xFF86e6fe, + 0xFF89e8fd, 0xFF8ee5fb, 0xFF92e2fa, 0xFF33bcfc, 0xFF32b9f7, 0xFF31bafd, 0xFF57c5f7, 0xFFf4ffde, + 0xFFfdffe7, 0xFFffffe7, 0xFFffffe7, 0xFFffffe6, 0xFFfdfce6, 0xFFfdfddd, 0xFFfdfdd5, 0xFFfdfdcd, + 0xFFfefdc5, 0xFFfdfaba, 0xFFfcf8af, 0xFFfef99f, 0xFFfffb8e, 0xFFfafe77, 0xFFf4fb7d, 0xFFf9f8d2, + 0xFFfdffee, 0xFFfefedf, 0xFFfffcd0, 0xFFfefacd, 0xFFfdf9ca, 0xFFa6d3ce, 0xFF0399eb, 0xFF1ea1ec, + 0xFF149ffa, 0xFF159ef6, 0xFF179ef2, 0xFF169cf3, 0xFF159af3, 0xFF1499f2, 0xFF1398f1, 0xFF1398f1, + 0xFF55d4f4, 0xFF5bd1f1, 0xFF69d6f6, 0xFF6ee2ff, 0xFF0c50a8, 0xFF1161be, 0xFF0f6acd, 0xFF1f83d6, + 0xFF1f89dc, 0xFF0f8cdd, 0xFF1a9be0, 0xFF22b1f4, 0xFF1dabe1, 0xFF14aedf, 0xFF26bdee, 0xFF15bae7, + 0xFF1fc1ef, 0xFF25c7ef, 0xFF2bcdef, 0xFF3dcdf1, 0xFF4ecef3, 0xFF5bd6f9, 0xFF68defe, 0xFF6eddfc, + 0xFF73ddfb, 0xFF76ddf5, 0xFF70d3f7, 0xFF31bafb, 0xFF33b9f6, 0xFF24b6ff, 0xFFa4dee5, 0xFFf9ffdc, + 0xFFfdfedc, 0xFFffffdc, 0xFFffffdc, 0xFFfefedb, 0xFFfcfdda, 0xFFfdfdd2, 0xFFfdfdcb, 0xFFfdfdc3, + 0xFFfefdbc, 0xFFfdfbaf, 0xFFfcfaa2, 0xFFfdfb93, 0xFFfefb83, 0xFFfcfd6b, 0xFFf9fc60, 0xFFfbf85d, + 0xFFfdf74c, 0xFFfef576, 0xFFfff2a1, 0xFFf6ec87, 0xFFf8e360, 0xFF51bbb4, 0xFF0d9afe, 0xFF1a9ef7, + 0xFF159ef6, 0xFF159df4, 0xFF159df2, 0xFF149bf2, 0xFF1299f2, 0xFF1299f2, 0xFF1299f2, 0xFF1299f2, + 0xFF67d4fd, 0xFF69d6f9, 0xFF6cd9f5, 0xFF4fb7dc, 0xFF1953af, 0xFF1c67c6, 0xFF005abd, 0xFF1a7eca, + 0xFF157bd4, 0xFF0581dc, 0xFF2aa1e7, 0xFF0189d3, 0xFF2dabe3, 0xFF23a7dc, 0xFF29b4e6, 0xFF17ade1, + 0xFF14b7ec, 0xFF15b9ea, 0xFF16bbe9, 0xFF1fbfec, 0xFF28c2ef, 0xFF3bcdf7, 0xFF4ed8ff, 0xFF56d5fb, + 0xFF5dd2f8, 0xFF5ed6f0, 0xFF4ec5f4, 0xFF2fb9fa, 0xFF35b8f4, 0xFF17b1ff, 0xFFf0f7d2, 0xFFfeffda, + 0xFFfdfcd2, 0xFFfdfdd1, 0xFFfdfed1, 0xFFfdfecf, 0xFFfcfecd, 0xFFfcfdc7, 0xFFfdfdc0, 0xFFfdfdb9, + 0xFFfdfdb2, 0xFFfdfca4, 0xFFfdfc95, 0xFFfdfc87, 0xFFfdfc79, 0xFFfdfa6c, 0xFFfef85f, 0xFFf9f645, + 0xFFf6ef47, 0xFFf2e938, 0xFFefe428, 0xFFeee425, 0xFFffdd05, 0xFF0399ff, 0xFF17a1f5, 0xFF179ef4, + 0xFF169cf3, 0xFF159cf3, 0xFF149cf3, 0xFF129bf1, 0xFF1099f0, 0xFF119af1, 0xFF129bf2, 0xFF129bf2, + 0xFF66d5fb, 0xFF70d5fc, 0xFF78e2ff, 0xFF3b86c7, 0xFF235fba, 0xFF1e6aba, 0xFF227ad1, 0xFF2787d8, + 0xFF248cd7, 0xFF1d8dd4, 0xFF2189d1, 0xFF2ca1ea, 0xFF2296d5, 0xFF31aaef, 0xFF20a1db, 0xFF17a1dd, + 0xFF0ea1e0, 0xFF1aace3, 0xFF13b1eb, 0xFF10b8ed, 0xFF0dc0ef, 0xFF1cc1ef, 0xFF2cc3f0, 0xFF36c4f2, + 0xFF40c5f4, 0xFF47c9f2, 0xFF45c3f6, 0xFF31bafa, 0xFF31b7f7, 0xFF4cc2f4, 0xFFf5fac0, 0xFFfdffc6, + 0xFFfdfcc5, 0xFFfdfdc4, 0xFFfdfdc4, 0xFFfcfdc2, 0xFFfbfdc1, 0xFFf8f9b6, 0xFFfdfdb3, 0xFFfdfdab, + 0xFFfdfca3, 0xFFfcfc95, 0xFFfcfb88, 0xFFfcfb7b, 0xFFfbfb6d, 0xFFfcf962, 0xFFfcf757, 0xFFf8f245, + 0xFFf4eb41, 0xFFf0e532, 0xFFebe023, 0xFFfbe01c, 0xFFc5d244, 0xFF0aa2fe, 0xFF169ff9, 0xFF179ff6, + 0xFF189ff3, 0xFF179ef2, 0xFF159df2, 0xFF179ff5, 0xFF18a1f8, 0xFF159ef5, 0xFF129bf2, 0xFF129bf2, + 0xFF65d7fa, 0xFF64d1f7, 0xFF5de7ff, 0xFF04439b, 0xFF0e4ca5, 0xFF317bcd, 0xFF0455c1, 0xFF0053c9, + 0xFF0368c6, 0xFF2687ca, 0xFF2881ca, 0xFF2789d1, 0xFF2791d7, 0xFF0774c9, 0xFF178dcf, 0xFF1f9ce1, + 0xFF179be4, 0xFF1e9eda, 0xFF0097de, 0xFF03a5e6, 0xFF08b1ee, 0xFF09b0e8, 0xFF0aafe2, 0xFF17b4e9, + 0xFF24b9ef, 0xFF30bdf4, 0xFF3cc1f9, 0xFF34bcf9, 0xFF2cb6f9, 0xFF80d2e8, 0xFFfafdaf, 0xFFfcfdb3, + 0xFFfdfcb7, 0xFFfdfcb7, 0xFFfdfdb7, 0xFFfcfcb6, 0xFFfbfcb5, 0xFFf4f4a5, 0xFFfdfda5, 0xFFfcfc9d, + 0xFFfcfc94, 0xFFfbfb87, 0xFFfbfb7b, 0xFFfafa6e, 0xFFfafa61, 0xFFfaf758, 0xFFfaf54e, 0xFFf7ee44, + 0xFFf3e73a, 0xFFede12c, 0xFFe7db1e, 0xFFffd21a, 0xFF78b090, 0xFF09a0fd, 0xFF159dfd, 0xFF18a0f8, + 0xFF1aa2f2, 0xFF18a0f2, 0xFF169ef2, 0xFF139bf2, 0xFF1099f1, 0xFF119af2, 0xFF129bf3, 0xFF129bf3, + 0xFF60d4f7, 0xFF67dcfd, 0xFF4fc2f0, 0xFF002c8a, 0xFF2e6bc0, 0xFF0547ad, 0xFF0044ba, 0xFF3685c4, + 0xFF064ebc, 0xFF1462c3, 0xFF2d70cb, 0xFF0f5ab4, 0xFF2274cd, 0xFF1169c2, 0xFF1979c2, 0xFF1d80d0, + 0xFF1980d7, 0xFF1a86d3, 0xFF1090de, 0xFF038dda, 0xFF0599e6, 0xFF059ce1, 0xFF049edd, 0xFF05a6e1, + 0xFF00a7de, 0xFF1fb6ee, 0xFF39bdf7, 0xFF38bcf6, 0xFF24b5fc, 0xFFbfe8b9, 0xFFfafea2, 0xFFfbfca5, + 0xFFfcfaa8, 0xFFfcfca7, 0xFFfdfda6, 0xFFfbfca3, 0xFFf9fb9f, 0xFFf6f795, 0xFFfafb92, 0xFFfbfb8b, + 0xFFfbfb85, 0xFFfafa79, 0xFFfafa6d, 0xFFf9f961, 0xFFf8f956, 0xFFf9f64c, 0xFFf9f442, 0xFFf5ec39, + 0xFFf2e531, 0xFFefde28, 0xFFecd620, 0xFFeed900, 0xFF32a6e5, 0xFF19a4ff, 0xFF29a4f4, 0xFF20a2f4, + 0xFF18a0f5, 0xFF179ef4, 0xFF159df4, 0xFF139bf3, 0xFF1199f2, 0xFF129af2, 0xFF129af3, 0xFF129af3, + 0xFF5bd1f5, 0xFF63dffa, 0xFF318dcc, 0xFF062d91, 0xFF0e499a, 0xFF00369f, 0xFF003897, 0xFF155fb6, + 0xFF53aad9, 0xFF31a6e2, 0xFF45bcef, 0xFF6dddff, 0xFF76defa, 0xFF6dd9f9, 0xFF64d5f9, 0xFF54c5f3, + 0xFF45b5ed, 0xFF238ed6, 0xFF1277ce, 0xFF006cc6, 0xFF0282de, 0xFF0187db, 0xFF008dd7, 0xFF079be1, + 0xFF0099dc, 0xFF22b1f0, 0xFF36baf4, 0xFF3cbcf4, 0xFF1cb5ff, 0xFFfffe89, 0xFFfbff96, 0xFFfbfc98, + 0xFFfbf99a, 0xFFfcfb98, 0xFFfdfd96, 0xFFfafb90, 0xFFf6f98a, 0xFFf7f984, 0xFFf8fa7f, 0xFFfafa7a, + 0xFFfbfb75, 0xFFfafa6a, 0xFFf9f960, 0xFFf8f855, 0xFFf7f84a, 0xFFf7f540, 0xFFf8f336, 0xFFf4eb2f, + 0xFFf0e328, 0xFFf0da24, 0xFFf0d121, 0xFFe9ca24, 0xFF049bff, 0xFF20a3f6, 0xFF16a1f7, 0xFF16a0f7, + 0xFF169ef7, 0xFF159df6, 0xFF149cf5, 0xFF139bf4, 0xFF129af3, 0xFF129af3, 0xFF129af3, 0xFF129af3, + 0xFF5ae3ff, 0xFF64d8ff, 0xFF0d4798, 0xFF002682, 0xFF1d6bb7, 0xFF3aa2de, 0xFF5fe5ff, 0xFF52d8fd, + 0xFF4dd6f6, 0xFF48ccf5, 0xFF5fd0f6, 0xFF68d9ff, 0xFF61d3f8, 0xFF5bd2f8, 0xFF42cbff, 0xFF53cefe, + 0xFF51cff5, 0xFF49caf6, 0xFF4acdff, 0xFF40baff, 0xFF0e7edb, 0xFF0069c2, 0xFF0584da, 0xFF0184d5, + 0xFF068cd8, 0xFF38bef8, 0xFF3abef7, 0xFF35beff, 0xFF62c7e2, 0xFFfbf379, 0xFFf8fa83, 0xFFf9f983, + 0xFFfaf884, 0xFFf9f77f, 0xFFf7f77b, 0xFFf8f979, 0xFFf9fa77, 0xFFf8f972, 0xFFf7f86c, 0xFFfcfc6c, + 0xFFf9f864, 0xFFf8f85b, 0xFFf8f752, 0xFFf7f649, 0xFFf6f53f, 0xFFf5f237, 0xFFf4ef2f, 0xFFf1e628, + 0xFFeede20, 0xFFead61f, 0xFFf2cc11, 0xFF9db96c, 0xFF0c9ffe, 0xFF1ba3f9, 0xFF17a2f9, 0xFF17a0f9, + 0xFF169ef8, 0xFF169df7, 0xFF159cf6, 0xFF149bf5, 0xFF139af5, 0xFF139af5, 0xFF139af5, 0xFF139af5, + 0xFF60d8f9, 0xFF5bd9f8, 0xFF4cadd7, 0xFF69ddff, 0xFF56ddf8, 0xFF55d6fc, 0xFF55d0ff, 0xFF5cd5ff, + 0xFF53cbf2, 0xFF4bcaf6, 0xFF43cafa, 0xFF47c9f8, 0xFF4cc8f6, 0xFF5ccff1, 0xFF46ccf8, 0xFF55caff, + 0xFF3ec4fa, 0xFF43c3fb, 0xFF48c2fd, 0xFF3ebff4, 0xFF44ccfb, 0xFF37b3fc, 0xFF0b7bdd, 0xFF006dc9, + 0xFF0d80d4, 0xFF4eccff, 0xFF3ec3fa, 0xFF2ec2ff, 0xFFa7dea8, 0xFFf8ec5b, 0xFFf5f570, 0xFFf7f66f, + 0xFFfaf76e, 0xFFf5f467, 0xFFf1f060, 0xFFf6f663, 0xFFfbfc65, 0xFFf8f95f, 0xFFf6f659, 0xFFfefe5d, + 0xFFf7f652, 0xFFf7f54c, 0xFFf7f545, 0xFFf6f33d, 0xFFf6f235, 0xFFf3ef2f, 0xFFf1eb29, 0xFFefe221, + 0xFFecd818, 0xFFe5d21a, 0xFFf3c700, 0xFF52a9b4, 0xFF14a4fb, 0xFF15a3fb, 0xFF17a3fc, 0xFF17a1fa, + 0xFF179ff8, 0xFF169df8, 0xFF159cf7, 0xFF159bf7, 0xFF1499f6, 0xFF1499f6, 0xFF1499f6, 0xFF1499f6, + 0xFF58cff2, 0xFF59ddfd, 0xFF55d5f9, 0xFF5ddeff, 0xFF4dcef3, 0xFF4dcbf3, 0xFF4cc8f3, 0xFF56d2fc, + 0xFF59d3fd, 0xFF50cefb, 0xFF47cafa, 0xFF48c9f9, 0xFF49c7f9, 0xFF51cbf6, 0xFF45c9f9, 0xFF4bc8fd, + 0xFF3fc5f9, 0xFF41c4fa, 0xFF43c2fb, 0xFF3bbdf3, 0xFF3ac0f4, 0xFF3ec7fc, 0xFF3ac6fc, 0xFF25a1e3, + 0xFF1f8dd9, 0xFF37b9f7, 0xFF26bbfa, 0xFF2abbf4, 0xFFced857, 0xFFf9fa5b, 0xFFd9db49, 0xFFedec58, + 0xFFfaf560, 0xFFf2ef4d, 0xFFe9ea3b, 0xFFeeef46, 0xFFf2f451, 0xFFf9f34f, 0xFFedf145, 0xFFfef84b, + 0xFFf4f542, 0xFFf5f43d, 0xFFf6f337, 0xFFf5f131, 0xFFf5ef2b, 0xFFf2eb27, 0xFFf0e622, 0xFFeedb1d, + 0xFFecd117, 0xFFf1cc09, 0xFFf5c509, 0xFF0fadff, 0xFF17a1f9, 0xFF18a1f9, 0xFF18a1f8, 0xFF18a0f9, + 0xFF179ff9, 0xFF169df9, 0xFF169cf8, 0xFF159bf8, 0xFF1599f8, 0xFF1599f8, 0xFF1599f8, 0xFF1599f8, + 0xFF60d5fb, 0xFF5bd3fb, 0xFF56d2fb, 0xFF55d1fc, 0xFF55d0fe, 0xFF54d0fa, 0xFF53d1f6, 0xFF51cef7, + 0xFF4ecbf8, 0xFF4dcbf9, 0xFF4ccafb, 0xFF49c8fb, 0xFF47c6fc, 0xFF45c6fb, 0xFF43c6fa, 0xFF41c6fa, + 0xFF40c7f9, 0xFF3fc5f9, 0xFF3ec3f9, 0xFF3fc3fb, 0xFF41c4fd, 0xFF38baf2, 0xFF40c1f8, 0xFF3dc3fb, + 0xFF3bc5fe, 0xFF37c1f6, 0xFF34beef, 0xFF2ebcf0, 0xFFded722, 0xFFbfdc38, 0xFFdee142, 0xFFecea4a, + 0xFFeae442, 0xFFeee942, 0xFFf2ee42, 0xFFeeed3f, 0xFFeaec3d, 0xFFfbee3f, 0xFFe5ec31, 0xFFfff239, + 0xFFf2f531, 0xFFf4f32e, 0xFFf5f12a, 0xFFf5ee25, 0xFFf4ec21, 0xFFf2e71e, 0xFFf0e11c, 0xFFeed519, + 0xFFecc917, 0xFFdec40c, 0xFFbbbe39, 0xFF0798f8, 0xFF1a9ff8, 0xFF1a9ff7, 0xFF1a9ff5, 0xFF189ff7, + 0xFF179ff9, 0xFF179ef9, 0xFF169cf9, 0xFF169bf9, 0xFF1699f9, 0xFF1699f9, 0xFF1699f9, 0xFF1699f9, + 0xFF5cd4f9, 0xFF58d4f9, 0xFF55d3f9, 0xFF56d2fa, 0xFF58d0fb, 0xFF56d0f8, 0xFF54d0f6, 0xFF51cef7, + 0xFF4dccf9, 0xFF4ccbfa, 0xFF4bcafb, 0xFF49c8fb, 0xFF47c7fb, 0xFF45c7fb, 0xFF43c6fa, 0xFF41c6fa, + 0xFF40c6f9, 0xFF3fc4f9, 0xFF3ec3f9, 0xFF3ec2fa, 0xFF3ec2fb, 0xFF3abef5, 0xFF3ec2f8, 0xFF3bc1f9, + 0xFF37c0f9, 0xFF36beff, 0xFF35bbff, 0xFF67bb84, 0xFFb0d219, 0xFFb4d31a, 0xFFd3da39, 0xFFe2dd3d, + 0xFFd6d532, 0xFFe1df38, 0xFFece93e, 0xFFe1e636, 0xFFe9e536, 0xFFf1e634, 0xFFe5e42b, 0xFFf6e62e, + 0xFFe9eb29, 0xFFf0ee2a, 0xFFf0e824, 0xFFece420, 0xFFe9e01d, 0xFFebdb1c, 0xFFedd71c, 0xFFe9ce19, + 0xFFe5c516, 0xFFe7c004, 0xFF6cb292, 0xFF109dfc, 0xFF18a1f7, 0xFF1aa0f5, 0xFF1ca0f3, 0xFF19a0f6, + 0xFF179ff9, 0xFF169ef9, 0xFF169cf9, 0xFF159bf8, 0xFF159af8, 0xFF1499f8, 0xFF1499f7, 0xFF1499f7, + 0xFF58d4f6, 0xFF56d4f6, 0xFF54d5f7, 0xFF57d3f7, 0xFF5bd1f8, 0xFF58d0f6, 0xFF54cff5, 0xFF50cef8, + 0xFF4dcdfa, 0xFF4bcbfb, 0xFF4acafb, 0xFF48c9fb, 0xFF46c7fb, 0xFF45c7fa, 0xFF43c7fa, 0xFF42c6fa, + 0xFF40c6f9, 0xFF3fc4f9, 0xFF3ec3f9, 0xFF3dc1f9, 0xFF3cc0f9, 0xFF3cc1f8, 0xFF3cc2f7, 0xFF38bff6, + 0xFF34bbf5, 0xFF35bdfd, 0xFF37beff, 0xFF46bcfc, 0xFF82c92c, 0xFFa0be02, 0xFFb8c420, 0xFFd8cf31, + 0xFFd2d632, 0xFFd4d52e, 0xFFd7d42a, 0xFFcdd725, 0xFFe9df2f, 0xFFe6dd2a, 0xFFe4dc25, 0xFFedd922, + 0xFFe0e220, 0xFFede927, 0xFFeae01e, 0xFFe4da1c, 0xFFded319, 0xFFe5d01a, 0xFFebcd1b, 0xFFe5c818, + 0xFFdec214, 0xFFf0bc00, 0xFF1da5eb, 0xFF19a1ff, 0xFF16a2f7, 0xFF19a2f4, 0xFF1ea2f1, 0xFF1aa0f5, + 0xFF169ff9, 0xFF169ef8, 0xFF159df8, 0xFF159cf8, 0xFF149bf8, 0xFF139af7, 0xFF1299f6, 0xFF1299f6, + 0xFF5ed5f9, 0xFF63d6fc, 0xFF68d6ff, 0xFF5fd3fc, 0xFF56d0f8, 0xFF53cff8, 0xFF51cef8, 0xFF4ecdf9, + 0xFF4bccfb, 0xFF4acbfb, 0xFF48cafb, 0xFF47c9fa, 0xFF46c8fb, 0xFF44c7fa, 0xFF43c7fa, 0xFF42c6fa, + 0xFF40c5f9, 0xFF3fc4f9, 0xFF3ec3f9, 0xFF3dc1f9, 0xFF3cc0f9, 0xFF3bc1f9, 0xFF3bc1f8, 0xFF38bff7, + 0xFF36bdf7, 0xFF35bdfa, 0xFF34bdfe, 0xFF22c3f6, 0xFF27bbfc, 0xFF53b0b2, 0xFF9bc606, 0xFFc1d322, + 0xFFd3dd36, 0xFFb4ba12, 0xFFc4c71f, 0xFFc5cf22, 0xFFd9d82d, 0xFFdfdb30, 0xFFdcd52b, 0xFFe8d520, + 0xFFd5d51c, 0xFFe8e428, 0xFFece324, 0xFFd1ce1f, 0xFFd3c51d, 0xFFdcc302, 0xFFcfc312, 0xFFe3c209, + 0xFFe3be00, 0xFF84bf6e, 0xFF0ca0f6, 0xFF129ffd, 0xFF18a2f6, 0xFF19a1f5, 0xFF1ba1f4, 0xFF18a0f6, + 0xFF169ff8, 0xFF159ef8, 0xFF159df8, 0xFF149cf7, 0xFF139bf7, 0xFF129af6, 0xFF1098f4, 0xFF1098f4, + 0xFF65d7fb, 0xFF5dd4fa, 0xFF56d2f8, 0xFF53d0f9, 0xFF50cff9, 0xFF4fcef9, 0xFF4dcdfa, 0xFF4bcdfa, + 0xFF4accfb, 0xFF48cbfb, 0xFF47cafb, 0xFF46c9fa, 0xFF45c8fa, 0xFF44c7fa, 0xFF43c7fa, 0xFF42c6fa, + 0xFF40c5fa, 0xFF3fc4f9, 0xFF3ec3f9, 0xFF3dc1f9, 0xFF3bc0f9, 0xFF3ac0f9, 0xFF39c0f9, 0xFF38bff9, + 0xFF37bff9, 0xFF34bef8, 0xFF31bcf7, 0xFF33bbf8, 0xFF35bbfa, 0xFF2cbcff, 0xFF61c2df, 0xFF93cb85, + 0xFFc5d52b, 0xFFcbd82f, 0xFFb0bb13, 0xFFb5be17, 0xFFb9c21b, 0xFFc7c826, 0xFFc5bf21, 0xFFdbc817, + 0xFFcac819, 0xFFdbd722, 0xFFddd61a, 0xFFb7bd0d, 0xFFc8bd04, 0xFFd0c000, 0xFFadc951, 0xFF6cb8b1, + 0xFF04a3ff, 0xFF13a4fb, 0xFF21a4f5, 0xFF1ea3f5, 0xFF1aa1f6, 0xFF19a1f6, 0xFF18a0f7, 0xFF17a0f7, + 0xFF169ff8, 0xFF159ef7, 0xFF149ef7, 0xFF139df7, 0xFF139cf6, 0xFF119af4, 0xFF0f98f2, 0xFF0f98f2, + 0xFF5cd5f9, 0xFF58d3f8, 0xFF53d1f8, 0xFF52d0f9, 0xFF50cff9, 0xFF4ecefa, 0xFF4ccdfa, 0xFF4accfa, + 0xFF48ccfa, 0xFF47cbfa, 0xFF46cafa, 0xFF45c9fa, 0xFF44c8fa, 0xFF43c7fa, 0xFF42c7fa, 0xFF41c6fa, + 0xFF40c5fa, 0xFF3fc4f9, 0xFF3ec2f9, 0xFF3cc1f9, 0xFF3bc0f9, 0xFF3ac0f9, 0xFF38bff9, 0xFF37bff9, + 0xFF36bff9, 0xFF35bdf6, 0xFF34bbf3, 0xFF35b9f7, 0xFF35b8fb, 0xFF22b5ff, 0xFF2fb5ff, 0xFF4dbae6, + 0xFF6bbfce, 0xFF27b1c5, 0xFF6cbc7c, 0xFF8abd49, 0xFFa7be15, 0xFFb9bf09, 0xFFccc000, 0xFFdac43d, + 0xFFbbca20, 0xFFaec73e, 0xFF99bc54, 0xFF5aad8b, 0xFF36abc4, 0xFF04b3ff, 0xFF15a7ff, 0xFF21a4ff, + 0xFF19a0fb, 0xFF1ba2fa, 0xFF1da4f9, 0xFF1ba3f8, 0xFF1aa1f7, 0xFF19a1f7, 0xFF18a0f7, 0xFF17a0f7, + 0xFF169ff8, 0xFF159ef7, 0xFF149ef7, 0xFF139df7, 0xFF129cf6, 0xFF119af5, 0xFF0f99f3, 0xFF0f99f3, + 0xFF53d2f6, 0xFF52d1f7, 0xFF51d1f8, 0xFF50d0f9, 0xFF4fcffa, 0xFF4dcefa, 0xFF4bcdfa, 0xFF49ccfa, + 0xFF47cbfa, 0xFF46caf9, 0xFF45caf9, 0xFF44c9f9, 0xFF44c8fa, 0xFF43c7fa, 0xFF42c6f9, 0xFF41c6f9, + 0xFF40c5fa, 0xFF3fc4f9, 0xFF3dc2f9, 0xFF3cc1f9, 0xFF3ac0f9, 0xFF39c0f9, 0xFF38bff9, 0xFF36bff9, + 0xFF35bef8, 0xFF36bcf4, 0xFF38baf0, 0xFF36b8f6, 0xFF34b5fc, 0xFF2cb6f9, 0xFF23b7f6, 0xFF25b5fa, + 0xFF28b4ff, 0xFF28b6ff, 0xFF29b7ff, 0xFF1fb5ff, 0xFF15b2ff, 0xFF20aef7, 0xFF3cb9ff, 0xFF5acbf0, + 0xFF42befa, 0xFF2ab6fc, 0xFF12adff, 0xFF18acfc, 0xFF1eacfa, 0xFF1ea9fd, 0xFF1ea7ff, 0xFF1ba8fa, + 0xFF18a8f4, 0xFF18a6f8, 0xFF18a4fd, 0xFF19a3fa, 0xFF1aa1f7, 0xFF19a1f7, 0xFF18a0f8, 0xFF17a0f8, + 0xFF169ff8, 0xFF159ef7, 0xFF149df7, 0xFF139cf6, 0xFF129bf6, 0xFF119af5, 0xFF1099f4, 0xFF1099f4, + 0xFF54d1f8, 0xFF52d1f8, 0xFF51d0f9, 0xFF4fcff9, 0xFF4ecffa, 0xFF4ccefa, 0xFF4acdf9, 0xFF48ccf9, + 0xFF45cbf9, 0xFF45caf9, 0xFF44c9f9, 0xFF43c8f9, 0xFF43c8f9, 0xFF42c7f9, 0xFF42c6f9, 0xFF41c5f9, + 0xFF40c5fa, 0xFF3fc4f9, 0xFF3dc2f9, 0xFF3bc1f9, 0xFF3ac0fa, 0xFF38bff9, 0xFF37bff9, 0xFF36bef9, + 0xFF34bef8, 0xFF35bcf6, 0xFF35baf5, 0xFF34b8f8, 0xFF33b6fc, 0xFF2eb6f9, 0xFF29b6f7, 0xFF29b5f8, + 0xFF2ab4fa, 0xFF2ab5fb, 0xFF2ab5fc, 0xFF2ab2f6, 0xFF2aafef, 0xFF1ba9f6, 0xFF9bcfd9, 0xFF6dcfe9, + 0xFF74c7e4, 0xFF80c9dd, 0xFF19adfb, 0xFF1cacf9, 0xFF1fabf8, 0xFF1fa9f9, 0xFF1ea7fb, 0xFF1ca7f9, + 0xFF1aa7f6, 0xFF1aa5f8, 0xFF1aa4fb, 0xFF1aa3fa, 0xFF1aa2f8, 0xFF19a1f8, 0xFF18a0f8, 0xFF17a0f8, + 0xFF169ff8, 0xFF159ef7, 0xFF149df7, 0xFF139cf6, 0xFF129bf6, 0xFF119bf5, 0xFF119af5, 0xFF119af5, + 0xFF55d0f9, 0xFF53d0fa, 0xFF51d0fa, 0xFF4fcffa, 0xFF4dcffa, 0xFF4bcefa, 0xFF49cdf9, 0xFF46ccf9, + 0xFF44caf8, 0xFF43caf8, 0xFF43c9f8, 0xFF43c8f9, 0xFF42c8f9, 0xFF42c7f9, 0xFF41c6f9, 0xFF41c6f9, + 0xFF40c5fa, 0xFF3ec3f9, 0xFF3dc2fa, 0xFF3bc1fa, 0xFF39c0fa, 0xFF38bff9, 0xFF36bff9, 0xFF35bef9, + 0xFF34bdf8, 0xFF33bcf9, 0xFF33bafa, 0xFF32b9fb, 0xFF32b8fc, 0xFF30b7fa, 0xFF2eb6f8, 0xFF2db5f7, + 0xFF2bb4f5, 0xFF2bb4f6, 0xFF2bb3f7, 0xFF29b2f9, 0xFF28b2fc, 0xFF30b2f7, 0xFF12a8fe, 0xFF7fd4e1, + 0xFF58bbe6, 0xFF15aafb, 0xFF1fadf8, 0xFF20acf7, 0xFF20aaf5, 0xFF1fa9f6, 0xFF1ea8f7, 0xFF1da6f7, + 0xFF1ca5f8, 0xFF1ca4f8, 0xFF1ba3f9, 0xFF1ba3f9, 0xFF1ba2f9, 0xFF19a1f9, 0xFF18a0f8, 0xFF17a0f8, + 0xFF169ff8, 0xFF159ef7, 0xFF149df7, 0xFF139cf6, 0xFF129bf5, 0xFF129bf5, 0xFF129bf5, 0xFF129bf5, + 0xFF55d0f9, 0xFF53d0fa, 0xFF51d0fa, 0xFF4fcffa, 0xFF4dcffa, 0xFF4bcefa, 0xFF49cdf9, 0xFF46ccf9, + 0xFF44caf8, 0xFF43caf8, 0xFF43c9f8, 0xFF43c8f9, 0xFF42c8f9, 0xFF42c7f9, 0xFF41c6f9, 0xFF41c6f9, + 0xFF40c5fa, 0xFF3ec3f9, 0xFF3dc2fa, 0xFF3bc1fa, 0xFF39c0fa, 0xFF38bff9, 0xFF36bff9, 0xFF35bef9, + 0xFF34bdf8, 0xFF33bcf9, 0xFF33bafa, 0xFF32b9fb, 0xFF32b8fc, 0xFF30b7fa, 0xFF2eb6f8, 0xFF2db5f7, + 0xFF2bb4f5, 0xFF2bb4f6, 0xFF2bb3f7, 0xFF2ab2f8, 0xFF29b2fa, 0xFF2db6f5, 0xFF1db5f6, 0xFF239bff, + 0xFF20b6f3, 0xFF0cacfb, 0xFF1eacf7, 0xFF1fabf6, 0xFF20aaf5, 0xFF1fa9f6, 0xFF1ea8f7, 0xFF1da6f7, + 0xFF1ca5f8, 0xFF1ca4f8, 0xFF1ba3f9, 0xFF1ba3f9, 0xFF1ba2f9, 0xFF19a1f9, 0xFF18a0f8, 0xFF17a0f8, + 0xFF169ff8, 0xFF159ef7, 0xFF149df7, 0xFF139cf6, 0xFF129bf5, 0xFF129bf5, 0xFF129bf5, 0xFF129bf5, + 0xFF55d0f9, 0xFF53d0fa, 0xFF51d0fa, 0xFF4fcffa, 0xFF4dcffa, 0xFF4bcefa, 0xFF49cdf9, 0xFF46ccf9, + 0xFF44caf8, 0xFF43caf8, 0xFF43c9f8, 0xFF43c8f9, 0xFF42c8f9, 0xFF42c7f9, 0xFF41c6f9, 0xFF41c6f9, + 0xFF40c5fa, 0xFF3ec3f9, 0xFF3dc2fa, 0xFF3bc1fa, 0xFF39c0fa, 0xFF38bff9, 0xFF36bff9, 0xFF35bef9, + 0xFF34bdf8, 0xFF33bcf9, 0xFF33bafa, 0xFF32b9fb, 0xFF32b8fc, 0xFF30b7fa, 0xFF2eb6f8, 0xFF2db5f7, + 0xFF2bb4f5, 0xFF2bb4f6, 0xFF2bb3f7, 0xFF2bb2f8, 0xFF2bb1f8, 0xFF22aff9, 0xFF19acfa, 0xFF1eadf7, + 0xFF24aef3, 0xFF20adf5, 0xFF1dabf6, 0xFF1fabf6, 0xFF20aaf5, 0xFF1fa9f6, 0xFF1ea8f7, 0xFF1da6f7, + 0xFF1ca5f8, 0xFF1ca4f8, 0xFF1ba3f9, 0xFF1ba3f9, 0xFF1ba2f9, 0xFF19a1f9, 0xFF18a0f8, 0xFF17a0f8, + 0xFF169ff8, 0xFF159ef7, 0xFF149df7, 0xFF139cf6, 0xFF129bf5, 0xFF129bf5, 0xFF129bf5, 0xFF129bf5, + 0xFF55d0f9, 0xFF53d0fa, 0xFF51d0fa, 0xFF4fcffa, 0xFF4dcffa, 0xFF4bcefa, 0xFF49cdf9, 0xFF46ccf9, + 0xFF44caf8, 0xFF43caf8, 0xFF43c9f8, 0xFF43c8f9, 0xFF42c8f9, 0xFF42c7f9, 0xFF41c6f9, 0xFF41c6f9, + 0xFF40c5fa, 0xFF3ec3f9, 0xFF3dc2fa, 0xFF3bc1fa, 0xFF39c0fa, 0xFF38bff9, 0xFF36bff9, 0xFF35bef9, + 0xFF34bdf8, 0xFF33bcf9, 0xFF33bafa, 0xFF32b9fb, 0xFF32b8fc, 0xFF30b7fa, 0xFF2eb6f8, 0xFF2db5f7, + 0xFF2bb4f5, 0xFF2bb4f6, 0xFF2bb3f7, 0xFF2bb2f8, 0xFF2bb1f8, 0xFF22aff9, 0xFF19acfa, 0xFF1eadf7, + 0xFF24aef3, 0xFF20adf5, 0xFF1dabf6, 0xFF1fabf6, 0xFF20aaf5, 0xFF1fa9f6, 0xFF1ea8f7, 0xFF1da6f7, + 0xFF1ca5f8, 0xFF1ca4f8, 0xFF1ba3f9, 0xFF1ba3f9, 0xFF1ba2f9, 0xFF19a1f9, 0xFF18a0f8, 0xFF17a0f8, + 0xFF169ff8, 0xFF159ef7, 0xFF149df7, 0xFF139cf6, 0xFF129bf5, 0xFF129bf5, 0xFF129bf5, 0xFF129bf5 +}; + +static int test_memcmp_offset(const BYTE* mem1, const BYTE* mem2, int size) +{ + int index = 0; + + while ((index < size) && (*mem1 == *mem2)) + { + mem1++; + mem2++; + index++; + } + + return (index == size) ? 1 : -index; +} + +static int test_memcmp_count(const BYTE* mem1, const BYTE* mem2, int size) +{ + int count = 0; + int index = 0; + + for (index = 0; index < size; index++) + { + if (*mem1 != *mem2) + count++; + + mem1++; + mem2++; + } + + return count; +} + +int TestPrimitivesYCbCr(int argc, char* argv[]) +{ + int cmp; + int cnt; + int size; + BYTE* actual; + BYTE* expected; + INT16* pYCbCr[3]; + const primitives_t* prims = primitives_get(); + static const prim_size_t roi_64x64 = { 64, 64 }; + + expected = (BYTE*) TEST_XRGB_IMAGE; + + size = 64 * 64 * 4; + actual = _aligned_malloc(size, 16); + + if (!actual) + return 1; + + ZeroMemory(actual, size); + + pYCbCr[0] = TEST_Y_COMPONENT; + pYCbCr[1] = TEST_CB_COMPONENT; + pYCbCr[2] = TEST_CR_COMPONENT; + + if (1) + { + prims->yCbCrToRGB_16s8u_P3AC4R((const INT16**) pYCbCr, 64 * 2, + actual, 64 * 4, &roi_64x64); + } + else + { + INT16* pSrcDst[3]; + + pSrcDst[0] = _aligned_malloc(4096 * 2, 16); + pSrcDst[1] = _aligned_malloc(4096 * 2, 16); + pSrcDst[2] = _aligned_malloc(4096 * 2, 16); + + CopyMemory(pSrcDst[0], pYCbCr[0], 4096 * 2); + CopyMemory(pSrcDst[1], pYCbCr[1], 4096 * 2); + CopyMemory(pSrcDst[2], pYCbCr[2], 4096 * 2); + + prims->yCbCrToRGB_16s16s_P3P3((const INT16**) pSrcDst, 64 * 2, + pSrcDst, 64 * 2, &roi_64x64); + + prims->RGBToRGB_16s8u_P3AC4R((const INT16**) pSrcDst, 64 * 2, + actual, 64 * 4, &roi_64x64); + + _aligned_free(pSrcDst[0]); + _aligned_free(pSrcDst[1]); + _aligned_free(pSrcDst[2]); + } + + cmp = test_memcmp_offset(actual, expected, size); + cnt = test_memcmp_count(actual, expected, size); + + if (cmp <= 0) + { + cmp *= -1; + float rate = ((float) cnt) / ((float) size) * 100.0f; + + printf("YCbCr to RGB conversion failure\n"); + + printf("Actual, Expected (offset: %d diff: %d/%d = %d%%):\n", + cmp, cnt, size, (int) rate); + + winpr_HexDump(&actual[cmp], 16); + winpr_HexDump(&expected[cmp], 16); + } + + _aligned_free(actual); + + return 0; +} + From 510a02ea94f7d7d114e21f1ec57a70e3e35e7581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Thu, 4 Sep 2014 16:52:41 -0400 Subject: [PATCH 27/30] libfreerdp-codec: improve progressive unit test --- .../codec/test/TestFreeRDPCodecProgressive.c | 43 +++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c index af35d1fc7..03533d2c1 100644 --- a/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c +++ b/libfreerdp/codec/test/TestFreeRDPCodecProgressive.c @@ -799,7 +799,7 @@ int test_progressive_load_bitmaps(char* ms_sample_path, EGFX_SAMPLE_FILE bitmaps return 1; } -static int test_memcmp(const BYTE* mem1, const BYTE* mem2, int size) +static int test_memcmp_offset(const BYTE* mem1, const BYTE* mem2, int size) { int index = 0; @@ -813,10 +813,29 @@ static int test_memcmp(const BYTE* mem1, const BYTE* mem2, int size) return (index == size) ? 1 : -index; } +static int test_memcmp_count(const BYTE* mem1, const BYTE* mem2, int size) +{ + int count = 0; + int index = 0; + + for (index = 0; index < size; index++) + { + if (*mem1 != *mem2) + count++; + + mem1++; + mem2++; + } + + return count; +} + int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE files[4], EGFX_SAMPLE_FILE bitmaps[4], int quarter, int count) { int cmp; + int cnt; int pass; + int size; int index; int status; int nXSrc, nYSrc; @@ -900,19 +919,23 @@ int test_progressive_decode(PROGRESSIVE_CONTEXT* progressive, EGFX_SAMPLE_FILE f PIXEL_FORMAT_XRGB32, 64 * 4, nXSrc, nYSrc); } - cmp = test_memcmp(g_DstData, bitmaps[pass].buffer, bitmaps[pass].size); + size = bitmaps[pass].size; + cmp = test_memcmp_offset(g_DstData, bitmaps[pass].buffer, size); + cnt = test_memcmp_count(g_DstData, bitmaps[pass].buffer, size); if (cmp <= 0) { + float rate = ((float) cnt) / ((float) size) * 100.0f; + cmp *= -1; - printf("bitmap decompression error: %d/%d\n", cmp, bitmaps[pass].size); + printf("Progressive RemoteFX decompression failure\n"); - printf("GOOD: "); - winpr_HexDump(&bitmaps[pass].buffer[cmp], 16); + printf("Actual, Expected (offset: %d diff: %d/%d = %.3f%%):\n", + cmp, cnt, size, rate); - printf("BAD: "); winpr_HexDump(&g_DstData[cmp], 16); + winpr_HexDump(&bitmaps[pass].buffer[cmp], 16); } //WLog_Image(progressive->log, WLOG_TRACE, g_DstData, g_Width, g_Height, 32); @@ -943,7 +966,7 @@ int test_progressive_ms_sample(char* ms_sample_path) if (status < 0) return -1; - count = 2; + count = 1; progressive = progressive_context_new(FALSE); @@ -955,6 +978,7 @@ int test_progressive_ms_sample(char* ms_sample_path) if (1) { + printf("Sample Image 1\n"); test_image_fill(g_DstData, g_DstStep, 0, 0, g_Width, g_Height, 0xFF000000); test_progressive_decode(progressive, files[0][0], bitmaps[0][0], 0, count); test_progressive_decode(progressive, files[0][1], bitmaps[0][1], 1, count); @@ -962,11 +986,11 @@ int test_progressive_ms_sample(char* ms_sample_path) test_progressive_decode(progressive, files[0][3], bitmaps[0][3], 3, count); } - /* image 2 */ + /* image 2 (incorrect) */ if (0) { - /* decompressed image set is incorrect for this one */ + printf("Sample Image 2\n"); test_image_fill(g_DstData, g_DstStep, 0, 0, g_Width, g_Height, 0xFF000000); test_progressive_decode(progressive, files[1][0], bitmaps[1][0], 0, count); test_progressive_decode(progressive, files[1][1], bitmaps[1][1], 1, count); @@ -978,6 +1002,7 @@ int test_progressive_ms_sample(char* ms_sample_path) if (0) { + printf("Sample Image 3\n"); test_image_fill(g_DstData, g_DstStep, 0, 0, g_Width, g_Height, 0xFF000000); test_progressive_decode(progressive, files[2][0], bitmaps[2][0], 0, count); test_progressive_decode(progressive, files[2][1], bitmaps[2][1], 1, count); From 66bbbf0519b145b0df26771fd7570e9570bbb0b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 5 Sep 2014 16:06:19 -0400 Subject: [PATCH 28/30] libfreerdp-gdi: enable altsec frame markers --- client/X11/xf_client.c | 69 +++++++++++++++++++++++--------------- client/X11/xf_gdi.c | 7 ++++ client/X11/xf_graphics.c | 1 - libfreerdp/core/settings.c | 2 +- libfreerdp/core/update.c | 2 ++ libfreerdp/gdi/gdi.c | 7 ++++ 6 files changed, 59 insertions(+), 29 deletions(-) diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 4df36d82f..a803edf74 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -180,31 +180,41 @@ void xf_draw_screen_scaled(xfContext *xfc, int x, int y, int w, int h, BOOL scal void xf_sw_begin_paint(rdpContext *context) { - rdpGdi *gdi = context->gdi; + rdpGdi* gdi = context->gdi; gdi->primary->hdc->hwnd->invalid->null = 1; gdi->primary->hdc->hwnd->ninvalid = 0; } void xf_sw_end_paint(rdpContext *context) { - rdpGdi *gdi; + int i; INT32 x, y; UINT32 w, h; - xfContext *xfc = (xfContext *) context; - gdi = context->gdi; - if(!xfc->remote_app) + int ninvalid; + HGDI_RGN cinvalid; + xfContext* xfc = (xfContext*) context; + rdpGdi* gdi = context->gdi; + + x = gdi->primary->hdc->hwnd->invalid->x; + y = gdi->primary->hdc->hwnd->invalid->y; + w = gdi->primary->hdc->hwnd->invalid->w; + h = gdi->primary->hdc->hwnd->invalid->h; + + ninvalid = gdi->primary->hdc->hwnd->ninvalid; + cinvalid = gdi->primary->hdc->hwnd->cinvalid; + + if (!xfc->remote_app) { - if(!xfc->complex_regions) + if (!xfc->complex_regions) { - if(gdi->primary->hdc->hwnd->invalid->null) + if (gdi->primary->hdc->hwnd->invalid->null) return; - x = gdi->primary->hdc->hwnd->invalid->x; - y = gdi->primary->hdc->hwnd->invalid->y; - w = gdi->primary->hdc->hwnd->invalid->w; - h = gdi->primary->hdc->hwnd->invalid->h; + xf_lock_x11(xfc, FALSE); + XPutImage(xfc->display, xfc->primary, xfc->gc, xfc->image, x, y, x, y, w, h); - if((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) + + if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) { xf_draw_screen_scaled(xfc, x, y, w, h, TRUE); } @@ -212,27 +222,27 @@ void xf_sw_end_paint(rdpContext *context) { XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y); } + xf_unlock_x11(xfc, FALSE); } else { - int i; - int ninvalid; - HGDI_RGN cinvalid; - if(gdi->primary->hdc->hwnd->ninvalid < 1) + if (gdi->primary->hdc->hwnd->ninvalid < 1) return; - ninvalid = gdi->primary->hdc->hwnd->ninvalid; - cinvalid = gdi->primary->hdc->hwnd->cinvalid; + xf_lock_x11(xfc, FALSE); - for(i = 0; i < ninvalid; i++) + + for (i = 0; i < ninvalid; i++) { x = cinvalid[i].x; y = cinvalid[i].y; w = cinvalid[i].w; h = cinvalid[i].h; + //combine xfc->primary with xfc->image XPutImage(xfc->display, xfc->primary, xfc->gc, xfc->image, x, y, x, y, w, h); - if((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) + + if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y)) { xf_draw_screen_scaled(xfc, x, y, w, h, TRUE); } @@ -241,20 +251,21 @@ void xf_sw_end_paint(rdpContext *context) XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y); } } + XFlush(xfc->display); + xf_unlock_x11(xfc, FALSE); } } else { - if(gdi->primary->hdc->hwnd->invalid->null) + if (gdi->primary->hdc->hwnd->invalid->null) return; - x = gdi->primary->hdc->hwnd->invalid->x; - y = gdi->primary->hdc->hwnd->invalid->y; - w = gdi->primary->hdc->hwnd->invalid->w; - h = gdi->primary->hdc->hwnd->invalid->h; + xf_lock_x11(xfc, FALSE); + xf_rail_paint(xfc, context->rail, x, y, x + w - 1, y + h - 1); + xf_unlock_x11(xfc, FALSE); } } @@ -264,12 +275,15 @@ void xf_sw_desktop_resize(rdpContext *context) rdpSettings *settings; xfContext *xfc = (xfContext *) context; settings = xfc->instance->settings; + xf_lock_x11(xfc, TRUE); - if(!xfc->fullscreen) + + if (!xfc->fullscreen) { rdpGdi *gdi = context->gdi; gdi_resize(gdi, xfc->width, xfc->height); - if(xfc->image) + + if (xfc->image) { xfc->image->data = NULL; XDestroyImage(xfc->image); @@ -277,6 +291,7 @@ void xf_sw_desktop_resize(rdpContext *context) (char *) gdi->primary_buffer, gdi->width, gdi->height, xfc->scanline_pad, 0); } } + xf_unlock_x11(xfc, TRUE); } diff --git a/client/X11/xf_gdi.c b/client/X11/xf_gdi.c index efd536d7f..c18846370 100644 --- a/client/X11/xf_gdi.c +++ b/client/X11/xf_gdi.c @@ -949,6 +949,11 @@ void xf_gdi_ellipse_cb(rdpContext* context, ELLIPSE_CB_ORDER* ellipse_cb) DEBUG_WARN( "EllipseCB\n"); } +void xf_gdi_frame_marker(rdpContext* context, FRAME_MARKER_ORDER* frameMarker) +{ + +} + void xf_gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker) { rdpSettings* settings; @@ -1187,5 +1192,7 @@ void xf_gdi_register_update_callbacks(rdpUpdate* update) update->SurfaceBits = xf_gdi_surface_bits; update->SurfaceFrameMarker = xf_gdi_surface_frame_marker; + + update->altsec->FrameMarker = xf_gdi_frame_marker; } diff --git a/client/X11/xf_graphics.c b/client/X11/xf_graphics.c index 971302ff3..330977684 100644 --- a/client/X11/xf_graphics.c +++ b/client/X11/xf_graphics.c @@ -389,7 +389,6 @@ void xf_Glyph_Draw(rdpContext* context, rdpGlyph* glyph, int x, int y) void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height, UINT32 bgcolor, UINT32 fgcolor) { - xfContext* context_ = (xfContext*) context; xfContext* xfc = (xfContext*) context; bgcolor = freerdp_color_convert_drawing_order_color_to_gdi_color(bgcolor, context->settings->ColorDepth, xfc->clrconv); diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index feb811967..0eec9b087 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -321,7 +321,7 @@ rdpSettings* freerdp_settings_new(DWORD flags) settings->DrawGdiPlusEnabled = FALSE; - settings->FrameMarkerCommandEnabled = FALSE; + settings->FrameMarkerCommandEnabled = TRUE; settings->SurfaceFrameMarkerEnabled = TRUE; settings->BitmapCacheV3Enabled = FALSE; diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index b400aaeed..11ff7c0a7 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -164,6 +164,8 @@ BOOL update_read_bitmap_update(rdpUpdate* update, wStream* s, BITMAP_UPDATE* bit Stream_Read_UINT16(s, bitmapUpdate->number); /* numberRectangles (2 bytes) */ + WLog_Print(update->log, WLOG_DEBUG, "BitmapUpdate: %d", bitmapUpdate->number); + if (bitmapUpdate->number > bitmapUpdate->count) { UINT16 count; diff --git a/libfreerdp/gdi/gdi.c b/libfreerdp/gdi/gdi.c index ee767cfd3..d78d780d9 100644 --- a/libfreerdp/gdi/gdi.c +++ b/libfreerdp/gdi/gdi.c @@ -764,6 +764,11 @@ void gdi_ellipse_cb(rdpContext* context, ELLIPSE_CB_ORDER* ellipse_cb) DEBUG_WARN( "EllipseCB\n"); } +void gdi_frame_marker(rdpContext* context, FRAME_MARKER_ORDER* frameMarker) +{ + +} + void gdi_surface_frame_marker(rdpContext* context, SURFACE_FRAME_MARKER* surface_frame_marker) { DEBUG_GDI("frameId %d frameAction %d", @@ -943,6 +948,8 @@ void gdi_register_update_callbacks(rdpUpdate* update) update->SurfaceBits = gdi_surface_bits; update->SurfaceFrameMarker = gdi_surface_frame_marker; + + update->altsec->FrameMarker = gdi_frame_marker; } void gdi_init_primary(rdpGdi* gdi) From f14b0e01959bfe249daed4fdba772fe1b93d1daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 5 Sep 2014 19:11:03 -0400 Subject: [PATCH 29/30] libfreerdp-codec: cleanup h264 decoder --- client/X11/xf_gfx.c | 6 - include/freerdp/codec/h264.h | 42 +- libfreerdp/codec/h264.c | 783 ++++++++++++++++++++++----------- libfreerdp/codec/progressive.c | 4 +- libfreerdp/utils/svc_plugin.c | 5 - 5 files changed, 555 insertions(+), 285 deletions(-) diff --git a/client/X11/xf_gfx.c b/client/X11/xf_gfx.c index 50e4bf8d5..3efdfdc8c 100644 --- a/client/X11/xf_gfx.c +++ b/client/X11/xf_gfx.c @@ -512,9 +512,6 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, return -1; } - printf("xf_SurfaceCommand_Progressive: status: %d surfaceId: %d contextId: %d\n", status, - cmd->surfaceId, cmd->contextId); - region = &(xfc->progressive->region); region16_init(&clippingRects); @@ -614,9 +611,6 @@ int xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd) int xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext) { - printf("DeleteEncodingContext: surfaceId: %d codecId: %d\n", - deleteEncodingContext->surfaceId, - deleteEncodingContext->codecContextId); return 1; } diff --git a/include/freerdp/codec/h264.h b/include/freerdp/codec/h264.h index 3c445d61a..61bfa1355 100644 --- a/include/freerdp/codec/h264.h +++ b/include/freerdp/codec/h264.h @@ -23,21 +23,22 @@ #include #include -#ifdef WITH_LIBAVCODEC -#ifdef WITH_OPENH264 -#undef WITH_OPENH264 -#endif -#endif +typedef struct _H264_CONTEXT H264_CONTEXT; -#ifdef WITH_OPENH264 -#include "wels/codec_def.h" -#include "wels/codec_api.h" -#endif +typedef BOOL (*pfnH264SubsystemInit)(H264_CONTEXT* h264); +typedef void (*pfnH264SubsystemUninit)(H264_CONTEXT* h264); -#ifdef WITH_LIBAVCODEC -#include -#include -#endif +typedef int (*pfnH264SubsystemDecompress)(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, + BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight); + +struct _H264_CONTEXT_SUBSYSTEM +{ + const char* name; + pfnH264SubsystemInit Init; + pfnH264SubsystemUninit Uninit; + pfnH264SubsystemDecompress Decompress; +}; +typedef struct _H264_CONTEXT_SUBSYSTEM H264_CONTEXT_SUBSYSTEM; struct _H264_CONTEXT { @@ -49,18 +50,9 @@ struct _H264_CONTEXT UINT32 height; int scanline; -#ifdef WITH_OPENH264 - ISVCDecoder* pDecoder; -#endif - -#ifdef WITH_LIBAVCODEC - AVCodec* codec; - AVCodecContext* codecContext; - AVCodecParserContext* codecParser; - AVFrame* videoFrame; -#endif + void* pSystemData; + H264_CONTEXT_SUBSYSTEM* subsystem; }; -typedef struct _H264_CONTEXT H264_CONTEXT; #ifdef __cplusplus extern "C" { @@ -71,8 +63,6 @@ FREERDP_API int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize FREERDP_API int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight); -FREERDP_API void h264_context_reset(H264_CONTEXT* h264); - FREERDP_API H264_CONTEXT* h264_context_new(BOOL Compressor); FREERDP_API void h264_context_free(H264_CONTEXT* h264); diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c index 9a5afb4ab..84095e7e7 100644 --- a/libfreerdp/codec/h264.c +++ b/libfreerdp/codec/h264.c @@ -28,65 +28,17 @@ #include #include -#define USE_GRAY_SCALE 0 -#define USE_UPCONVERT 0 - -#ifdef WITH_OPENH264 -static BYTE clip(int x) +static INLINE BYTE clip(int x) { if (x < 0) return 0; if (x > 255) return 255; - return (BYTE)x; + return (BYTE) x; } -static UINT32 YUV_to_RGB(BYTE Y, BYTE U, BYTE V) +static INLINE UINT32 YUV_to_RGB(BYTE Y, BYTE U, BYTE V) { - BYTE R, G, B; - -#if USE_GRAY_SCALE - /* - * Displays the Y plane as a gray-scale image. - */ - R = Y; - G = Y; - B = Y; -#else int C, D, E; - -#if 0 - /* - * Documented colorspace conversion from YUV to RGB. - * See http://msdn.microsoft.com/en-us/library/ms893078.aspx - */ - - C = Y - 16; - D = U - 128; - E = V - 128; - - R = clip(( 298 * C + 409 * E + 128) >> 8); - G = clip(( 298 * C - 100 * D - 208 * E + 128) >> 8); - B = clip(( 298 * C + 516 * D + 128) >> 8); -#endif - -#if 0 - /* - * These coefficients produce better results. - * See http://www.microchip.com/forums/m599060.aspx - */ - - C = Y; - D = U - 128; - E = V - 128; - - R = clip(( 256 * C + 359 * E + 128) >> 8); - G = clip(( 256 * C - 88 * D - 183 * E + 128) >> 8); - B = clip(( 256 * C + 454 * D + 128) >> 8); -#endif - -#if 1 - /* - * These coefficients produce excellent results. - */ + BYTE R, G, B; C = Y; D = U - 128; @@ -95,87 +47,524 @@ static UINT32 YUV_to_RGB(BYTE Y, BYTE U, BYTE V) R = clip(( 256 * C + 403 * E + 128) >> 8); G = clip(( 256 * C - 48 * D - 120 * E + 128) >> 8); B = clip(( 256 * C + 475 * D + 128) >> 8); -#endif - -#endif return RGB32(R, G, B); } -#endif /* WITH_OPENH264 */ -#if USE_UPCONVERT -static BYTE* convert_420_to_444(BYTE* chroma420, int chroma420Width, int chroma420Height, int chroma420Stride) +static int g_H264FrameId = 0; +static BOOL g_H264DumpFrames = FALSE; + +static void h264_dump_h264_data(BYTE* data, int size) { - BYTE *chroma444, *src, *dst; - int chroma444Width; - int chroma444Height; - int i, j; + FILE* fp; + char buf[4096]; - chroma444Width = chroma420Width * 2; - chroma444Height = chroma420Height * 2; - - chroma444 = (BYTE*) malloc(chroma444Width * chroma444Height); - - if (!chroma444) - return NULL; - - /* Upconvert in the horizontal direction. */ - - for (j = 0; j < chroma420Height; j++) - { - src = chroma420 + j * chroma420Stride; - dst = chroma444 + j * chroma444Width; - dst[0] = src[0]; - for (i = 1; i < chroma420Width; i++) - { - dst[2*i-1] = (3 * src[i-1] + src[i] + 2) >> 2; - dst[2*i] = (src[i-1] + 3 * src[i] + 2) >> 2; - } - dst[chroma444Width-1] = src[chroma420Width-1]; - } - - /* Upconvert in the vertical direction (in-place, bottom-up). */ - - for (i = 0; i < chroma444Width; i++) - { - src = chroma444 + i + (chroma420Height-2) * chroma444Width; - dst = chroma444 + i + (2*(chroma420Height-2)+1) * chroma444Width; - dst[2*chroma444Width] = src[chroma444Width]; - for (j = chroma420Height - 2; j >= 0; j--) - { - dst[chroma444Width] = (src[0] + 3 * src[chroma444Width] + 2) >> 2; - dst[0] = (3 * src[0] + src[chroma444Width] + 2) >> 2; - dst -= 2 * chroma444Width; - src -= chroma444Width; - } - } - - return chroma444; + snprintf(buf, sizeof(buf), "/tmp/wlog/bs_%d.h264", g_H264FrameId); + fp = fopen(buf, "wb"); + fwrite(data, 1, size, fp); + fflush(fp); + fclose(fp); } + +void h264_dump_yuv_data(BYTE* yuv[], int width, int height, int stride[]) +{ + FILE* fp; + BYTE* srcp; + char buf[4096]; + int j; + + snprintf(buf, sizeof(buf), "/tmp/wlog/H264_%d.ppm", g_H264FrameId); + fp = fopen(buf, "wb"); + fwrite("P5\n", 1, 3, fp); + snprintf(buf, sizeof(buf), "%d %d\n", width, height); + fwrite(buf, 1, strlen(buf), fp); + fwrite("255\n", 1, 4, fp); + + srcp = yuv[0]; + + for (j = 0; j < height; j++) + { + fwrite(srcp, 1, width, fp); + srcp += stride[0]; + } + + fflush(fp); + fclose(fp); +} + +int h264_prepare_rgb_buffer(H264_CONTEXT* h264, int width, int height) +{ + UINT32 size; + + h264->width = width; + h264->height = height; + h264->scanline = h264->width * 4; + size = h264->scanline * h264->height; + + if (size > h264->size) + { + h264->size = size; + h264->data = (BYTE*) realloc(h264->data, h264->size); + memset(h264->data, 0, h264->size); + } + + if (!h264->data) + return -1; + + return 1; +} + +int freerdp_image_copy_yuv420p_to_xrgb(BYTE* pDstData, int nDstStep, int nXDst, int nYDst, + int nWidth, int nHeight, BYTE* pSrcData[3], int nSrcStep[2], int nXSrc, int nYSrc) +{ + int x, y; + BYTE* pDstPixel8; + BYTE *pY, *pU, *pV; + int shift = 1; + + pY = pSrcData[0] + (nYSrc * nSrcStep[0]) + nXSrc; + + pDstPixel8 = &pDstData[(nYDst * nDstStep) + (nXDst * 4)]; + + for (y = 0; y < nHeight; y++) + { + pU = pSrcData[1] + ((nYSrc + y) >> shift) * nSrcStep[1]; + pV = pSrcData[2] + ((nYSrc + y) >> shift) * nSrcStep[1]; + + for (x = 0; x < nWidth; x++) + { + BYTE Y, U, V; + + Y = *pY; + U = pU[(nXSrc + x) >> shift]; + V = pV[(nXSrc + x) >> shift]; + + *((UINT32*) pDstPixel8) = YUV_to_RGB(Y, U, V); + + pDstPixel8 += 4; + pY++; + } + + pDstPixel8 += (nDstStep - (nWidth * 4)); + pY += (nSrcStep[0] - nWidth); + } + + return 1; +} + +/** + * Dummy subsystem + */ + +static int dummy_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, + BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) +{ + return -1; +} + +static void dummy_uninit(H264_CONTEXT* h264) +{ + +} + +static BOOL dummy_init(H264_CONTEXT* h264) +{ + return TRUE; +} + +static H264_CONTEXT_SUBSYSTEM g_Subsystem_dummy = +{ + "dummy", + dummy_init, + dummy_uninit, + dummy_decompress +}; + +/** + * OpenH264 subsystem + */ + +#ifdef WITH_OPENH264 + +#include "wels/codec_def.h" +#include "wels/codec_api.h" + +struct _H264_CONTEXT_OPENH264 +{ + ISVCDecoder* pDecoder; +}; +typedef struct _H264_CONTEXT_OPENH264 H264_CONTEXT_OPENH264; + +static BOOL g_openh264_trace_enabled = FALSE; + +static void openh264_trace_callback(H264_CONTEXT* h264, int level, const char* message) +{ + printf("%d - %s\n", level, message); +} + +static int openh264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, + BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) +{ + BYTE* pYUVData[3]; + DECODING_STATE state; + SBufferInfo sBufferInfo; + SSysMEMBuffer* pSystemBuffer; + H264_CONTEXT_OPENH264* sys = (H264_CONTEXT_OPENH264*) h264->pSystemData; + + if (!sys->pDecoder) + return -1; + + /* + * Decompress the image. The RDP host only seems to send I420 format. + */ + + pYUVData[0] = NULL; + pYUVData[1] = NULL; + pYUVData[2] = NULL; + + ZeroMemory(&sBufferInfo, sizeof(sBufferInfo)); + + state = (*sys->pDecoder)->DecodeFrame2( + sys->pDecoder, + pSrcData, + SrcSize, + pYUVData, + &sBufferInfo); + + /** + * Calling DecodeFrame2 twice apparently works around Openh264 issue #1136: + * https://github.com/cisco/openh264/issues/1136 + * + * This is a hack, but it works and it is only necessary for the first frame. + */ + + if (sBufferInfo.iBufferStatus != 1) + state = (*sys->pDecoder)->DecodeFrame2(sys->pDecoder, NULL, 0, pYUVData, &sBufferInfo); + + pSystemBuffer = &sBufferInfo.UsrData.sSystemBuffer; + +#if 0 + printf("h264_decompress: state=%u, pYUVData=[%p,%p,%p], bufferStatus=%d, width=%d, height=%d, format=%d, stride=[%d,%d]\n", + state, pYUVData[0], pYUVData[1], pYUVData[2], sBufferInfo.iBufferStatus, + pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iFormat, + pSystemBuffer->iStride[0], pSystemBuffer->iStride[1]); +#endif + + if (state != 0) + return -1; + + if (!pYUVData[0] || !pYUVData[1] || !pYUVData[2]) + return -1; + + if (sBufferInfo.iBufferStatus != 1) + return -1; + + if (pSystemBuffer->iFormat != videoFormatI420) + return -1; + + /* Convert I420 (same as IYUV) to XRGB. */ + + if (g_H264DumpFrames) + { + h264_dump_yuv_data(pYUVData, pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iStride); + } + + g_H264FrameId++; + + if (h264_prepare_rgb_buffer(h264, pSystemBuffer->iWidth, pSystemBuffer->iHeight) < 0) + return -1; + + freerdp_image_copy_yuv420p_to_xrgb(h264->data, h264->scanline, 0, 0, + h264->width, h264->height, pYUVData, pSystemBuffer->iStride, 0, 0); + + return 1; +} + +static void openh264_uninit(H264_CONTEXT* h264) +{ + H264_CONTEXT_OPENH264* sys = (H264_CONTEXT_OPENH264*) h264->pSystemData; + + if (sys) + { + if (sys->pDecoder) + { + (*sys->pDecoder)->Uninitialize(sys->pDecoder); + WelsDestroyDecoder(sys->pDecoder); + sys->pDecoder = NULL; + } + + free(sys); + h264->pSystemData = NULL; + } +} + +static BOOL openh264_init(H264_CONTEXT* h264) +{ + long status; + SDecodingParam sDecParam; + H264_CONTEXT_OPENH264* sys; + static int traceLevel = WELS_LOG_DEBUG; + static EVideoFormatType videoFormat = videoFormatI420; + static WelsTraceCallback traceCallback = (WelsTraceCallback) openh264_trace_callback; + + sys = (H264_CONTEXT_OPENH264*) calloc(1, sizeof(H264_CONTEXT_OPENH264)); + + if (!sys) + { + goto EXCEPTION; + } + + h264->pSystemData = (void*) sys; + + WelsCreateDecoder(&sys->pDecoder); + + if (!sys->pDecoder) + { + printf("Failed to create OpenH264 decoder\n"); + goto EXCEPTION; + } + + ZeroMemory(&sDecParam, sizeof(sDecParam)); + sDecParam.iOutputColorFormat = videoFormatI420; + sDecParam.uiEcActiveFlag = 1; + sDecParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT; + + status = (*sys->pDecoder)->Initialize(sys->pDecoder, &sDecParam); + + if (status != 0) + { + printf("Failed to initialize OpenH264 decoder (status=%ld)\n", status); + goto EXCEPTION; + } + + status = (*sys->pDecoder)->SetOption(sys->pDecoder, DECODER_OPTION_DATAFORMAT, &videoFormat); + + if (status != 0) + { + printf("Failed to set data format option on OpenH264 decoder (status=%ld)\n", status); + } + + if (g_openh264_trace_enabled) + { + status = (*sys->pDecoder)->SetOption(sys->pDecoder, DECODER_OPTION_TRACE_LEVEL, &traceLevel); + + if (status != 0) + { + printf("Failed to set trace level option on OpenH264 decoder (status=%ld)\n", status); + } + + status = (*sys->pDecoder)->SetOption(sys->pDecoder, DECODER_OPTION_TRACE_CALLBACK, &traceCallback); + + if (status != 0) + { + printf("Failed to set trace callback option on OpenH264 decoder (status=%ld)\n", status); + } + + status = (*sys->pDecoder)->SetOption(sys->pDecoder, DECODER_OPTION_TRACE_CALLBACK_CONTEXT, &h264); + + if (status != 0) + { + printf("Failed to set trace callback context option on OpenH264 decoder (status=%ld)\n", status); + } + } + + return TRUE; + +EXCEPTION: + openh264_uninit(h264); + + return FALSE; +} + +static H264_CONTEXT_SUBSYSTEM g_Subsystem_OpenH264 = +{ + "OpenH264", + openh264_init, + openh264_uninit, + openh264_decompress +}; + +#endif + +/** + * libavcodec subsystem + */ + +#ifdef WITH_LIBAVCODEC + +#include +#include + +struct _H264_CONTEXT_LIBAVCODEC +{ + AVCodec* codec; + AVCodecContext* codecContext; + AVCodecParserContext* codecParser; + AVFrame* videoFrame; +}; +typedef struct _H264_CONTEXT_LIBAVCODEC H264_CONTEXT_LIBAVCODEC; + +static int libavcodec_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, + BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) +{ + int status; + int gotFrame = 0; + AVPacket packet; + H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*) h264->pSystemData; + + av_init_packet(&packet); + + packet.data = pSrcData; + packet.size = SrcSize; + + status = avcodec_decode_video2(sys->codecContext, sys->videoFrame, &gotFrame, &packet); + + if (status < 0) + { + printf("Failed to decode video frame (status=%d)\n", status); + return -1; + } + + printf("libavcodec_decompress: frame decoded (status=%d, gotFrame=%d, width=%d, height=%d, Y=[%p,%d], U=[%p,%d], V=[%p,%d])\n", + status, gotFrame, sys->videoFrame->width, sys->videoFrame->height, + sys->videoFrame->data[0], sys->videoFrame->linesize[0], + sys->videoFrame->data[1], sys->videoFrame->linesize[1], + sys->videoFrame->data[2], sys->videoFrame->linesize[2]); + + fflush(stdout); + + if (gotFrame) + { + if (g_H264DumpFrames) + { + h264_dump_yuv_data(sys->videoFrame->data, sys->videoFrame->width, sys->videoFrame->height, sys->videoFrame->linesize); + } + + if (h264_prepare_rgb_buffer(h264, sys->videoFrame->width, sys->videoFrame->height) < 0) + return -1; + + freerdp_image_copy_yuv420p_to_xrgb(h264->data, h264->scanline, 0, 0, + h264->width, h264->height, sys->videoFrame->data, sys->videoFrame->linesize, 0, 0); + } + + return 1; +} + +static void libavcodec_uninit(H264_CONTEXT* h264) +{ + H264_CONTEXT_LIBAVCODEC* sys = (H264_CONTEXT_LIBAVCODEC*) h264->pSystemData; + + if (!sys) + return; + + if (sys->videoFrame) + { + av_free(sys->videoFrame); + } + + if (sys->codecParser) + { + av_parser_close(sys->codecParser); + } + + if (sys->codecContext) + { + avcodec_close(sys->codecContext); + av_free(sys->codecContext); + } + + free(sys); + h264->pSystemData = NULL; +} + +static BOOL libavcodec_init(H264_CONTEXT* h264) +{ + H264_CONTEXT_LIBAVCODEC* sys; + + sys = (H264_CONTEXT_LIBAVCODEC*) calloc(1, sizeof(H264_CONTEXT_LIBAVCODEC)); + + if (!sys) + { + goto EXCEPTION; + } + + h264->pSystemData = (void*) sys; + + avcodec_register_all(); + + sys->codec = avcodec_find_decoder(CODEC_ID_H264); + + if (!sys->codec) + { + printf("Failed to find libav H.264 codec\n"); + goto EXCEPTION; + } + + sys->codecContext = avcodec_alloc_context3(sys->codec); + + if (!sys->codecContext) + { + printf("Failed to allocate libav codec context\n"); + goto EXCEPTION; + } + + if (sys->codec->capabilities & CODEC_CAP_TRUNCATED) + { + sys->codecContext->flags |= CODEC_FLAG_TRUNCATED; + } + + if (avcodec_open2(sys->codecContext, sys->codec, NULL) < 0) + { + printf("Failed to open libav codec\n"); + goto EXCEPTION; + } + + sys->codecParser = av_parser_init(CODEC_ID_H264); + + if (!sys->codecParser) + { + printf("Failed to initialize libav parser\n"); + goto EXCEPTION; + } + + sys->videoFrame = avcodec_alloc_frame(); + + if (!sys->videoFrame) + { + printf("Failed to allocate libav frame\n"); + goto EXCEPTION; + } + + return TRUE; + +EXCEPTION: + libavcodec_uninit(h264); + + return FALSE; +} + +static H264_CONTEXT_SUBSYSTEM g_Subsystem_libavcodec = +{ + "libavcodec", + libavcodec_init, + libavcodec_uninit, + libavcodec_decompress +}; + #endif int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight) { -#ifdef WITH_OPENH264 - DECODING_STATE state; - SBufferInfo sBufferInfo; - SSysMEMBuffer* pSystemBuffer; - UINT32 UncompressedSize; BYTE* pDstData; - BYTE* pYUVData[3]; - BYTE* pY; - BYTE* pU; - BYTE* pV; - int Y, U, V; - int i, j; + UINT32 UncompressedSize; - if (!h264 || !h264->pDecoder) + if (!h264) return -1; #if 0 - DEBUG_MSG("h264_decompress: pSrcData=%p, SrcSize=%u, pDstData=%p, DstFormat=%lx, nDstStep=%d, nXDst=%d, nYDst=%d, nWidth=%d, nHeight=%d)\n", - pSrcData, SrcSize, *ppDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight); + printf("h264_decompress: pSrcData=%p, SrcSize=%u, pDstData=%p, nDstStep=%d, nXDst=%d, nYDst=%d, nWidth=%d, nHeight=%d)\n", + pSrcData, SrcSize, *ppDstData, nDstStep, nXDst, nYDst, nWidth, nHeight); #endif /* Allocate a destination buffer (if needed). */ @@ -197,87 +586,13 @@ int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, *ppDstData = pDstData; } - /* - * Decompress the image. The RDP host only seems to send I420 format. - */ - - pYUVData[0] = NULL; - pYUVData[1] = NULL; - pYUVData[2] = NULL; - - ZeroMemory(&sBufferInfo, sizeof(sBufferInfo)); - - state = (*h264->pDecoder)->DecodeFrame2( - h264->pDecoder, - pSrcData, - SrcSize, - pYUVData, - &sBufferInfo); - - pSystemBuffer = &sBufferInfo.UsrData.sSystemBuffer; - -#if 0 - DEBUG_MSG("h264_decompress: state=%u, pYUVData=[%p,%p,%p], bufferStatus=%d, width=%d, height=%d, format=%d, stride=[%d,%d]\n", - state, pYUVData[0], pYUVData[1], pYUVData[2], sBufferInfo.iBufferStatus, - pSystemBuffer->iWidth, pSystemBuffer->iHeight, pSystemBuffer->iFormat, - pSystemBuffer->iStride[0], pSystemBuffer->iStride[1]); -#endif - - if (state != 0) - return -1; - - if (!pYUVData[0] || !pYUVData[1] || !pYUVData[2]) - return -1; - - if (sBufferInfo.iBufferStatus != 1) - return -1; - - if (pSystemBuffer->iFormat != videoFormatI420) - return -1; - - /* Convert I420 (same as IYUV) to XRGB. */ - - pY = pYUVData[0]; - pU = pYUVData[1]; - pV = pYUVData[2]; - -#if USE_UPCONVERT - /* Convert 4:2:0 YUV to 4:4:4 YUV. */ - pU = convert_420_to_444(pU, pSystemBuffer->iWidth / 2, pSystemBuffer->iHeight / 2, pSystemBuffer->iStride[1]); - pV = convert_420_to_444(pV, pSystemBuffer->iWidth / 2, pSystemBuffer->iHeight / 2, pSystemBuffer->iStride[1]); -#endif - - for (j = 0; j < nHeight; j++) + if (g_H264DumpFrames) { - BYTE *pXRGB = pDstData + ((nYDst + j) * nDstStep) + (nXDst * 4); - int y = nYDst + j; - - for (i = 0; i < nWidth; i++) - { - int x = nXDst + i; - - Y = pY[(y * pSystemBuffer->iStride[0]) + x]; -#if USE_UPCONVERT - U = pU[(y * pSystemBuffer->iWidth) + x]; - V = pV[(y * pSystemBuffer->iWidth) + x]; -#else - U = pU[(y/2) * pSystemBuffer->iStride[1] + (x/2)]; - V = pV[(y/2) * pSystemBuffer->iStride[1] + (x/2)]; -#endif - - *(UINT32*)pXRGB = YUV_to_RGB(Y, U, V); - - pXRGB += 4; - } + h264_dump_h264_data(pSrcData, SrcSize); } -#if USE_UPCONVERT - free(pU); - free(pV); -#endif -#endif - - return 1; + return h264->subsystem->Decompress(h264, pSrcData, SrcSize, + pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight); } int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize) @@ -285,9 +600,25 @@ int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize, BYTE** ppD return 1; } -void h264_context_reset(H264_CONTEXT* h264) +BOOL h264_context_init(H264_CONTEXT* h264) { +#ifdef WITH_LIBAVCODEC + if (g_Subsystem_libavcodec.Init(h264)) + { + h264->subsystem = &g_Subsystem_libavcodec; + return TRUE; + } +#endif +#ifdef WITH_OPENH264 + if (g_Subsystem_OpenH264.Init(h264)) + { + h264->subsystem = &g_Subsystem_OpenH264; + return TRUE; + } +#endif + + return FALSE; } H264_CONTEXT* h264_context_new(BOOL Compressor) @@ -300,69 +631,29 @@ H264_CONTEXT* h264_context_new(BOOL Compressor) { h264->Compressor = Compressor; -#ifdef WITH_OPENH264 + h264->subsystem = &g_Subsystem_dummy; + + if (h264_prepare_rgb_buffer(h264, 256, 256) < 0) + return NULL; + + if (!h264_context_init(h264)) { - static EVideoFormatType videoFormat = videoFormatI420; - - SDecodingParam sDecParam; - long status; - - WelsCreateDecoder(&h264->pDecoder); - - if (!h264->pDecoder) - { - DEBUG_MSG("Failed to create OpenH264 decoder\n"); - goto EXCEPTION; - } - - ZeroMemory(&sDecParam, sizeof(sDecParam)); - sDecParam.iOutputColorFormat = videoFormatARGB; - status = (*h264->pDecoder)->Initialize(h264->pDecoder, &sDecParam); - if (status != 0) - { - DEBUG_MSG("Failed to initialize OpenH264 decoder (status=%ld)\n", status); - goto EXCEPTION; - } - - status = (*h264->pDecoder)->SetOption(h264->pDecoder, DECODER_OPTION_DATAFORMAT, &videoFormat); - if (status != 0) - { - DEBUG_MSG("Failed to set data format option on OpenH264 decoder (status=%ld)\n", status); - } + free(h264); + return NULL; } -#endif - - h264_context_reset(h264); } return h264; - -#ifdef WITH_OPENH264 -EXCEPTION: - if (h264->pDecoder) - { - WelsDestroyDecoder(h264->pDecoder); - } -#endif - - free(h264); - - return NULL; } void h264_context_free(H264_CONTEXT* h264) { if (h264) { -#ifdef WITH_OPENH264 - if (h264->pDecoder) - { - (*h264->pDecoder)->Uninitialize(h264->pDecoder); - WelsDestroyDecoder(h264->pDecoder); - } -#endif + free(h264->data); + + h264->subsystem->Uninit(h264); free(h264); } } - diff --git a/libfreerdp/codec/progressive.c b/libfreerdp/codec/progressive.c index f63b6896b..69092d161 100644 --- a/libfreerdp/codec/progressive.c +++ b/libfreerdp/codec/progressive.c @@ -1710,8 +1710,8 @@ int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UIN if (!region->tiles) return -1; - printf("numRects: %d numTiles: %d numQuant: %d numProgQuant: %d\n", - region->numRects, region->numTiles, region->numQuant, region->numProgQuant); + //printf("numRects: %d numTiles: %d numQuant: %d numProgQuant: %d\n", + // region->numRects, region->numTiles, region->numQuant, region->numProgQuant); status = progressive_process_tiles(progressive, &block[boffset], region->tileDataSize, surface); diff --git a/libfreerdp/utils/svc_plugin.c b/libfreerdp/utils/svc_plugin.c index a52763852..a96c36079 100644 --- a/libfreerdp/utils/svc_plugin.c +++ b/libfreerdp/utils/svc_plugin.c @@ -114,11 +114,6 @@ static void svc_plugin_process_received(rdpSvcPlugin* plugin, void* pData, UINT3 if (dataFlags & CHANNEL_FLAG_LAST) { - if (Stream_Capacity(s) != Stream_GetPosition(s)) - { - DEBUG_WARN( "svc_plugin_process_received: read error\n"); - } - plugin->data_in = NULL; Stream_SealLength(s); Stream_SetPosition(s, 0); From fe75405d5c59a273d9a5f71c5a2c90873ade5d40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Fri, 5 Sep 2014 19:38:33 -0400 Subject: [PATCH 30/30] libfreerdp-codec: fix build on Windows --- libfreerdp/codec/h264.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c index 84095e7e7..c32fc9727 100644 --- a/libfreerdp/codec/h264.c +++ b/libfreerdp/codec/h264.c @@ -59,7 +59,7 @@ static void h264_dump_h264_data(BYTE* data, int size) FILE* fp; char buf[4096]; - snprintf(buf, sizeof(buf), "/tmp/wlog/bs_%d.h264", g_H264FrameId); + sprintf_s(buf, sizeof(buf), "/tmp/wlog/bs_%d.h264", g_H264FrameId); fp = fopen(buf, "wb"); fwrite(data, 1, size, fp); fflush(fp); @@ -73,10 +73,10 @@ void h264_dump_yuv_data(BYTE* yuv[], int width, int height, int stride[]) char buf[4096]; int j; - snprintf(buf, sizeof(buf), "/tmp/wlog/H264_%d.ppm", g_H264FrameId); + sprintf_s(buf, sizeof(buf), "/tmp/wlog/H264_%d.ppm", g_H264FrameId); fp = fopen(buf, "wb"); fwrite("P5\n", 1, 3, fp); - snprintf(buf, sizeof(buf), "%d %d\n", width, height); + sprintf_s(buf, sizeof(buf), "%d %d\n", width, height); fwrite(buf, 1, strlen(buf), fp); fwrite("255\n", 1, 4, fp);