libfreerdp-core: improve bitmap codec negotiation

This commit is contained in:
Marc-André Moreau 2014-09-21 15:40:27 -04:00
parent 6cb4b59426
commit c4ad706c34
5 changed files with 224 additions and 71 deletions

View File

@ -759,6 +759,9 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_NSCodec 3712
#define FreeRDP_NSCodecId 3713
#define FreeRDP_FrameAcknowledge 3714
#define FreeRDP_NSCodecColorLossLevel 3715
#define FreeRDP_NSCodecAllowSubsampling 3716
#define FreeRDP_NSCodecAllowDynamicColorFidelity 3717
#define FreeRDP_JpegCodec 3776
#define FreeRDP_JpegCodecId 3777
#define FreeRDP_JpegQuality 3778
@ -1271,7 +1274,10 @@ struct rdp_settings
ALIGN64 BOOL NSCodec; /* 3712 */
ALIGN64 UINT32 NSCodecId; /* 3713 */
ALIGN64 UINT32 FrameAcknowledge; /* 3714 */
UINT64 padding3776[3776 - 3715]; /* 3715 */
ALIGN64 UINT32 NSCodecColorLossLevel; /* 3715 */
ALIGN64 BOOL NSCodecAllowSubsampling; /* 3716 */
ALIGN64 BOOL NSCodecAllowDynamicColorFidelity; /* 3717 */
UINT64 padding3776[3776 - 3718]; /* 3718 */
/* JPEG */
ALIGN64 BOOL JpegCodec; /* 3776 */

View File

@ -976,8 +976,11 @@ BOOL freerdp_get_param_bool(rdpSettings* settings, int id)
case FreeRDP_NSCodec:
return settings->NSCodec;
case FreeRDP_FrameAcknowledge:
return settings->FrameAcknowledge;
case FreeRDP_NSCodecAllowSubsampling:
return settings->NSCodecAllowSubsampling;
case FreeRDP_NSCodecAllowDynamicColorFidelity:
return settings->NSCodecAllowDynamicColorFidelity;
case FreeRDP_JpegCodec:
return settings->JpegCodec;
@ -1464,8 +1467,12 @@ int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param)
settings->NSCodec = param;
break;
case FreeRDP_FrameAcknowledge:
settings->FrameAcknowledge = param;
case FreeRDP_NSCodecAllowSubsampling:
settings->NSCodecAllowSubsampling = param;
break;
case FreeRDP_NSCodecAllowDynamicColorFidelity:
settings->NSCodecAllowDynamicColorFidelity = param;
break;
case FreeRDP_JpegCodec:
@ -1788,6 +1795,12 @@ UINT32 freerdp_get_param_uint32(rdpSettings* settings, int id)
case FreeRDP_NSCodecId:
return settings->NSCodecId;
case FreeRDP_FrameAcknowledge:
return settings->FrameAcknowledge;
case FreeRDP_NSCodecColorLossLevel:
return settings->NSCodecColorLossLevel;
case FreeRDP_JpegCodecId:
return settings->JpegCodecId;
@ -2095,6 +2108,14 @@ int freerdp_set_param_uint32(rdpSettings* settings, int id, UINT32 param)
settings->NSCodecId = param;
break;
case FreeRDP_FrameAcknowledge:
settings->FrameAcknowledge = param;
break;
case FreeRDP_NSCodecColorLossLevel:
settings->NSCodecColorLossLevel = param;
break;
case FreeRDP_JpegCodecId:
settings->JpegCodecId = param;
break;

View File

@ -2475,6 +2475,33 @@ BOOL rdp_print_surface_commands_capability_set(wStream* s, UINT16 length)
return TRUE;
}
void rdp_print_bitmap_codec_guid(GUID* guid)
{
WLog_INFO(TAG, "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
guid->Data1, guid->Data2, guid->Data3,
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
}
char* rdp_get_bitmap_codec_guid_name(GUID* guid)
{
RPC_STATUS rpc_status;
if (UuidEqual(guid, &CODEC_GUID_REMOTEFX, &rpc_status))
return "CODEC_GUID_REMOTEFX";
else if (UuidEqual(guid, &CODEC_GUID_NSCODEC, &rpc_status))
return "CODEC_GUID_NSCODEC";
else if (UuidEqual(guid, &CODEC_GUID_IGNORE, &rpc_status))
return "CODEC_GUID_IGNORE";
else if (UuidEqual(guid, &CODEC_GUID_IMAGE_REMOTEFX, &rpc_status))
return "CODEC_GUID_IMAGE_REMOTEFX";
else if (UuidEqual(guid, &CODEC_GUID_JPEG, &rpc_status))
return "CODEC_GUID_JPEG";
return "CODEC_GUID_UNKNOWN";
}
void rdp_read_bitmap_codec_guid(wStream* s, GUID* guid)
{
BYTE g[16];
@ -2518,32 +2545,6 @@ void rdp_write_bitmap_codec_guid(wStream* s, GUID* guid)
Stream_Write(s, g, 16);
}
void rdp_print_bitmap_codec_guid(GUID* guid)
{
WLog_INFO(TAG, "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X",
guid->Data1, guid->Data2, guid->Data3,
guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
}
char* rdp_get_bitmap_codec_guid_name(GUID* guid)
{
RPC_STATUS rpc_status;
if (UuidEqual(guid, &CODEC_GUID_REMOTEFX, &rpc_status))
return "CODEC_GUID_REMOTEFX";
else if (UuidEqual(guid, &CODEC_GUID_NSCODEC, &rpc_status))
return "CODEC_GUID_NSCODEC";
else if (UuidEqual(guid, &CODEC_GUID_IGNORE, &rpc_status))
return "CODEC_GUID_IGNORE";
else if (UuidEqual(guid, &CODEC_GUID_IMAGE_REMOTEFX, &rpc_status))
return "CODEC_GUID_IMAGE_REMOTEFX";
else if (UuidEqual(guid, &CODEC_GUID_JPEG, &rpc_status))
return "CODEC_GUID_JPEG";
return "CODEC_GUID_UNKNOWN";
}
/**
* Read bitmap codecs capability set.\n
* @msdn{dd891377}
@ -2554,13 +2555,15 @@ char* rdp_get_bitmap_codec_guid_name(GUID* guid)
BOOL rdp_read_bitmap_codecs_capability_set(wStream* s, UINT16 length, rdpSettings* settings)
{
BYTE codecId;
GUID codecGuid;
RPC_STATUS rpc_status;
BYTE bitmapCodecCount;
UINT16 codecPropertiesLength;
UINT16 remainingLength;
BOOL receivedRemoteFxCodec = FALSE;
BOOL receivedNSCodec = FALSE;
BOOL guidNSCodec = FALSE;
BOOL guidRemoteFx = FALSE;
BOOL guidRemoteFxImage = FALSE;
if (length < 5)
return FALSE;
@ -2575,28 +2578,7 @@ BOOL rdp_read_bitmap_codecs_capability_set(wStream* s, UINT16 length, rdpSetting
rdp_read_bitmap_codec_guid(s, &codecGuid); /* codecGuid (16 bytes) */
if (settings->ServerMode)
{
if (UuidEqual(&codecGuid, &CODEC_GUID_REMOTEFX, &rpc_status))
{
Stream_Read_UINT8(s, settings->RemoteFxCodecId);
receivedRemoteFxCodec = TRUE;
}
else if (UuidEqual(&codecGuid, &CODEC_GUID_NSCODEC, &rpc_status))
{
Stream_Read_UINT8(s, settings->NSCodecId);
receivedNSCodec = TRUE;
}
else
{
Stream_Seek_UINT8(s); /* codecID (1 byte) */
}
}
else
{
Stream_Seek_UINT8(s); /* codecID (1 byte) */
}
Stream_Read_UINT8(s, codecId); /* codecId (1 byte) */
Stream_Read_UINT16(s, codecPropertiesLength); /* codecPropertiesLength (2 bytes) */
remainingLength -= 19;
@ -2605,21 +2587,154 @@ BOOL rdp_read_bitmap_codecs_capability_set(wStream* s, UINT16 length, rdpSetting
if (settings->ServerMode)
{
UINT32 beg;
UINT32 end;
beg = (UINT32) Stream_GetPosition(s);
end = beg + codecPropertiesLength;
if (UuidEqual(&codecGuid, &CODEC_GUID_REMOTEFX, &rpc_status))
{
Stream_Seek_UINT32(s); /* length */
Stream_Read_UINT32(s, settings->RemoteFxCaptureFlags); /* captureFlags */
Stream_Rewind(s, 8);
UINT32 rfxCapsLength;
UINT32 rfxPropsLength;
UINT32 captureFlags;
if (settings->RemoteFxCaptureFlags & CARDP_CAPS_CAPTURE_NON_CAC)
guidRemoteFx = TRUE;
settings->RemoteFxCodecId = codecId;
Stream_Read_UINT32(s, rfxPropsLength); /* length (4 bytes) */
Stream_Read_UINT32(s, captureFlags); /* captureFlags (4 bytes) */
Stream_Read_UINT32(s, rfxCapsLength); /* capsLength (4 bytes) */
settings->RemoteFxCaptureFlags = captureFlags;
settings->RemoteFxOnly = (captureFlags & CARDP_CAPS_CAPTURE_NON_CAC) ? TRUE : FALSE;
if (rfxCapsLength)
{
settings->RemoteFxOnly = TRUE;
UINT16 blockType;
UINT32 blockLen;
UINT16 numCapsets;
BYTE rfxCodecId;
UINT16 capsetType;
UINT16 numIcaps;
UINT16 icapLen;
/* TS_RFX_CAPS */
Stream_Read_UINT16(s, blockType); /* blockType (2 bytes) */
Stream_Read_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Read_UINT16(s, numCapsets); /* numCapsets (2 bytes) */
if (blockType != 0xCBC0)
return FALSE;
if (blockLen != 8)
return FALSE;
if (numCapsets != 1)
return FALSE;
/* TS_RFX_CAPSET */
Stream_Read_UINT16(s, blockType); /* blockType (2 bytes) */
Stream_Read_UINT32(s, blockLen); /* blockLen (4 bytes) */
Stream_Read_UINT8(s, rfxCodecId); /* codecId (1 byte) */
Stream_Read_UINT16(s, capsetType); /* capsetType (2 bytes) */
Stream_Read_UINT16(s, numIcaps); /* numIcaps (2 bytes) */
Stream_Read_UINT16(s, icapLen); /* icapLen (2 bytes) */
if (blockType != 0xCBC1)
return FALSE;
if (rfxCodecId != 1)
return FALSE;
if (capsetType != 0xCFC0)
return FALSE;
while (numIcaps--)
{
UINT16 version;
UINT16 tileSize;
BYTE codecFlags;
BYTE colConvBits;
BYTE transformBits;
BYTE entropyBits;
/* TS_RFX_ICAP */
Stream_Read_UINT16(s, version); /* version (2 bytes) */
Stream_Read_UINT16(s, tileSize); /* tileSize (2 bytes) */
Stream_Read_UINT8(s, codecFlags); /* flags (1 byte) */
Stream_Read_UINT8(s, colConvBits); /* colConvBits (1 byte) */
Stream_Read_UINT8(s, transformBits); /* transformBits (1 byte) */
Stream_Read_UINT8(s, entropyBits); /* entropyBits (1 byte) */
if (version != 0x0100)
return FALSE;
if (tileSize != 0x0040)
return FALSE;
if (colConvBits != 1)
return FALSE;
if (transformBits != 1)
return FALSE;
}
}
}
else if (UuidEqual(&codecGuid, &CODEC_GUID_IMAGE_REMOTEFX, &rpc_status))
{
guidRemoteFxImage = TRUE;
Stream_Seek(s, codecPropertiesLength); /* codecProperties */
}
else if (UuidEqual(&codecGuid, &CODEC_GUID_NSCODEC, &rpc_status))
{
BYTE colorLossLevel;
BYTE fAllowSubsampling;
BYTE fAllowDynamicFidelity;
guidNSCodec = TRUE;
settings->NSCodecId = codecId;
Stream_Read_UINT8(s, fAllowDynamicFidelity); /* fAllowDynamicFidelity (1 byte) */
Stream_Read_UINT8(s, fAllowSubsampling); /* fAllowSubsampling (1 byte) */
Stream_Read_UINT8(s, colorLossLevel); /* colorLossLevel (1 byte) */
if (colorLossLevel < 1)
colorLossLevel = 1;
if (colorLossLevel > 7)
colorLossLevel = 7;
settings->NSCodecAllowDynamicColorFidelity = fAllowDynamicFidelity;
settings->NSCodecAllowSubsampling = fAllowSubsampling;
settings->NSCodecColorLossLevel = colorLossLevel;
}
else if (UuidEqual(&codecGuid, &CODEC_GUID_IGNORE, &rpc_status))
{
Stream_Seek(s, codecPropertiesLength); /* codecProperties */
}
else
{
Stream_Seek(s, codecPropertiesLength); /* codecProperties */
}
if (Stream_GetPosition(s) != end)
{
fprintf(stderr, "error while reading codec properties: actual offset: %d expected offset: %d\n",
Stream_GetPosition(s), end);
Stream_SetPosition(s, end);
}
remainingLength -= codecPropertiesLength;
}
else
{
Stream_Seek(s, codecPropertiesLength); /* codecProperties */
remainingLength -= codecPropertiesLength;
}
bitmapCodecCount--;
}
@ -2627,8 +2742,9 @@ BOOL rdp_read_bitmap_codecs_capability_set(wStream* s, UINT16 length, rdpSetting
if (settings->ServerMode)
{
/* only enable a codec if we've announced/enabled it before */
settings->RemoteFxCodec = settings->RemoteFxCodec && receivedRemoteFxCodec;
settings->NSCodec = settings->NSCodec && receivedNSCodec;
settings->RemoteFxCodec = settings->RemoteFxCodec && guidRemoteFx;
settings->RemoteFxImageCodec = settings->RemoteFxImageCodec && guidRemoteFxImage;
settings->NSCodec = settings->NSCodec && guidNSCodec;
settings->JpegCodec = FALSE;
}
@ -2699,9 +2815,9 @@ void rdp_write_nsc_client_capability_container(wStream* s, rdpSettings* settings
Stream_Write_UINT16(s, 3); /* codecPropertiesLength */
/* TS_NSCODEC_CAPABILITYSET */
Stream_Write_UINT8(s, 1); /* fAllowDynamicFidelity */
Stream_Write_UINT8(s, 1); /* fAllowSubsampling */
Stream_Write_UINT8(s, 3); /* colorLossLevel */
Stream_Write_UINT8(s, settings->NSCodecAllowDynamicColorFidelity); /* fAllowDynamicFidelity */
Stream_Write_UINT8(s, settings->NSCodecAllowSubsampling); /* fAllowSubsampling */
Stream_Write_UINT8(s, settings->NSCodecColorLossLevel); /* colorLossLevel */
}
void rdp_write_jpeg_client_capability_container(wStream* s, rdpSettings* settings)
@ -2764,9 +2880,6 @@ void rdp_write_bitmap_codecs_capability_set(wStream* s, rdpSettings* settings)
bitmapCodecCount = 0;
if (settings->RemoteFxCodec)
settings->RemoteFxImageCodec = TRUE;
if (settings->RemoteFxCodec)
bitmapCodecCount++;
if (settings->NSCodec)

View File

@ -402,6 +402,10 @@ rdpSettings* freerdp_settings_new(DWORD flags)
settings->FrameAcknowledge = 2;
settings->MouseMotion = TRUE;
settings->NSCodecColorLossLevel = 3;
settings->NSCodecAllowSubsampling = TRUE;
settings->NSCodecAllowDynamicColorFidelity = TRUE;
settings->AutoReconnectionEnabled = FALSE;
settings->AutoReconnectMaxRetries = 20;
@ -584,6 +588,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
_settings->RemoteFxCaptureFlags = settings->RemoteFxCaptureFlags; /* 3653 */
_settings->NSCodecId = settings->NSCodecId; /* 3713 */
_settings->FrameAcknowledge = settings->FrameAcknowledge; /* 3714 */
_settings->NSCodecColorLossLevel = settings->NSCodecColorLossLevel; /* 3715 */
_settings->JpegCodecId = settings->JpegCodecId; /* 3777 */
_settings->JpegQuality = settings->JpegQuality; /* 3778 */
_settings->BitmapCacheV3CodecId = settings->BitmapCacheV3CodecId; /* 3904 */
@ -708,6 +713,8 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings)
_settings->RemoteFxCodec = settings->RemoteFxCodec; /* 3649 */
_settings->RemoteFxImageCodec = settings->RemoteFxImageCodec; /* 3652 */
_settings->NSCodec = settings->NSCodec; /* 3712 */
_settings->NSCodecAllowSubsampling = settings->NSCodecAllowSubsampling; /* 3716 */
_settings->NSCodecAllowDynamicColorFidelity = settings->NSCodecAllowDynamicColorFidelity; /* 3717 */
_settings->JpegCodec = settings->JpegCodec; /* 3776 */
_settings->GfxThinClient = settings->GfxThinClient; /* 3840 */
_settings->GfxSmallCache = settings->GfxSmallCache; /* 3841 */

View File

@ -159,6 +159,12 @@ BOOL shadow_client_post_connect(freerdp_peer* peer)
if (settings->ColorDepth == 24)
settings->ColorDepth = 16; /* disable 24bpp */
if (settings->ColorDepth < 32)
{
settings->NSCodec = FALSE;
settings->RemoteFxCodec = FALSE;
}
WLog_ERR(TAG, "Client from %s is activated (%dx%d@%d)",
peer->hostname, settings->DesktopWidth, settings->DesktopHeight, settings->ColorDepth);