avformat/vapoursynth: load library at runtime

Signed-off-by: Stefan Oltmanns <stefan-oltmanns@gmx.net>
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
Stefan Oltmanns 2024-07-29 05:12:31 +02:00 committed by Paul B Mahol
parent 0902b0cc68
commit b73ac602f0
2 changed files with 64 additions and 3 deletions

2
configure vendored
View File

@ -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

View File

@ -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;