From b73ac602f0efb7cc9152040d0c66c37bac117689 Mon Sep 17 00:00:00 2001 From: Stefan Oltmanns Date: Mon, 29 Jul 2024 05:12:31 +0200 Subject: [PATCH] avformat/vapoursynth: load library at runtime Signed-off-by: Stefan Oltmanns Signed-off-by: Paul B Mahol --- configure | 2 +- libavformat/vapoursynth.c | 65 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/configure b/configure index 3f6435ae0f..a22ae98607 100755 --- a/configure +++ b/configure @@ -7075,7 +7075,7 @@ enabled rkmpp && { require_pkg_config rkmpp rockchip_mpp rockchip/r { enabled libdrm || die "ERROR: rkmpp requires --enable-libdrm"; } } -enabled vapoursynth && require_pkg_config vapoursynth "vapoursynth-script >= 55" VSScript4.h getVSScriptAPI +enabled vapoursynth && require_headers "vapoursynth/VSScript4.h vapoursynth/VapourSynth4.h" if enabled gcrypt; then diff --git a/libavformat/vapoursynth.c b/libavformat/vapoursynth.c index ed75e8350b..b7b526c0cc 100644 --- a/libavformat/vapoursynth.c +++ b/libavformat/vapoursynth.c @@ -25,7 +25,7 @@ #include -#include +#include #include "libavutil/avassert.h" #include "libavutil/avstring.h" @@ -39,11 +39,26 @@ #include "demux.h" #include "internal.h" +/* Platform-specific directives. */ +#ifdef _WIN32 + #include + #include "compat/w32dlfcn.h" + #include "libavutil/wchar_filename.h" + #undef EXTERN_C + #define VSSCRIPT_LIB "VSScript.dll" +#else + #include + #define VSSCRIPT_NAME "libvapoursynth-script" + #define VSSCRIPT_LIB VSSCRIPT_NAME SLIBSUF +#endif + struct VSState { const VSSCRIPTAPI *vssapi; VSScript *vss; }; +typedef const VSSCRIPTAPI *(*VSScriptGetAPIFunc)(int version); + typedef struct VSContext { const AVClass *class; @@ -51,6 +66,7 @@ typedef struct VSContext { const VSSCRIPTAPI *vssapi; const VSAPI *vsapi; + void *vslibrary; VSNode *outnode; int is_cfr; @@ -70,6 +86,40 @@ static const AVOption options[] = { {NULL} }; +static av_cold void* vs_load_library(VSScriptGetAPIFunc *get_vssapi) +{ + void *vslibrary = NULL; +#ifdef _WIN32 + const HKEY hkeys[] = {HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE}; + LONG r; + WCHAR vss_path[512]; + DWORD buf_size = sizeof(vss_path) - 2; + char *vss_path_utf8; + int i; + + for (i = 0; i < FF_ARRAY_ELEMS(hkeys); i++) { + if ((r = RegGetValueW(hkeys[i], L"SOFTWARE\\VapourSynth", + L"VSScriptDLL", RRF_RT_REG_SZ, NULL, + &vss_path, &buf_size)) == ERROR_SUCCESS) + break; + } + if (r == ERROR_SUCCESS && wchartoutf8(vss_path, &vss_path_utf8) == 0) { + vslibrary = dlopen(vss_path_utf8, RTLD_NOW | RTLD_GLOBAL); + av_free(vss_path_utf8); + } + else +#endif + vslibrary = dlopen(VSSCRIPT_LIB, RTLD_NOW | RTLD_GLOBAL); + + if (vslibrary != NULL) { + if (!(*get_vssapi = (VSScriptGetAPIFunc)dlsym(vslibrary, "getVSScriptAPI"))) { + dlclose(vslibrary); + return NULL; + } + } + return vslibrary; +} + static void free_vss_state(void *opaque, uint8_t *data) { struct VSState *vss = opaque; @@ -91,6 +141,9 @@ static av_cold int read_close_vs(AVFormatContext *s) vs->vsapi = NULL; vs->outnode = NULL; + if (vs->vslibrary) + dlclose(vs->vslibrary); + return 0; } @@ -170,6 +223,7 @@ static av_cold int read_header_vs(AVFormatContext *s) AVStream *st; AVIOContext *pb = s->pb; VSContext *vs = s->priv_data; + VSScriptGetAPIFunc get_vssapi; int64_t sz = avio_size(pb); char *buf = NULL; char dummy; @@ -178,7 +232,14 @@ static av_cold int read_header_vs(AVFormatContext *s) struct VSState *vss_state; int err = 0; - if (!(vs->vssapi = getVSScriptAPI(VSSCRIPT_API_VERSION))) { + if (!(vs->vslibrary = vs_load_library(&get_vssapi))) { + av_log(s, AV_LOG_ERROR, "Could not open " VSSCRIPT_LIB ". " + "Check VapourSynth installation.\n"); + err = AVERROR_EXTERNAL; + goto done; + } + + if (!(vs->vssapi = get_vssapi(VSSCRIPT_API_VERSION))) { av_log(s, AV_LOG_ERROR, "Failed to initialize VSScript (possibly PYTHONPATH not set).\n"); err = AVERROR_EXTERNAL; goto done;