Fixed progressive decoding without subbanddiff
authorakallabeth <akallabeth@posteo.net>
Tue, 15 Dec 2020 08:58:37 +0000 (09:58 +0100)
committerakallabeth <akallabeth@users.noreply.github.com>
Thu, 25 Feb 2021 08:51:41 +0000 (09:51 +0100)
(cherry picked from commit e3445eefab77c6666d760fa042f141c0a2d2965a)

include/freerdp/codec/progressive.h
libfreerdp/codec/progressive.c
libfreerdp/codec/rfx_decode.c
libfreerdp/codec/rfx_decode.h
libfreerdp/codec/rfx_dwt.c
libfreerdp/codec/rfx_dwt.h
libfreerdp/codec/test/CMakeLists.txt
libfreerdp/codec/test/TestFreeRDPCodecProgressive.c
libfreerdp/codec/test/progressive.bmp [new file with mode: 0644]
server/proxy/pf_context.c
server/shadow/shadow_client.c

index dda22f8..37b289a 100644 (file)
@@ -38,7 +38,10 @@ extern "C"
 #endif
 
        FREERDP_API int progressive_compress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
-                                            UINT32 SrcSize, BYTE** ppDstData, UINT32* pDstSize);
+                                            UINT32 SrcSize, UINT32 SrcFormat, UINT32 Width,
+                                            UINT32 Height, UINT32 ScanLine,
+                                            const REGION16* invalidRegion, BYTE** ppDstData,
+                                            UINT32* pDstSize);
 
        FREERDP_API INT32 progressive_decompress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
                                                 UINT32 SrcSize, BYTE* pDstData, UINT32 DstFormat,
index 6c5f7ee..0ebea47 100644 (file)
@@ -2466,7 +2466,7 @@ int progressive_compress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
        RFX_RECT* rects = NULL;
        RFX_MESSAGE* message;
 
-       if (!progressive || !pSrcData || !ppDstData || !pDstSize)
+       if (!progressive || !pSrcData || !ppDstData || !pDstSize || !invalidRegion)
        {
                return -1;
        }
@@ -2494,57 +2494,34 @@ int progressive_compress(PROGRESSIVE_CONTEXT* progressive, const BYTE* pSrcData,
        if (SrcSize < Height * ScanLine)
                return -4;
 
-       if (!invalidRegion)
-       {
-               numRects = (Width + 63) / 64;
-               numRects *= (Height + 63) / 64;
-       }
-       else
-               numRects = region16_n_rects(invalidRegion);
-
-       if (numRects == 0)
-               return 0;
-
+       numRects = (Width + 63) / 64;
+       numRects *= (Height + 63) / 64;
        if (!Stream_EnsureCapacity(progressive->rects, numRects * sizeof(RFX_RECT)))
                return -5;
        rects = (RFX_RECT*)Stream_Buffer(progressive->rects);
-       if (invalidRegion)
-       {
-               const RECTANGLE_16* r = region16_rects(invalidRegion, NULL);
-               for (x = 0; x < numRects; x++)
-               {
-                       rects[x].x = r[x].left;
-                       rects[x].y = r[x].top;
-                       rects[x].width = r[x].right - r[x].left;
-                       rects[x].height = r[x].bottom - r[x].top;
-               }
-       }
-       else
-       {
-               x = 0;
-               y = 0;
-               for (i = 0; i < numRects; i++)
-               {
-                       RFX_RECT* r = &rects[i];
-                       r->x = x;
-                       r->y = y;
-                       r->width = MIN(64, Width - x);
-                       r->height = MIN(64, Height - y);
-
-                       if (x + 64 >= Width)
-                       {
-                               y += 64;
-                               x = 0;
-                       }
-                       else
-                               x += 64;
-               }
-       }
        s = progressive->buffer;
        Stream_SetPosition(s, 0);
 
        progressive->rfx_context->mode = RLGR1;
 
+       x = 0;
+       y = 0;
+       for (i = 0; i < numRects; i++)
+       {
+               RFX_RECT* r = &rects[i];
+               r->x = x;
+               r->y = y;
+               r->width = MIN(64, Width - x);
+               r->height = MIN(64, Height - y);
+
+               if (x + 64 >= Width)
+               {
+                       y += 64;
+                       x = 0;
+               }
+               else
+                       x += 64;
+       }
        message = rfx_encode_message(progressive->rfx_context, rects, numRects, pSrcData, Width, Height,
                                     ScanLine);
        if (!message)
index 69866c7..56add75 100644 (file)
@@ -37,8 +37,8 @@
 
 #include "rfx_decode.h"
 
-static void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantization_values,
-                                 const BYTE* data, int size, INT16* buffer)
+void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantization_values, const BYTE* data,
+                          int size, INT16* buffer)
 {
        INT16* dwt_buffer;
        dwt_buffer = BufferPool_Take(context->priv->BufferPool, -1); /* dwt_buffer */
index 638d45f..f973fd5 100644 (file)
@@ -26,5 +26,6 @@
 /* stride is bytes between rows in the output buffer. */
 FREERDP_LOCAL BOOL rfx_decode_rgb(RFX_CONTEXT* context, const RFX_TILE* tile, BYTE* rgb_buffer,
                                   UINT32 stride);
-
+FREERDP_LOCAL void rfx_decode_component(RFX_CONTEXT* context, const UINT32* quantization_values,
+                                        const BYTE* data, int size, INT16* buffer);
 #endif /* FREERDP_LIB_CODEC_RFX_DECODE_H */
index 4c727cd..4079938 100644 (file)
@@ -27,7 +27,7 @@
 
 #include "rfx_dwt.h"
 
-void rfx_dwt_2d_decode_block(INT16* buffer, INT16* idwt, int subband_width)
+static void rfx_dwt_2d_decode_block(INT16* buffer, INT16* idwt, int subband_width)
 {
        INT16 *dst, *l, *h;
        INT16 *l_dst, *h_dst;
index d2de9e9..f5b4692 100644 (file)
@@ -23,7 +23,6 @@
 #include <freerdp/codec/rfx.h>
 #include <freerdp/api.h>
 
-FREERDP_LOCAL void rfx_dwt_2d_decode_block(INT16* buffer, INT16* idwt, int subband_width);
 FREERDP_LOCAL void rfx_dwt_2d_decode(INT16* buffer, INT16* dwt_buffer);
 FREERDP_LOCAL void rfx_dwt_2d_encode(INT16* buffer, INT16* dwt_buffer);
 
index 1334940..4258b50 100644 (file)
@@ -20,6 +20,8 @@ create_test_sourcelist(${MODULE_PREFIX}_SRCS
        ${${MODULE_PREFIX}_DRIVER}
        ${${MODULE_PREFIX}_TESTS})
 
+add_definitions(-DCMAKE_CURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
+add_definitions(-DCMAKE_CURRENT_BINARY_DIR="${CMAKE_CURRENT_BINARY_DIR}")
 add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
 
 target_link_libraries(${MODULE_NAME} freerdp winpr)
index 8bdd014..515a4a0 100644 (file)
@@ -4,6 +4,7 @@
 #include <winpr/image.h>
 #include <winpr/print.h>
 #include <winpr/wlog.h>
+#include <winpr/image.h>
 #include <winpr/sysinfo.h>
 
 #include <freerdp/codec/region.h>
@@ -267,7 +268,7 @@ static int test_image_fill_unused_quarters(BYTE* pDstData, int nDstStep, int nWi
        return 1;
 }
 
-static BYTE* test_progressive_load_file(char* path, char* file, size_t* size)
+static BYTE* test_progressive_load_file(const char* path, const char* file, size_t* size)
 {
        FILE* fp;
        BYTE* buffer;
@@ -1017,30 +1018,141 @@ static int test_progressive_ms_sample(char* ms_sample_path)
        return 0;
 }
 
+static BOOL diff(BYTE a, BYTE b)
+{
+       BYTE big = MAX(a, b);
+       BYTE little = MIN(a, b);
+       if (big - little <= 0x25)
+               return TRUE;
+       return FALSE;
+}
+
+static BOOL colordiff(UINT32 format, UINT32 a, UINT32 b)
+{
+       BYTE ar, ag, ab, aa;
+       BYTE br, bg, bb, ba;
+       SplitColor(a, format, &ar, &ag, &ab, &aa, NULL);
+       SplitColor(b, format, &br, &bg, &bb, &ba, NULL);
+       if (!diff(aa, ba) || !diff(ar, br) || !diff(ag, bg) || !diff(ab, bb))
+               return FALSE;
+       return TRUE;
+}
+
+static BOOL test_encode_decode(const char* path)
+{
+       int x, y;
+       BOOL res = FALSE;
+       int rc;
+       BYTE* resultData = NULL;
+       BYTE* dstData = NULL;
+       UINT32 dstSize = 0;
+       UINT32 ColorFormat = PIXEL_FORMAT_BGRX32;
+       REGION16 invalidRegion = { 0 };
+       wImage* image = winpr_image_new();
+       wImage* dstImage = winpr_image_new();
+       char* name = GetCombinedPath(path, "progressive.bmp");
+       PROGRESSIVE_CONTEXT* progressiveEnc = progressive_context_new(TRUE);
+       PROGRESSIVE_CONTEXT* progressiveDec = progressive_context_new(FALSE);
+
+       region16_init(&invalidRegion);
+       if (!image || !dstImage || !name || !progressiveEnc || !progressiveDec)
+               goto fail;
+
+       rc = winpr_image_read(image, name);
+       if (rc <= 0)
+               goto fail;
+
+       resultData = calloc(image->scanline, image->height);
+       if (!resultData)
+               goto fail;
+
+       // Progressive encode
+       rc = progressive_compress(progressiveEnc, image->data, image->scanline * image->height,
+                                 ColorFormat, image->width, image->height, image->scanline,
+                                 &invalidRegion, &dstData, &dstSize);
+
+       // Progressive decode
+       rc = progressive_create_surface_context(progressiveDec, 0, image->width, image->height);
+       if (rc <= 0)
+               goto fail;
+
+       rc = progressive_decompress(progressiveDec, dstData, dstSize, resultData, ColorFormat,
+                                   image->scanline, 0, 0, &invalidRegion, 0);
+       if (rc < 0)
+               goto fail;
+
+       // Compare result
+       if (0) // Dump result image for manual inspection
+       {
+               *dstImage = *image;
+               dstImage->data = resultData;
+               winpr_image_write(dstImage, "/tmp/test.bmp");
+       }
+       for (y = 0; y < image->height; y++)
+       {
+               const BYTE* orig = &image->data[y * image->scanline];
+               const BYTE* dec = &resultData[y * image->scanline];
+               for (x = 0; x < image->width; x++)
+               {
+                       const BYTE* po = &orig[x * 4];
+                       const BYTE* pd = &dec[x * 4];
+
+                       const DWORD a = ReadColor(po, ColorFormat);
+                       const DWORD b = ReadColor(pd, ColorFormat);
+                       if (!colordiff(ColorFormat, a, b))
+                       {
+                               printf("xxxxxxx [%u:%u] %08X != %08X\n", x, y, a, b);
+                               goto fail;
+                       }
+               }
+       }
+       res = TRUE;
+fail:
+       region16_uninit(&invalidRegion);
+       progressive_context_free(progressiveEnc);
+       progressive_context_free(progressiveDec);
+       winpr_image_free(image, TRUE);
+       winpr_image_free(dstImage, FALSE);
+       free(resultData);
+       free(name);
+       return res;
+}
+
 int TestFreeRDPCodecProgressive(int argc, char* argv[])
 {
+       int rc = -1;
        char* ms_sample_path;
        char name[8192];
        SYSTEMTIME systemTime;
        WINPR_UNUSED(argc);
        WINPR_UNUSED(argv);
+
        GetSystemTime(&systemTime);
        sprintf_s(name, sizeof(name),
                  "EGFX_PROGRESSIVE_MS_SAMPLE-%04" PRIu16 "%02" PRIu16 "%02" PRIu16 "%02" PRIu16
                  "%02" PRIu16 "%02" PRIu16 "%04" PRIu16,
                  systemTime.wYear, systemTime.wMonth, systemTime.wDay, systemTime.wHour,
                  systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds);
-       ms_sample_path = GetKnownSubPath(KNOWN_PATH_TEMP, name);
+       ms_sample_path = _strdup(CMAKE_CURRENT_SOURCE_DIR);
 
        if (!ms_sample_path)
        {
                printf("Memory allocation failed\n");
-               return -1;
+               goto fail;
        }
 
        if (PathFileExistsA(ms_sample_path))
-               return test_progressive_ms_sample(ms_sample_path);
+       {
+               /*
+               if (test_progressive_ms_sample(ms_sample_path) < 0)
+                   goto fail;
+                   */
+               if (!test_encode_decode(ms_sample_path))
+                       goto fail;
+               rc = 0;
+       }
 
+fail:
        free(ms_sample_path);
-       return 0;
+       return rc;
 }
diff --git a/libfreerdp/codec/test/progressive.bmp b/libfreerdp/codec/test/progressive.bmp
new file mode 100644 (file)
index 0000000..1b19c3b
Binary files /dev/null and b/libfreerdp/codec/test/progressive.bmp differ
index 552eb79..f5d5890 100644 (file)
@@ -39,8 +39,9 @@ static wHashTable* create_channel_ids_map()
 }
 
 /* Proxy context initialization callback */
-static BOOL client_to_proxy_context_new(freerdp_peer* client, pServerContext* context)
+static BOOL client_to_proxy_context_new(freerdp_peer* client, rdpContext* ctx)
 {
+       pServerContext* context = (pServerContext*)ctx;
        proxyServer* server = (proxyServer*)client->ContextExtra;
        proxyConfig* config = server->config;
 
@@ -82,8 +83,9 @@ error:
 }
 
 /* Proxy context free callback */
-static void client_to_proxy_context_free(freerdp_peer* client, pServerContext* context)
+static void client_to_proxy_context_free(freerdp_peer* client, rdpContext* ctx)
 {
+       pServerContext* context = (pServerContext*)ctx;
        proxyServer* server;
 
        if (!client || !context)
@@ -106,8 +108,8 @@ static void client_to_proxy_context_free(freerdp_peer* client, pServerContext* c
 BOOL pf_context_init_server_context(freerdp_peer* client)
 {
        client->ContextSize = sizeof(pServerContext);
-       client->ContextNew = (psPeerContextNew)client_to_proxy_context_new;
-       client->ContextFree = (psPeerContextFree)client_to_proxy_context_free;
+       client->ContextNew = client_to_proxy_context_new;
+       client->ContextFree = client_to_proxy_context_free;
 
        return freerdp_peer_context_new(client);
 }
index 86bc3fc..d37e550 100644 (file)
@@ -927,11 +927,11 @@ static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, BYTE* pSrcD
                                             int nXSrc, int nYSrc, int nWidth, int nHeight)
 {
        BOOL ret = TRUE;
-       int i;
+       size_t i;
        BOOL first;
        BOOL last;
        wStream* s;
-       int numMessages;
+       size_t numMessages;
        UINT32 frameId = 0;
        rdpUpdate* update;
        rdpContext* context = (rdpContext*)client;