summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-10-11 22:20:05 +0200
committerwm4 <wm4@nowhere>2014-10-12 01:33:09 +0200
commit1b4f51ae73a41a6c8b335d76b3dab3814cebaaa8 (patch)
tree7fe593383754e7f934a01e2b987253f0d02985ce
parentc2eca2e4b7320324c1c1d78d432dc6358fa860c2 (diff)
downloadmpv-1b4f51ae73a41a6c8b335d76b3dab3814cebaaa8.tar.bz2
mpv-1b4f51ae73a41a6c8b335d76b3dab3814cebaaa8.tar.xz
vf_vapoursynth: abstract scripting backend
In theory, vsscript should be doing it, but it's not there yet, neither did there seem to be any interest in making it flexible enough to handle more than 1 scripting language.
-rw-r--r--video/filter/vf_vapoursynth.c115
1 files changed, 87 insertions, 28 deletions
diff --git a/video/filter/vf_vapoursynth.c b/video/filter/vf_vapoursynth.c
index 8b4d52cad0..f5122df544 100644
--- a/video/filter/vf_vapoursynth.c
+++ b/video/filter/vf_vapoursynth.c
@@ -23,7 +23,6 @@
#include <assert.h>
#include <VapourSynth.h>
-#include <VSScript.h>
#include <VSHelper.h>
#include <libavutil/rational.h>
@@ -39,10 +38,12 @@
struct vf_priv_s {
VSCore *vscore;
const VSAPI *vsapi;
- VSScript *se;
VSNodeRef *out_node;
VSNodeRef *in_node;
+ const struct script_driver *drv;
+ struct VSScript *se;
+
struct mp_image_params fmt_in;
pthread_mutex_t lock;
@@ -72,6 +73,14 @@ struct vf_priv_s {
// priv->requested[n] points to this if a request for frame n is in-progress
static const struct mp_image dummy_img;
+struct script_driver {
+ int (*init)(struct vf_instance *vf); // first time init
+ void (*uninit)(struct vf_instance *vf); // last time uninit
+ int (*load_core)(struct vf_instance *vf); // make vsapi/vscore available
+ int (*load)(struct vf_instance *vf, VSMap *vars); // also set p->out_node
+ void (*unload)(struct vf_instance *vf); // unload script and maybe vs
+};
+
struct mpvs_fmt {
VSPresetFormat vs;
int mp;
@@ -499,12 +508,7 @@ static void destroy_vs(struct vf_instance *vf)
p->vsapi->freeNode(p->out_node);
p->in_node = p->out_node = NULL;
- if (p->se)
- vsscript_freeScript(p->se);
-
- p->se = NULL;
- p->vsapi = NULL;
- p->vscore = NULL;
+ p->drv->unload(vf);
assert(!p->in_node_active);
assert(num_requested(p) == 0); // async callback didn't return?
@@ -537,13 +541,7 @@ static int reinit_vs(struct vf_instance *vf)
MP_DBG(vf, "initializing...\n");
p->initializing = true;
- // First load an empty script to get a VSScript, so that we get the vsapi
- // and vscore.
- if (vsscript_evaluateScript(&p->se, "", NULL, 0))
- goto error;
- p->vsapi = vsscript_getVSApi();
- p->vscore = vsscript_getCore(p->se);
- if (!p->vsapi || !p->vscore) {
+ if (p->drv->load_core(vf) < 0 || !p->vsapi || !p->vscore) {
MP_FATAL(vf, "Could not get vapoursynth API handle.\n");
goto error;
}
@@ -569,13 +567,8 @@ static int reinit_vs(struct vf_instance *vf)
p->vsapi->propSetInt(vars, "video_in_dw", p->fmt_in.d_w, 0);
p->vsapi->propSetInt(vars, "video_in_dh", p->fmt_in.d_h, 0);
- vsscript_setVariable(p->se, vars);
-
- if (vsscript_evaluateFile(&p->se, p->cfg_file, 0)) {
- MP_FATAL(vf, "Script evaluation failed:\n%s\n", vsscript_getError(p->se));
+ if (p->drv->load(vf, vars) < 0)
goto error;
- }
- p->out_node = vsscript_getOutput(p->se, 0);
if (!p->out_node) {
MP_FATAL(vf, "Could not get script output node.\n");
goto error;
@@ -655,19 +648,16 @@ static void uninit(struct vf_instance *vf)
struct vf_priv_s *p = vf->priv;
destroy_vs(vf);
- vsscript_finalize();
+ p->drv->uninit(vf);
pthread_cond_destroy(&p->wakeup);
pthread_mutex_destroy(&p->lock);
}
-
static int vf_open(vf_instance_t *vf)
{
struct vf_priv_s *p = vf->priv;
- if (!vsscript_init()) {
- MP_FATAL(vf, "Could not initialize VapourSynth scripting.\n");
+ if (p->drv->init(vf) < 0)
return 0;
- }
if (!p->cfg_file || !p->cfg_file[0]) {
MP_FATAL(vf, "'file' parameter must be set.\n");
return 0;
@@ -697,10 +687,79 @@ static const m_option_t vf_opts_fields[] = {
{0}
};
+#include <VSScript.h>
+
+static int drv_vss_init(struct vf_instance *vf)
+{
+ if (!vsscript_init()) {
+ MP_FATAL(vf, "Could not initialize VapourSynth scripting.\n");
+ return -1;
+ }
+ return 0;
+}
+
+static void drv_vss_uninit(struct vf_instance *vf)
+{
+ vsscript_finalize();
+}
+
+static int drv_vss_load_core(struct vf_instance *vf)
+{
+ struct vf_priv_s *p = vf->priv;
+
+ // First load an empty script to get a VSScript, so that we get the vsapi
+ // and vscore.
+ if (vsscript_evaluateScript(&p->se, "", NULL, 0))
+ return -1;
+ p->vsapi = vsscript_getVSApi();
+ p->vscore = vsscript_getCore(p->se);
+ return 0;
+}
+
+static int drv_vss_load(struct vf_instance *vf, VSMap *vars)
+{
+ struct vf_priv_s *p = vf->priv;
+
+ vsscript_setVariable(p->se, vars);
+
+ if (vsscript_evaluateFile(&p->se, p->cfg_file, 0)) {
+ MP_FATAL(vf, "Script evaluation failed:\n%s\n", vsscript_getError(p->se));
+ return -1;
+ }
+ p->out_node = vsscript_getOutput(p->se, 0);
+ return 0;
+}
+
+static void drv_vss_unload(struct vf_instance *vf)
+{
+ struct vf_priv_s *p = vf->priv;
+
+ if (p->se)
+ vsscript_freeScript(p->se);
+ p->se = NULL;
+ p->vsapi = NULL;
+ p->vscore = NULL;
+}
+
+static const struct script_driver drv_vss = {
+ .init = drv_vss_init,
+ .uninit = drv_vss_uninit,
+ .load_core = drv_vss_load_core,
+ .load = drv_vss_load,
+ .unload = drv_vss_unload,
+};
+
+static int vf_open_vss(vf_instance_t *vf)
+{
+ struct vf_priv_s *p = vf->priv;
+ p->drv = &drv_vss;
+ return vf_open(vf);
+}
+
const vf_info_t vf_info_vapoursynth = {
- .description = "vapoursynth bridge",
+ .description = "VapourSynth bridge (Python)",
.name = "vapoursynth",
- .open = vf_open,
+ .open = vf_open_vss,
.priv_size = sizeof(struct vf_priv_s),
.options = vf_opts_fields,
};