libfreerdp-codec: make planar codec encoder context reusable
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Sun, 8 Dec 2013 22:06:59 +0000 (17:06 -0500)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Sun, 8 Dec 2013 22:06:59 +0000 (17:06 -0500)
include/freerdp/codec/bitmap.h
libfreerdp/codec/planar.c
libfreerdp/codec/planar.h
libfreerdp/codec/test/TestFreeRDPCodecPlanar.c

index 1dc7c25..6e09f2d 100644 (file)
@@ -33,7 +33,17 @@ FREERDP_API BOOL bitmap_decompress(BYTE* srcData, BYTE* dstData, int width, int
 FREERDP_API int freerdp_bitmap_compress(char* in_data, int width, int height,
                wStream* s, int bpp, int byte_limit, int start_line, wStream* temp_s, int e);
 
-FREERDP_API BYTE* freerdp_bitmap_compress_planar(BYTE* data, UINT32 format, int width, int height,
-               int scanline, BYTE* dstData, int* dstSize);
+#define PLANAR_FORMAT_HEADER_CS                (1 << 3)
+#define PLANAR_FORMAT_HEADER_RLE       (1 << 4)
+#define PLANAR_FORMAT_HEADER_NA                (1 << 5)
+#define PLANAR_FORMAT_HEADER_CLL_MASK  0x07
+
+typedef struct _BITMAP_PLANAR_CONTEXT BITMAP_PLANAR_CONTEXT;
+
+FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format,
+               int width, int height, int scanline, BYTE* dstData, int* dstSize);
+
+FREERDP_API BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, int maxWidth, int maxHeight);
+FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context);
 
 #endif /* FREERDP_CODEC_BITMAP_H */
index 6829bd1..4a66f87 100644 (file)
@@ -263,7 +263,7 @@ int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, in
        return (size == (srcp - srcData)) ? 0 : -1;
 }
 
-int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[5])
+int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[4])
 {
        int bpp;
        int i, j, k;
@@ -629,7 +629,7 @@ BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* inPlane, int width, int hei
        return outPlane;
 }
 
-int freerdp_bitmap_planar_compress_planes_rle(BYTE* inPlanes[5], int width, int height, BYTE* outPlanes, int* dstSizes)
+int freerdp_bitmap_planar_compress_planes_rle(BYTE* inPlanes[4], int width, int height, BYTE* outPlanes, int* dstSizes)
 {
        int outPlanesSize = width * height * 4;
 
@@ -713,7 +713,7 @@ BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int hei
        return outPlane;
 }
 
-int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[5], int width, int height, BYTE* outPlanes[5])
+int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[4], int width, int height, BYTE* outPlanes[4])
 {
        freerdp_bitmap_planar_delta_encode_plane(inPlanes[0], width, height, outPlanes[0]);
        freerdp_bitmap_planar_delta_encode_plane(inPlanes[1], width, height, outPlanes[1]);
@@ -723,88 +723,47 @@ int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[5], int width, int
        return 0;
 }
 
-//static int g_Count = 0;
-
-BYTE* freerdp_bitmap_compress_planar(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* dstData, int* dstSize)
+BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format,
+               int width, int height, int scanline, BYTE* dstData, int* dstSize)
 {
        int size;
        BYTE* dstp;
        int planeSize;
        int dstSizes[4];
-       BYTE* planes[5];
-       BYTE* planesBuffer;
-       BYTE* deltaPlanes[5];
-       BYTE* deltaPlanesBuffer;
-       BYTE* rlePlanes[4];
-       BYTE* rlePlanesBuffer;
        BYTE FormatHeader = 0;
 
-       FormatHeader |= PLANAR_FORMAT_HEADER_NA;
+       if (context->AllowSkipAlpha)
+               FormatHeader |= PLANAR_FORMAT_HEADER_NA;
 
        planeSize = width * height;
 
-       planesBuffer = malloc(planeSize * 5);
-       planes[0] = &planesBuffer[planeSize * 0];
-       planes[1] = &planesBuffer[planeSize * 1];
-       planes[2] = &planesBuffer[planeSize * 2];
-       planes[3] = &planesBuffer[planeSize * 3];
-       planes[4] = &planesBuffer[planeSize * 4];
-
-       deltaPlanesBuffer = malloc(planeSize * 5);
-       deltaPlanes[0] = &deltaPlanesBuffer[planeSize * 0];
-       deltaPlanes[1] = &deltaPlanesBuffer[planeSize * 1];
-       deltaPlanes[2] = &deltaPlanesBuffer[planeSize * 2];
-       deltaPlanes[3] = &deltaPlanesBuffer[planeSize * 3];
-       deltaPlanes[4] = &deltaPlanesBuffer[planeSize * 4];
-
-       rlePlanesBuffer = malloc(planeSize * 4);
-
-       freerdp_split_color_planes(data, format, width, height, scanline, planes);
-
-       freerdp_bitmap_planar_delta_encode_planes(planes, width, height, deltaPlanes);
+       freerdp_split_color_planes(data, format, width, height, scanline, context->planes);
 
-#if 0
+       if (context->AllowRunLengthEncoding)
        {
-               g_Count++;
-               BYTE* bitmap;
-               int bitmapLength;
-
-               bitmapLength = width * height * 4;
-               bitmap = malloc(width * height * 4);
-               ZeroMemory(bitmap, bitmapLength);
-
-               freerdp_bitmap_planar_decompress_plane_raw(planes[0], width, height, bitmap + 3, planeSize); /* A */
-               freerdp_bitmap_planar_decompress_plane_raw(planes[1], width, height, bitmap + 2, planeSize); /* R */
-               freerdp_bitmap_planar_decompress_plane_raw(planes[2], width, height, bitmap + 1, planeSize); /* G */
-               freerdp_bitmap_planar_decompress_plane_raw(planes[3], width, height, bitmap + 0, planeSize); /* B */
+               freerdp_bitmap_planar_delta_encode_planes(context->planes, width, height, context->deltaPlanes);
 
-               printf("Bitmap %02d\n", g_Count);
-               winpr_CArrayDump(bitmap, bitmapLength, 32);
-
-               free(bitmap);
-       }
-#endif
-
-       if (freerdp_bitmap_planar_compress_planes_rle(deltaPlanes, width, height, rlePlanesBuffer, (int*) &dstSizes) > 0)
-       {
-               int offset = 0;
+               if (freerdp_bitmap_planar_compress_planes_rle(context->deltaPlanes, width, height, context->rlePlanesBuffer, (int*) &dstSizes) > 0)
+               {
+                       int offset = 0;
 
-               FormatHeader |= PLANAR_FORMAT_HEADER_RLE;
+                       FormatHeader |= PLANAR_FORMAT_HEADER_RLE;
 
-               rlePlanes[0] = &rlePlanesBuffer[offset];
-               offset += dstSizes[0];
+                       context->rlePlanes[0] = &context->rlePlanesBuffer[offset];
+                       offset += dstSizes[0];
 
-               rlePlanes[1] = &rlePlanesBuffer[offset];
-               offset += dstSizes[1];
+                       context->rlePlanes[1] = &context->rlePlanesBuffer[offset];
+                       offset += dstSizes[1];
 
-               rlePlanes[2] = &rlePlanesBuffer[offset];
-               offset += dstSizes[2];
+                       context->rlePlanes[2] = &context->rlePlanesBuffer[offset];
+                       offset += dstSizes[2];
 
-               rlePlanes[3] = &rlePlanesBuffer[offset];
-               offset += dstSizes[3];
+                       context->rlePlanes[3] = &context->rlePlanesBuffer[offset];
+                       offset += dstSizes[3];
 
-               printf("R: [%d/%d] G: [%d/%d] B: [%d/%d]\n",
-                               dstSizes[1], planeSize, dstSizes[2], planeSize, dstSizes[3], planeSize);
+                       printf("R: [%d/%d] G: [%d/%d] B: [%d/%d]\n",
+                                       dstSizes[1], planeSize, dstSizes[2], planeSize, dstSizes[3], planeSize);
+               }
        }
 
        if (!dstData)
@@ -842,12 +801,12 @@ BYTE* freerdp_bitmap_compress_planar(BYTE* data, UINT32 format, int width, int h
        {
                if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
                {
-                       CopyMemory(dstp, rlePlanes[0], dstSizes[0]); /* Alpha */
+                       CopyMemory(dstp, context->rlePlanes[0], dstSizes[0]); /* Alpha */
                        dstp += dstSizes[0];
                }
                else
                {
-                       CopyMemory(dstp, planes[0], planeSize); /* Alpha */
+                       CopyMemory(dstp, context->planes[0], planeSize); /* Alpha */
                        dstp += planeSize;
                }
        }
@@ -856,12 +815,12 @@ BYTE* freerdp_bitmap_compress_planar(BYTE* data, UINT32 format, int width, int h
 
        if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
        {
-               CopyMemory(dstp, rlePlanes[1], dstSizes[1]); /* Red */
+               CopyMemory(dstp, context->rlePlanes[1], dstSizes[1]); /* Red */
                dstp += dstSizes[1];
        }
        else
        {
-               CopyMemory(dstp, planes[1], planeSize); /* Red */
+               CopyMemory(dstp, context->planes[1], planeSize); /* Red */
                dstp += planeSize;
        }
 
@@ -869,12 +828,12 @@ BYTE* freerdp_bitmap_compress_planar(BYTE* data, UINT32 format, int width, int h
 
        if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
        {
-               CopyMemory(dstp, rlePlanes[2], dstSizes[2]); /* Green */
+               CopyMemory(dstp, context->rlePlanes[2], dstSizes[2]); /* Green */
                dstp += dstSizes[2];
        }
        else
        {
-               CopyMemory(dstp, planes[2], planeSize); /* Green */
+               CopyMemory(dstp, context->planes[2], planeSize); /* Green */
                dstp += planeSize;
        }
 
@@ -882,12 +841,12 @@ BYTE* freerdp_bitmap_compress_planar(BYTE* data, UINT32 format, int width, int h
 
        if (FormatHeader & PLANAR_FORMAT_HEADER_RLE)
        {
-               CopyMemory(dstp, rlePlanes[3], dstSizes[3]); /* Blue */
+               CopyMemory(dstp, context->rlePlanes[3], dstSizes[3]); /* Blue */
                dstp += dstSizes[3];
        }
        else
        {
-               CopyMemory(dstp, planes[3], planeSize); /* Blue */
+               CopyMemory(dstp, context->planes[3], planeSize); /* Blue */
                dstp += planeSize;
        }
 
@@ -902,9 +861,63 @@ BYTE* freerdp_bitmap_compress_planar(BYTE* data, UINT32 format, int width, int h
        size = (dstp - dstData);
        *dstSize = size;
 
-       free(rlePlanesBuffer);
-       free(deltaPlanesBuffer);
-       free(planesBuffer);
-
        return dstData;
 }
+
+BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, int maxWidth, int maxHeight)
+{
+       BITMAP_PLANAR_CONTEXT* context;
+
+       context = (BITMAP_PLANAR_CONTEXT*) malloc(sizeof(BITMAP_PLANAR_CONTEXT));
+
+       if (!context)
+               return NULL;
+
+       ZeroMemory(context, sizeof(BITMAP_PLANAR_CONTEXT));
+
+       if (flags & PLANAR_FORMAT_HEADER_NA)
+               context->AllowSkipAlpha = TRUE;
+
+       if (flags & PLANAR_FORMAT_HEADER_RLE)
+               context->AllowRunLengthEncoding = TRUE;
+
+       if (flags & PLANAR_FORMAT_HEADER_CS)
+               context->AllowColorSubsampling = TRUE;
+
+       context->ColorLossLevel = flags & PLANAR_FORMAT_HEADER_CLL_MASK;
+
+       if (context->ColorLossLevel)
+               context->AllowDynamicColorFidelity = TRUE;
+
+       context->maxWidth = maxWidth;
+       context->maxHeight = maxHeight;
+       context->maxPlaneSize = context->maxWidth * context->maxHeight;
+
+       context->planesBuffer = malloc(context->maxPlaneSize * 4);
+       context->planes[0] = &context->planesBuffer[context->maxPlaneSize * 0];
+       context->planes[1] = &context->planesBuffer[context->maxPlaneSize * 1];
+       context->planes[2] = &context->planesBuffer[context->maxPlaneSize * 2];
+       context->planes[3] = &context->planesBuffer[context->maxPlaneSize * 3];
+
+       context->deltaPlanesBuffer = malloc(context->maxPlaneSize * 4);
+       context->deltaPlanes[0] = &context->deltaPlanesBuffer[context->maxPlaneSize * 0];
+       context->deltaPlanes[1] = &context->deltaPlanesBuffer[context->maxPlaneSize * 1];
+       context->deltaPlanes[2] = &context->deltaPlanesBuffer[context->maxPlaneSize * 2];
+       context->deltaPlanes[3] = &context->deltaPlanesBuffer[context->maxPlaneSize * 3];
+
+       context->rlePlanesBuffer = malloc(context->maxPlaneSize * 4);
+
+       return context;
+}
+
+void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context)
+{
+       if (!context)
+               return;
+
+       free(context->planesBuffer);
+       free(context->deltaPlanesBuffer);
+       free(context->rlePlanesBuffer);
+
+       free(context);
+}
index 8931f94..54a98e6 100644 (file)
@@ -23,6 +23,7 @@
 #include <winpr/crt.h>
 
 #include <freerdp/codec/color.h>
+#include <freerdp/codec/bitmap.h>
 
 #define PLANAR_CONTROL_BYTE(_nRunLength, _cRawBytes) \
        (_nRunLength & 0x0F) | ((_cRawBytes & 0x0F) << 4)
@@ -49,10 +50,6 @@ struct _RDP6_RLE_SEGMENTS
 };
 typedef struct _RDP6_RLE_SEGMENTS RDP6_RLE_SEGMENTS;
 
-#define PLANAR_FORMAT_HEADER_CS                (1 << 3)
-#define PLANAR_FORMAT_HEADER_RLE       (1 << 4)
-#define PLANAR_FORMAT_HEADER_NA                (1 << 5)
-
 struct _RDP6_BITMAP_STREAM
 {
        /**
@@ -67,11 +64,34 @@ struct _RDP6_BITMAP_STREAM
 };
 typedef struct _RDP6_BITMAP_STREAM RDP6_BITMAP_STREAM;
 
+struct _BITMAP_PLANAR_CONTEXT
+{
+       int maxWidth;
+       int maxHeight;
+       int maxPlaneSize;
+
+       BOOL AllowSkipAlpha;
+       BOOL AllowRunLengthEncoding;
+       BOOL AllowColorSubsampling;
+       BOOL AllowDynamicColorFidelity;
+
+       int ColorLossLevel;
+
+       BYTE* planes[4];
+       BYTE* planesBuffer;
+
+       BYTE* deltaPlanes[4];
+       BYTE* deltaPlanesBuffer;
+
+       BYTE* rlePlanes[4];
+       BYTE* rlePlanesBuffer;
+};
+
 int freerdp_bitmap_planar_decompress(BYTE* srcData, BYTE* dstData, int width, int height, int size);
 
-int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[5]);
+int freerdp_split_color_planes(BYTE* data, UINT32 format, int width, int height, int scanline, BYTE* planes[4]);
 BYTE* freerdp_bitmap_planar_compress_plane_rle(BYTE* plane, int width, int height, BYTE* outPlane, int* dstSize);
 BYTE* freerdp_bitmap_planar_delta_encode_plane(BYTE* inPlane, int width, int height, BYTE* outPlane);
-int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[5], int width, int height, BYTE* outPlanes[5]);
+int freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[4], int width, int height, BYTE* outPlanes[4]);
 
 #endif /* FREERDP_CODEC_PLANAR_PRIVATE_H */
index a00278d..85678d6 100644 (file)
@@ -1858,6 +1858,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
        int dstSize;
        UINT32 format;
        HCLRCONV clrconv;
+       DWORD planarFlags;
        BYTE* srcBitmap32;
        BYTE* srcBitmap16;
        int width, height;
@@ -1866,6 +1867,12 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
        BYTE* randomBitmap;
        BYTE* compressedBitmap;
        BYTE* decompressedBitmap;
+       BITMAP_PLANAR_CONTEXT* planar;
+
+       planarFlags = PLANAR_FORMAT_HEADER_NA;
+       //planarFlags |= PLANAR_FORMAT_HEADER_RLE;
+
+       planar = freerdp_bitmap_planar_context_new(planarFlags, 64, 64);
 
        clrconv = freerdp_clrconv_new(0);
        srcBitmap16 = (BYTE*) TEST_RLE_UNCOMPRESSED_BITMAP_16BPP;
@@ -1874,8 +1881,8 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
 
        format = FREERDP_PIXEL_FORMAT(32, FREERDP_PIXEL_FORMAT_TYPE_ARGB, FREERDP_PIXEL_FLIP_NONE);
 
-#if 0
-       freerdp_bitmap_compress_planar(srcBitmap32, format, 32, 32, 32 * 4, NULL, &dstSize);
+#if 1
+       freerdp_bitmap_compress_planar(planar, srcBitmap32, format, 32, 32, 32 * 4, NULL, &dstSize);
 
        freerdp_bitmap_planar_compress_plane_rle((BYTE*) TEST_RLE_SCANLINE_UNCOMPRESSED, 12, 1, NULL, &dstSize);
 
@@ -1892,7 +1899,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
                FillMemory(whiteBitmap, width * height * 4, 0xFF);
                fill_bitmap_alpha_channel(whiteBitmap, width, height, 0x00);
 
-               compressedBitmap = freerdp_bitmap_compress_planar(whiteBitmap, format, width, height, width * 4, NULL, &dstSize);
+               compressedBitmap = freerdp_bitmap_compress_planar(planar, whiteBitmap, format, width, height, width * 4, NULL, &dstSize);
 
                decompressedBitmap = (BYTE*) malloc(width * height * 4);
                ZeroMemory(decompressedBitmap, width * height * 4);
@@ -1932,7 +1939,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
                ZeroMemory(blackBitmap, width * height * 4);
                fill_bitmap_alpha_channel(blackBitmap, width, height, 0x00);
 
-               compressedBitmap = freerdp_bitmap_compress_planar(blackBitmap, format, width, height, width * 4, NULL, &dstSize);
+               compressedBitmap = freerdp_bitmap_compress_planar(planar, blackBitmap, format, width, height, width * 4, NULL, &dstSize);
 
                decompressedBitmap = (BYTE*) malloc(width * height * 4);
                ZeroMemory(decompressedBitmap, width * height * 4);
@@ -1977,7 +1984,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
 
                fill_bitmap_alpha_channel(randomBitmap, width, height, 0x00);
 
-               compressedBitmap = freerdp_bitmap_compress_planar(randomBitmap, format, width, height, width * 4, NULL, &dstSize);
+               compressedBitmap = freerdp_bitmap_compress_planar(planar, randomBitmap, format, width, height, width * 4, NULL, &dstSize);
 
                decompressedBitmap = (BYTE*) malloc(width * height * 4);
                ZeroMemory(decompressedBitmap, width * height * 4);
@@ -2009,13 +2016,13 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
        }
 #endif
 
-#if 0
+#if 1
        /* Experimental Case 01 */
 
        width = 64;
        height = 64;
 
-       compressedBitmap = freerdp_bitmap_compress_planar((BYTE*) TEST_RLE_BITMAP_EXPERIMENTAL_01,
+       compressedBitmap = freerdp_bitmap_compress_planar(planar, (BYTE*) TEST_RLE_BITMAP_EXPERIMENTAL_01,
                        format, width, height, width * 4, NULL, &dstSize);
 
        decompressedBitmap = (BYTE*) malloc(width * height * 4);
@@ -2052,13 +2059,13 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
        free(decompressedBitmap);
 #endif
 
-#if 0
+#if 1
        /* Experimental Case 02 */
 
        width = 64;
        height = 64;
 
-       compressedBitmap = freerdp_bitmap_compress_planar((BYTE*) TEST_RLE_BITMAP_EXPERIMENTAL_02,
+       compressedBitmap = freerdp_bitmap_compress_planar(planar, (BYTE*) TEST_RLE_BITMAP_EXPERIMENTAL_02,
                        format, width, height, width * 4, NULL, &dstSize);
 
        decompressedBitmap = (BYTE*) malloc(width * height * 4);
@@ -2100,7 +2107,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
        width = 64;
        height = 64;
 
-       compressedBitmap = freerdp_bitmap_compress_planar((BYTE*) TEST_RLE_BITMAP_EXPERIMENTAL_03,
+       compressedBitmap = freerdp_bitmap_compress_planar(planar, (BYTE*) TEST_RLE_BITMAP_EXPERIMENTAL_03,
                        format, width, height, width * 4, NULL, &dstSize);
 
        decompressedBitmap = (BYTE*) malloc(width * height * 4);
@@ -2139,5 +2146,7 @@ int TestFreeRDPCodecPlanar(int argc, char* argv[])
        freerdp_clrconv_free(clrconv);
        free(srcBitmap32);
 
+       freerdp_bitmap_planar_context_free(planar);
+
        return 0;
 }