codecs: added --jpeg command line, moved jpeg hack to bitmap cache v3, added bcv3 xxx setting

This commit is contained in:
Jay Sorg 2012-07-24 12:05:22 -07:00
parent c74cae4209
commit 238cf848c2
9 changed files with 217 additions and 18 deletions

View 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"
@ -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

View 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
};

View 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

View 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 */

View 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;
}

View 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);
}

View 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);
}

View 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 */

View 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;