From 06afc50953f389ff9de99f8854a521d4dc9fe5c4 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Sat, 9 Nov 2024 23:17:29 -0800 Subject: [PATCH 01/11] add openh264 support --- configure.ac | 7 + xrdp/Makefile.am | 7 + xrdp/xrdp_encoder.c | 72 +++++++- xrdp/xrdp_encoder.h | 18 ++ xrdp/xrdp_encoder_openh264.c | 308 +++++++++++++++++++++++++++++++++++ xrdp/xrdp_encoder_openh264.h | 39 +++++ xrdp/xrdp_tconfig.h | 7 + 7 files changed, 449 insertions(+), 9 deletions(-) create mode 100644 xrdp/xrdp_encoder_openh264.c create mode 100644 xrdp/xrdp_encoder_openh264.h diff --git a/configure.ac b/configure.ac index 4573608dd5..919e30c77c 100644 --- a/configure.ac +++ b/configure.ac @@ -171,6 +171,10 @@ AC_ARG_ENABLE(x264, AS_HELP_STRING([--enable-x264], [Use x264 library (default: no)]), [], [enable_x264=no]) AM_CONDITIONAL(XRDP_X264, [test x$enable_x264 = xyes]) +AC_ARG_ENABLE(openh264, AS_HELP_STRING([--enable-openh264], + [Use openh264 library (default: no)]), + [], [enable_openh264=no]) +AM_CONDITIONAL(XRDP_OPENH264, [test x$enable_openh264 = xyes]) AC_ARG_ENABLE(painter, AS_HELP_STRING([--disable-painter], [Do not use included painter library (default: no)]), [], [enable_painter=yes]) @@ -472,6 +476,8 @@ AS_IF( [test "x$enable_pixman" = "xyes"] , [PKG_CHECK_MODULES(PIXMAN, pixman-1 > AS_IF( [test "x$enable_x264" = "xyes"] , [PKG_CHECK_MODULES(XRDP_X264, x264 >= 0.3.0)] ) +AS_IF( [test "x$enable_openh264" = "xyes"] , [PKG_CHECK_MODULES(XRDP_OPENH264, openh264 >= 2.0.0)] ) + # checking for TurboJPEG if test "x$enable_tjpeg" = "xyes" then @@ -630,6 +636,7 @@ echo " jpeg $enable_jpeg" echo " turbo jpeg $enable_tjpeg" echo " rfxcodec $enable_rfxcodec" echo " x264 $enable_x264" +echo " openh264 $enable_openh264" echo " painter $enable_painter" echo " pixman $enable_pixman" echo " fuse $enable_fuse" diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am index 9ac8bf1e57..5c9252ed2f 100644 --- a/xrdp/Makefile.am +++ b/xrdp/Makefile.am @@ -34,6 +34,13 @@ XRDP_EXTRA_LIBS += $(XRDP_X264_LIBS) XRDP_EXTRA_SOURCES += xrdp_encoder_x264.c xrdp_encoder_x264.h endif +if XRDP_OPENH264 +AM_CPPFLAGS += -DXRDP_OPENH264 +AM_CPPFLAGS += $(XRDP_OPENH264_CFLAGS) +XRDP_EXTRA_LIBS += $(XRDP_OPENH264_LIBS) +XRDP_EXTRA_SOURCES += xrdp_encoder_openh264.c xrdp_encoder_openh264.h +endif + if XRDP_PIXMAN AM_CPPFLAGS += -DXRDP_PIXMAN AM_CPPFLAGS += $(PIXMAN_CFLAGS) diff --git a/xrdp/xrdp_encoder.c b/xrdp/xrdp_encoder.c index f6eb36e88e..268174c13b 100644 --- a/xrdp/xrdp_encoder.c +++ b/xrdp/xrdp_encoder.c @@ -38,6 +38,10 @@ #include "xrdp_encoder_x264.h" #endif +#ifdef XRDP_OPENH264 +#include "xrdp_encoder_openh264.h" +#endif + #define DEFAULT_XRDP_GFX_FRAMES_IN_FLIGHT 2 /* limits used for validate env var XRDP_GFX_FRAMES_IN_FLIGHT */ #define MIN_XRDP_GFX_FRAMES_IN_FLIGHT 1 @@ -94,7 +98,7 @@ process_enc_jpg(struct xrdp_encoder *self, XRDP_ENC_DATA *enc); static int process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc); #endif -#ifdef XRDP_X264 +#if defined(XRDP_X264) || defined(XRDP_OPENH264) static int process_enc_h264(struct xrdp_encoder *self, XRDP_ENC_DATA *enc); #endif @@ -171,7 +175,7 @@ xrdp_encoder_create(struct xrdp_mm *mm) client_info->capture_format = XRDP_a8b8g8r8; self->process_enc = process_enc_jpg; } -#ifdef XRDP_X264 +#if defined(XRDP_X264) || defined(XRDP_OPENH264) else if (mm->egfx_flags & XRDP_EGFX_H264) { LOG(LOG_LEVEL_INFO, @@ -309,6 +313,56 @@ xrdp_encoder_create(struct xrdp_mm *mm) /* make sure frames_in_flight is at least 1 */ self->frames_in_flight = MAX(self->frames_in_flight, 1); +#if defined(XRDP_X264) && defined(XRDP_OPENH264) + if (self->h264_flags == 0) + { + char *env = g_getenv("XRDP_PREFER_OPENH264"); + if (env != NULL) + { + LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: found env var " + "XRDP_PREFER_OPENH264=%s", env); + if (g_text2bool(env)) + { + ENC_SET_BIT(self->h264_flags, ENC_FLAGS_PREFER_OPENH264_BIT); + } + } + else + { + LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: " + "XRDP_PREFER_OPENH264 not found"); + } + } + if (ENC_IS_BIT_SET(self->h264_flags, ENC_FLAGS_PREFER_OPENH264_BIT)) + { + LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: using openh264 for " + "software encoder"); + self->xrdp_encoder_h264_create = xrdp_encoder_openh264_create; + self->xrdp_encoder_h264_delete = xrdp_encoder_openh264_delete; + self->xrdp_encoder_h264_encode = xrdp_encoder_openh264_encode; + } + else + { + LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: using x264 for " + "software encoder"); + self->xrdp_encoder_h264_create = xrdp_encoder_x264_create; + self->xrdp_encoder_h264_delete = xrdp_encoder_x264_delete; + self->xrdp_encoder_h264_encode = xrdp_encoder_x264_encode; + } +#elif defined(XRDP_OPENH264) + LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: using openh264 for " + "software encoder"); + self->h264_flags |= 1; + self->xrdp_encoder_h264_create = xrdp_encoder_openh264_create; + self->xrdp_encoder_h264_delete = xrdp_encoder_openh264_delete; + self->xrdp_encoder_h264_encode = xrdp_encoder_openh264_encode; +#elif defined(XRDP_X264) + LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: using x264 for " + "software encoder"); + self->xrdp_encoder_h264_create = xrdp_encoder_x264_create; + self->xrdp_encoder_h264_delete = xrdp_encoder_x264_delete; + self->xrdp_encoder_h264_encode = xrdp_encoder_x264_encode; +#endif + /* create thread to process messages */ tc_thread_create(proc_enc_msg, self); @@ -354,17 +408,17 @@ xrdp_encoder_delete(struct xrdp_encoder *self) } #endif -#if defined(XRDP_X264) +#if defined(XRDP_X264) || defined(XRDP_OPENH264) for (index = 0; index < 16; index++) { if (self->codec_handle_h264_gfx[index] != NULL) { - xrdp_encoder_x264_delete(self->codec_handle_h264_gfx[index]); + self->xrdp_encoder_h264_delete(self->codec_handle_h264_gfx[index]); } } if (self->codec_handle_h264 != NULL) { - xrdp_encoder_x264_delete(self->codec_handle_h264); + self->xrdp_encoder_h264_delete(self->codec_handle_h264); } #endif @@ -628,7 +682,7 @@ process_enc_rfx(struct xrdp_encoder *self, XRDP_ENC_DATA *enc) } #endif -#if defined(XRDP_X264) +#if defined(XRDP_X264) || defined(XRDP_OPENH264) /*****************************************************************************/ static int @@ -734,7 +788,7 @@ gfx_wiretosurface1(struct xrdp_encoder *self, struct xrdp_egfx_bulk *bulk, struct stream *in_s, XRDP_ENC_DATA *enc) { -#ifdef XRDP_X264 +#if defined(XRDP_X264) || defined(XRDP_OPENH264) int index; int surface_id; int codec_id; @@ -901,7 +955,7 @@ gfx_wiretosurface1(struct xrdp_encoder *self, if (self->codec_handle_h264_gfx[mon_index] == NULL) { self->codec_handle_h264_gfx[mon_index] = - xrdp_encoder_x264_create(); + self->xrdp_encoder_h264_create(); if (self->codec_handle_h264_gfx[mon_index] == NULL) { g_free(s->data); @@ -909,7 +963,7 @@ gfx_wiretosurface1(struct xrdp_encoder *self, return NULL; } } - error = xrdp_encoder_x264_encode( + error = self->xrdp_encoder_h264_encode( self->codec_handle_h264_gfx[mon_index], 0, 0, 0, width, height, twidth, theight, 0, diff --git a/xrdp/xrdp_encoder.h b/xrdp/xrdp_encoder.h index 3996fac540..b5fcf3f32b 100644 --- a/xrdp/xrdp_encoder.h +++ b/xrdp/xrdp_encoder.h @@ -14,6 +14,19 @@ struct xrdp_enc_data; +typedef void *(*xrdp_encoder_h264_create_proc)(void); +typedef int (*xrdp_encoder_h264_delete_proc)(void *handle); +typedef int (*xrdp_encoder_h264_encode_proc)( + void *handle, int session, int left, int top, + int width, int height, int twidth, int theight, + int format, const char *data, + short *crects, int num_crects, + char *cdata, int *cdata_bytes, + int connection_type, int *flags_ptr); + +/* h264_flags */ +#define ENC_FLAGS_PREFER_OPENH264_BIT 0 + /* for codec mode operations */ struct xrdp_encoder { @@ -46,6 +59,11 @@ struct xrdp_encoder int quant_idx_y; int quant_idx_u; int quant_idx_v; + int h264_flags; + int pad0; + xrdp_encoder_h264_create_proc xrdp_encoder_h264_create; + xrdp_encoder_h264_delete_proc xrdp_encoder_h264_delete; + xrdp_encoder_h264_encode_proc xrdp_encoder_h264_encode; }; /* cmd_id = 0 */ diff --git a/xrdp/xrdp_encoder_openh264.c b/xrdp/xrdp_encoder_openh264.c new file mode 100644 index 0000000000..f695dd9a2c --- /dev/null +++ b/xrdp/xrdp_encoder_openh264.c @@ -0,0 +1,308 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2016-2024 + * Copyright (C) Christopher Pitstick 2023-2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * openh264 Encoder + */ + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "xrdp.h" +#include "arch.h" +#include "os_calls.h" +#include "xrdp_encoder_openh264.h" +#include "xrdp_tconfig.h" + +#define OPENH264_MAX_ENCODERS 16 + +struct openh264_encoder +{ + ISVCEncoder *openh264_enc_han; + char *yuvdata; + int width; + int height; +}; + +struct openh264_global +{ + struct openh264_encoder encoders[OPENH264_MAX_ENCODERS]; + struct xrdp_tconfig_gfx_openh264_param + openh264_param[NUM_CONNECTION_TYPES]; +}; + +/*****************************************************************************/ +void * +xrdp_encoder_openh264_create(void) +{ + struct openh264_global *og; + struct xrdp_tconfig_gfx gfxconfig; + + LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_encoder_openh264_create:"); + og = g_new0(struct openh264_global, 1); + tconfig_load_gfx(GFX_CONF, &gfxconfig); + memcpy(&og->openh264_param, &gfxconfig.openh264_param, + sizeof(struct xrdp_tconfig_gfx_openh264_param) * + NUM_CONNECTION_TYPES); + return og; + +} + +/*****************************************************************************/ +int +xrdp_encoder_openh264_delete(void *handle) +{ + struct openh264_global *og; + struct openh264_encoder *oe; + int index; + + if (handle == NULL) + { + return 0; + } + og = (struct openh264_global *) handle; + for (index = 0; index < 16; index++) + { + oe = &(og->encoders[index]); + if (oe->openh264_enc_han != NULL) + { + WelsDestroySVCEncoder(oe->openh264_enc_han); + } + g_free(oe->yuvdata); + } + g_free(og); + return 0; +} + +/*****************************************************************************/ +int +xrdp_encoder_openh264_encode(void *handle, int session, int left, int top, + int width, int height, int twidth, int theight, + int format, const char *data, + short *crects, int num_crects, + char *cdata, int *cdata_bytes, + int connection_type, int *flags_ptr) +{ + struct openh264_global *og; + struct openh264_encoder *oe; + const char *src8; + const char *src8a; + char *dst8; + char *dst8a; + char *dst8b; + char *dst8c; + int index; + int jndex; + int flags; + int x; + int y; + int cx; + int cy; + int ct; /* connection_type */ + SSourcePicture pic1; + SFrameBSInfo info; + SLayerBSInfo *layer; + SEncParamExt encParamExt; + SSpatialLayerConfig *slc; + int status; + int layer_position; + char *write_location; + unsigned char *payload; + int size; + int lcdata_bytes; + + LOG(LOG_LEVEL_TRACE, "xrdp_encoder_openh264_encode:"); + flags = 0; + og = (struct openh264_global *) handle; + oe = &(og->encoders[session % OPENH264_MAX_ENCODERS]); + /* validate connection type */ + ct = connection_type; + if (ct > CONNECTION_TYPE_LAN || ct < CONNECTION_TYPE_MODEM) + { + ct = CONNECTION_TYPE_LAN; + } + if ((oe->openh264_enc_han == NULL) || + (oe->width != width) || (oe->height != height)) + { + if (oe->openh264_enc_han != NULL) + { + LOG(LOG_LEVEL_INFO, "xrdp_encoder_openh264_encode: " + "WelsDestroySVCEncoder %p", oe->openh264_enc_han); + WelsDestroySVCEncoder(oe->openh264_enc_han); + oe->openh264_enc_han = NULL; + g_free(oe->yuvdata); + oe->yuvdata = NULL; + flags |= 2; + } + if ((width > 0) && (height > 0)) + { + status = WelsCreateSVCEncoder(&oe->openh264_enc_han); + if ((status != 0) || (oe->openh264_enc_han == NULL)) + { + LOG(LOG_LEVEL_ERROR, "Failed to create H.264 encoder"); + return 1; + } + LOG(LOG_LEVEL_INFO, "xrdp_encoder_openh264_encode: " + "WelsCreateSVCEncoder rv %p for width %d height %d", + oe->openh264_enc_han, width, height); + status = (*oe->openh264_enc_han)->GetDefaultParams( + oe->openh264_enc_han, &encParamExt); + LOG(LOG_LEVEL_INFO, "xrdp_encoder_openh264_encode: " + "GetDefaultParams rv %d", status); + if (status == 0) + { + encParamExt.iUsageType = CAMERA_VIDEO_REAL_TIME; + encParamExt.iPicWidth = (width + 15) & ~15; + encParamExt.iPicHeight = (height + 15) & ~15; + encParamExt.iRCMode = RC_OFF_MODE; + encParamExt.bEnableFrameSkip = 0; + encParamExt.iSpatialLayerNum = 1; + /* defaults to INCREASING_ID, Mac client needs CONSTANT_ID */ + encParamExt.eSpsPpsIdStrategy = CONSTANT_ID; + slc = encParamExt.sSpatialLayers + 0; + slc->fFrameRate = encParamExt.fMaxFrameRate; + slc->iVideoWidth = encParamExt.iPicWidth; + slc->iVideoHeight = encParamExt.iPicHeight; + slc->iSpatialBitrate = encParamExt.iTargetBitrate; + slc->iMaxSpatialBitrate = encParamExt.iMaxBitrate; + status = (*oe->openh264_enc_han)->InitializeExt( + oe->openh264_enc_han, &encParamExt); + LOG(LOG_LEVEL_INFO, "xrdp_encoder_openh264_encode: " + "InitializeExt rv %d", status); + } + oe->yuvdata = g_new(char, (width + 16) * (height + 16) * 2); + if (oe->yuvdata == NULL) + { + WelsDestroySVCEncoder(oe->openh264_enc_han); + oe->openh264_enc_han = NULL; + return 2; + } + flags |= 1; + } + oe->width = width; + oe->height = height; + } + + if ((data != NULL) && (oe->openh264_enc_han != NULL)) + { + g_memset(&pic1, 0, sizeof(pic1)); + pic1.iPicWidth = (width + 15) & ~15; + pic1.iPicHeight = (height + 15) & ~15; + pic1.iColorFormat = videoFormatI420; + pic1.iStride[0] = pic1.iPicWidth; + pic1.iStride[1] = pic1.iPicWidth / 2; + pic1.iStride[2] = pic1.iPicWidth / 2; + pic1.pData[0] = (unsigned char *) (oe->yuvdata); + pic1.pData[1] = pic1.pData[0] + pic1.iPicWidth * pic1.iPicHeight; + pic1.pData[2] = pic1.pData[1] + (pic1.iPicWidth / 2) * + (pic1.iPicHeight / 2); + for (index = 0; index < num_crects; index++) + { + src8 = data; + dst8 = (char *) (pic1.pData[0]); + x = crects[index * 4 + 0]; + y = crects[index * 4 + 1]; + cx = crects[index * 4 + 2]; + cy = crects[index * 4 + 3]; + LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_encoder_openh264_encode: " + "x %d y %d cx %d cy %d", x, y, cx, cy); + src8 += twidth * y + x; + dst8 += pic1.iStride[0] * (y - top) + (x - left); + for (; cy > 0; cy -= 1) + { + g_memcpy(dst8, src8, cx); + src8 += twidth; + dst8 += pic1.iStride[0]; + } + } + for (index = 0; index < num_crects; index++) + { + src8 = data; /* uv */ + src8 += twidth * theight; + dst8 = (char *) (pic1.pData[1]); /* u */ + dst8a = (char *) (pic1.pData[2]); /* v */ + x = crects[index * 4 + 0]; + y = crects[index * 4 + 1]; + cx = crects[index * 4 + 2]; + cy = crects[index * 4 + 3]; + src8 += twidth * (y / 2) + x; + dst8 += pic1.iStride[1] * ((y - top) / 2) + ((x - left) / 2); + dst8a += pic1.iStride[2] * ((y - top) / 2) + ((x - left) / 2); + for (; cy > 0; cy -= 2) + { + src8a = src8; /* uv */ + dst8b = dst8; /* u */ + dst8c = dst8a; /* v */ + for (jndex = 0; jndex < cx; jndex += 2) + { + *(dst8b++) = *(src8a++); /* u */ + *(dst8c++) = *(src8a++); /* v */ + } + src8 += twidth; /* uv */ + dst8 += pic1.iStride[1]; /* u */ + dst8a += pic1.iStride[2]; /* v */ + } + } + g_memset(&info, 0, sizeof(info)); + status = (*oe->openh264_enc_han)->EncodeFrame(oe->openh264_enc_han, + &pic1, &info); + if (status != 0) + { + LOG(LOG_LEVEL_INFO, "Failed to encode frame"); + return 3; + } + if (info.eFrameType == videoFrameTypeSkip) + { + LOG(LOG_LEVEL_INFO, "frame was skipped!"); + return 4; + } + lcdata_bytes = 0; + for (index = 0; index < info.iLayerNum; index++) + { + layer_position = 0; + layer = info.sLayerInfo + index; + for (jndex = 0; jndex < layer->iNalCount; jndex++) + { + write_location = cdata + lcdata_bytes; + payload = layer->pBsBuf + layer_position; + size = layer->pNalLengthInByte[jndex]; + if (lcdata_bytes + size > *cdata_bytes) + { + LOG(LOG_LEVEL_INFO, "out of room"); + return 5; + } + g_memcpy(write_location, payload, size); + layer_position += size; + lcdata_bytes += size; + } + } + *cdata_bytes = lcdata_bytes; + } + if (flags_ptr != NULL) + { + *flags_ptr = flags; + } + return 0; +} diff --git a/xrdp/xrdp_encoder_openh264.h b/xrdp/xrdp_encoder_openh264.h new file mode 100644 index 0000000000..6c40f2e179 --- /dev/null +++ b/xrdp/xrdp_encoder_openh264.h @@ -0,0 +1,39 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2016-2024 + * Copyright (C) Christopher Pitstick 2023-2024 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * openh264 Encoder + */ + +#ifndef _XRDP_ENCODER_OPENH264_H +#define _XRDP_ENCODER_OPENH264_H + +#include "arch.h" + +void * +xrdp_encoder_openh264_create(void); +int +xrdp_encoder_openh264_delete(void *handle); +int +xrdp_encoder_openh264_encode(void *handle, int session, int left, int top, + int width, int height, int twidth, int theight, + int format, const char *data, + short *crects, int num_crects, + char *cdata, int *cdata_bytes, + int connection_type, int *flags_ptr); + +#endif diff --git a/xrdp/xrdp_tconfig.h b/xrdp/xrdp_tconfig.h index 649d649028..2bebee8a6f 100644 --- a/xrdp/xrdp_tconfig.h +++ b/xrdp/xrdp_tconfig.h @@ -42,6 +42,11 @@ struct xrdp_tconfig_gfx_x264_param int fps_den; }; +struct xrdp_tconfig_gfx_openh264_param +{ + int pad0; +}; + enum xrdp_tconfig_codecs { XTC_H264, @@ -59,6 +64,8 @@ struct xrdp_tconfig_gfx struct xrdp_tconfig_gfx_codec_order codec; /* store x264 parameters for each connection type */ struct xrdp_tconfig_gfx_x264_param x264_param[NUM_CONNECTION_TYPES]; + struct xrdp_tconfig_gfx_openh264_param + openh264_param[NUM_CONNECTION_TYPES]; }; static const char *const rdpbcgr_connection_type_names[] = From ddab8d35b554c55df9be6a640602a115aafa9f4d Mon Sep 17 00:00:00 2001 From: Koichiro Iwao Date: Fri, 22 Nov 2024 20:51:03 +0900 Subject: [PATCH 02/11] Revice OpenH264 description --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 919e30c77c..a53fb7f32a 100644 --- a/configure.ac +++ b/configure.ac @@ -172,7 +172,7 @@ AC_ARG_ENABLE(x264, AS_HELP_STRING([--enable-x264], [], [enable_x264=no]) AM_CONDITIONAL(XRDP_X264, [test x$enable_x264 = xyes]) AC_ARG_ENABLE(openh264, AS_HELP_STRING([--enable-openh264], - [Use openh264 library (default: no)]), + [Use Cisco OpenH264 library (default: no)]), [], [enable_openh264=no]) AM_CONDITIONAL(XRDP_OPENH264, [test x$enable_openh264 = xyes]) AC_ARG_ENABLE(painter, AS_HELP_STRING([--disable-painter], From 93ad14ff2546cfbf08bb5061f2253d2640420eed Mon Sep 17 00:00:00 2001 From: Koichiro Iwao Date: Sun, 24 Nov 2024 09:36:16 +0900 Subject: [PATCH 03/11] Add preferred H.264 encoder configuration in gfx.toml --- xrdp/gfx.toml | 12 ++++++++++ xrdp/xrdp_encoder.c | 55 +++++++++++++++++---------------------------- xrdp/xrdp_encoder.h | 4 ---- xrdp/xrdp_tconfig.c | 45 +++++++++++++++++++++++++++++++++++++ xrdp/xrdp_tconfig.h | 7 ++++++ 5 files changed, 85 insertions(+), 38 deletions(-) diff --git a/xrdp/gfx.toml b/xrdp/gfx.toml index af3fcf86ed..ef1b72527a 100644 --- a/xrdp/gfx.toml +++ b/xrdp/gfx.toml @@ -1,6 +1,12 @@ [codec] order = [ "H.264", "RFX" ] +# Specify a preferred H.264 encoder, "x264" or "OpenH264". +# This parameter takes effect only when more than one encoder is +# enabled at compile time. If only one encoder is enabled, the encoder +# will be used regardless the value of this parameter. +h264_encoder = "OpenH264" + [x264.default] preset = "ultrafast" tune = "zerolatency" @@ -38,3 +44,9 @@ preset = "fast" tune = "zerolatency" vbv_max_bitrate = 1200 vbv_buffer_size = 50 + +[OpenH264.default] +TargetBitrate = 0 +MaxBitrate = 0 + + diff --git a/xrdp/xrdp_encoder.c b/xrdp/xrdp_encoder.c index 268174c13b..1997ced4c5 100644 --- a/xrdp/xrdp_encoder.c +++ b/xrdp/xrdp_encoder.c @@ -314,44 +314,31 @@ xrdp_encoder_create(struct xrdp_mm *mm) self->frames_in_flight = MAX(self->frames_in_flight, 1); #if defined(XRDP_X264) && defined(XRDP_OPENH264) - if (self->h264_flags == 0) - { - char *env = g_getenv("XRDP_PREFER_OPENH264"); - if (env != NULL) - { - LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: found env var " - "XRDP_PREFER_OPENH264=%s", env); - if (g_text2bool(env)) - { - ENC_SET_BIT(self->h264_flags, ENC_FLAGS_PREFER_OPENH264_BIT); - } - } - else - { - LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: " - "XRDP_PREFER_OPENH264 not found"); - } - } - if (ENC_IS_BIT_SET(self->h264_flags, ENC_FLAGS_PREFER_OPENH264_BIT)) - { - LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: using openh264 for " - "software encoder"); - self->xrdp_encoder_h264_create = xrdp_encoder_openh264_create; - self->xrdp_encoder_h264_delete = xrdp_encoder_openh264_delete; - self->xrdp_encoder_h264_encode = xrdp_encoder_openh264_encode; - } - else + struct xrdp_tconfig_gfx gfxconfig; + tconfig_load_gfx(GFX_CONF, &gfxconfig); + + switch (gfxconfig.h264_encoder) { - LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: using x264 for " - "software encoder"); - self->xrdp_encoder_h264_create = xrdp_encoder_x264_create; - self->xrdp_encoder_h264_delete = xrdp_encoder_x264_delete; - self->xrdp_encoder_h264_encode = xrdp_encoder_x264_encode; + case XTC_H264_OPENH264: + LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: using OpenH264 for " + "software encoder"); + self->xrdp_encoder_h264_create = xrdp_encoder_openh264_create; + self->xrdp_encoder_h264_delete = xrdp_encoder_openh264_delete; + self->xrdp_encoder_h264_encode = xrdp_encoder_openh264_encode; + break; + case XTC_H264_X264: + default: + /* x264 is the default H.264 software encoder */ + LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: using x264 for " + "software encoder"); + self->xrdp_encoder_h264_create = xrdp_encoder_x264_create; + self->xrdp_encoder_h264_delete = xrdp_encoder_x264_delete; + self->xrdp_encoder_h264_encode = xrdp_encoder_x264_encode; + break; } #elif defined(XRDP_OPENH264) - LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: using openh264 for " + LOG(LOG_LEVEL_INFO, "xrdp_encoder_create: using OpenH264 for " "software encoder"); - self->h264_flags |= 1; self->xrdp_encoder_h264_create = xrdp_encoder_openh264_create; self->xrdp_encoder_h264_delete = xrdp_encoder_openh264_delete; self->xrdp_encoder_h264_encode = xrdp_encoder_openh264_encode; diff --git a/xrdp/xrdp_encoder.h b/xrdp/xrdp_encoder.h index b5fcf3f32b..fdf4dab55c 100644 --- a/xrdp/xrdp_encoder.h +++ b/xrdp/xrdp_encoder.h @@ -24,9 +24,6 @@ typedef int (*xrdp_encoder_h264_encode_proc)( char *cdata, int *cdata_bytes, int connection_type, int *flags_ptr); -/* h264_flags */ -#define ENC_FLAGS_PREFER_OPENH264_BIT 0 - /* for codec mode operations */ struct xrdp_encoder { @@ -59,7 +56,6 @@ struct xrdp_encoder int quant_idx_y; int quant_idx_u; int quant_idx_v; - int h264_flags; int pad0; xrdp_encoder_h264_create_proc xrdp_encoder_h264_create; xrdp_encoder_h264_delete_proc xrdp_encoder_h264_delete; diff --git a/xrdp/xrdp_tconfig.c b/xrdp/xrdp_tconfig.c index 744cc3d8f3..e8d099243a 100644 --- a/xrdp/xrdp_tconfig.c +++ b/xrdp/xrdp_tconfig.c @@ -247,6 +247,49 @@ tconfig_load_gfx_x264_ct(toml_table_t *tfile, const int connection_type, return 0; } +static int tconfig_load_gfx_h264_encoder(toml_table_t *tfile, struct xrdp_tconfig_gfx *config) +{ + TCLOG(LOG_LEVEL_TRACE, "[h264 encoder]"); + + toml_table_t *codec; + int valid_encoder_found = 0; + + if ((codec = toml_table_in(tfile, "codec")) != NULL) + { + toml_datum_t h264_encoder = toml_string_in(codec, "h264_encoder"); + + if (h264_encoder.ok) + { + if (g_strcasecmp(h264_encoder.u.s, "x264") == 0) + { + TCLOG(LOG_LEVEL_DEBUG, "[h264 encoder] x264"); + valid_encoder_found = 1; + config->h264_encoder = XTC_H264_X264; + } + if (g_strcasecmp(h264_encoder.u.s, "OpenH264") == 0) + { + TCLOG(LOG_LEVEL_DEBUG, "[h264 encoder] OpenH264"); + valid_encoder_found = 1; + config->h264_encoder = XTC_H264_OPENH264; + } + + free(h264_encoder.u.s); + } + } + + if (valid_encoder_found == 0) + { + TCLOG(LOG_LEVEL_WARNING, "[h264 encoder] could not get valid H.264 encoder , " + "using default \"x264\""); + + /* default to x264 */ + config->h264_encoder = XTC_H264_X264; + return 1; + } + + return 0; +} + static int tconfig_load_gfx_order(toml_table_t *tfile, struct xrdp_tconfig_gfx *config) { char buff[64]; @@ -393,6 +436,8 @@ tconfig_load_gfx(const char *filename, struct xrdp_tconfig_gfx *config) /* Load GFX codec order */ tconfig_load_gfx_order(tfile, config); + /* Load H.264 encoder */ + tconfig_load_gfx_h264_encoder(tfile, config); /* H.264 configuration */ if (codec_enabled(&config->codec, XTC_H264)) diff --git a/xrdp/xrdp_tconfig.h b/xrdp/xrdp_tconfig.h index 2bebee8a6f..dab7876414 100644 --- a/xrdp/xrdp_tconfig.h +++ b/xrdp/xrdp_tconfig.h @@ -53,6 +53,12 @@ enum xrdp_tconfig_codecs XTC_RFX }; +enum xrdp_tconfig_h264_encoders +{ + XTC_H264_X264, + XTC_H264_OPENH264 +}; + struct xrdp_tconfig_gfx_codec_order { enum xrdp_tconfig_codecs codecs[2]; @@ -62,6 +68,7 @@ struct xrdp_tconfig_gfx_codec_order struct xrdp_tconfig_gfx { struct xrdp_tconfig_gfx_codec_order codec; + enum xrdp_tconfig_h264_encoders h264_encoder; /* store x264 parameters for each connection type */ struct xrdp_tconfig_gfx_x264_param x264_param[NUM_CONNECTION_TYPES]; struct xrdp_tconfig_gfx_openh264_param From e87a7dd878201fd10632469e96e778b21184115b Mon Sep 17 00:00:00 2001 From: Koichiro Iwao Date: Thu, 28 Nov 2024 00:19:32 +0900 Subject: [PATCH 04/11] OpenH264: apply encoding parameters from gfx.toml --- xrdp/gfx.toml | 40 +++++++++- xrdp/xrdp_encoder_openh264.c | 8 +- xrdp/xrdp_tconfig.c | 143 ++++++++++++++++++++++++++++++++--- xrdp/xrdp_tconfig.h | 5 +- 4 files changed, 179 insertions(+), 17 deletions(-) diff --git a/xrdp/gfx.toml b/xrdp/gfx.toml index ef1b72527a..c20f537333 100644 --- a/xrdp/gfx.toml +++ b/xrdp/gfx.toml @@ -7,7 +7,11 @@ order = [ "H.264", "RFX" ] # will be used regardless the value of this parameter. h264_encoder = "OpenH264" +# +# Configurations for x264 +# [x264.default] +# NOTE: x264 specifies bitrate in unit of kbps. preset = "ultrafast" tune = "zerolatency" profile = "main" # profile is forced to baseline if preset == ultrafast @@ -45,8 +49,40 @@ tune = "zerolatency" vbv_max_bitrate = 1200 vbv_buffer_size = 50 +# +# Configurations for OpenH264 +# [OpenH264.default] -TargetBitrate = 0 -MaxBitrate = 0 +# NOTE: OpenH264 specifies bitrate in unit of bps, not kbps. +EnableFrameSkip = false +TargetBitrate = 20_000_000 +MaxBitrate = 0 # unspecified +MaxFrameRate = 60.0 +[OpenH264.lan] +# inherits default + +[OpenH264.wan] +TargetBitrate = 10_000_000 +MaxBitrate = 12_000_000 + +[OpenH264.broadband_high] +EnableFrameSkip = true +TargetBitrate = 8_000_000 +MaxBitrate = 10_000_000 + +[OpenH264.satellite] +EnableFrameSkip = true +TargetBitrate = 4_000_000 +MaxBitrate = 6_000_000 + +[OpenH264.broadband_low] +EnableFrameSkip = true +TargetBitrate = 1_600_000 +MaxBitrate = 1_800_000 + +[OpenH264.modem] +EnableFrameSkip = true +TargetBitrate = 600_000 +MaxBitrate = 1_200_000 diff --git a/xrdp/xrdp_encoder_openh264.c b/xrdp/xrdp_encoder_openh264.c index f695dd9a2c..9623efaa55 100644 --- a/xrdp/xrdp_encoder_openh264.c +++ b/xrdp/xrdp_encoder_openh264.c @@ -176,9 +176,13 @@ xrdp_encoder_openh264_encode(void *handle, int session, int left, int top, encParamExt.iUsageType = CAMERA_VIDEO_REAL_TIME; encParamExt.iPicWidth = (width + 15) & ~15; encParamExt.iPicHeight = (height + 15) & ~15; - encParamExt.iRCMode = RC_OFF_MODE; - encParamExt.bEnableFrameSkip = 0; + encParamExt.iRCMode = RC_BITRATE_MODE; encParamExt.iSpatialLayerNum = 1; + /* Set encode parameters from config */ + encParamExt.bEnableFrameSkip = og->openh264_param[ct].EnableFrameSkip; + encParamExt.iTargetBitrate = og->openh264_param[ct].TargetBitrate; + encParamExt.iMaxBitrate = og->openh264_param[ct].MaxBitrate; + encParamExt.fMaxFrameRate = og->openh264_param[ct].MaxFrameRate; /* defaults to INCREASING_ID, Mac client needs CONSTANT_ID */ encParamExt.eSpsPpsIdStrategy = CONSTANT_ID; slc = encParamExt.sSpatialLayers + 0; diff --git a/xrdp/xrdp_tconfig.c b/xrdp/xrdp_tconfig.c index e8d099243a..c04ffee089 100644 --- a/xrdp/xrdp_tconfig.c +++ b/xrdp/xrdp_tconfig.c @@ -67,6 +67,7 @@ tconfig_codec_order_to_str( if (p > 0) { buff[p++] = ','; + buff[p++] = ' '; } switch (codec_order->codecs[i]) @@ -96,6 +97,95 @@ tconfig_codec_order_to_str( return buff; } +static int +tconfig_load_gfx_openh264_ct(toml_table_t *tfile, const int connection_type, + struct xrdp_tconfig_gfx_openh264_param *param) +{ + TCLOG(LOG_LEVEL_TRACE, "[OpenH264]"); + + if (connection_type > NUM_CONNECTION_TYPES) + { + TCLOG(LOG_LEVEL_ERROR, "[OpenH264] Invalid connection type is given"); + return 1; + } + + toml_table_t *oh264 = toml_table_in(tfile, "OpenH264"); + if (!oh264) + { + TCLOG(LOG_LEVEL_WARNING, "[OpenH264] OpenH264 params are not defined"); + return 1; + } + + toml_table_t *oh264_ct = + toml_table_in(oh264, rdpbcgr_connection_type_names[connection_type]); + toml_datum_t datum; + + if (!oh264_ct) + { + TCLOG(LOG_LEVEL_WARNING, "OpenH264 params for connection type [%s] is not defined", + rdpbcgr_connection_type_names[connection_type]); + return 1; + } + + /* EnableFrameSkip */ + datum = toml_bool_in(oh264_ct, "EnableFrameSkip"); + if (datum.ok) + { + param[connection_type].EnableFrameSkip = datum.u.b; + } + else if (connection_type == 0) + { + TCLOG(LOG_LEVEL_WARNING, + "[OpenH264.%s] EnableFrameSkip is not set, adopting the default value [0]", + rdpbcgr_connection_type_names[connection_type]); + param[connection_type].EnableFrameSkip = 0; + } + + /* TargetBitrate */ + datum = toml_int_in(oh264_ct, "TargetBitrate"); + if (datum.ok) + { + param[connection_type].TargetBitrate = datum.u.i; + } + else if (connection_type == 0) + { + TCLOG(LOG_LEVEL_WARNING, + "[OpenH264.%s] TargetBitrate is not set, adopting the default value [0]", + rdpbcgr_connection_type_names[connection_type]); + param[connection_type].TargetBitrate = 0; + } + + /* MaxBitrate */ + datum = toml_int_in(oh264_ct, "MaxBitrate"); + if (datum.ok) + { + param[connection_type].MaxBitrate = datum.u.i; + } + else if (connection_type == 0) + { + TCLOG(LOG_LEVEL_WARNING, + "[OpenH264.%s] MaxBitrate is not set, adopting the default value [0]", + rdpbcgr_connection_type_names[connection_type]); + param[connection_type].MaxBitrate = 0; + } + + /* MaxFrameRate */ + datum = toml_double_in(oh264_ct, "MaxFrameRate"); + if (datum.ok) + { + param[connection_type].MaxFrameRate = (float)datum.u.d; + } + else if (connection_type == 0) + { + TCLOG(LOG_LEVEL_WARNING, + "[OpenH264.%s] MaxFrameRate is not set, adopting the default value [0]", + rdpbcgr_connection_type_names[connection_type]); + param[connection_type].MaxFrameRate = 0; + } + + return 0; +} + static int tconfig_load_gfx_x264_ct(toml_table_t *tfile, const int connection_type, struct xrdp_tconfig_gfx_x264_param *param) @@ -249,7 +339,7 @@ tconfig_load_gfx_x264_ct(toml_table_t *tfile, const int connection_type, static int tconfig_load_gfx_h264_encoder(toml_table_t *tfile, struct xrdp_tconfig_gfx *config) { - TCLOG(LOG_LEVEL_TRACE, "[h264 encoder]"); + TCLOG(LOG_LEVEL_TRACE, "[codec]"); toml_table_t *codec; int valid_encoder_found = 0; @@ -262,13 +352,13 @@ static int tconfig_load_gfx_h264_encoder(toml_table_t *tfile, struct xrdp_tconfi { if (g_strcasecmp(h264_encoder.u.s, "x264") == 0) { - TCLOG(LOG_LEVEL_DEBUG, "[h264 encoder] x264"); + TCLOG(LOG_LEVEL_DEBUG, "[codec] h264_encoder = x264"); valid_encoder_found = 1; config->h264_encoder = XTC_H264_X264; } if (g_strcasecmp(h264_encoder.u.s, "OpenH264") == 0) { - TCLOG(LOG_LEVEL_DEBUG, "[h264 encoder] OpenH264"); + TCLOG(LOG_LEVEL_DEBUG, "[codec] h264_encoder = OpenH264"); valid_encoder_found = 1; config->h264_encoder = XTC_H264_OPENH264; } @@ -279,7 +369,7 @@ static int tconfig_load_gfx_h264_encoder(toml_table_t *tfile, struct xrdp_tconfi if (valid_encoder_found == 0) { - TCLOG(LOG_LEVEL_WARNING, "[h264 encoder] could not get valid H.264 encoder , " + TCLOG(LOG_LEVEL_WARNING, "[codec] could not get valid H.264 encoder, " "using default \"x264\""); /* default to x264 */ @@ -443,14 +533,13 @@ tconfig_load_gfx(const char *filename, struct xrdp_tconfig_gfx *config) if (codec_enabled(&config->codec, XTC_H264)) { /* First of all, read the default params */ - if (tconfig_load_gfx_x264_ct(tfile, 0, config->x264_param) != 0) - { - /* We can't read the H.264 defaults. Disable H.264 */ - LOG(LOG_LEVEL_WARNING, "H.264 support will be disabled"); - disable_codec(&config->codec, XTC_H264); - rv = 1; - } - else + int x264_loaded; + int oh264_loaded; + + x264_loaded = tconfig_load_gfx_x264_ct(tfile, 0, config->x264_param); + oh264_loaded = tconfig_load_gfx_openh264_ct(tfile, 0, config->openh264_param); + + if (x264_loaded == 0) { /* Copy default params to other connection types, and * then override them */ @@ -461,6 +550,36 @@ tconfig_load_gfx(const char *filename, struct xrdp_tconfig_gfx *config) tconfig_load_gfx_x264_ct(tfile, ct, config->x264_param); } } + + if (oh264_loaded == 0) + { + /* Copy default params to other connection types, and + * then override them */ + for (int ct = CONNECTION_TYPE_MODEM; ct < NUM_CONNECTION_TYPES; + ct++) + { + config->openh264_param[ct] = config->openh264_param[0]; + tconfig_load_gfx_openh264_ct(tfile, ct, config->openh264_param); + } + } + + if (x264_loaded != 0 && config->h264_encoder == XTC_H264_X264) + { + /* We can't get x264 defaults. Disable H.264. */ + TCLOG(LOG_LEVEL_WARNING, "x264 is selected as H.264 encoder but " + "cannot load default config for x264, disabling H.264"); + disable_codec(&config->codec, XTC_H264); + rv = 1; + } + + if (oh264_loaded != 0 && config->h264_encoder == XTC_H264_OPENH264) + { + /* We can't get OpenH264 defaults. Disable H.264. */ + TCLOG(LOG_LEVEL_WARNING, "OpenH264 is selected as H.264 encoder but " + "cannot load default config for OpenH264, disabling H.264"); + disable_codec(&config->codec, XTC_H264); + rv = 1; + } } toml_free(tfile); diff --git a/xrdp/xrdp_tconfig.h b/xrdp/xrdp_tconfig.h index dab7876414..5ab0bf7c7f 100644 --- a/xrdp/xrdp_tconfig.h +++ b/xrdp/xrdp_tconfig.h @@ -44,7 +44,10 @@ struct xrdp_tconfig_gfx_x264_param struct xrdp_tconfig_gfx_openh264_param { - int pad0; + bool_t EnableFrameSkip; + int TargetBitrate; + int MaxBitrate; + float MaxFrameRate; }; enum xrdp_tconfig_codecs From b95f6e94afa0bcb48607812d9b6ef60fb0ce8edc Mon Sep 17 00:00:00 2001 From: Koichiro Iwao Date: Thu, 28 Nov 2024 11:34:10 +0900 Subject: [PATCH 05/11] OpenH264: throw out some logs to TRACE level --- xrdp/xrdp_encoder_openh264.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xrdp/xrdp_encoder_openh264.c b/xrdp/xrdp_encoder_openh264.c index 9623efaa55..32d0ba75cd 100644 --- a/xrdp/xrdp_encoder_openh264.c +++ b/xrdp/xrdp_encoder_openh264.c @@ -274,12 +274,12 @@ xrdp_encoder_openh264_encode(void *handle, int session, int left, int top, &pic1, &info); if (status != 0) { - LOG(LOG_LEVEL_INFO, "Failed to encode frame"); + LOG(LOG_LEVEL_TRACE, "OpenH264: Failed to encode frame"); return 3; } if (info.eFrameType == videoFrameTypeSkip) { - LOG(LOG_LEVEL_INFO, "frame was skipped!"); + LOG(LOG_LEVEL_TRACE, "OpenH264: frame was skipped!"); return 4; } lcdata_bytes = 0; From d81b496d7f305d9ea567aa0648fbb757b5633b2d Mon Sep 17 00:00:00 2001 From: Koichiro Iwao Date: Thu, 28 Nov 2024 12:17:29 +0900 Subject: [PATCH 06/11] x264: cleanup gfx.toml --- xrdp/gfx.toml | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/xrdp/gfx.toml b/xrdp/gfx.toml index c20f537333..ef98c4e1f9 100644 --- a/xrdp/gfx.toml +++ b/xrdp/gfx.toml @@ -17,36 +17,34 @@ tune = "zerolatency" profile = "main" # profile is forced to baseline if preset == ultrafast vbv_max_bitrate = 0 vbv_buffer_size = 0 -fps_num = 24 +fps_num = 60 fps_den = 1 [x264.lan] # inherits default [x264.wan] -vbv_max_bitrate = 15000 -vbv_buffer_size = 1500 +vbv_max_bitrate = 15_000 +vbv_buffer_size = 1_500 [x264.broadband_high] preset = "superfast" -vbv_max_bitrate = 8000 +vbv_max_bitrate = 8_000 vbv_buffer_Size = 800 [x264.satellite] preset = "superfast" -vbv_max_bitrate = 5000 +vbv_max_bitrate = 5_000 vbv_buffer_size = 500 [x264.broadband_low] preset = "veryfast" -tune = "zerolatency" -vbv_max_bitrate = 1600 +vbv_max_bitrate = 1_600 vbv_buffer_size = 66 [x264.modem] preset = "fast" -tune = "zerolatency" -vbv_max_bitrate = 1200 +vbv_max_bitrate = 1_200 vbv_buffer_size = 50 # From 655215f3038b653eb163ad00899c182b68ea8c64 Mon Sep 17 00:00:00 2001 From: Koichiro Iwao Date: Thu, 28 Nov 2024 12:43:29 +0900 Subject: [PATCH 07/11] tests: fix tests after OpenH264 --- tests/xrdp/Makefile.am | 7 +++++ tests/xrdp/gfx/gfx.toml | 64 +++++++++++++++++++++++++++++++++------ tests/xrdp/test_tconfig.c | 2 +- xrdp/xrdp_tconfig.h | 2 ++ 4 files changed, 65 insertions(+), 10 deletions(-) diff --git a/tests/xrdp/Makefile.am b/tests/xrdp/Makefile.am index 26870bf021..7656584b39 100644 --- a/tests/xrdp/Makefile.am +++ b/tests/xrdp/Makefile.am @@ -83,3 +83,10 @@ test_xrdp_LDADD += \ $(top_builddir)/xrdp/xrdp_encoder_x264.o \ $(XRDP_X264_LIBS) endif + +if XRDP_OPENH264 +AM_CPPFLAGS += -DXRDP_X264 $(XRDP_OPENH264_CFLAGS) +test_xrdp_LDADD += \ + $(top_builddir)/xrdp/xrdp_encoder_openh264.o \ + $(XRDP_OPENH264_LIBS) +endif diff --git a/tests/xrdp/gfx/gfx.toml b/tests/xrdp/gfx/gfx.toml index af3fcf86ed..ef98c4e1f9 100644 --- a/tests/xrdp/gfx/gfx.toml +++ b/tests/xrdp/gfx/gfx.toml @@ -1,40 +1,86 @@ [codec] order = [ "H.264", "RFX" ] +# Specify a preferred H.264 encoder, "x264" or "OpenH264". +# This parameter takes effect only when more than one encoder is +# enabled at compile time. If only one encoder is enabled, the encoder +# will be used regardless the value of this parameter. +h264_encoder = "OpenH264" + +# +# Configurations for x264 +# [x264.default] +# NOTE: x264 specifies bitrate in unit of kbps. preset = "ultrafast" tune = "zerolatency" profile = "main" # profile is forced to baseline if preset == ultrafast vbv_max_bitrate = 0 vbv_buffer_size = 0 -fps_num = 24 +fps_num = 60 fps_den = 1 [x264.lan] # inherits default [x264.wan] -vbv_max_bitrate = 15000 -vbv_buffer_size = 1500 +vbv_max_bitrate = 15_000 +vbv_buffer_size = 1_500 [x264.broadband_high] preset = "superfast" -vbv_max_bitrate = 8000 +vbv_max_bitrate = 8_000 vbv_buffer_Size = 800 [x264.satellite] preset = "superfast" -vbv_max_bitrate = 5000 +vbv_max_bitrate = 5_000 vbv_buffer_size = 500 [x264.broadband_low] preset = "veryfast" -tune = "zerolatency" -vbv_max_bitrate = 1600 +vbv_max_bitrate = 1_600 vbv_buffer_size = 66 [x264.modem] preset = "fast" -tune = "zerolatency" -vbv_max_bitrate = 1200 +vbv_max_bitrate = 1_200 vbv_buffer_size = 50 + +# +# Configurations for OpenH264 +# +[OpenH264.default] +# NOTE: OpenH264 specifies bitrate in unit of bps, not kbps. +EnableFrameSkip = false +TargetBitrate = 20_000_000 +MaxBitrate = 0 # unspecified +MaxFrameRate = 60.0 + +[OpenH264.lan] +# inherits default + +[OpenH264.wan] +TargetBitrate = 10_000_000 +MaxBitrate = 12_000_000 + +[OpenH264.broadband_high] +EnableFrameSkip = true +TargetBitrate = 8_000_000 +MaxBitrate = 10_000_000 + +[OpenH264.satellite] +EnableFrameSkip = true +TargetBitrate = 4_000_000 +MaxBitrate = 6_000_000 + +[OpenH264.broadband_low] +EnableFrameSkip = true +TargetBitrate = 1_600_000 +MaxBitrate = 1_800_000 + +[OpenH264.modem] +EnableFrameSkip = true +TargetBitrate = 600_000 +MaxBitrate = 1_200_000 + diff --git a/tests/xrdp/test_tconfig.c b/tests/xrdp/test_tconfig.c index 81184984d1..1fd29ad691 100644 --- a/tests/xrdp/test_tconfig.c +++ b/tests/xrdp/test_tconfig.c @@ -27,7 +27,7 @@ START_TEST(test_tconfig_gfx_x264_load_basic) ck_assert_str_eq(gfxconfig.x264_param[0].profile, "main"); ck_assert_int_eq(gfxconfig.x264_param[0].vbv_max_bitrate, 0); ck_assert_int_eq(gfxconfig.x264_param[0].vbv_buffer_size, 0); - ck_assert_int_eq(gfxconfig.x264_param[0].fps_num, 24); + ck_assert_int_eq(gfxconfig.x264_param[0].fps_num, 60); ck_assert_int_eq(gfxconfig.x264_param[0].fps_den, 1); } diff --git a/xrdp/xrdp_tconfig.h b/xrdp/xrdp_tconfig.h index 5ab0bf7c7f..263da4d714 100644 --- a/xrdp/xrdp_tconfig.h +++ b/xrdp/xrdp_tconfig.h @@ -26,6 +26,8 @@ #ifndef _XRDP_TCONFIG_H_ #define _XRDP_TCONFIG_H_ +#include "arch.h" + /* The number of connection types in MS-RDPBCGR 2.2.1.3.2 */ #define NUM_CONNECTION_TYPES 7 #define GFX_CONF XRDP_CFG_PATH "/gfx.toml" From a9c7373b75fe60848c6cb6189bb39595a35159bd Mon Sep 17 00:00:00 2001 From: Koichiro Iwao Date: Thu, 28 Nov 2024 12:56:02 +0900 Subject: [PATCH 08/11] x264 is the default H.264 encoder --- xrdp/gfx.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xrdp/gfx.toml b/xrdp/gfx.toml index ef98c4e1f9..94b7514411 100644 --- a/xrdp/gfx.toml +++ b/xrdp/gfx.toml @@ -5,7 +5,7 @@ order = [ "H.264", "RFX" ] # This parameter takes effect only when more than one encoder is # enabled at compile time. If only one encoder is enabled, the encoder # will be used regardless the value of this parameter. -h264_encoder = "OpenH264" +h264_encoder = "x264" # # Configurations for x264 From 92bd0812a398bc8d966e978cac32d3f80ffb1df2 Mon Sep 17 00:00:00 2001 From: Koichiro Iwao Date: Thu, 28 Nov 2024 23:21:20 +0900 Subject: [PATCH 09/11] tests: add tests for OpenH264 params and prefered H264 encoder --- tests/xrdp/Makefile.am | 15 ++-- tests/xrdp/gfx/gfx_h264_encoder_invalid.toml | 86 +++++++++++++++++++ tests/xrdp/gfx/gfx_h264_encoder_openh264.toml | 86 +++++++++++++++++++ .../xrdp/gfx/gfx_h264_encoder_undefined.toml | 86 +++++++++++++++++++ tests/xrdp/gfx/gfx_h264_encoder_x264.toml | 86 +++++++++++++++++++ tests/xrdp/test_tconfig.c | 59 +++++++++++++ 6 files changed, 413 insertions(+), 5 deletions(-) create mode 100644 tests/xrdp/gfx/gfx_h264_encoder_invalid.toml create mode 100644 tests/xrdp/gfx/gfx_h264_encoder_openh264.toml create mode 100644 tests/xrdp/gfx/gfx_h264_encoder_undefined.toml create mode 100644 tests/xrdp/gfx/gfx_h264_encoder_x264.toml diff --git a/tests/xrdp/Makefile.am b/tests/xrdp/Makefile.am index 7656584b39..bdeda5fd62 100644 --- a/tests/xrdp/Makefile.am +++ b/tests/xrdp/Makefile.am @@ -20,13 +20,18 @@ EXTRA_DIST = \ test_not4_24bit.bmp \ test1.jpg \ test_alpha_blend.png \ - gfx/gfx.toml\ - gfx/gfx_codec_order_undefined.toml \ - gfx/gfx_codec_h264_preferred.toml \ + gfx/gfx.toml \ gfx/gfx_codec_h264_only.toml \ - gfx/gfx_codec_rfx_preferred.toml \ + gfx/gfx_codec_h264_preferred.toml \ + gfx/gfx_codec_order_undefined.toml \ + gfx/gfx_codec_rfx_only.toml \ gfx/gfx_codec_rfx_preferred_odd.toml \ - gfx/gfx_codec_rfx_only.toml + gfx/gfx_codec_rfx_preferred.toml \ + gfx/gfx_h264_encoder_invalid.toml \ + gfx/gfx_h264_encoder_openh264.toml \ + gfx/gfx_h264_encoder_undefined.toml \ + gfx/gfx_h264_encoder_x264.toml \ + gfx/gfx_missing_h264.toml TESTS = test_xrdp check_PROGRAMS = test_xrdp diff --git a/tests/xrdp/gfx/gfx_h264_encoder_invalid.toml b/tests/xrdp/gfx/gfx_h264_encoder_invalid.toml new file mode 100644 index 0000000000..7aee69716c --- /dev/null +++ b/tests/xrdp/gfx/gfx_h264_encoder_invalid.toml @@ -0,0 +1,86 @@ +[codec] +order = [ "H.264", "RFX" ] + +# Specify a preferred H.264 encoder, "x264" or "OpenH264". +# This parameter takes effect only when more than one encoder is +# enabled at compile time. If only one encoder is enabled, the encoder +# will be used regardless the value of this parameter. +h264_encoder = "FreeH264" + +# +# Configurations for x264 +# +[x264.default] +# NOTE: x264 specifies bitrate in unit of kbps. +preset = "ultrafast" +tune = "zerolatency" +profile = "main" # profile is forced to baseline if preset == ultrafast +vbv_max_bitrate = 0 +vbv_buffer_size = 0 +fps_num = 60 +fps_den = 1 + +[x264.lan] +# inherits default + +[x264.wan] +vbv_max_bitrate = 15_000 +vbv_buffer_size = 1_500 + +[x264.broadband_high] +preset = "superfast" +vbv_max_bitrate = 8_000 +vbv_buffer_Size = 800 + +[x264.satellite] +preset = "superfast" +vbv_max_bitrate = 5_000 +vbv_buffer_size = 500 + +[x264.broadband_low] +preset = "veryfast" +vbv_max_bitrate = 1_600 +vbv_buffer_size = 66 + +[x264.modem] +preset = "fast" +vbv_max_bitrate = 1_200 +vbv_buffer_size = 50 + +# +# Configurations for OpenH264 +# +[OpenH264.default] +# NOTE: OpenH264 specifies bitrate in unit of bps, not kbps. +EnableFrameSkip = false +TargetBitrate = 20_000_000 +MaxBitrate = 0 # unspecified +MaxFrameRate = 60.0 + +[OpenH264.lan] +# inherits default + +[OpenH264.wan] +TargetBitrate = 10_000_000 +MaxBitrate = 12_000_000 + +[OpenH264.broadband_high] +EnableFrameSkip = true +TargetBitrate = 8_000_000 +MaxBitrate = 10_000_000 + +[OpenH264.satellite] +EnableFrameSkip = true +TargetBitrate = 4_000_000 +MaxBitrate = 6_000_000 + +[OpenH264.broadband_low] +EnableFrameSkip = true +TargetBitrate = 1_600_000 +MaxBitrate = 1_800_000 + +[OpenH264.modem] +EnableFrameSkip = true +TargetBitrate = 600_000 +MaxBitrate = 1_200_000 + diff --git a/tests/xrdp/gfx/gfx_h264_encoder_openh264.toml b/tests/xrdp/gfx/gfx_h264_encoder_openh264.toml new file mode 100644 index 0000000000..ef98c4e1f9 --- /dev/null +++ b/tests/xrdp/gfx/gfx_h264_encoder_openh264.toml @@ -0,0 +1,86 @@ +[codec] +order = [ "H.264", "RFX" ] + +# Specify a preferred H.264 encoder, "x264" or "OpenH264". +# This parameter takes effect only when more than one encoder is +# enabled at compile time. If only one encoder is enabled, the encoder +# will be used regardless the value of this parameter. +h264_encoder = "OpenH264" + +# +# Configurations for x264 +# +[x264.default] +# NOTE: x264 specifies bitrate in unit of kbps. +preset = "ultrafast" +tune = "zerolatency" +profile = "main" # profile is forced to baseline if preset == ultrafast +vbv_max_bitrate = 0 +vbv_buffer_size = 0 +fps_num = 60 +fps_den = 1 + +[x264.lan] +# inherits default + +[x264.wan] +vbv_max_bitrate = 15_000 +vbv_buffer_size = 1_500 + +[x264.broadband_high] +preset = "superfast" +vbv_max_bitrate = 8_000 +vbv_buffer_Size = 800 + +[x264.satellite] +preset = "superfast" +vbv_max_bitrate = 5_000 +vbv_buffer_size = 500 + +[x264.broadband_low] +preset = "veryfast" +vbv_max_bitrate = 1_600 +vbv_buffer_size = 66 + +[x264.modem] +preset = "fast" +vbv_max_bitrate = 1_200 +vbv_buffer_size = 50 + +# +# Configurations for OpenH264 +# +[OpenH264.default] +# NOTE: OpenH264 specifies bitrate in unit of bps, not kbps. +EnableFrameSkip = false +TargetBitrate = 20_000_000 +MaxBitrate = 0 # unspecified +MaxFrameRate = 60.0 + +[OpenH264.lan] +# inherits default + +[OpenH264.wan] +TargetBitrate = 10_000_000 +MaxBitrate = 12_000_000 + +[OpenH264.broadband_high] +EnableFrameSkip = true +TargetBitrate = 8_000_000 +MaxBitrate = 10_000_000 + +[OpenH264.satellite] +EnableFrameSkip = true +TargetBitrate = 4_000_000 +MaxBitrate = 6_000_000 + +[OpenH264.broadband_low] +EnableFrameSkip = true +TargetBitrate = 1_600_000 +MaxBitrate = 1_800_000 + +[OpenH264.modem] +EnableFrameSkip = true +TargetBitrate = 600_000 +MaxBitrate = 1_200_000 + diff --git a/tests/xrdp/gfx/gfx_h264_encoder_undefined.toml b/tests/xrdp/gfx/gfx_h264_encoder_undefined.toml new file mode 100644 index 0000000000..74f4d618d2 --- /dev/null +++ b/tests/xrdp/gfx/gfx_h264_encoder_undefined.toml @@ -0,0 +1,86 @@ +[codec] +order = [ "H.264", "RFX" ] + +# Specify a preferred H.264 encoder, "x264" or "OpenH264". +# This parameter takes effect only when more than one encoder is +# enabled at compile time. If only one encoder is enabled, the encoder +# will be used regardless the value of this parameter. +#h264_encoder = "OpenH264" + +# +# Configurations for x264 +# +[x264.default] +# NOTE: x264 specifies bitrate in unit of kbps. +preset = "ultrafast" +tune = "zerolatency" +profile = "main" # profile is forced to baseline if preset == ultrafast +vbv_max_bitrate = 0 +vbv_buffer_size = 0 +fps_num = 60 +fps_den = 1 + +[x264.lan] +# inherits default + +[x264.wan] +vbv_max_bitrate = 15_000 +vbv_buffer_size = 1_500 + +[x264.broadband_high] +preset = "superfast" +vbv_max_bitrate = 8_000 +vbv_buffer_Size = 800 + +[x264.satellite] +preset = "superfast" +vbv_max_bitrate = 5_000 +vbv_buffer_size = 500 + +[x264.broadband_low] +preset = "veryfast" +vbv_max_bitrate = 1_600 +vbv_buffer_size = 66 + +[x264.modem] +preset = "fast" +vbv_max_bitrate = 1_200 +vbv_buffer_size = 50 + +# +# Configurations for OpenH264 +# +[OpenH264.default] +# NOTE: OpenH264 specifies bitrate in unit of bps, not kbps. +EnableFrameSkip = false +TargetBitrate = 20_000_000 +MaxBitrate = 0 # unspecified +MaxFrameRate = 60.0 + +[OpenH264.lan] +# inherits default + +[OpenH264.wan] +TargetBitrate = 10_000_000 +MaxBitrate = 12_000_000 + +[OpenH264.broadband_high] +EnableFrameSkip = true +TargetBitrate = 8_000_000 +MaxBitrate = 10_000_000 + +[OpenH264.satellite] +EnableFrameSkip = true +TargetBitrate = 4_000_000 +MaxBitrate = 6_000_000 + +[OpenH264.broadband_low] +EnableFrameSkip = true +TargetBitrate = 1_600_000 +MaxBitrate = 1_800_000 + +[OpenH264.modem] +EnableFrameSkip = true +TargetBitrate = 600_000 +MaxBitrate = 1_200_000 + diff --git a/tests/xrdp/gfx/gfx_h264_encoder_x264.toml b/tests/xrdp/gfx/gfx_h264_encoder_x264.toml new file mode 100644 index 0000000000..94b7514411 --- /dev/null +++ b/tests/xrdp/gfx/gfx_h264_encoder_x264.toml @@ -0,0 +1,86 @@ +[codec] +order = [ "H.264", "RFX" ] + +# Specify a preferred H.264 encoder, "x264" or "OpenH264". +# This parameter takes effect only when more than one encoder is +# enabled at compile time. If only one encoder is enabled, the encoder +# will be used regardless the value of this parameter. +h264_encoder = "x264" + +# +# Configurations for x264 +# +[x264.default] +# NOTE: x264 specifies bitrate in unit of kbps. +preset = "ultrafast" +tune = "zerolatency" +profile = "main" # profile is forced to baseline if preset == ultrafast +vbv_max_bitrate = 0 +vbv_buffer_size = 0 +fps_num = 60 +fps_den = 1 + +[x264.lan] +# inherits default + +[x264.wan] +vbv_max_bitrate = 15_000 +vbv_buffer_size = 1_500 + +[x264.broadband_high] +preset = "superfast" +vbv_max_bitrate = 8_000 +vbv_buffer_Size = 800 + +[x264.satellite] +preset = "superfast" +vbv_max_bitrate = 5_000 +vbv_buffer_size = 500 + +[x264.broadband_low] +preset = "veryfast" +vbv_max_bitrate = 1_600 +vbv_buffer_size = 66 + +[x264.modem] +preset = "fast" +vbv_max_bitrate = 1_200 +vbv_buffer_size = 50 + +# +# Configurations for OpenH264 +# +[OpenH264.default] +# NOTE: OpenH264 specifies bitrate in unit of bps, not kbps. +EnableFrameSkip = false +TargetBitrate = 20_000_000 +MaxBitrate = 0 # unspecified +MaxFrameRate = 60.0 + +[OpenH264.lan] +# inherits default + +[OpenH264.wan] +TargetBitrate = 10_000_000 +MaxBitrate = 12_000_000 + +[OpenH264.broadband_high] +EnableFrameSkip = true +TargetBitrate = 8_000_000 +MaxBitrate = 10_000_000 + +[OpenH264.satellite] +EnableFrameSkip = true +TargetBitrate = 4_000_000 +MaxBitrate = 6_000_000 + +[OpenH264.broadband_low] +EnableFrameSkip = true +TargetBitrate = 1_600_000 +MaxBitrate = 1_800_000 + +[OpenH264.modem] +EnableFrameSkip = true +TargetBitrate = 600_000 +MaxBitrate = 1_200_000 + diff --git a/tests/xrdp/test_tconfig.c b/tests/xrdp/test_tconfig.c index 1fd29ad691..2971b2781a 100644 --- a/tests/xrdp/test_tconfig.c +++ b/tests/xrdp/test_tconfig.c @@ -14,6 +14,56 @@ START_TEST(test_tconfig_gfx_always_success) } END_TEST +START_TEST(test_tconfig_gfx_h264_oh264) +{ + struct xrdp_tconfig_gfx gfxconfig; + tconfig_load_gfx(GFXCONF_STUBDIR "/gfx_h264_encoder_openh264.toml", &gfxconfig); + + /* H.264 encoder is OpenH264 */ + ck_assert_int_eq(gfxconfig.h264_encoder, XTC_H264_OPENH264); +} + +START_TEST(test_tconfig_gfx_h264_x264) +{ + struct xrdp_tconfig_gfx gfxconfig; + tconfig_load_gfx(GFXCONF_STUBDIR "/gfx_h264_encoder_x264.toml", &gfxconfig); + + /* H.264 encoder is x264 */ + ck_assert_int_eq(gfxconfig.h264_encoder, XTC_H264_X264); +} + +START_TEST(test_tconfig_gfx_h264_undefined) +{ + struct xrdp_tconfig_gfx gfxconfig; + tconfig_load_gfx(GFXCONF_STUBDIR "/gfx_h264_encoder_undefined.toml", &gfxconfig); + + /* H.264 encoder is x264 if undefined */ + ck_assert_int_eq(gfxconfig.h264_encoder, XTC_H264_X264); +} + +START_TEST(test_tconfig_gfx_h264_invalid) +{ + struct xrdp_tconfig_gfx gfxconfig; + tconfig_load_gfx(GFXCONF_STUBDIR "/gfx_h264_encoder_invalid.toml", &gfxconfig); + + /* H.264 encoder is x264 if invalid, unknown encoder specified */ + ck_assert_int_eq(gfxconfig.h264_encoder, XTC_H264_X264); +} + +START_TEST(test_tconfig_gfx_oh264_load_basic) +{ + struct xrdp_tconfig_gfx gfxconfig; + int rv = tconfig_load_gfx(GFXCONF_STUBDIR "/gfx.toml", &gfxconfig); + + ck_assert_int_eq(rv, 0); + + /* default */ + ck_assert_int_eq(gfxconfig.openh264_param[0].EnableFrameSkip, 0); + ck_assert_int_eq(gfxconfig.openh264_param[0].TargetBitrate, 20000000); + ck_assert_int_eq(gfxconfig.openh264_param[0].MaxBitrate, 0); + ck_assert_float_eq(gfxconfig.openh264_param[0].MaxFrameRate, 60.0); +} + START_TEST(test_tconfig_gfx_x264_load_basic) { struct xrdp_tconfig_gfx gfxconfig; @@ -111,6 +161,15 @@ make_suite_tconfig_load_gfx(void) tcase_add_test(tc_tconfig_load_gfx, test_tconfig_gfx_missing_file); tcase_add_test(tc_tconfig_load_gfx, test_tconfig_gfx_missing_h264); + /* OpenH264 */ + tcase_add_test(tc_tconfig_load_gfx, test_tconfig_gfx_oh264_load_basic); + + /* H.264 encoder */ + tcase_add_test(tc_tconfig_load_gfx, test_tconfig_gfx_h264_oh264); + tcase_add_test(tc_tconfig_load_gfx, test_tconfig_gfx_h264_x264); + tcase_add_test(tc_tconfig_load_gfx, test_tconfig_gfx_h264_undefined); + tcase_add_test(tc_tconfig_load_gfx, test_tconfig_gfx_h264_invalid); + suite_add_tcase(s, tc_tconfig_load_gfx); return s; From efd2a5fbd8b0d5024c16edc2d4a51e5371c679e8 Mon Sep 17 00:00:00 2001 From: Koichiro Iwao Date: Fri, 29 Nov 2024 00:39:13 +0900 Subject: [PATCH 10/11] CI: add OpenH264 to max features --- .github/workflows/build.yml | 2 +- scripts/install_xrdp_build_dependencies_with_apt.sh | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 939cb9bef5..ff14d8b276 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -114,7 +114,7 @@ jobs: CONF_FLAGS_amd64_max: "--enable-ipv6 --enable-jpeg --enable-fuse --enable-mp3lame --enable-fdkaac --enable-opus --enable-rfxcodec --enable-painter --enable-pixman --with-imlib2 --with-freetype2 --enable-tests - --enable-x264" + --enable-x264 --enable-openh264" CONF_FLAGS_i386_max: "--enable-ipv6 --enable-jpeg --enable-mp3lame --enable-opus --enable-rfxcodec --enable-painter --disable-pixman --with-imlib2 --with-freetype2 diff --git a/scripts/install_xrdp_build_dependencies_with_apt.sh b/scripts/install_xrdp_build_dependencies_with_apt.sh index beb049c3d7..fd03a348a9 100755 --- a/scripts/install_xrdp_build_dependencies_with_apt.sh +++ b/scripts/install_xrdp_build_dependencies_with_apt.sh @@ -96,7 +96,8 @@ in libimlib2-dev \ libopus-dev \ libpixman-1-dev \ - libx264-dev" + libx264-dev + libopenh264-dev" ;; *) echo "unsupported feature set: $FEATURE_SET" From 1f74edee0e036fa3288fac3d0b5d919ac66d96bf Mon Sep 17 00:00:00 2001 From: Koichiro Iwao Date: Sat, 30 Nov 2024 21:15:43 +0900 Subject: [PATCH 11/11] CI: fix build with g++ --- xrdp/xrdp_encoder_openh264.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/xrdp/xrdp_encoder_openh264.c b/xrdp/xrdp_encoder_openh264.c index 32d0ba75cd..4bae6b97c8 100644 --- a/xrdp/xrdp_encoder_openh264.c +++ b/xrdp/xrdp_encoder_openh264.c @@ -53,6 +53,20 @@ struct openh264_global openh264_param[NUM_CONNECTION_TYPES]; }; +/* The method invocations on ISVCEncoder are different for C and C++, as + ISVCEncoder is a true class in C++, but an emulated one in C */ +#ifdef __cplusplus /* compiling with g++ */ +#define ENC_GET_DEFAULT_PARAMS(obj, pParam) (obj)->GetDefaultParams(pParam) +#define ENC_INITIALIZE_EXT(obj, pParam) (obj)->InitializeExt(pParam) +#define ENC_ENCODE_FRAME(obj, kpSrcPic, pBsInfo) \ + (obj)->EncodeFrame(kpSrcPic, pBsInfo) +#else +#define ENC_GET_DEFAULT_PARAMS(obj, pParam) (*obj)->GetDefaultParams(obj, pParam) +#define ENC_INITIALIZE_EXT(obj, pParam) (*obj)->InitializeExt(obj, pParam) +#define ENC_ENCODE_FRAME(obj, kpSrcPic, pBsInfo) \ + (*obj)->EncodeFrame(obj, kpSrcPic, pBsInfo) +#endif + /*****************************************************************************/ void * xrdp_encoder_openh264_create(void) @@ -167,7 +181,7 @@ xrdp_encoder_openh264_encode(void *handle, int session, int left, int top, LOG(LOG_LEVEL_INFO, "xrdp_encoder_openh264_encode: " "WelsCreateSVCEncoder rv %p for width %d height %d", oe->openh264_enc_han, width, height); - status = (*oe->openh264_enc_han)->GetDefaultParams( + status = ENC_GET_DEFAULT_PARAMS( oe->openh264_enc_han, &encParamExt); LOG(LOG_LEVEL_INFO, "xrdp_encoder_openh264_encode: " "GetDefaultParams rv %d", status); @@ -191,7 +205,7 @@ xrdp_encoder_openh264_encode(void *handle, int session, int left, int top, slc->iVideoHeight = encParamExt.iPicHeight; slc->iSpatialBitrate = encParamExt.iTargetBitrate; slc->iMaxSpatialBitrate = encParamExt.iMaxBitrate; - status = (*oe->openh264_enc_han)->InitializeExt( + status = ENC_INITIALIZE_EXT( oe->openh264_enc_han, &encParamExt); LOG(LOG_LEVEL_INFO, "xrdp_encoder_openh264_encode: " "InitializeExt rv %d", status); @@ -270,8 +284,7 @@ xrdp_encoder_openh264_encode(void *handle, int session, int left, int top, } } g_memset(&info, 0, sizeof(info)); - status = (*oe->openh264_enc_han)->EncodeFrame(oe->openh264_enc_han, - &pic1, &info); + status = ENC_ENCODE_FRAME(oe->openh264_enc_han, &pic1, &info); if (status != 0) { LOG(LOG_LEVEL_TRACE, "OpenH264: Failed to encode frame");