diff options
author | Stefan Oltmanns <stefan-oltmanns@gmx.net> | 2024-07-29 05:12:31 +0200 |
---|---|---|
committer | Ramiro Polla <ramiro.polla@gmail.com> | 2024-08-26 10:30:52 +0200 |
commit | d42cd5b75bd7eeeba8ef7f433edf61b31f6f2858 (patch) | |
tree | 28695eae8f627135fdc03d8f1e0c10b4b03f1bc5 | |
parent | eac611f1a4c494e5e3efe61e7867517e65706534 (diff) | |
download | ffmpeg-d42cd5b75bd7eeeba8ef7f433edf61b31f6f2858.tar.gz |
avformat/vapoursynth: load library at runtime
Signed-off-by: Stefan Oltmanns <stefan-oltmanns@gmx.net>
-rwxr-xr-x | configure | 2 | ||||
-rw-r--r-- | libavformat/vapoursynth.c | 65 |
2 files changed, 64 insertions, 3 deletions
@@ -7090,7 +7090,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 26c9986138..0fa5affa63 100644 --- a/libavformat/vapoursynth.c +++ b/libavformat/vapoursynth.c @@ -25,7 +25,7 @@ #include <limits.h> -#include <VSScript4.h> +#include <vapoursynth/VSScript4.h> #include "libavutil/avassert.h" #include "libavutil/avstring.h" @@ -39,11 +39,26 @@ #include "demux.h" #include "internal.h" +/* Platform-specific directives. */ +#ifdef _WIN32 + #include <windows.h> + #include "compat/w32dlfcn.h" + #include "libavutil/wchar_filename.h" + #undef EXTERN_C + #define VSSCRIPT_LIB "VSScript.dll" +#else + #include <dlfcn.h> + #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; |