codecs: added --jpeg command line, moved jpeg hack to bitmap cache v3, added bcv3...
authorJay Sorg <jay.sorg@gmail.com>
Tue, 24 Jul 2012 19:05:22 +0000 (12:05 -0700)
committerJay Sorg <jay.sorg@gmail.com>
Tue, 24 Jul 2012 19:05:22 +0000 (12:05 -0700)
client/X11/xf_graphics.c
include/freerdp/constants.h
include/freerdp/graphics.h
include/freerdp/settings.h
libfreerdp-cache/bitmap.c
libfreerdp-core/capabilities.c
libfreerdp-gdi/graphics.c
libfreerdp-gdi/graphics.h
libfreerdp-utils/args.c

index ce9e028..cc14ffd 100644 (file)
@@ -25,6 +25,7 @@
 #endif
 
 #include <freerdp/codec/bitmap.h>
+#include <freerdp/codec/rfx.h>
 #include <freerdp/codec/jpeg.h>
 
 #include "xf_graphics.h"
@@ -61,7 +62,7 @@ void xf_Bitmap_New(rdpContext* context, rdpBitmap* bitmap)
                {
                        if (data != bitmap->data)
                                xfree(bitmap->data);
-                       
+
                        bitmap->data = data;
                }
        }
@@ -106,9 +107,14 @@ void xf_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
 }
 
 void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
-               uint8* data, int width, int height, int bpp, int length, boolean compressed)
+               uint8* data, int width, int height, int bpp, int length, int compressed)
 {
        uint16 size;
+       RFX_MESSAGE* msg;
+       uint8* src;
+       uint8* dst;
+       int yindex;
+       int xindex;
 
        size = width * height * (bpp + 7) / 8;
 
@@ -117,22 +123,52 @@ void xf_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
        else
                bitmap->data = (uint8*) xrealloc(bitmap->data, size);
 
-       if (compressed == 2)
+       if (compressed == 4)
+       {
+               printf("xf_Bitmap_Decompress: nsc not done\n");
+       }
+       else if (compressed == 3)
+       {
+               xfInfo* xfi = ((xfContext*)context)->xfi;
+               rfx_context_set_pixel_format(xfi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
+               msg = rfx_process_message(xfi->rfx_context, data, length);
+               if (msg == NULL)
+               {
+                       printf("xf_Bitmap_Decompress: rfx Decompression Failed\n");
+               }
+               else
+               {
+                       for (yindex = 0; yindex < height; yindex++)
+                       {
+                               src = msg->tiles[0]->data + yindex * 64 * 4;
+                               dst = bitmap->data + yindex * width * 3;
+                               for (xindex = 0; xindex < width; xindex++)
+                               {
+                                       *(dst++) = *(src++);
+                                       *(dst++) = *(src++);
+                                       *(dst++) = *(src++);
+                                       src++;
+                               }
+                       }
+                       rfx_message_free(xfi->rfx_context, msg);
+               }
+       }
+       else if (compressed == 2)
        {
                if (!jpeg_decompress(data, bitmap->data, width, height, length, bpp))
                {
-                       printf("jpeg Decompression Failed\n");
+                       printf("xf_Bitmap_Decompress: jpeg Decompression Failed\n");
                }
        }
-       else if (compressed)
+       else if (compressed == 1)
        {
                boolean status;
 
                status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp);
 
-               if (status != true)
+               if (status == false)
                {
-                       printf("Bitmap Decompression Failed\n");
+                       printf("xf_Bitmap_Decompress: Bitmap Decompression Failed\n");
                }
        }
        else
index 88b3c32..c9bcf67 100644 (file)
@@ -27,6 +27,7 @@ enum RDP_CODEC_ID
 {
        CODEC_ID_NONE = 0x00,
        CODEC_ID_NSCODEC = 0x01,
+       CODEC_ID_JPEG = 0x02,
        CODEC_ID_REMOTEFX = 0x03
 };
 
index 033ff3a..bf0a00a 100644 (file)
@@ -35,7 +35,7 @@ typedef void (*pBitmap_New)(rdpContext* context, rdpBitmap* bitmap);
 typedef void (*pBitmap_Free)(rdpContext* context, rdpBitmap* bitmap);
 typedef void (*pBitmap_Paint)(rdpContext* context, rdpBitmap* bitmap);
 typedef void (*pBitmap_Decompress)(rdpContext* context, rdpBitmap* bitmap,
-               uint8* data, int width, int height, int bpp, int length, boolean compressed);
+               uint8* data, int width, int height, int bpp, int length, int compressed);
 typedef void (*pBitmap_SetSurface)(rdpContext* context, rdpBitmap* bitmap, boolean primary);
 
 struct rdp_bitmap
index 5ff5a0d..572be4c 100644 (file)
@@ -388,7 +388,11 @@ struct rdp_settings
        ALIGN64 uint32 ns_codec_id; /* 283 */
        ALIGN64 uint32 rfx_codec_mode; /* 284 */
        ALIGN64 boolean frame_acknowledge; /* 285 */
-       ALIGN64 uint64 paddingM[296 - 286]; /* 286 */
+       ALIGN64 boolean jpeg_codec; /* 286 */
+       ALIGN64 uint32 jpeg_codec_id; /* 287 */
+       ALIGN64 uint32 jpeg_quality; /* 288 */
+       ALIGN64 uint32 preferred_codec_id; /* 289 */
+       ALIGN64 uint64 paddingM[296 - 290]; /* 290 */
 
        /* Recording */
        ALIGN64 boolean dump_rfx; /* 296 */
index 6d42d26..dede3a7 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <freerdp/freerdp.h>
+#include <freerdp/constants.h>
 #include <freerdp/utils/stream.h>
 #include <freerdp/utils/memory.h>
 
@@ -125,6 +126,54 @@ void update_gdi_cache_bitmap_v2(rdpContext* context, CACHE_BITMAP_V2_ORDER* cach
        bitmap_cache_put(cache->bitmap, cache_bitmap_v2->cacheId, cache_bitmap_v2->cacheIndex, bitmap);
 }
 
+void update_gdi_cache_bitmap_v3(rdpContext* context, CACHE_BITMAP_V3_ORDER* cache_bitmap_v3)
+{
+       rdpBitmap* bitmap;
+       rdpBitmap* prevBitmap;
+       rdpCache* cache = context->cache;
+       BITMAP_DATA_EX* bitmapData = &cache_bitmap_v3->bitmapData;
+       boolean compression;
+
+       bitmap = Bitmap_Alloc(context);
+
+       Bitmap_SetDimensions(context, bitmap, bitmapData->width, bitmapData->height);
+
+       if (cache_bitmap_v3->bitmapData.bpp == 0)
+       {
+               /* Workaround for Windows 8 bug where bitmapBpp is not set */
+               cache_bitmap_v3->bitmapData.bpp = context->instance->settings->color_depth;
+       }
+
+       switch (bitmapData->codecID)
+       {
+               case CODEC_ID_JPEG:
+                       compression = 2;
+                       break;
+               case CODEC_ID_REMOTEFX:
+                       compression = 3;
+                       break;
+               case CODEC_ID_NSCODEC:
+                       compression = 4;
+                       break;
+               default:
+                       compression = 1;
+                       break;
+       }
+
+       bitmap->Decompress(context, bitmap,
+                       bitmapData->data, bitmap->width, bitmap->height,
+                       bitmapData->bpp, bitmapData->length, compression);
+
+       bitmap->New(context, bitmap);
+
+       prevBitmap = bitmap_cache_get(cache->bitmap, cache_bitmap_v3->cacheId, cache_bitmap_v3->cacheIndex);
+
+       if (prevBitmap != NULL)
+               Bitmap_Free(context, prevBitmap);
+
+       bitmap_cache_put(cache->bitmap, cache_bitmap_v3->cacheId, cache_bitmap_v3->cacheIndex, bitmap);
+}
+
 void update_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmap_update)
 {
        int i;
@@ -229,6 +278,7 @@ void bitmap_cache_register_callbacks(rdpUpdate* update)
 
        update->secondary->CacheBitmap = update_gdi_cache_bitmap;
        update->secondary->CacheBitmapV2 = update_gdi_cache_bitmap_v2;
+       update->secondary->CacheBitmapV3 = update_gdi_cache_bitmap_v3;
 
        update->BitmapUpdate = update_gdi_bitmap_update;
 }
index 43615cd..080ad95 100644 (file)
@@ -62,6 +62,9 @@ static const char* const CAPSET_TYPE_STRINGS[] =
 /* CODEC_GUID_NSCODEC  0xCA8D1BB9000F154F589FAE2D1A87E2D6 */
 #define CODEC_GUID_NSCODEC "\xb9\x1b\x8d\xca\x0f\x00\x4f\x15\x58\x9f\xae\x2d\x1a\x87\xe2\xd6"
 
+/* CODEC_GUID_JPEG 0x430C9EED1BAF4CE6869ACB8B37B66237*/
+#define CODEC_GUID_JPEG "\xE6\x4C\xAF\x1B\xED\x9E\x0C\x43\x86\x9A\xCB\x8B\x37\xB6\x62\x37"
+
 void rdp_read_capability_set_header(STREAM* s, uint16* length, uint16* type)
 {
        stream_read_uint16(s, *type); /* capabilitySetType */
@@ -1014,7 +1017,6 @@ void rdp_write_bitmap_cache_v2_capability_set(STREAM* s, rdpSettings* settings)
        header = rdp_capability_set_start(s);
 
        cacheFlags = ALLOW_CACHE_WAITING_LIST_FLAG;
-       cacheFlags |= 0x80; /* jpeg hack */
 
        if (settings->persistent_bitmap_cache)
                cacheFlags |= PERSISTENT_KEYS_EXPECTED_FLAG;
@@ -1529,6 +1531,12 @@ void rdp_write_nsc_client_capability_container(STREAM* s, rdpSettings* settings)
        stream_write_uint8(s, 3);  /* colorLossLevel */
 }
 
+void rdp_write_jpeg_client_capability_container(STREAM* s, rdpSettings* settings)
+{
+       stream_write_uint16(s, 1); /* codecPropertiesLength */
+       stream_write_uint8(s, settings->jpeg_quality);
+}
+
 /**
  * Write RemoteFX Server Capability Container.\n
  * @param s stream
@@ -1540,6 +1548,12 @@ void rdp_write_rfx_server_capability_container(STREAM* s, rdpSettings* settings)
        stream_write_uint32(s, 0); /* reserved */
 }
 
+void rdp_write_jpeg_server_capability_container(STREAM* s, rdpSettings* settings)
+{
+       stream_write_uint16(s, 1); /* codecPropertiesLength */
+       stream_write_uint8(s, 75);
+}
+
 /**
  * Write NSCODEC Server Capability Container.\n
  * @param s stream
@@ -1571,6 +1585,8 @@ void rdp_write_bitmap_codecs_capability_set(STREAM* s, rdpSettings* settings)
                bitmapCodecCount++;
        if (settings->ns_codec)
                bitmapCodecCount++;
+       if (settings->jpeg_codec)
+               bitmapCodecCount++;
 
        stream_write_uint8(s, bitmapCodecCount);
 
@@ -1603,6 +1619,20 @@ void rdp_write_bitmap_codecs_capability_set(STREAM* s, rdpSettings* settings)
                        rdp_write_nsc_client_capability_container(s, settings);
                }
        }
+       if (settings->jpeg_codec)
+       {
+               stream_write(s, CODEC_GUID_JPEG, 16);
+               if (settings->server_mode)
+               {
+                       stream_write_uint8(s, 0); /* codecID is defined by the client */
+                       rdp_write_jpeg_server_capability_container(s, settings);
+               }
+               else
+               {
+                       stream_write_uint8(s, CODEC_ID_JPEG); /* codecID */
+                       rdp_write_jpeg_client_capability_container(s, settings);
+               }
+       }
        rdp_capability_set_finish(s, header, CAPSET_TYPE_BITMAP_CODECS);
 }
 
@@ -2098,4 +2128,3 @@ boolean rdp_send_confirm_active(rdpRdp* rdp)
 
        return rdp_send_pdu(rdp, s, PDU_TYPE_CONFIRM_ACTIVE, rdp->mcs->user_id);
 }
-
index d83ed20..1ea61d7 100644 (file)
@@ -23,6 +23,7 @@
 #include <freerdp/gdi/region.h>
 #include <freerdp/gdi/bitmap.h>
 #include <freerdp/codec/jpeg.h>
+#include <freerdp/codec/rfx.h>
 #include <freerdp/gdi/drawing.h>
 #include <freerdp/gdi/clipping.h>
 #include <freerdp/codec/color.h>
@@ -88,9 +89,14 @@ void gdi_Bitmap_Paint(rdpContext* context, rdpBitmap* bitmap)
 }
 
 void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
-               uint8* data, int width, int height, int bpp, int length, boolean compressed)
+               uint8* data, int width, int height, int bpp, int length, int compressed)
 {
        uint16 size;
+       RFX_MESSAGE* msg;
+       uint8* src;
+       uint8* dst;
+       int yindex;
+       int xindex;
 
        size = width * height * (bpp + 7) / 8;
 
@@ -99,11 +105,41 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
        else
                bitmap->data = (uint8*) xrealloc(bitmap->data, size);
 
-       if (compressed == 2)
+       if (compressed == 4)
+       {
+               printf("gdi_Bitmap_Decompress: nsc not done\n");
+       }
+       else if (compressed == 3)
+       {
+               rdpGdi* gdi = context->gdi;
+               rfx_context_set_pixel_format(gdi->rfx_context, RDP_PIXEL_FORMAT_B8G8R8A8);
+               msg = rfx_process_message(gdi->rfx_context, data, length);
+               if (msg == NULL)
+               {
+                       printf("gdi_Bitmap_Decompress: rfx Decompression Failed\n");
+               }
+               else
+               {
+                       for (yindex = 0; yindex < height; yindex++)
+                       {
+                               src = msg->tiles[0]->data + yindex * 64 * 4;
+                               dst = bitmap->data + yindex * width * 3;
+                               for (xindex = 0; xindex < width; xindex++)
+                               {
+                                       *(dst++) = *(src++);
+                                       *(dst++) = *(src++);
+                                       *(dst++) = *(src++);
+                                       src++;
+                               }
+                       }
+                       rfx_message_free(gdi->rfx_context, msg);
+               }
+       }
+       else if (compressed == 2)
        {
                if (!jpeg_decompress(data, bitmap->data, width, height, length, bpp))
                {
-                       printf("jpeg Decompression Failed\n");
+                       printf("gdi_Bitmap_Decompress: jpeg Decompression Failed\n");
                }
        }
        else if (compressed)
@@ -112,9 +148,9 @@ void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
 
                status = bitmap_decompress(data, bitmap->data, width, height, length, bpp, bpp);
 
-               if (status != true)
+               if (status == false)
                {
-                       printf("Bitmap Decompression Failed\n");
+                       printf("gdi_Bitmap_Decompress: Bitmap Decompression Failed\n");
                }
        }
        else
@@ -244,4 +280,3 @@ void gdi_register_graphics(rdpGraphics* graphics)
        graphics_register_glyph(graphics, glyph);
        xfree(glyph);
 }
-
index 3940a44..35d2685 100644 (file)
@@ -28,7 +28,7 @@ HGDI_BITMAP gdi_create_bitmap(rdpGdi* gdi, int width, int height, int bpp, uint8
 void gdi_Bitmap_New(rdpContext* context, rdpBitmap* bitmap);
 void gdi_Bitmap_Free(rdpContext* context, rdpBitmap* bitmap);
 void gdi_Bitmap_Decompress(rdpContext* context, rdpBitmap* bitmap,
-               uint8* data, int width, int height, int bpp, int length, boolean compressed);
+               uint8* data, int width, int height, int bpp, int length, int compressed);
 void gdi_register_graphics(rdpGraphics* graphics);
 
 #endif /* __GDI_GRAPHICS_H */
index 8e510f9..ce7eb4a 100644 (file)
@@ -86,10 +86,13 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
                                "  --gdi: graphics rendering (hw, sw)\n"
                                "  --no-osb: disable offscreen bitmaps\n"
                                "  --no-bmp-cache: disable bitmap cache\n"
+                               "  --bcv3: codec for bitmap cache v3 (rfx, nsc, jpeg)\n"
                                "  --plugin: load a virtual channel plugin\n"
                                "  --rfx: enable RemoteFX\n"
                                "  --rfx-mode: RemoteFX operational flags (v[ideo], i[mage]), default is video\n"
                                "  --nsc: enable NSCodec (experimental)\n"
+                               "  --jpeg: enable jpeg codec, uses 75 quality\n"
+                               "  --jpegex: enable jpeg and set quality(1..99)\n"
                                "  --disable-wallpaper: disables wallpaper\n"
                                "  --composition: enable desktop composition\n"
                                "  --disable-full-window-drag: disables full window drag\n"
@@ -346,6 +349,47 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv,
                                return FREERDP_ARGS_PARSE_FAILURE;
                        }
                }
+               else if (strcmp("--bcv3", argv[index]) == 0)
+               {
+                       index++;
+                       if (index == argc)
+                       {
+                               printf("missing codec name\n");
+                               return FREERDP_ARGS_PARSE_FAILURE;
+                       }
+                       settings->bitmap_cache_v3 = true;
+                       if (strcmp("rfx", argv[index]) == 0)
+                       {
+                               printf("setting rfx\n");
+                               settings->preferred_codec_id = 3; /* CODEC_ID_REMOTEFX */
+                       }
+                       else if (strcmp("nsc", argv[index]) == 0)
+                       {
+                               printf("setting codec nsc\n");
+                               settings->preferred_codec_id = 1; /* CODEC_ID_NSCODEC */
+                       }
+                       else if (strcmp("jpeg", argv[index]) == 0)
+                       {
+                               printf("setting codec jpeg\n");
+                               settings->preferred_codec_id = 2;
+                       }
+               }
+               else if (strcmp("--jpeg", argv[index]) == 0)
+               {
+                       settings->jpeg_codec = true;
+                       settings->jpeg_quality = 75;
+               }
+               else if (strcmp("--jpegex", argv[index]) == 0)
+               {
+                       index++;
+                       if (index == argc)
+                       {
+                               printf("missing codec name\n");
+                               return FREERDP_ARGS_PARSE_FAILURE;
+                       }
+                       settings->jpeg_codec = true;
+                       settings->jpeg_quality = atoi(argv[index]);
+               }
                else if (strcmp("--rfx", argv[index]) == 0)
                {
                        settings->rfx_codec = true;