#endif
#include <freerdp/codec/bitmap.h>
+#include <freerdp/codec/rfx.h>
#include <freerdp/codec/jpeg.h>
#include "xf_graphics.h"
{
if (data != bitmap->data)
xfree(bitmap->data);
-
+
bitmap->data = data;
}
}
}
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;
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
{
CODEC_ID_NONE = 0x00,
CODEC_ID_NSCODEC = 0x01,
+ CODEC_ID_JPEG = 0x02,
CODEC_ID_REMOTEFX = 0x03
};
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
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 */
*/
#include <freerdp/freerdp.h>
+#include <freerdp/constants.h>
#include <freerdp/utils/stream.h>
#include <freerdp/utils/memory.h>
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;
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;
}
/* 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 */
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;
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
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
bitmapCodecCount++;
if (settings->ns_codec)
bitmapCodecCount++;
+ if (settings->jpeg_codec)
+ bitmapCodecCount++;
stream_write_uint8(s, bitmapCodecCount);
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);
}
return rdp_send_pdu(rdp, s, PDU_TYPE_CONFIRM_ACTIVE, rdp->mcs->user_id);
}
-
#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>
}
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;
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)
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
graphics_register_glyph(graphics, glyph);
xfree(glyph);
}
-
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 */
" --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"
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;