From 1c855068a2591ae22df1f2c6bb56462609f655f8 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 11 Jan 2019 11:40:31 +0100 Subject: [PATCH 1/2] Using runtime linking for OpenH264. This allows removing the hard dependency on OpenH264 and use the cisco provided binary. --- CMakeLists.txt | 4 ++ libfreerdp/CMakeLists.txt | 4 +- libfreerdp/codec/h264_openh264.c | 111 ++++++++++++++++++++++++++++--- 3 files changed, 109 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ecad9444..347b8214e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -870,6 +870,10 @@ find_feature(soxr ${SOXR_FEATURE_TYPE} ${SOXR_FEATURE_PURPOSE} ${SOXR_FEATURE_DE find_feature(GSSAPI ${GSSAPI_FEATURE_TYPE} ${GSSAPI_FEATURE_PURPOSE} ${GSSAPI_FEATURE_DESCRIPTION}) +if (WITH_OPENH264 AND NOT WITH_OPENH264_LOADING) + set(WITH_OPENH264_LOADING OFF) +endif (WITH_OPENH264 AND NOT WITH_OPENH264_LOADING) + if ((WITH_FFMPEG OR WITH_DSP_FFMPEG) AND NOT FFMPEG_FOUND) message(FATAL_ERROR "FFMPEG support requested but not detected") endif() diff --git a/libfreerdp/CMakeLists.txt b/libfreerdp/CMakeLists.txt index fe05a79ef..f64ce090b 100644 --- a/libfreerdp/CMakeLists.txt +++ b/libfreerdp/CMakeLists.txt @@ -206,7 +206,9 @@ endif() if(WITH_OPENH264) set(CODEC_SRCS ${CODEC_SRCS} codec/h264_openh264.c) freerdp_include_directory_add(${OPENH264_INCLUDE_DIR}) - freerdp_library_add(${OPENH264_LIBRARIES}) + if (NOT WITH_OPENH264_LOADING) + freerdp_library_add(${OPENH264_LIBRARIES}) + endif (NOT WITH_OPENH264_LOADING) endif() if(WITH_FFMPEG) diff --git a/libfreerdp/codec/h264_openh264.c b/libfreerdp/codec/h264_openh264.c index 7f22c7d94..01127c87e 100644 --- a/libfreerdp/codec/h264_openh264.c +++ b/libfreerdp/codec/h264_openh264.c @@ -20,25 +20,49 @@ */ #include #include +#include #include "wels/codec_def.h" #include "wels/codec_api.h" #include "wels/codec_ver.h" -#if (OPENH264_MAJOR == 1) && (OPENH264_MINOR < 3) || (OPENH264_MAJOR < 1) -#error "Unsupported OpenH264 version "OPENH264_MAJOR"."OPENH264_MINOR"."OPENH264_REVISION" detected!" -#elif (OPENH264_MAJOR > 1) || (OPENH264_MINOR > 7) -#warning "Untested OpenH264 version "OPENH264_MAJOR"."OPENH264_MINOR"."OPENH264_REVISION" detected!" -#endif +typedef void (*pWelsGetCodecVersionEx)(OpenH264Version* pVersion); + +typedef long (*pWelsCreateDecoder)(ISVCDecoder** ppDecoder); +typedef void (*pWelsDestroyDecoder)(ISVCDecoder* pDecoder); + +typedef int (*pWelsCreateSVCEncoder)(ISVCEncoder** ppEncoder); +typedef void (*pWelsDestroySVCEncoder)(ISVCEncoder* pEncoder); struct _H264_CONTEXT_OPENH264 { +#if defined (WITH_OPENH264_LOADING) + HMODULE lib; +#endif + pWelsGetCodecVersionEx WelsGetCodecVersionEx; + pWelsCreateDecoder WelsCreateDecoder; + pWelsDestroyDecoder WelsDestroyDecoder; + pWelsCreateSVCEncoder WelsCreateSVCEncoder; + pWelsDestroySVCEncoder WelsDestroySVCEncoder; ISVCDecoder* pDecoder; ISVCEncoder* pEncoder; SEncParamExt EncParamExt; }; typedef struct _H264_CONTEXT_OPENH264 H264_CONTEXT_OPENH264; +#if defined (WITH_OPENH264_LOADING) +static const char* openh264_library_names[] = +{ +#if defined(_WIN32) + "openh264.dll" +#elif defined(__APPLE__) + "libopenh264.dylib" +#else + "libopenh264.so" +#endif +}; +#endif + static void openh264_trace_callback(H264_CONTEXT* h264, int level, const char* message) { @@ -313,25 +337,73 @@ static void openh264_uninit(H264_CONTEXT* h264) if (sys->pDecoder) { (*sys->pDecoder)->Uninitialize(sys->pDecoder); - WelsDestroyDecoder(sys->pDecoder); + sysContexts->WelsDestroyDecoder(sys->pDecoder); sys->pDecoder = NULL; } if (sys->pEncoder) { (*sys->pEncoder)->Uninitialize(sys->pEncoder); - WelsDestroySVCEncoder(sys->pEncoder); + sysContexts->WelsDestroySVCEncoder(sys->pEncoder); sys->pEncoder = NULL; } } +#if defined (WITH_OPENH264_LOADING) + FreeLibrary(sysContexts->lib); +#endif free(h264->pSystemData); h264->pSystemData = NULL; } } +#if defined (WITH_OPENH264_LOADING) +static BOOL openh264_load_functionpointers(H264_CONTEXT* h264, const char* name) +{ + OpenH264Version version; + H264_CONTEXT_OPENH264* sysContexts; + + if (!h264) + return FALSE; + + sysContexts = h264->pSystemData; + + if (!sysContexts) + return FALSE; + + sysContexts->lib = sysContexts->lib = LoadLibraryA(name); + + if (!sysContexts->lib) + return FALSE; + + sysContexts->WelsGetCodecVersionEx = GetProcAddress(sysContexts->lib, "WelsGetCodecVersionEx"); + sysContexts->WelsCreateDecoder = GetProcAddress(sysContexts->lib, "WelsCreateDecoder"); + sysContexts->WelsDestroyDecoder = GetProcAddress(sysContexts->lib, "WelsDestroyDecoder"); + sysContexts->WelsCreateSVCEncoder = GetProcAddress(sysContexts->lib, "WelsCreateSVCEncoder"); + sysContexts->WelsDestroySVCEncoder = GetProcAddress(sysContexts->lib, "WelsDestroySVCEncoder"); + + if (!sysContexts->WelsCreateDecoder || !sysContexts->WelsDestroyDecoder || + !sysContexts->WelsCreateSVCEncoder || !sysContexts->WelsDestroySVCEncoder || + !sysContexts->WelsGetCodecVersionEx) + { + FreeLibrary(sysContexts->lib); + sysContexts->lib = NULL; + return FALSE; + } + + sysContexts->WelsGetCodecVersionEx(&version); + WLog_Print(h264->log, WLOG_INFO, "loaded %s %d.%d.%d", name, version.uMajor, version.uMinor, + version.uRevision); + return TRUE; +} +#endif + static BOOL openh264_init(H264_CONTEXT* h264) { +#if defined (WITH_OPENH264_LOADING) + BOOL success = FALSE; + size_t i; +#endif UINT32 x; long status; SDecodingParam sDecParam; @@ -350,6 +422,27 @@ static BOOL openh264_init(H264_CONTEXT* h264) goto EXCEPTION; h264->pSystemData = (void*) sysContexts; +#if defined (WITH_OPENH264_LOADING) + + for (i = 0; i < ARRAYSIZE(openh264_library_names); i++) + { + const char* current = openh264_library_names[i]; + success = openh264_load_functionpointers(h264, current); + + if (success) + break; + } + + if (!success) + goto EXCEPTION; + +#else + sysContexts->WelsGetCodecVersionEx = WelsGetCodecVersionEx; + sysContexts->WelsCreateDecoder = WelsCreateDecoder; + sysContexts->WelsDestroyDecoder = WelsDestroyDecoder; + sysContexts->WelsCreateSVCEncoder = WelsCreateSVCEncoder; + sysContexts->WelsDestroySVCEncoder = WelsDestroySVCEncoder; +#endif for (x = 0; x < h264->numSystemData; x++) { @@ -357,7 +450,7 @@ static BOOL openh264_init(H264_CONTEXT* h264) if (h264->Compressor) { - WelsCreateSVCEncoder(&sys->pEncoder); + sysContexts->WelsCreateSVCEncoder(&sys->pEncoder); if (!sys->pEncoder) { @@ -367,7 +460,7 @@ static BOOL openh264_init(H264_CONTEXT* h264) } else { - WelsCreateDecoder(&sys->pDecoder); + sysContexts->WelsCreateDecoder(&sys->pDecoder); if (!sys->pDecoder) { From 8c41bd21ea4eaef4d3f11842737a6260087e545b Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 15 Jan 2019 09:49:48 +0100 Subject: [PATCH 2/2] Added version check for dynamic OpenH264 use. --- config.h.in | 1 + libfreerdp/codec/h264_openh264.c | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/config.h.in b/config.h.in index 92f447e6b..2877eea2a 100644 --- a/config.h.in +++ b/config.h.in @@ -60,6 +60,7 @@ #cmakedefine WITH_SOXR #cmakedefine WITH_GFX_H264 #cmakedefine WITH_OPENH264 +#cmakedefine WITH_OPENH264_LOADING #cmakedefine WITH_FFMPEG #cmakedefine WITH_DSP_EXPERIMENTAL #cmakedefine WITH_DSP_FFMPEG diff --git a/libfreerdp/codec/h264_openh264.c b/libfreerdp/codec/h264_openh264.c index 01127c87e..41cd3fc0c 100644 --- a/libfreerdp/codec/h264_openh264.c +++ b/libfreerdp/codec/h264_openh264.c @@ -18,6 +18,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include #include #include @@ -38,6 +42,7 @@ struct _H264_CONTEXT_OPENH264 { #if defined (WITH_OPENH264_LOADING) HMODULE lib; + OpenH264Version version; #endif pWelsGetCodecVersionEx WelsGetCodecVersionEx; pWelsCreateDecoder WelsCreateDecoder; @@ -360,7 +365,6 @@ static void openh264_uninit(H264_CONTEXT* h264) #if defined (WITH_OPENH264_LOADING) static BOOL openh264_load_functionpointers(H264_CONTEXT* h264, const char* name) { - OpenH264Version version; H264_CONTEXT_OPENH264* sysContexts; if (!h264) @@ -391,9 +395,22 @@ static BOOL openh264_load_functionpointers(H264_CONTEXT* h264, const char* name) return FALSE; } - sysContexts->WelsGetCodecVersionEx(&version); - WLog_Print(h264->log, WLOG_INFO, "loaded %s %d.%d.%d", name, version.uMajor, version.uMinor, - version.uRevision); + sysContexts->WelsGetCodecVersionEx(&sysContexts->version); + WLog_Print(h264->log, WLOG_INFO, "loaded %s %d.%d.%d", name, sysContexts->version.uMajor, + sysContexts->version.uMinor, + sysContexts->version.uRevision); + + if ((sysContexts->version.uMajor < 1) || (sysContexts->version.uMinor < 6)) + { + WLog_Print(h264->log, WLOG_ERROR, + "OpenH264 %s %d.%d.%d is too old, need at least version 1.6.0 for dynamic loading", + name, sysContexts->version.uMajor, sysContexts->version.uMinor, + sysContexts->version.uRevision); + FreeLibrary(sysContexts->lib); + sysContexts->lib = NULL; + return FALSE; + } + return TRUE; } #endif