diff --git a/DOCS/man/vf.rst b/DOCS/man/vf.rst index 28c2db07d6..5c576e6bad 100644 --- a/DOCS/man/vf.rst +++ b/DOCS/man/vf.rst @@ -443,31 +443,6 @@ Available mpv-only filters are: ``display_fps`` Refresh rate of the current display. Note that this value can be 0. -``vapoursynth-lazy`` - The same as ``vapoursynth``, but doesn't load Python scripts. Instead, a - custom backend using Lua and the raw VapourSynth API is used. The syntax - is completely different, and absolutely no convenience features are - provided. There's no type checking either, and you can trigger crashes. - - .. admonition:: Example: - - :: - - video_out = invoke("morpho", "Open", {clip = video_in}) - - The special variable ``video_in`` is the mpv video source, while the - special variable ``video_out`` is used to read video from. The 1st argument - is the plugin (queried with ``getPluginByNs``), the 2nd is the filter name, - and the 3rd argument is a table with the arguments. Positional arguments - are not supported. The types must match exactly. Since Lua is terrible and - can't distinguish integers and floats, integer arguments must be prefixed - with ``i_``, in which case the prefix is removed and the argument is cast - to an integer. Should the argument's name start with ``i_``, you're out of - luck. - - Clips (VSNodeRef) are passed as light userdata, so trying to pass any - other userdata type will result in hard crashes. - ``vavpp`` VA-API video post processing. Requires the system to support VA-API, i.e. Linux/BSD only. Works with ``--vo=vaapi`` and ``--vo=gpu`` only. diff --git a/filters/user_filters.c b/filters/user_filters.c index 89d7743d53..e1b7a8bce1 100644 --- a/filters/user_filters.c +++ b/filters/user_filters.c @@ -64,12 +64,9 @@ const struct mp_user_filter_entry *vf_list[] = { &vf_lavfi, &vf_lavfi_bridge, &vf_sub, -#if HAVE_VAPOURSYNTH_CORE && HAVE_VAPOURSYNTH +#if HAVE_VAPOURSYNTH &vf_vapoursynth, #endif -#if HAVE_VAPOURSYNTH_CORE && HAVE_VAPOURSYNTH_LAZY - &vf_vapoursynth_lazy, -#endif #if HAVE_VDPAU &vf_vdpaupp, #endif diff --git a/filters/user_filters.h b/filters/user_filters.h index a2cca7cba0..88cb859a71 100644 --- a/filters/user_filters.h +++ b/filters/user_filters.h @@ -29,7 +29,6 @@ extern const struct mp_user_filter_entry vf_lavfi; extern const struct mp_user_filter_entry vf_lavfi_bridge; extern const struct mp_user_filter_entry vf_sub; extern const struct mp_user_filter_entry vf_vapoursynth; -extern const struct mp_user_filter_entry vf_vapoursynth_lazy; extern const struct mp_user_filter_entry vf_format; extern const struct mp_user_filter_entry vf_vdpaupp; extern const struct mp_user_filter_entry vf_vavpp; diff --git a/video/filter/vf_vapoursynth.c b/video/filter/vf_vapoursynth.c index 4227ee6fa6..986399c748 100644 --- a/video/filter/vf_vapoursynth.c +++ b/video/filter/vf_vapoursynth.c @@ -812,8 +812,6 @@ static const m_option_t vf_opts_fields[] = { {0} }; -#if HAVE_VAPOURSYNTH - #include static int drv_vss_init(struct priv *p) @@ -872,7 +870,7 @@ static const struct script_driver drv_vss = { const struct mp_user_filter_entry vf_vapoursynth = { .desc = { - .description = "VapourSynth bridge (Python)", + .description = "VapourSynth bridge", .name = "vapoursynth", .priv_size = sizeof(OPT_BASE_STRUCT), .priv_defaults = &(const OPT_BASE_STRUCT){ @@ -882,241 +880,3 @@ const struct mp_user_filter_entry vf_vapoursynth = { }, .create = vf_vapoursynth_create, }; - -#endif - -#if HAVE_VAPOURSYNTH_LAZY - -#include -#include -#include - -#if LUA_VERSION_NUM <= 501 -#define mp_cpcall lua_cpcall -#define FUCKYOUOHGODWHY(L) lua_pushvalue(L, LUA_GLOBALSINDEX) -#else -// Curse whoever had this stupid idea. Curse whoever thought it would be a good -// idea not to include an emulated lua_cpcall() even more. -static int mp_cpcall (lua_State *L, lua_CFunction func, void *ud) -{ - lua_pushcfunction(L, func); // doesn't allocate in 5.2 (but does in 5.1) - lua_pushlightuserdata(L, ud); - return lua_pcall(L, 1, 0, 0); -} -// Hey, let's replace old mechanisms with something slightly different! -#define FUCKYOUOHGODWHY lua_pushglobaltable -#endif - -static int drv_lazy_init(struct priv *p) -{ - p->ls = luaL_newstate(); - if (!p->ls) - return -1; - luaL_openlibs(p->ls); - p->vsapi = getVapourSynthAPI(VAPOURSYNTH_API_VERSION); - p->vscore = p->vsapi ? p->vsapi->createCore(0) : NULL; - if (!p->vscore) { - MP_FATAL(p, "Could not load VapourSynth.\n"); - lua_close(p->ls); - return -1; - } - return 0; -} - -static void drv_lazy_uninit(struct priv *p) -{ - lua_close(p->ls); - p->vsapi->freeCore(p->vscore); -} - -static int drv_lazy_load_core(struct priv *p) -{ - // not needed - return 0; -} - -static struct priv *get_priv(lua_State *L) -{ - lua_getfield(L, LUA_REGISTRYINDEX, "p"); // p - struct priv *p = lua_touserdata(L, -1); // p - lua_pop(L, 1); // - - return p; -} - -static void vsmap_to_table(lua_State *L, int index, VSMap *map) -{ - struct priv *p = get_priv(L); - const VSAPI *vsapi = p->vsapi; - for (int n = 0; n < vsapi->propNumKeys(map); n++) { - const char *key = vsapi->propGetKey(map, n); - VSPropTypes t = vsapi->propGetType(map, key); - switch (t) { - case ptInt: - lua_pushnumber(L, vsapi->propGetInt(map, key, 0, NULL)); - break; - case ptFloat: - lua_pushnumber(L, vsapi->propGetFloat(map, key, 0, NULL)); - break; - case ptNode: { - VSNodeRef *r = vsapi->propGetNode(map, key, 0, NULL); - MP_TARRAY_APPEND(p, p->gc_noderef, p->num_gc_noderef, r); - lua_pushlightuserdata(L, r); - break; - } - default: - luaL_error(L, "unknown map type"); - } - lua_setfield(L, index, key); - } -} - -static VSMap *table_to_vsmap(lua_State *L, int index) -{ - struct priv *p = get_priv(L); - const VSAPI *vsapi = p->vsapi; - assert(index > 0); - VSMap *map = vsapi->createMap(); - MP_TARRAY_APPEND(p, p->gc_map, p->num_gc_map, map); - if (!map) - luaL_error(L, "out of memory"); - lua_pushnil(L); // nil - while (lua_next(L, index) != 0) { // key value - if (lua_type(L, -2) != LUA_TSTRING) { - luaL_error(L, "key must be a string, but got %s", - lua_typename(L, -2)); - } - const char *key = lua_tostring(L, -2); - switch (lua_type(L, -1)) { - case LUA_TNUMBER: { - // gross hack because we hate everything - if (strncmp(key, "i_", 2) == 0) { - vsapi->propSetInt(map, key + 2, lua_tointeger(L, -1), 0); - } else { - vsapi->propSetFloat(map, key, lua_tonumber(L, -1), 0); - } - break; - } - case LUA_TSTRING: { - const char *s = lua_tostring(L, -1); - vsapi->propSetData(map, key, s, strlen(s), 0); - break; - } - case LUA_TLIGHTUSERDATA: { // assume it's VSNodeRef* - VSNodeRef *node = lua_touserdata(L, -1); - vsapi->propSetNode(map, key, node, 0); - break; - } - default: - luaL_error(L, "unknown type"); - break; - } - lua_pop(L, 1); // key - } - return map; -} - -static int l_invoke(lua_State *L) -{ - struct priv *p = get_priv(L); - const VSAPI *vsapi = p->vsapi; - - VSPlugin *plugin = vsapi->getPluginByNs(luaL_checkstring(L, 1), p->vscore); - if (!plugin) - luaL_error(L, "plugin not found"); - VSMap *map = table_to_vsmap(L, 3); - VSMap *r = vsapi->invoke(plugin, luaL_checkstring(L, 2), map); - MP_TARRAY_APPEND(p, p->gc_map, p->num_gc_map, r); - if (!r) - luaL_error(L, "?"); - const char *err = vsapi->getError(r); - if (err) - luaL_error(L, "error calling invoke(): %s", err); - int err2 = 0; - VSNodeRef *node = vsapi->propGetNode(r, "clip", 0, &err2); - MP_TARRAY_APPEND(p, p->gc_noderef, p->num_gc_noderef, node); - if (node) - lua_pushlightuserdata(L, node); - return 1; -} - -struct load_ctx { - struct priv *p; - VSMap *vars; - int status; -}; - -static int load_stuff(lua_State *L) -{ - struct load_ctx *ctx = lua_touserdata(L, -1); - lua_pop(L, 1); // - - struct priv *p = ctx->p; - - // setup stuff; should be idempotent - lua_pushlightuserdata(L, p); - lua_setfield(L, LUA_REGISTRYINDEX, "p"); // - - lua_pushcfunction(L, l_invoke); - lua_setglobal(L, "invoke"); - - FUCKYOUOHGODWHY(L); - vsmap_to_table(L, lua_gettop(L), ctx->vars); - if (luaL_dofile(L, p->opts->file)) - lua_error(L); - lua_pop(L, 1); - - lua_getglobal(L, "video_out"); // video_out - if (!lua_islightuserdata(L, -1)) - luaL_error(L, "video_out not set or has wrong type"); - p->out_node = p->vsapi->cloneNodeRef(lua_touserdata(L, -1)); - return 0; -} - -static int drv_lazy_load(struct priv *p, VSMap *vars) -{ - struct load_ctx ctx = {p, vars, 0}; - if (mp_cpcall(p->ls, load_stuff, &ctx)) { - MP_FATAL(p, "filter creation failed: %s\n", lua_tostring(p->ls, -1)); - lua_pop(p->ls, 1); - ctx.status = -1; - } - assert(lua_gettop(p->ls) == 0); - return ctx.status; -} - -static void drv_lazy_unload(struct priv *p) -{ - for (int n = 0; n < p->num_gc_noderef; n++) { - VSNodeRef *ref = p->gc_noderef[n]; - if (ref) - p->vsapi->freeNode(ref); - } - p->num_gc_noderef = 0; - for (int n = 0; n < p->num_gc_map; n++) { - VSMap *map = p->gc_map[n]; - if (map) - p->vsapi->freeMap(map); - } - p->num_gc_map = 0; -} - -static const struct script_driver drv_lazy = { - .init = drv_lazy_init, - .uninit = drv_lazy_uninit, - .load_core = drv_lazy_load_core, - .load = drv_lazy_load, - .unload = drv_lazy_unload, -}; - -const struct mp_user_filter_entry vf_vapoursynth_lazy = { - .desc = { - .description = "VapourSynth bridge (Lua)", - .name = "vapoursynth-lazy", - .priv_size = sizeof(OPT_BASE_STRUCT), - .priv_defaults = &(const OPT_BASE_STRUCT){ - .drv = &drv_lazy, - }, - .options = vf_opts_fields, - }, - .create = vf_vapoursynth_create, -}; - -#endif diff --git a/wscript b/wscript index f19ba6565a..75e90aceab 100644 --- a/wscript +++ b/wscript @@ -392,19 +392,9 @@ iconv support use --disable-iconv.", 'func': check_pkg_config('lcms2', '>= 2.6'), }, { 'name': '--vapoursynth', - 'desc': 'VapourSynth filter bridge (Python)', + 'desc': 'VapourSynth filter bridge', 'func': check_pkg_config('vapoursynth', '>= 24', 'vapoursynth-script', '>= 23'), - }, { - 'name': '--vapoursynth-lazy', - 'desc': 'VapourSynth filter bridge (Lazy Lua)', - 'deps': 'lua', - 'func': check_pkg_config('vapoursynth', '>= 24'), - }, { - 'name': 'vapoursynth-core', - 'desc': 'VapourSynth filter bridge (core)', - 'deps': 'vapoursynth || vapoursynth-lazy', - 'func': check_true, }, { 'name': '--libarchive', 'desc': 'libarchive wrapper for reading zip files and more', diff --git a/wscript_build.py b/wscript_build.py index 8f2f804a39..56668f1a09 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -391,7 +391,7 @@ def build(ctx): ( "video/filter/vf_d3d11vpp.c", "d3d-hwaccel" ), ( "video/filter/vf_format.c" ), ( "video/filter/vf_sub.c" ), - ( "video/filter/vf_vapoursynth.c", "vapoursynth-core" ), + ( "video/filter/vf_vapoursynth.c", "vapoursynth" ), ( "video/filter/vf_vavpp.c", "vaapi" ), ( "video/filter/vf_vdpaupp.c", "vdpau" ), ( "video/fmt-conversion.c" ),