Added GFX planar and rfx encoder to shadow

This commit is contained in:
akallabeth 2021-07-01 10:43:19 +02:00 committed by akallabeth
parent bd256b91bc
commit 6deb65175f
10 changed files with 148 additions and 9 deletions

View File

@ -94,6 +94,7 @@ struct rdp_shadow_client
HANDLE thread;
BOOL activated;
BOOL first_frame;
BOOL inLobby;
BOOL mayView;
BOOL mayInteract;

View File

@ -862,6 +862,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_GfxSendQoeAck (3846)
#define FreeRDP_GfxAVC444v2 (3847)
#define FreeRDP_GfxCapsFilter (3848)
#define FreeRDP_GfxPlanar (3849)
#define FreeRDP_BitmapCacheV3CodecId (3904)
#define FreeRDP_DrawNineGridEnabled (3968)
#define FreeRDP_DrawNineGridCacheSize (3969)
@ -1475,7 +1476,8 @@ struct rdp_settings
ALIGN64 BOOL GfxSendQoeAck; /* 3846 */
ALIGN64 BOOL GfxAVC444v2; /* 3847 */
ALIGN64 UINT32 GfxCapsFilter; /* 3848 */
UINT64 padding3904[3904 - 3849]; /* 3849 */
ALIGN64 BOOL GfxPlanar; /* 3849 */
UINT64 padding3904[3904 - 3850]; /* 3850 */
/**
* Caches

View File

@ -943,7 +943,7 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
static INLINE BOOL freerdp_split_color_planes(const BYTE* data, UINT32 format, UINT32 width,
UINT32 height, UINT32 scanline, BYTE* planes[4])
{
INT32 i, j, k;
INT64 i, j, k;
if ((width > INT32_MAX) || (height > INT32_MAX) || (scanline > INT32_MAX))
return FALSE;
@ -952,11 +952,11 @@ static INLINE BOOL freerdp_split_color_planes(const BYTE* data, UINT32 format, U
if (scanline == 0)
scanline = width * GetBytesPerPixel(format);
for (i = (INT32)height - 1; i >= 0; i--)
for (i = (INT64)height - 1; i >= 0; i--)
{
const BYTE* pixel = &data[(INT32)scanline * i];
const BYTE* pixel = &data[scanline * (UINT32)i];
for (j = 0; j < (INT32)width; j++)
for (j = 0; j < (INT64)width; j++)
{
const UINT32 color = ReadColor(pixel, format);
pixel += GetBytesPerPixel(format);

View File

@ -234,6 +234,9 @@ BOOL freerdp_settings_get_bool(const rdpSettings* settings, size_t id)
case FreeRDP_GfxH264:
return settings->GfxH264;
case FreeRDP_GfxPlanar:
return settings->GfxPlanar;
case FreeRDP_GfxProgressive:
return settings->GfxProgressive;
@ -820,6 +823,10 @@ BOOL freerdp_settings_set_bool(rdpSettings* settings, size_t id, BOOL val)
settings->GfxH264 = val;
break;
case FreeRDP_GfxPlanar:
settings->GfxPlanar = val;
break;
case FreeRDP_GfxProgressive:
settings->GfxProgressive = val;
break;

View File

@ -83,6 +83,7 @@ static const struct settings_str_entry settings_map[] = {
{ FreeRDP_GfxAVC444, 0, "FreeRDP_GfxAVC444" },
{ FreeRDP_GfxAVC444v2, 0, "FreeRDP_GfxAVC444v2" },
{ FreeRDP_GfxH264, 0, "FreeRDP_GfxH264" },
{ FreeRDP_GfxPlanar, 0, "FreeRDP_GfxPlanar" },
{ FreeRDP_GfxProgressive, 0, "FreeRDP_GfxProgressive" },
{ FreeRDP_GfxProgressiveV2, 0, "FreeRDP_GfxProgressiveV2" },
{ FreeRDP_GfxSendQoeAck, 0, "FreeRDP_GfxSendQoeAck" },

View File

@ -558,6 +558,7 @@ rdpSettings* freerdp_settings_new(DWORD flags)
!freerdp_settings_set_bool(settings, FreeRDP_GfxSmallCache, FALSE) ||
!freerdp_settings_set_bool(settings, FreeRDP_GfxProgressive, FALSE) ||
!freerdp_settings_set_bool(settings, FreeRDP_GfxProgressiveV2, FALSE) ||
!freerdp_settings_set_bool(settings, FreeRDP_GfxPlanar, TRUE) ||
!freerdp_settings_set_bool(settings, FreeRDP_GfxH264, FALSE) ||
!freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444, FALSE) ||
!freerdp_settings_set_bool(settings, FreeRDP_GfxSendQoeAck, FALSE))

View File

@ -72,6 +72,7 @@ static const size_t bool_list_indices[] = {
FreeRDP_GfxAVC444,
FreeRDP_GfxAVC444v2,
FreeRDP_GfxH264,
FreeRDP_GfxPlanar,
FreeRDP_GfxProgressive,
FreeRDP_GfxProgressiveV2,
FreeRDP_GfxSendQoeAck,

View File

@ -81,6 +81,10 @@ int main(int argc, char** argv)
"NTLM SAM file for NLA authentication" },
{ "gfx-progressive", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
"Allow GFX progressive codec" },
{ "gfx-rfx", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
"Allow GFX RFX codec" },
{ "gfx-planar", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
"Allow GFX planar codec" },
{ "gfx-avc420", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
"Allow GFX AVC420 codec" },
{ "gfx-avc444", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
@ -114,6 +118,7 @@ int main(int argc, char** argv)
/* By default allow all GFX modes.
* This can be changed with command line flags [+|-]gfx-CODEC
*/
freerdp_settings_set_bool(settings, FreeRDP_RemoteFxCodec, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_GfxH264, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444v2, TRUE);

View File

@ -138,6 +138,7 @@ static INLINE BOOL shadow_client_rdpgfx_reset_graphic(rdpShadowClient* client)
return FALSE;
}
client->first_frame = TRUE;
return TRUE;
}
@ -797,6 +798,8 @@ static BOOL shadow_client_caps_test_version(RdpgfxServerContext* context, rdpSha
if (currentCaps->version == capsVersion)
{
UINT32 flags;
BOOL planar = FALSE;
BOOL rfx = FALSE;
BOOL avc444v2 = FALSE;
BOOL avc444 = FALSE;
BOOL avc420 = FALSE;
@ -825,6 +828,12 @@ static BOOL shadow_client_caps_test_version(RdpgfxServerContext* context, rdpSha
progressive = freerdp_settings_get_bool(srvSettings, FreeRDP_GfxProgressiveV2);
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxProgressiveV2, progressive);
rfx = freerdp_settings_get_bool(srvSettings, FreeRDP_RemoteFxCodec);
freerdp_settings_set_bool(clientSettings, FreeRDP_RemoteFxCodec, rfx);
planar = freerdp_settings_get_bool(srvSettings, FreeRDP_GfxPlanar);
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxPlanar, planar);
if (!avc444v2 && !avc444 && !avc420)
pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
@ -994,10 +1003,11 @@ static INLINE UINT32 rdpgfx_estimate_h264_avc420(RDPGFX_AVC420_BITMAP_STREAM* ha
*
* @return TRUE on success
*/
static BOOL shadow_client_send_surface_gfx(const rdpShadowClient* client, const BYTE* pSrcData,
static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE* pSrcData,
UINT32 nSrcStep, UINT32 SrcFormat, UINT16 nXSrc,
UINT16 nYSrc, UINT16 nWidth, UINT16 nHeight)
{
UINT32 id;
UINT error = CHANNEL_RC_OK;
const rdpContext* context = (const rdpContext*)client;
const rdpSettings* settings;
@ -1016,6 +1026,12 @@ static BOOL shadow_client_send_surface_gfx(const rdpShadowClient* client, const
if (!settings || !encoder)
return FALSE;
if (client->first_frame)
{
rfx_context_reset(encoder->rfx, nWidth, nHeight);
client->first_frame = FALSE;
}
cmdstart.frameId = shadow_encoder_create_frame_id(encoder);
GetSystemTime(&sTime);
cmdstart.timestamp = (UINT32)(sTime.wHour << 22U | sTime.wMinute << 16U | sTime.wSecond << 10U |
@ -1035,6 +1051,7 @@ static BOOL shadow_client_send_surface_gfx(const rdpShadowClient* client, const
cmd.data = NULL;
cmd.extra = NULL;
id = freerdp_settings_get_uint32(settings, FreeRDP_RemoteFxCodecId);
if (settings->GfxAVC444 || settings->GfxAVC444v2)
{
INT32 rc;
@ -1130,6 +1147,57 @@ static BOOL shadow_client_send_surface_gfx(const rdpShadowClient* client, const
return FALSE;
}
}
else if (freerdp_settings_get_bool(settings, FreeRDP_RemoteFxCodec) && (id != 0))
{
BOOL rc;
wStream* s;
RECTANGLE_16 rect;
if (shadow_encoder_prepare(encoder, FREERDP_CODEC_REMOTEFX) < 0)
{
WLog_ERR(TAG, "Failed to prepare encoder FREERDP_CODEC_REMOTEFX");
return FALSE;
}
s = Stream_New(NULL, 1024);
WINPR_ASSERT(s);
WINPR_ASSERT(cmd.left <= UINT16_MAX);
WINPR_ASSERT(cmd.top <= UINT16_MAX);
WINPR_ASSERT(cmd.right <= UINT16_MAX);
WINPR_ASSERT(cmd.bottom <= UINT16_MAX);
rect.left = (UINT16)cmd.left;
rect.top = (UINT16)cmd.top;
rect.right = (UINT16)cmd.right;
rect.bottom = (UINT16)cmd.bottom;
rc = rfx_compose_message(encoder->rfx, s, &rect, 1, pSrcData, nWidth, nHeight, nSrcStep);
if (!rc)
{
WLog_ERR(TAG, "rfx_compose_message failed");
Stream_Free(s, TRUE);
return FALSE;
}
/* rc > 0 means new data */
if (rc > 0)
{
cmd.codecId = RDPGFX_CODECID_CAVIDEO;
cmd.data = Stream_Buffer(s);
cmd.length = Stream_GetPosition(s);
IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
&cmdend);
}
Stream_Free(s, TRUE);
if (error)
{
WLog_ERR(TAG, "SurfaceFrameCommand failed with error %" PRIu32 "", error);
return FALSE;
}
}
else if (freerdp_settings_get_bool(settings, FreeRDP_GfxProgressive))
{
INT32 rc;
@ -1176,6 +1244,47 @@ static BOOL shadow_client_send_surface_gfx(const rdpShadowClient* client, const
return FALSE;
}
}
else if (freerdp_settings_get_bool(settings, FreeRDP_GfxPlanar))
{
BOOL rc;
const UINT32 w = cmd.right - cmd.left;
const UINT32 h = cmd.bottom - cmd.top;
const size_t step = w * GetBytesPerPixel(SrcFormat);
const size_t size = step * h;
BYTE* dst;
if (shadow_encoder_prepare(encoder, FREERDP_CODEC_PLANAR) < 0)
{
WLog_ERR(TAG, "Failed to prepare encoder FREERDP_CODEC_PLANAR");
return FALSE;
}
rc = freerdp_bitmap_planar_context_reset(encoder->planar, w, h);
WINPR_ASSERT(rc);
dst = malloc(size);
WINPR_ASSERT(dst);
rc = freerdp_image_copy(dst, SrcFormat, step, 0, 0, w, h, pSrcData, SrcFormat, nSrcStep,
cmd.left, cmd.top, NULL, FREERDP_FLIP_VERTICAL);
WINPR_ASSERT(rc);
cmd.data = freerdp_bitmap_compress_planar(encoder->planar, dst, SrcFormat, w, h, step, NULL,
&cmd.length);
WINPR_ASSERT(cmd.data || (cmd.length == 0));
free(dst);
cmd.codecId = RDPGFX_CODECID_PLANAR;
IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
&cmdend);
free(cmd.data);
if (error)
{
WLog_ERR(TAG, "SurfaceFrameCommand failed with error %" PRIu32 "", error);
return FALSE;
}
}
else
{
BOOL rc;
@ -1183,10 +1292,10 @@ static BOOL shadow_client_send_surface_gfx(const rdpShadowClient* client, const
const UINT32 h = cmd.bottom - cmd.top;
const UINT32 length = w * 4 * h;
BYTE* data = malloc(length);
if (!data)
return FALSE;
rc = freerdp_image_copy(data, PIXEL_FORMAT_BGRA32, w * 4, 0, 0, w, h, pSrcData, SrcFormat,
WINPR_ASSERT(data);
rc = freerdp_image_copy(data, PIXEL_FORMAT_BGRA32, 0, 0, 0, w, h, pSrcData, SrcFormat,
nSrcStep, cmd.left, cmd.top, NULL, 0);
WINPR_ASSERT(rc);
@ -1501,6 +1610,7 @@ static BOOL shadow_client_send_bitmap_update(rdpShadowClient* client, BYTE* pSrc
UINT32 dstSize;
buffer = encoder->grid[k];
data = &pSrcData[(bitmap->destTop * nSrcStep) + (bitmap->destLeft * 4)];
buffer =
freerdp_bitmap_compress_planar(encoder->planar, data, SrcFormat, bitmap->width,
bitmap->height, nSrcStep, buffer, &dstSize);

View File

@ -371,6 +371,17 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
arg->Value ? TRUE : FALSE))
return COMMAND_LINE_ERROR;
}
CommandLineSwitchCase(arg, "gfx-rfx")
{
if (!freerdp_settings_set_bool(settings, FreeRDP_RemoteFxCodec,
arg->Value ? TRUE : FALSE))
return COMMAND_LINE_ERROR;
}
CommandLineSwitchCase(arg, "gfx-planar")
{
if (!freerdp_settings_set_bool(settings, FreeRDP_GfxPlanar, arg->Value ? TRUE : FALSE))
return COMMAND_LINE_ERROR;
}
CommandLineSwitchCase(arg, "gfx-avc420")
{
if (!freerdp_settings_set_bool(settings, FreeRDP_GfxH264, arg->Value ? TRUE : FALSE))