Added RDPGFX_CODECID_UNCOMPRESSED path to shadow

This commit is contained in:
akallabeth 2021-06-30 13:04:22 +02:00 committed by akallabeth
parent 1974cbda2b
commit 3ac50697a0
4 changed files with 184 additions and 67 deletions

View File

@ -341,7 +341,7 @@ endif()
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-shadow-subsystem freerdp-shadow winpr) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-shadow-subsystem freerdp-shadow freerdp winpr)
target_link_libraries(${MODULE_NAME} PRIVATE ${${MODULE_PREFIX}_LIBS}) target_link_libraries(${MODULE_NAME} PRIVATE ${${MODULE_PREFIX}_LIBS})

View File

@ -79,6 +79,12 @@ int main(int argc, char** argv)
"nla extended protocol security" }, "nla extended protocol security" },
{ "sam-file", COMMAND_LINE_VALUE_REQUIRED, "<file>", NULL, NULL, -1, NULL, { "sam-file", COMMAND_LINE_VALUE_REQUIRED, "<file>", NULL, NULL, -1, NULL,
"NTLM SAM file for NLA authentication" }, "NTLM SAM file for NLA authentication" },
{ "gfx-progressive", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL,
"Allow GFX progressive 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,
"Allow GFX AVC444 codec" },
{ "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1, { "version", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_VERSION, NULL, NULL, NULL, -1,
NULL, "Print version" }, NULL, "Print version" },
{ "buildconfig", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_BUILDCONFIG, NULL, NULL, NULL, { "buildconfig", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_BUILDCONFIG, NULL, NULL, NULL,
@ -105,6 +111,15 @@ int main(int argc, char** argv)
settings->TlsSecurity = TRUE; settings->TlsSecurity = TRUE;
settings->RdpSecurity = TRUE; settings->RdpSecurity = TRUE;
/* By default allow all GFX modes.
* This can be changed with command line flags [+|-]gfx-CODEC
*/
freerdp_settings_set_bool(settings, FreeRDP_GfxH264, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444v2, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_GfxProgressive, TRUE);
freerdp_settings_set_bool(settings, FreeRDP_GfxProgressiveV2, TRUE);
#ifdef WITH_SHADOW_X11 #ifdef WITH_SHADOW_X11
server->authentication = TRUE; server->authentication = TRUE;
#else #else

View File

@ -136,16 +136,27 @@ static INLINE void shadow_client_free_queued_message(void* obj)
} }
} }
static BOOL shadow_client_context_new(freerdp_peer* peer, rdpShadowClient* client) static BOOL shadow_client_context_new(freerdp_peer* peer, rdpContext* context)
{ {
const char bind_address[] = "bind-address,"; const char bind_address[] = "bind-address,";
rdpShadowClient* client = (rdpShadowClient*)context;
rdpSettings* settings; rdpSettings* settings;
rdpShadowServer* server; rdpShadowServer* server;
const wObject cb = { NULL, NULL, NULL, shadow_client_free_queued_message, NULL }; const wObject cb = { NULL, NULL, NULL, shadow_client_free_queued_message, NULL };
WINPR_ASSERT(client);
WINPR_ASSERT(peer);
server = (rdpShadowServer*)peer->ContextExtra; server = (rdpShadowServer*)peer->ContextExtra;
WINPR_ASSERT(server);
client->server = server; client->server = server;
client->subsystem = server->subsystem; client->subsystem = server->subsystem;
WINPR_ASSERT(client->subsystem);
settings = peer->settings; settings = peer->settings;
WINPR_ASSERT(settings);
settings->ColorDepth = 32; settings->ColorDepth = 32;
settings->NSCodec = TRUE; settings->NSCodec = TRUE;
settings->RemoteFxCodec = TRUE; settings->RemoteFxCodec = TRUE;
@ -220,10 +231,16 @@ fail_cert_file:
return FALSE; return FALSE;
} }
static void shadow_client_context_free(freerdp_peer* peer, rdpShadowClient* client) static void shadow_client_context_free(freerdp_peer* peer, rdpContext* context)
{ {
rdpShadowServer* server = client->server; rdpShadowClient* client = (rdpShadowClient*)context;
rdpShadowServer* server;
WINPR_ASSERT(context);
WINPR_UNUSED(peer); WINPR_UNUSED(peer);
server = client->server;
WINPR_ASSERT(server);
ArrayList_Remove(server->clients, (void*)client); ArrayList_Remove(server->clients, (void*)client);
if (client->encoder) if (client->encoder)
@ -656,16 +673,27 @@ static BOOL shadow_are_caps_filtered(const rdpSettings* settings, UINT32 caps)
return TRUE; return TRUE;
} }
static BOOL shadow_client_caps_test_version(RdpgfxServerContext* context, BOOL h264, static BOOL shadow_client_caps_test_version(RdpgfxServerContext* context, rdpShadowClient* client,
const RDPGFX_CAPSET* capsSets, UINT32 capsSetCount, BOOL h264, const RDPGFX_CAPSET* capsSets,
UINT32 capsVersion, UINT* rc) UINT32 capsSetCount, UINT32 capsVersion, UINT* rc)
{ {
UINT32 flags = 0;
UINT32 index; UINT32 index;
rdpSettings* settings; const rdpSettings* srvSettings;
settings = context->rdpcontext->settings; rdpSettings* clientSettings;
if (shadow_are_caps_filtered(settings, capsVersion)) WINPR_ASSERT(context);
WINPR_ASSERT(client);
WINPR_ASSERT(capsSets || (capsSetCount == 0));
WINPR_ASSERT(rc);
WINPR_ASSERT(context->rdpcontext);
srvSettings = context->rdpcontext->settings;
WINPR_ASSERT(srvSettings);
clientSettings = client->context.settings;
WINPR_ASSERT(clientSettings);
if (shadow_are_caps_filtered(srvSettings, capsVersion))
return FALSE; return FALSE;
for (index = 0; index < capsSetCount; index++) for (index = 0; index < capsSetCount; index++)
@ -674,25 +702,39 @@ static BOOL shadow_client_caps_test_version(RdpgfxServerContext* context, BOOL h
if (currentCaps->version == capsVersion) if (currentCaps->version == capsVersion)
{ {
UINT32 flags;
BOOL avc444v2 = FALSE;
BOOL avc444 = FALSE;
BOOL avc420 = FALSE;
BOOL progressive = FALSE;
RDPGFX_CAPSET caps = *currentCaps; RDPGFX_CAPSET caps = *currentCaps;
RDPGFX_CAPS_CONFIRM_PDU pdu; RDPGFX_CAPS_CONFIRM_PDU pdu = { 0 };
pdu.capsSet = &caps; pdu.capsSet = &caps;
if (settings) flags = pdu.capsSet->flags;
{
flags = pdu.capsSet->flags;
settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
if (h264) clientSettings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 =
!(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED);
else
{
settings->GfxAVC444v2 = settings->GfxAVC444 = settings->GfxH264 = FALSE;
pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
}
}
avc444v2 = avc444 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED);
if (!freerdp_settings_get_bool(srvSettings, FreeRDP_GfxAVC444v2) || !h264)
avc444v2 = FALSE;
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxAVC444v2, avc444v2);
if (!freerdp_settings_get_bool(srvSettings, FreeRDP_GfxAVC444) || !h264)
avc444 = FALSE;
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxAVC444, avc444);
if (!freerdp_settings_get_bool(srvSettings, FreeRDP_GfxH264) || !h264)
avc420 = FALSE;
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxH264, avc420);
progressive = freerdp_settings_get_bool(srvSettings, FreeRDP_GfxProgressive);
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxProgressive, progressive);
progressive = freerdp_settings_get_bool(srvSettings, FreeRDP_GfxProgressiveV2);
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxProgressiveV2, progressive);
if (!avc444v2 && !avc444 && !avc420)
pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
WINPR_ASSERT(context->CapsConfirm);
*rc = context->CapsConfirm(context, &pdu); *rc = context->CapsConfirm(context, &pdu);
return TRUE; return TRUE;
} }
@ -711,50 +753,68 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context,
{ {
UINT16 index; UINT16 index;
UINT rc = ERROR_INTERNAL_ERROR; UINT rc = ERROR_INTERNAL_ERROR;
const rdpSettings* srvSettings;
rdpSettings* clientSettings;
BOOL h264 = FALSE; BOOL h264 = FALSE;
rdpSettings* settings = context->rdpcontext->settings;
UINT32 flags = 0; UINT32 flags = 0;
rdpShadowClient* client = (rdpShadowClient*)context->custom; rdpShadowClient* client;
WINPR_ASSERT(context);
WINPR_ASSERT(capsAdvertise);
client = (rdpShadowClient*)context->custom;
WINPR_ASSERT(client);
WINPR_ASSERT(context->rdpcontext);
srvSettings = context->rdpcontext->settings;
WINPR_ASSERT(srvSettings);
clientSettings = client->context.settings;
WINPR_ASSERT(clientSettings);
#ifdef WITH_GFX_H264 #ifdef WITH_GFX_H264
if (shadow_encoder_prepare(client->encoder, FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444) >= 0) h264 =
h264 = TRUE; (shadow_encoder_prepare(client->encoder, FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444) >= 0);
#else
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxAVC444v2, FALSE);
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxAVC444, FALSE);
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxH264, FALSE);
#endif #endif
/* Request full screen update for new gfx channel */ /* Request full screen update for new gfx channel */
if (!shadow_client_refresh_rect(&client->context, 0, NULL)) if (!shadow_client_refresh_rect(&client->context, 0, NULL))
return rc; return rc;
if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets, if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_106, &rc)) capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_106, &rc))
return rc; return rc;
if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets, if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_105, &rc)) capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_105, &rc))
return rc; return rc;
if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets, if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_104, &rc)) capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_104, &rc))
return rc; return rc;
if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets, if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_103, &rc)) capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_103, &rc))
return rc; return rc;
if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets, if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_102, &rc)) capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_102, &rc))
return rc; return rc;
if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets, if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_101, &rc)) capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_101, &rc))
return rc; return rc;
if (shadow_client_caps_test_version(context, h264, capsAdvertise->capsSets, if (shadow_client_caps_test_version(context, client, h264, capsAdvertise->capsSets,
capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_10, &rc)) capsAdvertise->capsSetCount, RDPGFX_CAPVERSION_10, &rc))
return rc; return rc;
if (!shadow_are_caps_filtered(settings, RDPGFX_CAPVERSION_81)) if (!shadow_are_caps_filtered(srvSettings, RDPGFX_CAPVERSION_81))
{ {
for (index = 0; index < capsAdvertise->capsSetCount; index++) for (index = 0; index < capsAdvertise->capsSetCount; index++)
{ {
@ -766,29 +826,35 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context,
RDPGFX_CAPS_CONFIRM_PDU pdu; RDPGFX_CAPS_CONFIRM_PDU pdu;
pdu.capsSet = &caps; pdu.capsSet = &caps;
if (settings)
{
flags = pdu.capsSet->flags; flags = pdu.capsSet->flags;
settings->GfxAVC444v2 = settings->GfxAVC444 = FALSE;
settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_THINCLIENT);
settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
#ifndef WITH_GFX_H264
settings->GfxH264 = FALSE;
pdu.capsSet->flags &= ~RDPGFX_CAPS_FLAG_AVC420_ENABLED;
#else
if (h264)
settings->GfxH264 = (flags & RDPGFX_CAPS_FLAG_AVC420_ENABLED);
else
settings->GfxH264 = FALSE;
#endif
}
return context->CapsConfirm(context, &pdu); freerdp_settings_set_bool(clientSettings, FreeRDP_GfxAVC444v2, FALSE);
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxAVC444, FALSE);
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxThinClient,
(flags & RDPGFX_CAPS_FLAG_THINCLIENT));
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxSmallCache,
(flags & RDPGFX_CAPS_FLAG_SMALL_CACHE));
#ifndef WITH_GFX_H264
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxH264, FALSE);
pdu.capsSet->flags &= ~RDPGFX_CAPS_FLAG_AVC420_ENABLED;
#else
if (h264)
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxH264,
(flags & RDPGFX_CAPS_FLAG_AVC420_ENABLED));
else
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxH264, FALSE);
#endif
WINPR_ASSERT(context->CapsConfirm);
return context->CapsConfirm(context, &pdu);
} }
} }
} }
if (!shadow_are_caps_filtered(settings, RDPGFX_CAPVERSION_8)) if (!shadow_are_caps_filtered(srvSettings, RDPGFX_CAPVERSION_8))
{ {
for (index = 0; index < capsAdvertise->capsSetCount; index++) for (index = 0; index < capsAdvertise->capsSetCount; index++)
{ {
@ -799,14 +865,18 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context,
RDPGFX_CAPSET caps = *currentCaps; RDPGFX_CAPSET caps = *currentCaps;
RDPGFX_CAPS_CONFIRM_PDU pdu; RDPGFX_CAPS_CONFIRM_PDU pdu;
pdu.capsSet = &caps; pdu.capsSet = &caps;
flags = pdu.capsSet->flags;
if (settings) freerdp_settings_set_bool(clientSettings, FreeRDP_GfxAVC444v2, FALSE);
{ freerdp_settings_set_bool(clientSettings, FreeRDP_GfxAVC444, FALSE);
flags = pdu.capsSet->flags; freerdp_settings_set_bool(clientSettings, FreeRDP_GfxH264, FALSE);
settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_THINCLIENT);
settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE);
}
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxThinClient,
(flags & RDPGFX_CAPS_FLAG_THINCLIENT));
freerdp_settings_set_bool(clientSettings, FreeRDP_GfxSmallCache,
(flags & RDPGFX_CAPS_FLAG_SMALL_CACHE));
WINPR_ASSERT(context->CapsConfirm);
return context->CapsConfirm(context, &pdu); return context->CapsConfirm(context, &pdu);
} }
} }
@ -829,13 +899,13 @@ static INLINE UINT32 rdpgfx_estimate_h264_avc420(RDPGFX_AVC420_BITMAP_STREAM* ha
* *
* @return TRUE on success * @return TRUE on success
*/ */
static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE* pSrcData, static BOOL shadow_client_send_surface_gfx(const rdpShadowClient* client, const BYTE* pSrcData,
UINT32 nSrcStep, UINT16 nXSrc, UINT16 nYSrc, UINT32 nSrcStep, UINT16 nXSrc, UINT16 nYSrc,
UINT16 nWidth, UINT16 nHeight) UINT16 nWidth, UINT16 nHeight)
{ {
UINT error = CHANNEL_RC_OK; UINT error = CHANNEL_RC_OK;
rdpContext* context = (rdpContext*)client; const rdpContext* context = (const rdpContext*)client;
rdpSettings* settings; const rdpSettings* settings;
rdpShadowEncoder* encoder; rdpShadowEncoder* encoder;
RDPGFX_SURFACE_COMMAND cmd; RDPGFX_SURFACE_COMMAND cmd;
RDPGFX_START_FRAME_PDU cmdstart; RDPGFX_START_FRAME_PDU cmdstart;
@ -965,7 +1035,7 @@ static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE*
return FALSE; return FALSE;
} }
} }
else else if (freerdp_settings_get_bool(settings, FreeRDP_GfxProgressive))
{ {
INT32 rc; INT32 rc;
REGION16 region; REGION16 region;
@ -1011,6 +1081,21 @@ static BOOL shadow_client_send_surface_gfx(rdpShadowClient* client, const BYTE*
return FALSE; return FALSE;
} }
} }
else
{
cmd.data = pSrcData;
cmd.length = nSrcStep * nHeight;
cmd.codecId = RDPGFX_CODECID_UNCOMPRESSED;
IFCALLRET(client->rdpgfx->SurfaceFrameCommand, error, client->rdpgfx, &cmd, &cmdstart,
&cmdend);
if (error)
{
WLog_ERR(TAG, "SurfaceFrameCommand failed with error %" PRIu32 "", error);
return FALSE;
}
}
return TRUE; return TRUE;
} }
@ -2055,8 +2140,8 @@ BOOL shadow_client_accepted(freerdp_listener* listener, freerdp_peer* peer)
server = (rdpShadowServer*)listener->info; server = (rdpShadowServer*)listener->info;
peer->ContextExtra = (void*)server; peer->ContextExtra = (void*)server;
peer->ContextSize = sizeof(rdpShadowClient); peer->ContextSize = sizeof(rdpShadowClient);
peer->ContextNew = (psPeerContextNew)shadow_client_context_new; peer->ContextNew = shadow_client_context_new;
peer->ContextFree = (psPeerContextFree)shadow_client_context_free; peer->ContextFree = shadow_client_context_free;
peer->settings = freerdp_settings_clone(server->settings); peer->settings = freerdp_settings_clone(server->settings);
if (!freerdp_peer_context_new(peer)) if (!freerdp_peer_context_new(peer))

View File

@ -365,6 +365,23 @@ int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** a
if (!WLog_AddStringLogFilters(arg->Value)) if (!WLog_AddStringLogFilters(arg->Value))
return COMMAND_LINE_ERROR; return COMMAND_LINE_ERROR;
} }
CommandLineSwitchCase(arg, "gfx-progressive")
{
if (!freerdp_settings_set_bool(settings, FreeRDP_GfxProgressive,
arg->Value ? TRUE : FALSE))
return COMMAND_LINE_ERROR;
}
CommandLineSwitchCase(arg, "gfx-avc420")
{
if (!freerdp_settings_set_bool(settings, FreeRDP_GfxH264, arg->Value ? TRUE : FALSE))
return COMMAND_LINE_ERROR;
}
CommandLineSwitchCase(arg, "gfx-avc444")
{
if (!freerdp_settings_set_bool(settings, FreeRDP_GfxAVC444v2,
arg->Value ? TRUE : FALSE))
return COMMAND_LINE_ERROR;
}
CommandLineSwitchDefault(arg) CommandLineSwitchDefault(arg)
{ {
} }