diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 775a92101..815e08dcb 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -87,26 +87,29 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) if (gfx->SmallCache) capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; +#ifdef WITH_GFX_H264 if (gfx->H264) capsSet->flags |= RDPGFX_CAPS_FLAG_AVC420_ENABLED; +#endif - if (gfx->AVC444) - { - capsSet = &capsSets[pdu.capsSetCount++]; - capsSet->version = RDPGFX_CAPVERSION_10; - capsSet->flags = 0; + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_10; + capsSet->flags = 0; - if (gfx->SmallCache) - capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + if (gfx->SmallCache) + capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; - if (!gfx->H264) - capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; +#ifdef WITH_GFX_H264 + if (!gfx->AVC444) + capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; +#else + capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; +#endif - capsSets[pdu.capsSetCount] = *capsSet; - capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_102; - capsSets[pdu.capsSetCount] = *capsSet; - capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_103; - } + capsSets[pdu.capsSetCount] = *capsSet; + capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_102; + capsSets[pdu.capsSetCount] = *capsSet; + capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_103; header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE); diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 937db5274..4a658fc87 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -121,11 +121,17 @@ static COMMAND_LINE_ARGUMENT_A args[] = { "themes", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable themes" }, { "wallpaper", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Enable wallpaper" }, { "gdi", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "GDI rendering" }, +#ifdef WITH_GFX_H264 { "gfx", COMMAND_LINE_VALUE_OPTIONAL, "", NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" }, +#else + { "gfx", COMMAND_LINE_VALUE_OPTIONAL, "", NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" }, +#endif { "gfx-thin-client", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8 graphics pipeline using thin client mode" }, { "gfx-small-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8 graphics pipeline using small cache mode" }, { "gfx-progressive", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "RDP8 graphics pipeline using progressive codec" }, +#ifdef WITH_GFX_H264 { "gfx-h264", COMMAND_LINE_VALUE_OPTIONAL, "", NULL, NULL, -1, NULL, "RDP8.1 graphics pipeline using H264 codec" }, +#endif { "rfx", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "RemoteFX" }, { "rfx-mode", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "RemoteFX mode" }, { "frame-ack", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Number of frame acknowledgement" }, @@ -2085,6 +2091,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (arg->Value) { +#ifdef WITH_GFX_H264 if (_strnicmp("AVC444", arg->Value, 6) == 0) { settings->GfxH264 = TRUE; @@ -2094,7 +2101,9 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { settings->GfxH264 = TRUE; } - else if (_strnicmp("RFX", arg->Value, 3) != 0) + else +#endif + if (_strnicmp("RFX", arg->Value, 3) != 0) return COMMAND_LINE_ERROR; } } @@ -2114,6 +2123,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, settings->GfxThinClient = settings->GfxProgressive ? FALSE : TRUE; settings->SupportGraphicsPipeline = TRUE; } +#ifdef WITH_GFX_H264 CommandLineSwitchCase(arg, "gfx-h264") { settings->SupportGraphicsPipeline = TRUE; @@ -2129,6 +2139,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, return COMMAND_LINE_ERROR; } } +#endif CommandLineSwitchCase(arg, "rfx") { settings->RemoteFxCodec = TRUE; diff --git a/cmake/ConfigOptions.cmake b/cmake/ConfigOptions.cmake index 67b298e13..6dacffb7d 100644 --- a/cmake/ConfigOptions.cmake +++ b/cmake/ConfigOptions.cmake @@ -41,13 +41,15 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_COMPILER_IS_CLANG 1) endif() +option(WITH_GFX_H264 "Build GFX H264 support. A backend (OpenH264|FFMPEG|X264|MediaFoundation) must also be compiled in." OFF) if(NOT WIN32) CMAKE_DEPENDENT_OPTION(WITH_VALGRIND_MEMCHECK "Compile with valgrind helpers." OFF "NOT WITH_SANITIZE_ADDRESS; NOT WITH_SANITIZE_LEAK" OFF) CMAKE_DEPENDENT_OPTION(WITH_SANITIZE_ADDRESS "Compile with gcc/clang address sanitizer." OFF "NOT WITH_VALGRIND_MEMCHECK; NOT WITH_SANITIZE_LEAK" OFF) CMAKE_DEPENDENT_OPTION(WITH_SANITIZE_LEAK "Compile with gcc/clang leak sanitizer." OFF "NOT WITH_VALGRIND_MEMCHECK; NOT WITH_SANITIZE_ADDRESS" OFF) else() if(NOT UWP) - option(WITH_MEDIA_FOUNDATION "Enable H264 media foundation decoder." ON) + CMAKE_DEPENDENT_OPTION(WITH_MEDIA_FOUNDATION "Enable H264 media foundation decoder." ON + "WITH_GFX_H264" OFF) endif() endif() @@ -138,3 +140,4 @@ endif(ANDROID) if(IOS) include(ConfigOptionsiOS) endif(IOS) + diff --git a/config.h.in b/config.h.in index 0c8ab218e..4e97ee121 100644 --- a/config.h.in +++ b/config.h.in @@ -37,7 +37,6 @@ #cmakedefine WITH_EVENTFD_READ_WRITE #cmakedefine HAVE_MATH_C99_LONG_DOUBLE -#cmakedefine WITH_FFMPEG #cmakedefine WITH_GSTREAMER_1_0 #cmakedefine WITH_GSTREAMER_0_10 #cmakedefine WITH_WINMM @@ -48,6 +47,10 @@ #cmakedefine WITH_IOSAUDIO #cmakedefine WITH_OPENSLES #cmakedefine WITH_GSM +#cmakedefine WITH_GFX_H264 +#cmakedefine WITH_OPENH264 +#cmakedefine WITH_FFMPEG +#cmakedefine WITH_X264 #cmakedefine WITH_MEDIA_FOUNDATION /* Plugins */ diff --git a/include/freerdp/channels/rdpgfx.h b/include/freerdp/channels/rdpgfx.h index 88b1204fc..03a44ab87 100644 --- a/include/freerdp/channels/rdpgfx.h +++ b/include/freerdp/channels/rdpgfx.h @@ -105,10 +105,10 @@ struct _RDPGFX_CAPSET }; typedef struct _RDPGFX_CAPSET RDPGFX_CAPSET; -#define RDPGFX_CAPS_FLAG_THINCLIENT 0x00000001 /* 8.0+ */ -#define RDPGFX_CAPS_FLAG_SMALL_CACHE 0x00000002 /* 8.0+ */ -#define RDPGFX_CAPS_FLAG_AVC420_ENABLED 0x00000010 /* 8.1+ */ -#define RDPGFX_CAPS_FLAG_AVC_DISABLED 0x00000020 /* 10.0+ */ +#define RDPGFX_CAPS_FLAG_THINCLIENT 0x00000001U /* 8.0+ */ +#define RDPGFX_CAPS_FLAG_SMALL_CACHE 0x00000002U /* 8.0+ */ +#define RDPGFX_CAPS_FLAG_AVC420_ENABLED 0x00000010U /* 8.1+ */ +#define RDPGFX_CAPS_FLAG_AVC_DISABLED 0x00000020U /* 10.0+ */ struct _RDPGFX_CAPSET_VERSION8 { diff --git a/libfreerdp/CMakeLists.txt b/libfreerdp/CMakeLists.txt index 17687739b..605b5f2cf 100644 --- a/libfreerdp/CMakeLists.txt +++ b/libfreerdp/CMakeLists.txt @@ -166,21 +166,18 @@ endif() if(WITH_X264) set(CODEC_SRCS ${CODEC_SRCS} codec/h264_x264.c) - freerdp_definition_add(-DWITH_X264) freerdp_include_directory_add(${X264_INCLUDE_DIR}) freerdp_library_add(${X264_LIBRARIES}) endif() if(WITH_OPENH264) set(CODEC_SRCS ${CODEC_SRCS} codec/h264_openh264.c) - freerdp_definition_add(-DWITH_OPENH264) freerdp_include_directory_add(${OPENH264_INCLUDE_DIR}) freerdp_library_add(${OPENH264_LIBRARIES}) endif() if(WITH_FFMPEG) set(CODEC_SRCS ${CODEC_SRCS} codec/h264_ffmpeg.c) - freerdp_definition_add(-DWITH_LIBAVCODEC) freerdp_include_directory_add(${FFMPEG_INCLUDE_DIRS}) freerdp_library_add(${FFMPEG_LIBRARIES}) endif() diff --git a/libfreerdp/codec/h264.c b/libfreerdp/codec/h264.c index 0e163cd6d..fbf089f22 100644 --- a/libfreerdp/codec/h264.c +++ b/libfreerdp/codec/h264.c @@ -457,7 +457,7 @@ static BOOL CALLBACK h264_register_subsystems(PINIT_ONCE once, PVOID param, PVOI i++; #endif -#ifdef WITH_LIBAVCODEC +#ifdef WITH_FFMPEG extern H264_CONTEXT_SUBSYSTEM g_Subsystem_libavcodec; subSystems[i] = &g_Subsystem_libavcodec; i++; diff --git a/libfreerdp/codec/h264_ffmpeg.c b/libfreerdp/codec/h264_ffmpeg.c index d290c1f99..847f35982 100644 --- a/libfreerdp/codec/h264_ffmpeg.c +++ b/libfreerdp/codec/h264_ffmpeg.c @@ -26,6 +26,8 @@ #define TAG FREERDP_TAG("codec") +#warning "FFMPEG does not support H264 encoding (GFX H264 server mode). Please review your configuration!" + /* Fallback support for older libavcodec versions */ #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 59, 100) #define AV_CODEC_ID_H264 CODEC_ID_H264 diff --git a/libfreerdp/codec/h264_x264.c b/libfreerdp/codec/h264_x264.c index 40d1d29e5..11e7f0eb4 100644 --- a/libfreerdp/codec/h264_x264.c +++ b/libfreerdp/codec/h264_x264.c @@ -38,6 +38,8 @@ #include #include +#error "X264 backend not implemented, please review your configuration!" + struct _H264_CONTEXT_X264 { void* dummy; diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c index 1db42531f..caff4dce6 100644 --- a/server/shadow/shadow_client.c +++ b/server/shadow/shadow_client.c @@ -621,7 +621,6 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, RDPGFX_CAPS_ADVERTISE_PDU* capsAdvertise) { UINT16 index; - RDPGFX_CAPS_CONFIRM_PDU pdu; rdpSettings* settings = context->rdpcontext->settings; UINT32 flags = 0; /* Request full screen update for new gfx channel */ @@ -629,15 +628,24 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, for (index = 0; index < capsAdvertise->capsSetCount; index++) { - pdu.capsSet = &(capsAdvertise->capsSets[index]); + const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index]; - if (pdu.capsSet->version == RDPGFX_CAPVERSION_102) + if (currentCaps->version == RDPGFX_CAPVERSION_102) { + RDPGFX_CAPSET caps = *currentCaps; + RDPGFX_CAPS_CONFIRM_PDU pdu; + pdu.capsSet = ∩︀ + if (settings) { flags = pdu.capsSet->flags; settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); +#ifndef WITH_GFX_H264 + settings->GfxH264 = FALSE; + pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; +#else settings->GfxH264 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED); +#endif } return context->CapsConfirm(context, &pdu); @@ -646,15 +654,24 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, for (index = 0; index < capsAdvertise->capsSetCount; index++) { - pdu.capsSet = &(capsAdvertise->capsSets[index]); + const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index]; - if (pdu.capsSet->version == RDPGFX_CAPVERSION_10) + if (currentCaps->version == RDPGFX_CAPVERSION_10) { + RDPGFX_CAPSET caps = *currentCaps; + RDPGFX_CAPS_CONFIRM_PDU pdu; + pdu.capsSet = ∩︀ + if (settings) { flags = pdu.capsSet->flags; settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); +#ifndef WITH_GFX_H264 + settings->GfxH264 = FALSE; + pdu.capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; +#else settings->GfxH264 = !(flags & RDPGFX_CAPS_FLAG_AVC_DISABLED); +#endif } return context->CapsConfirm(context, &pdu); @@ -663,14 +680,25 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, for (index = 0; index < capsAdvertise->capsSetCount; index++) { - if (pdu.capsSet->version == RDPGFX_CAPVERSION_81) - { + const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index]; + + if (currentCaps->version == RDPGFX_CAPVERSION_81) + { + RDPGFX_CAPSET caps = *currentCaps; + RDPGFX_CAPS_CONFIRM_PDU pdu; + pdu.capsSet = ∩︀ + if (settings) { flags = pdu.capsSet->flags; settings->GfxThinClient = (flags & RDPGFX_CAPS_FLAG_THINCLIENT); - settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); + settings->GfxSmallCache = (flags & RDPGFX_CAPS_FLAG_SMALL_CACHE); +#ifndef WITH_GFX_H264 + settings->GfxH264 = FALSE; + pdu.capsSet->flags &= ~RDPGFX_CAPS_FLAG_AVC420_ENABLED; +#else settings->GfxH264 = (flags & RDPGFX_CAPS_FLAG_AVC420_ENABLED); +#endif } return context->CapsConfirm(context, &pdu); @@ -679,8 +707,14 @@ static UINT shadow_client_rdpgfx_caps_advertise(RdpgfxServerContext* context, for (index = 0; index < capsAdvertise->capsSetCount; index++) { - if (pdu.capsSet->version == RDPGFX_CAPVERSION_8) + const RDPGFX_CAPSET* currentCaps = &capsAdvertise->capsSets[index]; + + if (currentCaps->version == RDPGFX_CAPVERSION_8) { + RDPGFX_CAPSET caps = *currentCaps; + RDPGFX_CAPS_CONFIRM_PDU pdu; + pdu.capsSet = ∩︀ + if (settings) { flags = pdu.capsSet->flags;