diff --git a/docs/man/gfx.toml.5.in b/docs/man/gfx.toml.5.in index b260e495..d0642fc5 100644 --- a/docs/man/gfx.toml.5.in +++ b/docs/man/gfx.toml.5.in @@ -68,7 +68,7 @@ for use with xrdp. Here are available options: .TP \fBprofile\fR = \fI\fR -Select a profile. Here are available options: +Select a profile. Here are available options: .B main, baseline, high, high10, high422, high444 @@ -83,12 +83,20 @@ Set the size of the VBV buffer size in kilobits. .TP \fBfps_num\fR = \fI\fR -Set the fps numerator. +Set the fps numerator. .TP \fBfps_den\fR = \fI\fR Set the fps denominator. +.TP +\fBthreads = \fI\fR +Specify how many CPU threads to use for H.264 encoding per screen (0 for +auto). Carefully evaluate this value when configuring it to avoid exhausting +the available threads. For example, if 3 users are connected simultaneously +with dual screens, xrdp may use up to * 3 * 2 threads for H.264 +encoding. Please also note that too many threads can hurt quality. + .SH "OPENH264" \fB[OpenH264]\fR section defines encoding parameters that will be passed to diff --git a/tests/xrdp/gfx/gfx_codec_h264_only.toml b/tests/xrdp/gfx/gfx_codec_h264_only.toml index 86fa7d70..8a6e228b 100644 --- a/tests/xrdp/gfx/gfx_codec_h264_only.toml +++ b/tests/xrdp/gfx/gfx_codec_h264_only.toml @@ -9,6 +9,7 @@ vbv_max_bitrate = 0 vbv_buffer_size = 0 fps_num = 24 fps_den = 1 +threads = 1 [x264.lan] [x264.wan] diff --git a/tests/xrdp/gfx/gfx_codec_h264_preferred.toml b/tests/xrdp/gfx/gfx_codec_h264_preferred.toml index 7d5b11ad..4cd405d9 100644 --- a/tests/xrdp/gfx/gfx_codec_h264_preferred.toml +++ b/tests/xrdp/gfx/gfx_codec_h264_preferred.toml @@ -9,6 +9,7 @@ vbv_max_bitrate = 0 vbv_buffer_size = 0 fps_num = 24 fps_den = 1 +threads = 1 [x264.lan] [x264.wan] diff --git a/tests/xrdp/gfx/gfx_codec_order_undefined.toml b/tests/xrdp/gfx/gfx_codec_order_undefined.toml index 7432cb97..28773555 100644 --- a/tests/xrdp/gfx/gfx_codec_order_undefined.toml +++ b/tests/xrdp/gfx/gfx_codec_order_undefined.toml @@ -9,6 +9,7 @@ vbv_max_bitrate = 0 vbv_buffer_size = 0 fps_num = 24 fps_den = 1 +threads = 1 [x264.lan] [x264.wan] diff --git a/tests/xrdp/gfx/gfx_codec_rfx_only.toml b/tests/xrdp/gfx/gfx_codec_rfx_only.toml index 9ab14ea2..cdd974a4 100644 --- a/tests/xrdp/gfx/gfx_codec_rfx_only.toml +++ b/tests/xrdp/gfx/gfx_codec_rfx_only.toml @@ -9,6 +9,7 @@ vbv_max_bitrate = 0 vbv_buffer_size = 0 fps_num = 24 fps_den = 1 +threads = 1 [x264.lan] [x264.wan] diff --git a/tests/xrdp/gfx/gfx_codec_rfx_preferred.toml b/tests/xrdp/gfx/gfx_codec_rfx_preferred.toml index c09d029b..5f1f4250 100644 --- a/tests/xrdp/gfx/gfx_codec_rfx_preferred.toml +++ b/tests/xrdp/gfx/gfx_codec_rfx_preferred.toml @@ -9,6 +9,7 @@ vbv_max_bitrate = 0 vbv_buffer_size = 0 fps_num = 24 fps_den = 1 +threads = 1 [x264.lan] [x264.wan] diff --git a/tests/xrdp/gfx/gfx_codec_rfx_preferred_odd.toml b/tests/xrdp/gfx/gfx_codec_rfx_preferred_odd.toml index ff5c7015..66442884 100644 --- a/tests/xrdp/gfx/gfx_codec_rfx_preferred_odd.toml +++ b/tests/xrdp/gfx/gfx_codec_rfx_preferred_odd.toml @@ -9,6 +9,7 @@ vbv_max_bitrate = 0 vbv_buffer_size = 0 fps_num = 24 fps_den = 1 +threads = 1 [x264.lan] [x264.wan] diff --git a/tests/xrdp/gfx/gfx_h264_encoder_invalid.toml b/tests/xrdp/gfx/gfx_h264_encoder_invalid.toml index 7aee6971..673dff21 100644 --- a/tests/xrdp/gfx/gfx_h264_encoder_invalid.toml +++ b/tests/xrdp/gfx/gfx_h264_encoder_invalid.toml @@ -19,6 +19,7 @@ vbv_max_bitrate = 0 vbv_buffer_size = 0 fps_num = 60 fps_den = 1 +threads = 1 [x264.lan] # inherits default diff --git a/tests/xrdp/gfx/gfx_h264_encoder_openh264.toml b/tests/xrdp/gfx/gfx_h264_encoder_openh264.toml index ef98c4e1..a49350b5 100644 --- a/tests/xrdp/gfx/gfx_h264_encoder_openh264.toml +++ b/tests/xrdp/gfx/gfx_h264_encoder_openh264.toml @@ -19,6 +19,7 @@ vbv_max_bitrate = 0 vbv_buffer_size = 0 fps_num = 60 fps_den = 1 +threads = 1 [x264.lan] # inherits default diff --git a/tests/xrdp/gfx/gfx_h264_encoder_undefined.toml b/tests/xrdp/gfx/gfx_h264_encoder_undefined.toml index 74f4d618..46dc057b 100644 --- a/tests/xrdp/gfx/gfx_h264_encoder_undefined.toml +++ b/tests/xrdp/gfx/gfx_h264_encoder_undefined.toml @@ -19,6 +19,7 @@ vbv_max_bitrate = 0 vbv_buffer_size = 0 fps_num = 60 fps_den = 1 +threads = 1 [x264.lan] # inherits default diff --git a/tests/xrdp/gfx/gfx_h264_encoder_x264.toml b/tests/xrdp/gfx/gfx_h264_encoder_x264.toml index 94b75144..ee89ab95 100644 --- a/tests/xrdp/gfx/gfx_h264_encoder_x264.toml +++ b/tests/xrdp/gfx/gfx_h264_encoder_x264.toml @@ -19,6 +19,7 @@ vbv_max_bitrate = 0 vbv_buffer_size = 0 fps_num = 60 fps_den = 1 +threads = 1 [x264.lan] # inherits default diff --git a/xrdp/gfx.toml b/xrdp/gfx.toml index 94b75144..ae4a8974 100644 --- a/xrdp/gfx.toml +++ b/xrdp/gfx.toml @@ -19,6 +19,7 @@ vbv_max_bitrate = 0 vbv_buffer_size = 0 fps_num = 60 fps_den = 1 +threads = 1 # recommended: 1 or 2, see `man gfx.toml` for details [x264.lan] # inherits default diff --git a/xrdp/xrdp_encoder_x264.c b/xrdp/xrdp_encoder_x264.c index 29f1dcc9..01622cca 100644 --- a/xrdp/xrdp_encoder_x264.c +++ b/xrdp/xrdp_encoder_x264.c @@ -153,7 +153,7 @@ xrdp_encoder_x264_encode(void *handle, int session, int left, int top, x264_param_default_preset(&(xe->x264_params), xg->x264_param[ct].preset, xg->x264_param[ct].tune); - xe->x264_params.i_threads = 1; + xe->x264_params.i_threads = xg->x264_param[ct].threads; xe->x264_params.i_width = (width + 15) & ~15; xe->x264_params.i_height = (height + 15) & ~15; xe->x264_params.i_fps_num = xg->x264_param[ct].fps_num; diff --git a/xrdp/xrdp_tconfig.c b/xrdp/xrdp_tconfig.c index c04ffee0..5fc475be 100644 --- a/xrdp/xrdp_tconfig.c +++ b/xrdp/xrdp_tconfig.c @@ -47,6 +47,7 @@ #define X264_DEFAULT_PROFILE "main" #define X264_DEFAULT_FPS_NUM 24 #define X264_DEFAULT_FPS_DEN 1 +#define X264_DEFAULT_THREADS 1 /* not to exhaust CPU threads for 1 user */ const char * tconfig_codec_order_to_str( @@ -334,6 +335,33 @@ tconfig_load_gfx_x264_ct(toml_table_t *tfile, const int connection_type, param[connection_type].fps_den = X264_DEFAULT_FPS_DEN; } + /* threads */ + datum = toml_int_in(x264_ct, "threads"); + if (datum.ok) + { + if (datum.u.i >= 0) + { + param[connection_type].threads = datum.u.i; + } + else + { + TCLOG(LOG_LEVEL_WARNING, + "[x264.%s] an invalid value (< 0) is specified for threads, " + "adopting the default value [%d]", + rdpbcgr_connection_type_names[connection_type], + X264_DEFAULT_THREADS); + param[connection_type].threads = X264_DEFAULT_THREADS; + } + } + else if (connection_type == 0) + { + TCLOG(LOG_LEVEL_WARNING, + "[x264.%s] threads is not set, adopting the default value [%d]", + rdpbcgr_connection_type_names[connection_type], + X264_DEFAULT_THREADS); + param[connection_type].threads = X264_DEFAULT_THREADS; + } + return 0; } diff --git a/xrdp/xrdp_tconfig.h b/xrdp/xrdp_tconfig.h index 263da4d7..2f759fee 100644 --- a/xrdp/xrdp_tconfig.h +++ b/xrdp/xrdp_tconfig.h @@ -42,6 +42,7 @@ struct xrdp_tconfig_gfx_x264_param int vbv_buffer_size; int fps_num; int fps_den; + int threads; }; struct xrdp_tconfig_gfx_openh264_param