Skip to content

Commit

Permalink
Merge branch 'dev2' into doodle2
Browse files Browse the repository at this point in the history
Some necessary evil:
```
def tcanny(**args):
    if 'gmmax' in args:
        args['scale'] = args['gmmax'] / 255.0
        del args['gmmax']
    return core.tcanny._TCanny(**args)
core.tcanny._register_func('TCanny', core.tcanny.TCanny.signature+'gmmax:float:opt;', core.tcanny.TCanny.return_signature, tcanny, override=True)
```
and
```
import havsfunc as haf
core._create_plugin('id', 'haf')._register_func('QTGMC', \
    'clip:vnode;any', 'clip:vnode', \
    lambda clip, **kwargs: haf.QTGMC(clip, **kwargs))

c = core.std.BlankClip(format=vs.YUV420P10)
d = c.haf.QTGMC(TFF=1)
```
  • Loading branch information
AkarinVS committed Jan 19, 2022
2 parents abe7054 + a160fb7 commit 61e784f
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Makefile.am
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
warningflags = -Wall -Wextra -Wno-unused-parameter -Wno-unused-function -Wno-ignored-attributes
commoncflags = -O3 -fvisibility=hidden $(warningflags) -I$(srcdir)/include $(DEBUGCFLAGS) $(MFLAGS) $(UNICODECFLAGS) $(STACKREALIGN)
AM_CXXFLAGS = -std=c++14 $(commoncflags)
AM_CXXFLAGS = -std=c++17 $(commoncflags)
AM_CFLAGS = -std=c99 $(commoncflags)
ACLOCAL_AMFLAGS = -I m4

Expand Down
37 changes: 37 additions & 0 deletions include/VapourSynthC.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2012-2022 Fredrik Mellbin
*
* This file is part of VapourSynth Classic.
*
* VS-C is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* VapourSynth is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with VapourSynth; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

// This API is for VS-C internal use only.

#ifndef VAPOURSYNTHC_H
#define VAPOURSYNTHC_H

#include <stdint.h>

#define VAPOURSYNTHC_API_VERSION 0x76732d63 // 'vs-c'

typedef struct VSCAPI {
int (VS_CC *getPluginAPIVersion)(const VSPlugin *); // major version only
int (VS_CC *pluginSetRO)(VSPlugin *, int readonly); // returns old status
int (VS_CC *pluginRenameFunc)(VSPlugin *, const char *oldname, const char *newname);
VSPlugin *(VS_CC *createPlugin)(const char *id, const char *ns, int version, VSCore *core);
} VSCAPI;

#endif /* VAPOURSYNTHC_H */
8 changes: 4 additions & 4 deletions msvc_project/Core/Core.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NOMINMAX;VS_CORE_EXPORTS;VS_TARGET_OS_WINDOWS;VS_TARGET_CPU_X86;VS_USE_MIMALLOC;VS_GRAPH_API;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp14</LanguageStandard>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
Expand All @@ -108,7 +108,7 @@
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NOMINMAX;VS_CORE_EXPORTS;VS_TARGET_OS_WINDOWS;VS_TARGET_CPU_X86;VS_USE_MIMALLOC;VS_GRAPH_API;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp14</LanguageStandard>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
Expand All @@ -130,7 +130,7 @@
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp14</LanguageStandard>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
Expand All @@ -154,7 +154,7 @@
<PreprocessorDefinitions>NOMINMAX;VS_CORE_EXPORTS;VS_TARGET_OS_WINDOWS;VS_TARGET_CPU_X86;VS_USE_MIMALLOC;VS_GRAPH_API;_CRT_SECURE_NO_WARNINGS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp14</LanguageStandard>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
Expand Down
57 changes: 57 additions & 0 deletions src/core/vsapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "cpufeatures.h"
#include "vslog.h"
#include "VSHelper4.h"
#include "VapourSynthC.h"
#include <cassert>
#include <cstring>
#include <string>
Expand Down Expand Up @@ -1278,6 +1279,60 @@ const vs3::VSAPI3 vs_internal_vsapi3 = {
&getCoreInfo2
};

///////////////////////////////
static int VS_CC getPluginAPIVersion(const VSPlugin *plugin) VS_NOEXCEPT {
assert(plugin);
if (!plugin)
return -1;
return plugin->getAPIVersion();
}
static int VS_CC pluginSetRO(VSPlugin *plugin, int readonly) VS_NOEXCEPT {
assert(plugin);
const bool old = plugin->isLocked();
if (readonly)
plugin->lock();
else
plugin->unlock();
return old;
}
bool VSPluginFunction::rename(const std::string &newname) {
if (name == newname)
return false;

std::lock_guard<std::mutex> lock(plugin->functionLock);

auto &funcs = plugin->funcs;
auto node = funcs.extract(name);
node.key() = newname;
funcs.insert(std::move(node));

name = newname;
return true;
}
static int VS_CC pluginRenameFunc(VSPlugin *plugin, const char *oldname, const char *newname) VS_NOEXCEPT {
assert(plugin && oldname && newname);
VSPluginFunction *func = plugin->getFunctionByName(oldname);
if (!func) return false;
return func->rename(newname);
}
void VSCore::addPlugin(const std::string &name, VSPlugin *plugin) {
std::lock_guard<std::recursive_mutex> lock(pluginLock);
plugins.emplace(name, plugin);
}
static VSPlugin *VS_CC createPlugin(const char *id, const char *ns, int version, VSCore *core) {
assert(id && ns && core);
VSPlugin *p = new VSPlugin(core);
vs_internal_vspapi.configPlugin(id, ns, "python plugin", version, VAPOURSYNTH_API_VERSION, 0, p);
p->lock();
core->addPlugin(ns, p);
return p;
}
static const VSCAPI vsc_internal_api = {
&getPluginAPIVersion,
&pluginSetRO,
&pluginRenameFunc,
&createPlugin,
};
///////////////////////////////

const VSAPI *getVSAPIInternal(int apiMajor) {
Expand Down Expand Up @@ -1305,6 +1360,8 @@ const VSAPI *VS_CC getVapourSynthAPI(int version) VS_NOEXCEPT {
return &vs_internal_vsapi;
} else if (apiMajor == VAPOURSYNTH3_API_MAJOR && apiMinor <= VAPOURSYNTH3_API_MINOR) {
return reinterpret_cast<const VSAPI *>(&vs_internal_vsapi3);
} else if (version == VAPOURSYNTHC_API_VERSION) {
return reinterpret_cast<const VSAPI *>(&vsc_internal_api);
} else {
return nullptr;
}
Expand Down
13 changes: 13 additions & 0 deletions src/core/vscore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
#include <queue>
#include <bitset>

#ifdef VS_PROFILE_CREATE
#include <iostream>
#endif

#ifdef VS_TARGET_CPU_X86
#include "x86utils.h"
#endif
Expand Down Expand Up @@ -813,7 +817,16 @@ VSMap *VSPluginFunction::invoke(const VSMap &args) {
std::string fullName = plugin->getNamespace() + "." + name;
plugin->core->functionFrame = std::make_shared<VSFunctionFrame>(fullName, new VSMap(&args), plugin->core->functionFrame);
}

#ifdef VS_PROFILE_CREATE
std::chrono::time_point<std::chrono::high_resolution_clock> startTime = std::chrono::high_resolution_clock::now();
#endif
func(&args, v, functionData, plugin->core, getVSAPIInternal(plugin->apiMajor));
#ifdef VS_PROFILE_CREATE
std::chrono::nanoseconds duration = std::chrono::high_resolution_clock::now() - startTime;
std::cerr << this->plugin->fnamespace << "." << this->name << " uses " << 0.001 * (double)duration.count() << " us" << std::endl;
#endif

if (enableGraphInspection) {
assert(plugin->core->functionFrame);
plugin->core->functionFrame = plugin->core->functionFrame->next;
Expand Down
6 changes: 6 additions & 0 deletions src/core/vscore.h
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,7 @@ struct VSPluginFunction {
bool isV3Compatible() const;
std::string getV4ArgString() const;
std::string getV3ArgString() const;
bool rename(const std::string &newname); // 'vs-c'
};


Expand Down Expand Up @@ -1035,6 +1036,8 @@ struct VSPlugin {
VSPlugin(const std::string &relFilename, const std::string &forcedNamespace, const std::string &forcedId, bool altSearchPath, VSCore *core);
~VSPlugin();
void lock() { readOnly = true; }
void unlock() { readOnly = false; } // 'vs-c'
bool isLocked() const { return readOnly; } // 'vs-c'
bool configPlugin(const std::string &identifier, const std::string &pluginsNamespace, const std::string &fullname, int pluginVersion, int apiVersion, int flags);
bool registerFunction(const std::string &name, const std::string &args, const std::string &returnType, VSPublicFunction argsFunc, void *functionData);
VSMap *invoke(const std::string &funcName, const VSMap &args);
Expand All @@ -1045,6 +1048,7 @@ struct VSPlugin {
const std::string &getNamespace() const { return fnamespace; }
const std::string &getFilename() const { return filename; }
int getPluginVersion() const { return pluginVersion; }
int getAPIVersion() const { return apiMajor; } // 'vs-c'
void getFunctions3(VSMap *out) const;
};

Expand Down Expand Up @@ -1163,6 +1167,8 @@ struct VSCore {

explicit VSCore(int flags);
void freeCore();

void addPlugin(const std::string &name, VSPlugin *plugin); // 'vs-c'
};

#endif // VSCORE_H
9 changes: 9 additions & 0 deletions src/cython/vapoursynth.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -388,3 +388,12 @@ cdef extern from "include/VapourSynth4.h" nogil:
bint removeLogHandler(VSLogHandle *handle, VSCore *core) nogil

const VSAPI *getVapourSynthAPI(int version) nogil

cdef extern from "include/VapourSynthC.h" nogil:
enum:
VAPOURSYNTHC_API_VERSION
ctypedef struct VSCAPI:
int getPluginAPIVersion(VSPlugin *) nogil
int pluginSetRO(VSPlugin *, int) nogil
int pluginRenameFunc(VSPlugin *, const char *, const char *) nogil
VSPlugin *createPlugin(const char *id, const char *ns, int version, VSCore *core) nogil
117 changes: 116 additions & 1 deletion src/cython/vapoursynth.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ cdef class StandaloneEnvironmentPolicy:
cdef object _policy = None

cdef const VSAPI *_vsapi = NULL
cdef const VSCAPI *_vscapi = NULL


cdef void _set_logger(EnvironmentData env, VSLogHandler handler, VSLogHandlerFree free, void *userData):
Expand Down Expand Up @@ -2337,6 +2338,18 @@ cdef class Core(object):
s += '\tNumber of Threads: ' + str(self.num_threads) + '\n'
return s

def _create_plugin(self, id, ns, int version=0): # 'vs-c'
if os.getenv('VSC_DEBUG_REGISTER_FUNC'):
print('[VS-C]: creating plugin %s: id=%s, version=%d' % (ns, id, version), file=sys.stderr)
if _vscapi == NULL:
getVSAPIInternal()
tid = id.encode('utf-8')
cdef const char *cid = tid
tns = ns.encode('utf-8')
cdef const char *cns = tns
cdef VSPlugin *p = _vscapi.createPlugin(cid, cns, version, self.core)
return createPlugin(p, self.funcs, self)

cdef object createNode(VSNode *node, const VSAPI *funcs, Core core):
if funcs.getNodeType(node) == VIDEO:
return createVideoNode(node, funcs, core)
Expand Down Expand Up @@ -2491,6 +2504,106 @@ cdef class Plugin(object):
return True
return False

def _register_func(self, name, args, returnType, func, *, override=False): # 'vs-c'
if os.getenv('VSC_DEBUG_REGISTER_FUNC'):
dbgname = '%s.%s' % (self.namespace, name)
print('[VS-C]: registering %s(%s) -> %s, override=%r' % (dbgname, args, returnType, override), file=sys.stderr)
traceback.print_stack()
func_ = func
def wrapped(**args):
print('[VS-C] registered Python filter %s called with %r' % (dbgname, args), file=sys.stderr)
return func_(**args)
func = wrapped
myfuncs = self.__dir__()
if not override and name in myfuncs:
raise Error('cannot override existing filter "' + name + '" without explicitly setting override.')
if override:
if isinstance(override, str):
newname = override
else:
newname = '_' + name
if newname in myfuncs:
raise Error('renamed function "' + newname + '" already exists')

if _vscapi == NULL:
getVSAPIInternal()

tname = name.encode('utf-8')
cdef const char *cname = tname

cdef int apiver = _vscapi.getPluginAPIVersion(self.plugin)
if apiver < VAPOURSYNTH_API_MAJOR:
args = args.replace(':vnode', ':clip').replace(':vframe', ':frame')
returnType = 'any'

cdef const char *cargs = NULL
cdef const char *crett = NULL

cdef VSPluginFunction *mfunc = self.funcs.getPluginFunctionByName(cname, self.plugin)
if (args is None or returnType is None) and mfunc == NULL:
raise Error('args or return type cannot be None unless the function already exists')
if args is None:
cargs = self.funcs.getPluginFunctionArguments(mfunc)
else:
targs = args.encode('utf-8')
cargs = targs
if returnType is None:
crett = self.funcs.getPluginFunctionReturnType(mfunc)
else:
trett = returnType.encode('utf-8')
crett = trett

cdef bint ro = _vscapi.pluginSetRO(self.plugin, 0)
cdef const char *cnewname = NULL
if override:
tnewname = newname.encode('utf-8')
cnewname = tnewname
if not _vscapi.pluginRenameFunc(self.plugin, cname, cnewname):
raise Error('failed to rename existing filter')

fdata = createFilterFuncData(func, self.core.core)
Py_INCREF(fdata)

cdef bint ret = self.funcs.registerFunction(cname, cargs, crett, publicFilterFunction, <void *>fdata, self.plugin)
if not ret:
if cnewname != NULL:
assert _vscapi.pluginRenameFunc(self.plugin, cnewname, cname), 'failed to restore old filter name'
Py_DECREF(fdata)
if ro:
_vscapi.pluginSetRO(self.plugin, 1)
return ret

cdef class FilterFuncData(object):
cdef object func
cdef VSCore *core

def __init__(self):
raise Error('Class cannot be instantiated directly')

def __call__(self, **kwargs):
return self.func(**kwargs)

cdef FuncData createFilterFuncData(object func, VSCore *core):
cdef FuncData instance = FuncData.__new__(FuncData)
instance.func = func
instance.core = core
return instance

cdef void __stdcall publicFilterFunction(const VSMap *inm, VSMap *outm, void *userData, VSCore *core, const VSAPI *vsapi_do_not_use) nogil:
with gil:
d = <FilterFuncData>userData
try:
m = mapToDict(inm, False)
ret = d(**m)
if not isinstance(ret, dict):
if ret is None:
ret = 0
ret = {'clip':ret}
dictToMap(ret, outm, core, _vsapi)
except BaseException, e:
emsg = str(e).encode('utf-8')
_vsapi.mapSetError(outm, emsg)

cdef Plugin createPlugin(VSPlugin *plugin, const VSAPI *funcs, Core core):
cdef Plugin instance = Plugin.__new__(Plugin)
instance.core = core
Expand Down Expand Up @@ -3074,9 +3187,11 @@ cdef public api const VSAPI *vpy4_getVSAPI(int version) nogil:
return getVapourSynthAPI(version)

cdef const VSAPI *getVSAPIInternal() nogil:
global _vsapi
global _vsapi, _vscapi
if _vsapi == NULL:
_vsapi = getVapourSynthAPI(VAPOURSYNTH_API_VERSION)
if _vscapi == NULL:
_vscapi = <const VSCAPI *>getVapourSynthAPI(VAPOURSYNTHC_API_VERSION)
return _vsapi

cdef public api int vpy4_getVariable(VSScript *se, const char *name, VSMap *dst) nogil:
Expand Down

0 comments on commit 61e784f

Please sign in to comment.